The Benefits of Base Classes
Let’s take the classic example of a DAO. The purpose of a Data Access Object is to allow CRUD (Create, Read, Update and Delete) operations on a persistable entity (one that will be stored in and retrieved from a persistent storage mechanism – usually a relational database although it could be a file or a call to some “black box” web service that hides the persistence mechanism from your application).
Lets pretend for a moment that we have a really simple application where every persistent object is stored in a single table and where any relationship logic between objects (User has many addresses) for retrieval, editing and cascaded deleting purposes is taken care of elsewhere. What would our DAOs look like?
Well, there would probably be four core methods to handle insert, update, delete and get operations (later this week I'll blog on a slightly less naïve implementation including the ability to get by different parameters and a public save() method hiding private insert() and update() methods).
Let’s just take one of those methods – delete. The core query for a User object is going to look something like:
DELETE
FROM UserTable
WHERE UserID = <cfqueryparam value = "#ARGUMENTS.UserID#" cfsqltype = "cf_sql_integer">
</cfquery>
Now imagine the same for an Article:
DELETE
FROM ArticleTable
WHERE ArticleID = <cfqueryparam value = "#ARGUMENTS.ArticleID#" cfsqltype = "cf_sql_integer">
</cfquery>
or a Product:
DELETE
FROM ProductTable
WHERE ProductID = <cfqueryparam value = "#ARGUMENTS.ProductID#" cfsqltype = "cf_sql_integer">
</cfquery>
Seeing a pattern yet?! Now of course, you could generate this code pretty quickly using a CFTemplate and metadata, but why mess up your application with all of this redundant code? Imagine if you ever had to manually update the application to use “soft deletes” replacing the DELETE with an UPDATE and a bit called something like Deleted which would then be added as part of the WHERE clause to any get() methods for the objects. It would be a lot of redundant, error prone work.
So, why not create a BaseDAO? A BaseDAO can provide a default implementation for all of the basic methods, so all you need to do is to create a UserDAO.cfc that extends BaseDAO as follows:
<cffunction name="Init" returntype="userDAO" access="public" output="no" displayname="Initialize" hint="I initialize the User DAO.">
<cfscript>
// Call parents initialization script super.init();
// Add any User specific initialization here VARIABLES.TableName = “UserTable”;
VARIABLES.IDFieldName = “UserID”;
VARIABLES.FieldNameList = “FirstName,LastName,UserID”;
</cfscript>
<cfreturn this />
</cffunction>
<!--- Add any custom methods here --->
<!--- END Add any custom methods here --->
</cfcomponent>
Now you need to make sure that you have a BaseDAO that performs all of the key operations required. For instance, the BaseDAO.delete() will include:
DELETE
FROM #VARIABLES.TableName#
WHERE #VARIABLES.IDFieldName# = <cfqueryparam value = "#ARGUMENTS. ID#" cfsqltype = "cf_sql_integer">
</cfquery>
A real world example would also include a VARIABLES.IDFieldDataType property as the above code assumes the ID field for the entity is an integer which is not always the case.
That’s it. If you have a BaseDAO with CRUD functions, the above code will immediately give you the ability to create, read, update and delete records for your business entity, but if you need to overload the methods for a given object (perhaps User.delete() should also delete the users addresses) you can just add a delete method to the child class and that will be used instead of the parents method.
Inheritance is not a panacea. It creates a very tight dependence between objects within the hierarchy and because ColdFusion (luckily) does not support multiple inheritance, once you’ve chosen something to inherit you’re out of inheritance options. However, where there is a very clear "is a" relationship (a UserDAO clearly IS A DAO), base classes can be a great solution.
Firstly they allow you to get the application up and running in a simplistic way very quickly indeed. Secondly they can make it easier to avoid repetitive code (as the Pragmatics say: Don’t Repeat Yourself), creating a much more maintainable application.





Thanks.
Will
Thanks for the comment! I will be releasing a full set of base classes (BaseService, BaseDAO, BaseIBO, BaseController, BaseObject and maybe one or two others) as part of the LightBase framework so keep an eye out for that later this month - I'll blog about it when I release it!