Custom Objects/Collections and Tiered Development

Recently I was involved in a discussion on creating BusinessObjects, BusinessObject Collections, and where one should keep the code to create the objects.
In a N-tiered system, you want to create seperate tiers.  While most people can quote the name of the tiers, understanding them and actually keeping them seperated is the fall short area.
I have created a sample which has a:
Presentation Tier ( a Console App )
Business Tier.
DataLayer Tier.
I am piggy-backing off the NorthWind database for my example. 
I have created 2 strong objects (Customer and Order), and 2 Collection objects (CustomerCollection and OrderCollection).
I have also created a CustomerController object to handle the creation of Customer’s and Order’s.
The CustomerController is a business object, which calls the DataLayer object, and gets an IDataReader to populate the data.
(Sql Server 2000/7.0/2005 scripts are included in the download as well).
I am also using the DAAB 2.0 "SQLHelper" class to assist with the datalayer object.  While I use the EnterpriseLibrary project now in my production code, the SQLHelper is good for this demo, as it is Sql Server (2000 usually) specific.  It also provides an easier mechanism for implementing the connection string property.
However, it points out the fact that I should be able to move from one DataHelper (SQLHelper) to another (EnterpriseLibrary.Data) and *never* have to touch/recompile the
Presentation Code or the
BusinessLogic Code
In fact, you could switch from Sql Server to Oracle, and never have to recompile these 2 upper tiers (again, Presentation and BusinessLogic should be isolated from the database vendor of choice)
Hopefully the sample will provide an illustration to avoid common mistakes.
Those mistakes are:
1.  Intertwined business layer logic and database connectivity.
2.  Substituting the SQLHelper class ~in place of~ the application’s DataLayer object.  The SQLHelper (as the name implies) is there to assist/help the DataLayer object, not replace it.
3.  Keeping objects (their properties, methods and sometimes events) seperate from the code which creates them.
I show how to create a sub collection of Orders per Customer, and how to accomplish this with one database call.  (IDataReader.NextResult();)
I show how the DataAccessLayer should be simple, and pretty much return only data.
My rule of thumb is that:
The DataLayer object should return:
DataSet’s (typed and untyped)
Scalars ( count(*) is an example here)
void/Nothing (aka, you just call a stored procedure which does something, but does not return anything)
That’s it.  That’s what the DataLayer should return.
The obvious reason is that any RDBMS or datastore should be able to return DataSet’s and IDataReaders.  That’s the goal, to provide data to the business layer without having intricate knowledge of the backend database.
As a bonus, I include some time-test code to compare:
Custom Objects/Collections being populated with an IDataReader
Typed DataSet object, with Constraints enabled.
Typed DataSet object, with no Constaints (in the xsd definition)
You can view the results.
In regards to Custom Objects/Collections vs Typed DataSet’s vs other methods:
Like in most areas of software development, there are not "blanket statements" for which method to use.
There are pro’s and con’s, and it depends.
I usually go with the CustomObjects/Collections.
I jokingly refer to DataSet’s as the "poor man’s business object".  However, there are times when they make good sense.
You can download the example code here. ("Right Click"/"Save Target As" is the best approach I think)
I am working up a DotNet 2.0 example also, where I replace the CollectionBase objects with generics.  Look for that code soon.
And a reference to read from start to finish, aka, very informative for a bird’s eye view:
This entry was posted in Software Development. Bookmark the permalink.

4 Responses to Custom Objects/Collections and Tiered Development

  1. Unknown says:

    In my opninon, this is a good approch if ur presentation tier is going to call ur business tier less frequently. This is a classic Engine-Collection-Class design pattern but this has some problems.
    First is performance. As everything is happing in memory, u need to have more memory. More u use the memory less the performace as less memory is available for some other processes.
    Secondly, if the server hosting business tier crashes then ur memory is lost and so as the data.
    Third, if u have farm at the business tier then it is difficult to maintain the state.
    If above is not a implcit requirement then this is a good approch

  2. Max says:

    HI,nice example, and explanation. Got a question, though:Your \’common mistake\’ number 3 states \’Keeping objects (their properties, methods and sometimes events) seperate from the code which creates them\’I wonder exactly why you say this is a mistake? If my object wants to persist itself in a database, then \’populating itself\’ from, say, a DataRow would seem like a good idea, to me.Am I missing some good reason for not doing this?

  3. Sloan says:

    Because you are assuming the Business Object will always be coming to/from a DataRow. Microsoft changes its database access technology every 2.5 years I think (see Rocky "The CSLA guy" for this stat). So while today it makes sense, one day your object may not be coming from a DataRow.Another reason is serialization (like wcf). You want to keep your objects POCO simple, so that when they go across the wire they are as small as possible.

  4. Sloan says:

    I apologize for the lateness, my posts got spammed out the waa-zoo and I\’m trying to clean them up.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s