Monday, May 29, 2006

A case against DAOs?

Ok, maybe the title is a little provocative, but here is the thought. 100% of the work that I do, plan to do, and have done in the past have dictated the database to be used. A lot of CF devs are pushing the use of DAOs as a way to encapsulate the interaction between their business objects and the database. The argument goes that it's easier to swap out the database, roll a new set of DAOs and you're back in business.

For some projects this is probably true, especially when you need your project to support multiple databases (MSSQL, ORACLE, etc.) out of the gate. You let the user/administrator set a switch for the type of db and the code is already in place. This makes a lot of sense when you are building an application that you plan on distributing.

For the type of work that I do, this looks like a lot of extra work for little or no gain when the db choice is stable and your app has little chance of seeing any kind of distribution.

For me, just adding the CRUDS (create, read, update, delete, save) methods to the business objects themselves seems to work just fine and reduces the size of the app. As long as they are done consistantly and in roughly the same place, I don't really see a down side. If you found that you had to change to support multiple dbs down the road, it's not really that much trouble to strip the functions out and set up DAOs if needed, although it's a little more work than if you had set it up that way from the beginning.

Is this too short-sighted?


  1. Of course it's not shortsighted. Encapsulation is good, but in a lot of cases DAO's are overkill. Spending 3 weeks writing code to support MySQL and Postgre porting is ridicolous in some companies where changing the database used company wide would be a monumentous event, thus there is absolutely no point on spending time on something that would never happen. Even if it did, you'd just end up re-writing everything anyway.

    For smaller companies, or those distributing software packaged for a variety of uses, heck yeah it's worth it, I agree with what you've said.

    Purists would disagree, but I'm pragmatic, not a purist. Hours, days, or even weeks spent writing code for an event that would never happen cannot be justified business wise, and if I were a customer who had instituted that all products utilize SQL 200x, I'd refuse to pay the contractor for time spent on that particular task.

    If I were writing open source software, totally different.

  2. I know the "changing DBMS vendor" is a common argument in favor of this but as you point out, that's a pretty bogus argument.

    There are plenty of other good reasons for placing CRUD code outside your business objects.

    I like having my SQL code in a separate "layer" simply because I find it easier to maintain - I don't have to go digging around in my business objects to find the SQL, I can go straight to my DAO/Gateway CFCs and work on it independently. I really don't think it's any extra work to put the CRUD methods in a separate CFC and just call those methods from elsewhere.

    Sometimes I have business objects that are not always persisted. A service layer that orchestrates the operations on the model decides what to persist and when: it calls the data layer as needed and the business objects know nothing about persistence.

    And then, of course, this becomes somewhat moot when you're using an ORM framework like Reactor or Transfer to manage persistence since it handles all of the SQL for you, and you just write your business logic (and the "management" logic that tells the ORM when to persist / load objects).

    Sean Corfield

  3. Being able to easily change databases isn't the only reason to use DAOs. This definitely isn't a case of "you ain't gonna need it" in my mind. Your SQL code has to exist somewhere, so it's not as if writing DAOs is even that much (or any, really) extra work, and even if you aren't ever going to change database platforms, it still abstracts your database-related code and keeps your business objects cleaner. Separation of concerns is a good thing even if you spend all your time using a single database server.

    Matt Woodward

  4. Interesting comments. I think maybe one reason everybody tends to think a little bit differently about these objects is that maybe we wire them up differently to begin with. Sean, it sounds like you put both single instance db calls and collection oriented db calls in the same object. That seems really reasonable, but for some reason I've always separated functions into two components. I think I gravitated that way because I tend to wire my DAO functions to the Business object and the gateway seems to work in the reverse where it returns instances of the business object. Putting both seems like a more logical grouping, but I'll have to try it out first. I think if you have both types of services in your DAO, you are going to be much more disinclined to lump the functions into the business object. I'm not sure it's even possible that way.

    Matt, you're right when you say it's not that much more work. For me it was really just a couple of wrapper functions in the business object to provide access to the data functions. It does keep the objects a little cleaner, at the expense of having to hunt through another component. Not a problem as long as you maintain consistancy and the rest of your team plays along.

    I have an opportunity now to take a stab at what I think Sean is suggesting, so I'll take a stab at it today.