The Design of Software (CLOSED)

A public forum for discussing the design of software, from the user interface to the code architecture. Now closed.

The "Design of Software" discussion group has been merged with the main Joel on Software discussion group.

The archives will remain online indefinitely.

Data Access Layer vs get/set

Hi all,

what are the advantages of having an additional layer over implementing the CRUD methods inside getters and setters?

At the moment my code works like this:
User.Delete(int UserID) is just a wrap over a static method DALUser.Delete(int UserID) where all the database connection is established and closed, sqlparameters are added, the sqlcommand is executed and exception catched.

To me the above method looks like just a code duplication but maybe I'm getting everything wrong and a usual DAL doesn't look like I intended it.

BTW I'm using C#

Lorenzo Bolognini Send private email
Sunday, September 11, 2005
Well, today it may just be a wrapper but tomorrow you may need to do more than that. For example, what would happen if your code needed to look like this?

public static void Delete(int userID)
    // Make sure the user doesn't have any active orders.
    if (DALOrders.UserOrderExists(userID)
        // Don't let the delete occur. Throw an exception
        // or something.

    // Call a web service to cause the user's last paycheck
    // to be printed and mailed.

    // Go ahead and delete the user

Also, don't forget that your DAL may not just operate with a database. You may also be communicating with web services some day. This is what you are abstracting away with your current code. Calling User.Delete(userID) could cause a web service to be called, a validation script to run, and the user's last paycheck to be printed. It's a silly example but you get the point.
Sunday, September 11, 2005
1. DAL's are useful for separating out the logical layers in order to improve organization and maintainability. Martin Fowler's book Patterns of Enterprise Application Development goes into detail on the various data access patterns.

2. DAL's are also useful for over-engineering small applications. <g>

There is a lot of quick and dirty application development done, and developers often aren't in control of the timeline or resources available. Maybe someone needs to write a "Best Practices for Quick and Dirty Development" book.

Also, most data access sample code you see looks like UI <=> Data source, not UI <=> BLL <=> DAL <=> Data Source.

So I wouldn't be surprised if the vast majority of data access code out in the wild did not use a DAL.
Nick Hebb Send private email
Sunday, September 11, 2005
Why provide the extra level of abstraction where it is not necessary?

Could you use a refactoring tool later to add in the extra layer when you need it?

Building complexity in to start is wasting your time on a what if, and if it's such a simple refactoring why not pay for it when you need it.

Monday, September 12, 2005
Your business objects don't have to look so similar to your data access objects.

In my designs, the data access objects are generally a relational looking object/collection/manager (does the CRUD) that looks and acts like a table. My business objects, on the other hand, look different.

Say you have a Users table and a UserPermissions table. I would have a UserDataObjectBroker* and a UserPermissionDataObjectBroker. But in my business objects I would just have a User. It would have a child Permissions object. When I call UserBroker.Delete(User u), it actually calls UserDataObjectBroker.Delete(userID) as well as UserPermissionsDataObjectBroker.DeleteByUserID(userID).

The way I look at it is the job of the Data layer/domain layer combo is to map relational data (represented by the data layer) into object oriented data (in the domain layer (or business layer)).

Another example is the use of joining tables in many to many relationships. If you have an Owners table and a Pets table, and a pet can have many owners and an owner can have many pets, you'll have a table joining them. In my data layer, I'd have 3 classes (one for each table). But in my domain (business) layer, I'd only have two. My Owner object would have a Pets property, which when called will use the joining table to get all the pets, and my Pets object would have an Owners property. This way the GUI never knows about the third table (which it shouldn't).

* The broker thing:

I use a design that involves 3 main classes for each entity. The first is a representation of the object, ie
  string Username;
  string Password;

Then theres a UserCollection, which is really a List<User>.

Then theres a UserBroker. The broker has all the methods to call the data layer and it returns User and UserCollection objects.

At the data layer I do the same thing. I have a
and a UserDataObjectBroker

The use of a "broker" is very clever in my opinion, because it means I can replace a broker that gets data from SQL Server with one that gets it from Oracle easily.

In a project I'm doing now, my UserDataObjectBroker is actually an abstract class with an Instance property (it's a Singleton). Inheriting from it is a SqlUserDataObjectBroker and an OracleDataObjectBroker. They both return UserDataObject's and UserDataObjectCollection's, but one uses SQL Server underlying whilst another uses Oracle.

