Since I have transitioned from a world of spaghetti code through the land of the uber-cfc, and finally onto some OO concepts, I have tried to figure out what the best way to create the business objects and persist them to the database. For nearly ever application I have developed, I have created the database first, since, in my mind, understanding the data is the first step to understanding the way the application will function.
However, in the OO world, the primary step is to design the business objects. In my latest project I decided to take one step deeper into the OO world and develop all my business objects forgetting all about how the database would be laid out. I had no problems with this, authoring complex objects containing arrays or instances of other objects without issue.
Then I needed to figure out how to persist them. In the past, each of my business objects directly mapped to a table in my database. This made it easy to build a code generator, read in the DB metadata and, in the words of John Madden, “Boom”, I had my beans, DAOs, and Gateways.
Now, I see what Sean Corfield refers to as the “5:1 Syndrome”. I have a dumb bean object, a DAO, a Gateway, a Service and, if using Model-Glue, a Controller for nearly every object, and in turn every table in the database. This always seemed like code bloat to me, so I was very happy to see other, like Sean, refer to it as such. There must be a better way!
Trying to avoid this I decided, OK I’ll use Reactor. Active Record, generated code, sounds good. Then I realized that I have to create the database first. Back to square one.
Should business objects reflect the organization of the database? They can, but if it doesn’t fit the way the business object is used in the application, then no, it shouldn’t. Also, from the other way, the best way to organized the business objects is probably not the best way to organize the database. The database should be in 3NF, avoid duplication whereever possible, etc, etc.
Not wanting to trash all the BOs I created already, I decided I would write all the persistance stuff myself. So now that I have some beans, I created a service for each and wired them up in ColdSpring. I put all the methods that would normally go in my DAO (save, new, and CRUD) in my service as well as some getAll() calls.
As a side note, I don’t return query objects since, even though they are faster than creating an array of objects, I cant call a complex getter, such as a calculated value easily, and this allows me to use the same calls to get the data for one instance of an object as I do for a collection.
Now I have a BO and a service that is completely separate from the DB. Persisting complex objects is a bit more complicated than using the 1:1 BO to DB mapping, but it works. The only issue is, I don’t want to have to maintain all this manually. I wish we had a mapping tool to handle persistance from BO to DB without requiring that the DB reflect the BO or vice versa.
Java has Hibernate to handle this issue. With CF8 we can now use Hibernate with a Java model, but what if we want to model using CFCs? cfHibernate attempted to do this and seems to have run into some issues. Can we use Hibernate to map CF objects to the DB? I am going to attempt to find an answer for this in the next few weeks for my current project. Hopefully I can find a solution.