Multi-Tiered Architecture
Posted by Daryl on 01/01/2010
Muti-Tiered Architecture is a very important software concept. Whenever I am givien someone elses code to fix my brain explodes when I see All three of the major teirs in the same function. The three tiers are: Presentation, Application, and Database. In my opinion these three areas should never mix. Your UI should never call the database, and your Application Layer should never interact with the UI. Sometimes you will find yourself in a situation where you have to do some business logic in the UI or inside that database tier, but you should never, ever have to mix the Presentation with the database.
Personally I prefer what I call a 4 tier model. I break down the Development into 4 distinct Areas:
UI – (User Interface or Presentation)
BL – (Business Logic or Application, or I even prefer calling it the Logic Layer)
DL – (Data Layer)
DB – (Database)
I break out the database Layer into two parts, the Data Layer, and the Data Base, this is not the actual database that would be a different layer if anything. The purpose of the data Layer is to convert all database objects into your custom business objects. The database layer only returns datasets, data tables, and other database related objects, but not SQL objects. The Database Layer uses SQL objects or whatever type of database your are connecting to, but only passes back the common database objects like datatables and the sort. This allows TRUE database portability. If you want to change from SQL to mySQL or any other database technology you only have to change one small layer of your code. Your UI has NO idea that underneath it all there is a SQL database or a mySQL database, or an XML flat file, it does not know, nor does it care.
I allways create a common library that has the base objects that I use to transfer data. I use the namespace ‘common’. So I use somthing like ‘vbguru.Common.User’ as my common user object. This way all layers can have access to a common object and pass data back and forth using it. I also separate my tiers into at least different files, I don’t mix tiers in one code file, I even prefer to put them into their own projects for what I would call ‘ultimate portability.’ By breaking down your logic into small chunks it makes it easier to reuse. I love the idea of perfecting some logic and creating a DLL and never looking at it’s code again, just add it to a new project as the dll.
Here is an example of some good muti-tiered code. I am putting it all in one file so that it is easy to read here. Normally, I would put each piece in it’s own file.
Namespace vbGuru
Public Class UI
Public Sub UI_Function()
Dim Obj As vbGuru.Common.MyData()
Dim AL As vbGuru.Logic = New vbGuru.Logic
Obj = AL.GetObj
‘Add UI Stuff
End Sub
End Class
End Namespace
Namespace vbGuru.Common
Public Structure MyData
Public id As Integer
Public Name As String
Public Value As String
End Structure
End Namespace
Namespace vbGuru
Public Class Logic
Public Function GetObj() As vbGuru.Common.MyData()
Dim Data As vbGuru.Data = New vbGuru.Data
Dim Obj As vbGuru.Common.MyData() = Data.GetObj()
‘Add any logic that you need to manipulate the object
Return Obj
End Function
End Class
End Namespace
Namespace vbGuru
Public Class Data
Public Function GetObj() As vbGuru.Common.MyData()
Dim DB As vbGuru.DB = New vbGuru.DB
Dim dt As DataTable = DB.GetObj()
If dt Is Nothing Then Return Nothing
‘I don’t think this second line is needed
‘But I allways put it in just in case.
If dt.Rows.Count = 0 Then Return Nothing
Dim Que As Queue(Of vbGuru.Common.MyData) = New Queue(Of vbGuru.Common.MyData)
‘I like to use Queues to avoid for next loops and i’s
For Each drow In dt.Rows
Dim obj As vbGuru.Common.MyData
obj.id = drow("id")
obj.Name = drow("Name")
obj.Value = drow("Value")
Que.Enqueue(obj)
Next
Return Que.ToArray
End Function
End Class
End Namespace
Namespace vbGuru
Public Class DB
Public Function GetObj() As DataTable
Dim cn As System.Data.SqlClient.SqlConnection = New System.Data.SqlClient.SqlConnection("CNSTRING")
Dim cmd As System.Data.SqlClient.SqlCommand = New System.Data.SqlClient.SqlCommand("SELECT * FROM TMP", cn)
Dim ds As System.Data.SqlClient.SqlDataAdapter = New System.Data.SqlClient.SqlDataAdapter(cmd)
Dim dt As DataTable = New DataTable
ds.Fill(dt)
Return dt
End Function
End Class
End Namespace
It may seem like a lot of steps just to do a simple function but by separating it all out it makes your code easier to maintain, easier to make a database change, and easily reusable.