Rails' ActiveRecord, Reactor, Illudium: All backwords for OO.
So, what's with the guy who put together the MG:U stack calling this stuff backwords for something he pushes (OO)? I'm not writing this to start a flame war: I'm writing this because I'd like people to think about the tools they're using and the appropriate contexts for their use, and I chose a bit of an inflammatory title to get you to click. :)
Why are the backwords?
To make a long story short, all four of these tools rely on defining a data model first and reflecting an object model based on its structure. When you use one, you're making an instant tradeoff of chaining your persistent objects to a data model: sure, you can override things like a column name, turning nastiness like tbl_user.usr_frst_nm to User.firstName. However, you're always going to be anchored by the relational data model.
It's a backwords approach to OO design, and I've found myself kicking myself for using it in larger systems.
Crash Course in OO Design
The following steps don't need to be defined in UML, a architectural document, or even written on a whiteboard. Often, on a small project, I'll just go through them in my head to break down a system.
OO design on a professional level should not start with "finding the nouns." Instead, it beings with defining perspectives and goals, often in the format of use cases (which aren't even OO!). Without a perspective, a domain model is largely useless: who cares if your Tree class falls in the woods if you haven't defined a perspective from which your Tree matters?
From tools like use cases, domain objects (which are not necessarily software objects / classes!) can then be defined: a Reader of a Blog. The uses cases can be decomposed into logical sequences, often in the form of a sequence diagram. We're still working at a conceptual level, not talking about classes.
After we've identified the domain objects and the sequential interactions between them that fulfill the user goals of our system, we can assign responsibilities to objects in the sequence. Often, I'll split a domain object into smaller objects at this point: I'm moving towards software classes and cohesion starts to kick in. Once I start to see the classes develop, I'll look at the messages they need to pass (their methods).
At this point, we're looking at the formation of software classes, their responsibilities, and their collaborations.
Still no sign of a database. It's a very pure way to work - you're making sure you're creating a model that fulfills user goals. You could even start coding it and testing it at this point.
Finally, at some point, you'll need to use some of the state from some of the objects in one use case in another use case, or persist that state between steps in a given use case.
It's not until now that you start to look at a database: cook up a schema that'll save the state, write some DAOs, and we're in business.
OO development makes data models and schema almost an ancillary task (From the perspective of an OO programmer. Don't say that to your DBA if (s)he's a valued friend).
So Why Are They Backwards?
The OO design process focuses on identifying goals, participants in achievement, and then modelling those participants in terms of collaboration and responsibility.
It does not model in terms of a relational data model or allow the implementation details of a persistence mechanism, such a relational database, float up into your object model.
That last sentence is important: allowing persistence implementation into your design model is an instant encapsulation issue. So if you're basing the very structure of your model off of your persistence implementation...
Heh.
When They're Appropriate
The Rails guys say this up front: a lot of Web apps are pretty simple CRUD/List apps with some extra behavior tacked on, and that's the sweet spot for Rails.
That holds true for the other technologies I listed. They're fantastically productive for doing datacentric applications, and I use them in this situation.
Conclusion
In a datacentric context, where you're mainly concerned about manipulating data in a database and "instance" is almost synonymous with "row," these tools can be appropriate.
For building out larger OO system, where the primary concern is modelling processes to achieve goals, they should be approached with caution, and only brought in once it's shown that their capabilities will support a model you've designed without them or databases.


It also sends a message that every table has a set of 5 or more CFC equivalents, which is absolutely false. I have even emphasized this in recent tutorials about how you would actually utilize Illudium.
I also emphasize that the generated CFCs, while they will work out of the box are intended to be modified by hand. They only have properties and no behaviors (hence the anemic domain). So your user object will be able to tell you its name, but won't actually be able to *do* anything. That is not a good model.
All that said, if you are comfortable in your OO development, it can be invaluable to not have to handle some of the very repetitive tasks in OO development (much the same as the other tools you list).
I think this is a pretty huge issue, particularly for programmers like me who have procedural systems with existing, mature data models. Making this transition is a big challenge.
On the one hand, it's really tempting to use a tool that can map that existing data model onto an object model without a lot of repetitive coding. And it seems pretty clear that on a system with 100+ tables, if you didn't use a tool, there WOULD be a lot of repetitive coding involved.
On the other hand, it's clear that the objects generated by these tools are not richly thought-out for the OO world; their design is determined by principles of database normalization, not principles of OO design .
Although I'm using OO on some of my smaller systems, I've hesitated to switch over for my largest system for just this reason-- creating a full object model from scratch is a huge amount of work, but creating one using a code generator may result in an object model that ultimately doesn't meet our needs.
The eventual answer will probably be that we use Illudium or something like it to generate a first version of the object model, and then we'll refine it extensively by hand.
I'd be interested to hear how others have handled situations like this.
I should have said that I appreciate that you've stated that - Doug's done similar things, saying that Reactor makes a good DAO solution but should that using Reactor "records" as business objects is someting to approach with caution.
I've also been quiet about the fact that I use Illudium from time to time - it's saved me a heck of a lot of typing. I always find myself making my own custom projects as well as customizing bits of the engine, but it's been always been at least 90% of what I've needed to build my own "jigs".
@David,
I can feel your pain! I've been in situations where I've either stuck to manipulating a data model or written "objects" that do nothing but reflect the data model simply because that's how it's already been done and the environment around the project isn't ready for the shift.
I think that when it is ready, it'll often be a good time to go through a full OO design process where you ignore the existing data model. You'll likely find that you create an object model that makes the application tier more geared towards user needs and future flexibility, and that the mismatches between what you end up with as an object model aren't too large to overcome with a nicely isolated data access layer.
My formal education (which was very OO centric) taught me to start with use cases, sequence diagrams etc. And it was truly amazing that once you did it this way, you realized how much pain you were saving yourself down the road from having to go back and try to change things. And some things, cannot be changed if the process is so different that a simple modification doesn't do the trick.
Thanks again for the article, and I am glad to see these types of posts in the CF world.
Of course when the problem domain *IS* a database, then you're totally free to start with AR or a similar tool :)
Of course when the problem domain *IS* a database, then you're totally free to start with AR or a similar tool :)
Oh, I'm supposed to do a little html
oh my, now I can use a little coldfusion to send an email
Hmmm, now I've got database support
Oh man, I'm loving CF now!
Hmmm, what's this OOP stuff?
Read blog blog blog UG videos, etc. etc.
Start using design patterns and code generators without knowing what they actually do.
(the problem is that all of this information isn't in the most convenient format for learning -- remember books!)
I have to say that the book that helped me understand OOP the most was head first object oriented Analysis and Design. I believe that every CF OOP newb needs to read that book. It is truly awesome. It seems like everyone recommends Head Frist design patters, but if you don't know the prior, the latter is confusing.