In a conversation that I had with Brian Kotek yesterday, I think I finally codified one of the pain points that I am finding with Object Oriented Programming in ColdFusion. I understand that an object is supposed to be "Idealized"; meaning, that it is supposed to model the more perfect version of a "real world" object - the ideal version. But what is "ideal"? Because an ideal object is better than its real counterpart, it is beyond something that I can know - it is only something about which I can hypothesize.
Now, we can't actually figure out what properties of an object are always ideal. After all, ideal is something that is context specific. Functionality required by one application might be totally overkill or fall short for another application - not every system requires that a Person object be able to Befriend() another Person object. Just as in real life, "ideal" is different for every one and for every situation.
So, if we can't figure out what is universally ideal, we have to be able to at least figure out what is ideal for a given application. We have to be able to understand the principles behind the "idealization" of an object.
Let's start out by just listing some common CRUD-type methods:
Methods like these are clearly related to the object itself. They are used, for the most part, to modify the data of the object in question. As such, it is very easy to argue that they should be methods of the given object. But what about something like this:
In this case, we have an article that is returning a collection of articles that are of a similar nature; maybe the algorithm behind this is using keyword density; maybe it is using meta tags; maybe it is using categories, or authors - we don't know. What we can probably guess is that this method is not modifying the given object or returning data about the given object. As such, does it make sense to have this method as a method of the object in question?
Let's say Yes, that it does make sense because it is, after all, generating a collection of objects based on data within the given object. I think of this in the same way that I think about:
This method, GetPreviousNode(), uses information contained in the given Node instance to return a related Node instance. Again, we are using or manipulating the data of the given object in some way.
But what about something like:
- Article.GetMostPopularArticles( 10 )
In this case, we have an article returning the 10 most popular articles in the system. Everything in my gut is telling me that this is a bad idea. Because the GetMostPopularArticles() method does not require any of the data contained in the given Article object, this method is forcing the Article to act purely as a utility object, making it no better than a singleton.
Although we have only covered a few situations, I think I am seeing a pattern starting to emerge. For all of the methods that we decided should be part of an object, we made that decision because the method either modified the data of the given object or leveraged the data in some way. So really, what we're beginning to understand is that an "idealized" object contains all the methods that either access/mutate its data or leverage its data. If a method does not concern the data in a given object, it should not be there.
I'm feeling really good about this. I am sure there will be exceptions to this type of rule (there are always exceptions); but, as a core principles go, I think this will help me effectively model my domain.