When you use the UserDataObjectBroker.Instance property, it looks at the config file and returns the right type of broker, either SQL or Oracle. The end result is the domain layer says "Oi, I want a Broker for Users", and the data layer gives it whatever it's configured to use. The domain layer doesn't know or care where the data is coming from, and the use of the abstract UserDataObjectBroker class defines exactly what methods each broker for users should implement.
Paul Stovell Send private email
Monday, September 12, 2005
I have a system very similar to Paul (above), except I cut it a slightly different way.  I have just one data container (his UserObject, UserDataObject), and for a collection of them I often like to use an array.  All those objects inherit from a base, and that base defines all the information that is required for general use of the data container. 

What he calls a UserDataObjectBroker* I call a Data Connection.  The Data Connection is written to use the interface of an abstract object which is the thing that actually has all the SQL/Oracle/Access C#.NET DAL prebuilt objects.  That way, I can switch from SQL Server to Oracle by just inheriting from the abstract class. 

His UserBroker is called a UserBusinessObject in my design, but it does much the same thing.  I don't think it is a coincidence that these designs are similar, I would guess, in fact, that they are repeated across the vast majority of business applications (CRM systems, ERP systems, Accounting Systems, etc).  Everywhere I have worked has used some variation of this design.
Joshua Volz Send private email
Tuesday, September 13, 2005
Is this you guys use an implementation of the Martin Fowler Data Mapper pattern?
Lorenzo Bolognini Send private email
Wednesday, September 14, 2005
From OP "To me the above method looks like just a code duplication".

It is code duplication.  Why have two classes to model a User when you only need one?

Put all the data access code in the User.Delete method, that way ALL logic to do with deleting a user will be defined in the User class.  The database connection information can be read in from a config file.

This way you won't break encapsulation either, because only one class is responsible for managing User information.  Having a separate DAL breaks the fundamental OO rule of encapsulation.
Edward James
Friday, September 16, 2005
Ok I did some homework! I researched a bit on this 3-tier/n-tier/n-layer/crud/data mapper/active record/table gateway approach [2] :-)

My findings are that very few people have a correct use of terminology (myself I don't blog so I'm excused!) and this makes it VERY difficult to understand what one is trying to say.

Also these people that distill in their blogs/articles/msdn make the case for using one or another technology with akward examples, too many diagrams and too little code which, most of the times, is just a representation of a too trivial or too corner, non real-life scenario.

Having a separate layer to access a datasource is good if and only if you have to abstract the kind of datasource (XML, database, flat file) but this is not my case: i plan to only deal with database and the absolute minimum with XML.

So where were we? Ah yeah CRUD... yeah the approch of implementing the CRUD inside the same class is a good idea i guess which i overlooked because when i'm in "planning mode" i tend to overengineer my stuff. But i think you're right... besides the KIS (Keep It Simple) approach is my all-time favorite.

During my research i found also 1 good blog which clears a lot of the haze around the OOP/Patterns terminology ( and a good article on CRUD ( which basically says to take into account concurrency when implementing CRUD in data mapper/active record (which the good guys that built ActiveRecord for Ruby On Rails did [1])

[2] data mapper and active records are to be intended as formalized in Martin Fowler Patterns of Enterprise Application Architecture
Lorenzo Bolognini Send private email
Saturday, September 17, 2005

I hope you rethink this decision. A well designed data-access layer is really a beautiful thing.

First of all, when you're writing your business logic you get this warm fuzzy feeling because when you want to delete a user, retrieve a category listing, update a record, insert into a table, all you ever have to do is call a single line of code (assuming your object is already instantiated).

But more importantly, you can change your underlying database structure without every having to let your UI or Business Logic know. Let's say you decide to throw that 1,240,000 row log table into its own DB; or you finally denormalize the invoice table like the accountant has been BEGGING you to; or--as someone said before--you decide to gather your user data from some Directory service XML feed and get rid of your local user tables.

All of those changes would be implemented in your data access layer and you never have to check-out a single business object or read thru a single mal-indented interface page.

It's beautiful.
Shane Harter Send private email
Wednesday, September 28, 2005

This topic is archived. No further replies will be accepted.

Other recent topics Other recent topics
Powered by FogBugz