What started off as a blog comment has morphed into this rather long blog entry. I apologize for the length but I wanted to get it all out there in one shot rather than try to break it up.
I mentioned Joe's blog entry on ORM frameworks yesterday, and he seems to have hit a nerve if the comments and blog reactions are an indication. He posted a follow up to clarify what he thinks an ORM needs to handle, and there are more interesting comments piling up there as well.
I did want to post my own slightly different take on all of this. First, Mark Mandel, the creator of Transfer, has weighed in through some blog comments. To be clear, I personally have great respect for Mark and consider him a friend, and I know Joe does as well. No one is singling out Transfer, but as the most popular and actively developed CF ORM out there it's probably inevitable that Transfer acts as something of a proxy for all of the frameworks out there.
Mark works incredibly hard on Transfer, and Joe's comments aren't meant to be an exercise in "look at what Transfer can't do that Hibernate can", because that's a pretty unfair comparison. Hibernate has been around for a very long time and has man-YEARS of effort behind it from a huge team of contributors. Mark is one person, and I applaud him for everything he's been able to do with Transfer. I think Joe is taking a much more general look at the state of CF ORM frameworks, and if anyone thinks that Transfer is actually the target, I again say that's a misperception based on Transfer's widespread use.
That said, it doesn't detract from Joe's overall point, and I think it's always wise to take careful looks at where things are in ColdFusion-land and objectively compare them to what else is going on in the wider development world. With that in mind, I thought I would pose a few questions of my own that have been rattling around in my head (for years in some cases).
The reality is that something like Transfer is about the best option we have in the ColdFusion world for helping speed up database interactions in our applications. Is it perfect? Of course not, and even Mark would be the first to agree. He's got a laundry list of features that he's planning to add to Transfer. But the question isn't really "is it perfect?", it's "is it good enough to use in spite of its limitations?"
I have used Transfer myself on a large number of projects, and have tried to contribute to its growth. While none of the CF ORMs out there handle everything that Hibernate can in terms of schema generation, inheritance, polymorphism, and more, does this matter a great deal? I'm not sure that it does, but there are several issues at play and the answer depends on the way those issues come together.
First, most ColdFusion applications are very database-centric. Many of them do not have the need for complex domain models. They need to take data from forms, display lists of information, allow people to edit data, and help people visualize data through graphs and reports. Most people aren't building massive business intelligence systems or recommendation engines. Oh, some people are, don't get me wrong. But most aren't. And there's nothing wrong with that: data is crucial to any organization.
Mark noted in one of his comments that one can get a lot of the way to a good OO model despite the fact that most CF ORMs use the database schema to drive the structure of the domain model. While there is absolutely an impedance mismatch between relational database structure and object models, I would probably agree with Mark that the most common needs can indeed be represented fairly well in a relational schema. Basic forms of composition can be handled as one to many and many to many relationships. Table columns can often represent object properties. This basic similarity is why Transfer seems to work pretty well for a large number of developers.
However, this leads into the second issue at play: even though we can handle some common situations using a database-driven object model, should we? Here we get into more of a grey area.
On one hand, it seems like even data-centric objects or anemic domain models do gain some benefits from things like encapsulation, inheritance, and polymorphism. I'm not saying everyone that uses a CF ORM ends up with completely data-centric objects, and I wrote my ColdSpring Bean Utilities library to help make this less of an issue by allowing Transfer Objects to have ColdSpring-managed beans autowired into them. But I would have to say that most people building CFC-based models probably do have anemic domain models (whether they use Transfer or not). Despite this, one could make the argument that the benefits of OO techniques are still real even in this situation.
But is that true? Do the benefits of OO techniques make data-centric objects worthwhile? My friend Hal Helms would say no. And he does make a convincing argument. OOP is hard. There is a lot of ancillary machinery that tends to do along with it: resolving dependencies, getting data into and out of the object to load or display them, and increased complexity. Procedural code is very straightforward: start at the top and go to the bottom. OOP introduces layers of indirection. Without careful consideration, attempting to follow the execution path of an OO system can be very difficult. You tend to have more files, and more code in those files. Hal likes to say that with anemic, data-centric objects, one reaps all of the pain and complexity of OO with none of the benefits that behavior-rich objects should offer. And if I stand back and look at what he's saying, part of me wonders if he is right.
OOP is clearly the dominant paradigm in programming. As such, it is probably wise for any developer that plans to continue their career to learn it. But if one entertains the possibility that the widespread data-centric approach to OOP in ColdFusion is a bad idea, are we actually harming ourselves as a result? Put another way: are we learning this wrong?
I don't really have an answer. I can see both sides of this and I feel like they both have merits. I believe it comes down to these two points:
- I think it is very dangerous if someone is taking this anemic, data-centric approach under the illusion that they are really learning OOP. It can be hard to "unlearn" something once it is ingrained, and this situation could very well end up a detriment later on.
- However, if you are aware that you are using data-centric objects and are doing this with a deliberate choice, that changes things. While the debate about whether the overhead of OO is worth the effort for data-centric objects is still there, at least one is weighing the pros and cons with full awareness of the situation.
The question we all may have to ask ourselves is "Which one are we"? Answering it isn't easy. I'm sure everyone would say they are in the second group, and I'm sure many people are. One may simply have a data-centric application, as many developers do, but may still believe that OO principles like encapsulation, coupled with the range of tools available like Transfer and ColdSpring, are worth the effort and complexity. In fact, I'd wager that most folks who will read this blog entry or frequent the Transfer, CFC-DEV, or ColdSpring lists, are probably doing exactly that. I hope that many may even use my ColdSpring utilities library or other tools to give their objects richer behavior that goes beyond just storing data as properties.
The bigger worry to me is the first group, the group who may be taking this anemic approach under the illusion that they are actually doing and learning real OOP. I don't want to be the guy who tries to wag his finger at someone who is doing something that works for them. But since it seems clear that there are a large number of people who fall into that first category, I have to wonder if there is anything we as a community can do to try and move them into the second group. While the debate about whether the perceived benefits of OO apply even to a more data-centric domain model remains open, I feel like it's important that people be making that choice for themselves, deliberately, with a full understanding of what they're doing. Since I consider myself a proponent of object-oriented programming, I'd hate to think that the current trend to adopt OOP in the ColdFusion world may actually be causing more harm than good to many people. I'd love to hear thoughts and comments on this.