Rails' ActiveRecord, Reactor, Illudium: All backwords for OO.
Posted by Joe Rinehart at 10:14 AM
8 comments - Categories:
OOP | Causing Trouble
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.
Brian Rinaldi wrote on 08/17/07 11:48 AM
I completely agree with you, which is why I always emphasize that you have to first understand the principles you are dealing with before using Illudium. It's also why I have regularly stated that it isn't a tool for learning OO becuase it lends itself towards creating anemic domain models if you don't know what you are doing.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).