OO Part 1: From code libraries to instances
Code libraries
When people first start using CFC's they often use them as a handy way to group related functions together. For example, if you could put all the functions that deal with users into the same cfc and you may have something like the following pseudocode:function getUserName(id)
function getFirstName(id)
function getLastName(id)
function authenticate(username,password)
function getAllUsers()
function getUserCount()
function createUser(username,password,firstname,lastname)
function updateUser(id,username,password,firstname,lastname)
While this is a useful and valid way to use CFC's it isn't using them to their full potential.
Dealing with a single user
When working in object oriented way we try to discern what the different objects in a system would be. In this case User would be an object - and the user would know certain things about itself (name, username, password, date created) and just as importantly it would not know certain things (eg: total number of users in system)
var id //We store the user id in the cfc
function init(id)
function getUserName() //id is not required as it is already in the instance function getFirstName()
function getLastName()
function updateUser(username,password,firstname,lastname) //also no id required here
This "instance" of a user gives us access to all the properties that a user knows about but shields us from many of the functions that are not relevant.
We now have a user that we can easily conceptualise and work with without having all of the other methods such as getAllUsers() or getUserCount() getting in our way. It also allows a team of programmers to have a set of guidelines as to where code should live. If it deals with a single user it will be in the user CFC
But how do we create a new user
You'll notice that the above code has no way of creating a user - this is because it doesn't make sense for a user to be able to create another user (we're not talking about giving birth here). So how do we create a user.We need a place to put the create user method that is outside of the User.cfc - and I have typically used something like UserManager.cfc.
UserManager is also responsible for all functions that deal with more than one user.
function authenticate(username,password) // We don't have a valid user at this point
function getAllUsers()
function getUserCount()
function createUser(username,password,firstname,lastname)
This works really well in that there is now a logical place to put all of the code relating to Users and if all the people working on the application know where things should go.
Two CFC's for each object type?
However having two CFC's for each object type can get really messy, espcially when you are drawing Class diagrams. The java solution to this lies in the use of Static methods.Static methods (or Class methods) are functions that are available on the Class as opposed to the Instance - i.e. when we are dealing with the concept of Users as opposed to a specific user Steve Bennett who works on level 5.
So now we are back to having the following:
var id
// static methods
function authenticate(username,password)
function getAllUsers()
function getUserCount()
function createUser(username,password,firstname,lastname)
function init(id)
//Instance methods
function getUserName() //id is not required as it is already in the instance
function getFirstName()
function getLastName()
function updateUser(username,password,firstname,lastname) //also no id required here
But aren't we back where we started with everything jumbled together? Not really, we now have a obvious set methods that deal with a single instance and another set that deal with multiple users.
In this example you only have half the number of methods to look through when you are dealing with a specific user (i.e. all the instance methods) and the same when you are dealing with multiple users.
Enforcing it in ColdFusion
However Coldfusion doesn't naturally handle the differentiation of Static methods from Instance methods - however with a bit of ingenuity (aka hackery) we can enforce it in our CFC's. I've got a working prototype of this and I'll post some more on it shortly.
Further reading
If you are interested in getting more aquainted with Object Oriented design I've found the following books very helpful:




For example of what some very knowledgable CF developers advocate for doing object-oriented CF programming that is different then your recommendation see:
Architecting Your ColdFusion Objects, Peter Bell, http://coldfusion.sys-con.com/read/317562.htm
Coldfusion Components and Validation, Ray Camden,
http://ray.camdenfamily.com/index.cfm/2005/8/30/As...
I'm wondering why you feel your approach is better then separating out tasks to different CFCs.
I'm not so much moving away from the CF standards as trying to use the more developed Java way of doing things. That said the two ways solve the same problem in mostly the same way.
For example in my approach the Static Class methods are functionally equivalent to the Service objects in Peter's article. The instance methods are equivalent to the functionality in the main business objects as described by Peter.
Re DAO's and gateways - I typically build this functionality directly into the object but am looking at abstracting this out a bit more as I get to understand it's benefits (and drawbacks). For example in an application that has to run on multiple DB's there is definite advantage in doing this. There is nothing in this design that prevents it from being abstracted, I just haven't covered it here.
Hope that helps and thanks for reading - if it doesn't feel free to ask more questions.
Cheers,
Mark
Nice posting! Just to clarify, there are two reasons that I usually use a service class based approach (UserService or UserManager being a singleton and handling collections of users). The first is just the fact that (as you mentioned), CF doesn't support the distinction between static and instance methods within a class. I'm looking forward to seeing your approach to implementing that as I think there would be an elegance to having one cfc per business object (it is something like closures - I don't know if I'd use it tomorrow, but I'd love to see how it would be possible in CF!).
That said, from my experience, as the complexity in a system grows, you end up with quite a lot of methods in each business object and in each service/manager singleton. As such I find a benefit of breaking out the responsibilities of handling collections of objects from the responsibilities of being a single object quite useful from a pragmatic "separation of concerns" perspective even though a SmallTalk trained OO programmer would probably take an approach closer to the one you are advocating! I also find breaking out the data access helps to enforce a clean separation of concerns between business logic and persistence, although as you point out there in nothing to stop a static method from calling a separate DAO. I would also have to think through the unit testing implications of a single User.cfc with static and instance methods. As you know, one of the problems with unit testing is handling of state within tests. I like the flexibility of ColdSpring or LightWire to use text based XML for using mock objects for testing purposes and I wonder if having less objects would make it harder to implement mocks (as you have a physical coupling between the class and instance variables). I think testing (and complexity) would be the two concerns I'd have of actually using a single User.cfc class in a real world project, but I'd love to see you develop a process for implementing static methods (while you're at it, you might want to hack "final"s as well for class variables :->
Again, great posting and looking forward to seeing how this progresses!
Also, I'd point out that while Java supports static methods, the Service/Manager pattern is pretty common (I'd be tempted to say the default approach) in the Java world.
Firstly thanks for reading - I've been reading your blog for a while now and it's always an interesting read.
It's a good point about the complexity of the application - I'm going to implement it in a mid sized project I'm working on and see how it works out. I'll try to keep blogging about my progress.
One of the reasons I like the single object is that just reduces the number of objects (and similarly named objects at that) which can confuse people learning OO. I'm not sure if Instance and Class methods will be any easier though.
I must have a look at lightwire - I've heard good things :-)
Cheers,
Mark
Glad you enjoy! I'll keep an eye out for more postings on this from you as it is always good to try different things. You should also make sure people like Ben Nadel and Sammy Larbi see what you're doing. They're always up for some interesting hackery (and I use that term in the most flattering possible manner :->).
More objects = less methods per object and visa-versa, so I'm sure this will fit nicely for a certain size of apps for experienced developers, but personally I think having more objects is BETTER for less experienced OO developers as it clearly distinguishes the different responsibilities and roles of the various classes which helps people to think in a more OO way. I think less classes in the early days might lead to more "procedural OO" coding, so I'd recommend everyone to create all of the different objects first and then once they've got the best practices and thinking down they can play with compressing the number of files through these kind of techniques!
Re: LightWire, it should just keep getting better. Expect more interesting improvements over the next couple of months!