Are We Adopting OO For The Right Reasons? (A More General Take On The ORM Frameworks Discussion)

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.

Comments
Just to take this one step further since we're doing this sort of fundamental questioning, maybe we should ask "are we using CFML for the right reasons?"

Now before I get labeled a "hater," that's not my intent by bringint that up. It just seems a logical further point of discussion since it seems to me what we're really getting at with all these discussions is what's CFML good at, what's it not so good at, and are we trying to turn it into something it isn't or use it in ways that are less than optimal.

Flame-retardant kevlar vest on--fire away. ;-)
# Posted By Matt Woodward | 11/4/08 12:27 PM
It's probably a valid point Matt. I'd like to hope that CF is, or can, be a platform to build just about anything, from small contact lists to massive OO systems. And if it can't, what can we do to make it able to do so? Further, should we try? Clearly the majority of apps are not massive OO systems, so one must wonder how much effort Adobe, Railo, and BlueDragon can or should put into that. While a focus on non-OO apps may seem the way to help current developers build applications now, a focus on OO capabilities might help CF adoption on large OO systems in the future. Since resources are finite it's clearly a tradeoff, and where to draw that line and how or when to change the core focus is definitely a topic worthy of discussion.
# Posted By Brian Kotek | 11/4/08 1:05 PM
Speaking as an intermediate OO software developer who learned OO in CF through Model-Glue tutorials a year ago, I think we need some more insightful blog posts on how to get OUT of the Anemic Domain Model.

The usual use cases presented by those tutorials of a framework are often gathering fields off a form, and saving them into a table in the database. To be fair, that's what most simple webapps do, but do you see how we are trained to do the Anemic Domain Model way?
# Posted By Henry Ho | 11/4/08 2:21 PM
I don't think a line needs to be drawn at all. The beauty of ColdFusion is that you can pick which ever paradigm meets your needs. I think Adobe should continue to offer new features that help OO porgrammers make more pure OO applications, while keeping the core syntax simple enough for a small business owner, who is not interested in being an applications architect at a fortune 500 company, to be able maintain his little intranet application that he and his 5 employees use.
There are ColdFusion developers that can't do much beyond making minor tweaks to small content management systems, and their are developers that can develop complex business applications for multi-national corporations, and ColdFusion should be able to meet both of their needs.
# Posted By Scott Bennett | 11/4/08 2:25 PM
Scott, to be clear, by "drawing a line" I just mean how they decide to spend the majority of their effort, time, and money. That's all. At some point a product manager has to allocate resources to different feature sets. Some get more time and effort devoted to them, some get less. I was just responding to Matt's question about whether we're using CF in was that are less than optimal by considering how, or if, that should be addressed.
# Posted By Brian Kotek | 11/4/08 2:35 PM
I'd put myself in the second group. My apps are mostly data-centric but I'm not under the illusion that my code is what someone like Hal Helms would consider 100% certified OOP. Because yes -- his brand of OO would be more painful than beneficial in my case.
What you said rings true with me -- there are a lot of OO-concepts like encapsulation, inheritance, and polymorphism that are very useful even with data-centric applications. I'll take concepts that I learn from reading stuff that people like you, Hal, or Sean have written and apply them as I see fit for my use cases. Yes, I use a lot of CFC's, but I also will use queries over arrays of objects most of the time. My objects aren't all anemic -- they'll usually at least have self-validation and a few calculated properties. It doesn't have to be an an all-or-nothing proposition and I've experienced HUGE benefits since switching from purely procedural a couple of years ago.
Would OO purists consider my code OO? Probably not, but it's OO enough for me and brings us to another subject which, I think Isaac Dealy addressed very well in this blog post:
http://ontap.riaforge.org/blog/index.cfm/2008/11/3...
# Posted By Tony Garcia | 11/4/08 4:51 PM
@Tony: Do you know the difference between an object purist and a terrorist?

You can reason with the terrorist...

All kidding aside, the idea that "object purity" is some far-off, unattainable goal is just not true. But that mantra is used by people to avoid the difficult task of learning OO.
# Posted By Hal Helms | 11/4/08 5:47 PM
@Brian,

I think I understand what you are trying to say, and I think the "core focus" of ColdFusion as a product has always been enabling developers to be more productive with less learning curve by making the hard things easy. I also think that the language is at the point where there are really not any new features that procedural developers *need* to be successful in their chosen paradigm. However, I *do* think there are a few things that the OO developers need to be successful in their paradigm. So if there is a way for Adobe to make it easier to develop OO applications, then they should. I don't think that making OO easier to do in coldfusion will be a shift in the core focus of the product.

I think many of the features that might be seen as catering to the procedural paradigm are really just the features that Adobe adds for the "Hype-factor", to help sell the product to the non programmer management. Nothing in CF8 had an impact on weather we can effectively program well organized procedural applications.

So if a line needs to be drawn, it is not between OO or Procedural. It is between how much time needs to be spent focused on wow-ing non-programmers into buying the product, and how much time needs to be allocated to making it easy for programmers to program the way they are comfortable programming.

This could even be applied to programmers who prefer script syntax over tag based syntax. The tag based syntax people have always been fat and happy and the script syntax people just got all their favorite operators in CF8, but they may have more things they would like to see happen with cfscript so they can develop the way they feel comfortable.

That is the beauty of ColdFusion to me, no matter which syntax or programming paradigm you prefer, ColdFusion should make it easier for you develop applications, and that is where I think Adobe should keep their primary focus.
# Posted By Scott Bennett | 11/4/08 5:51 PM
Tony, I'd be interested to hear any specific examples of how using data-centric objects provided you huge benefits, because that's a big part of the uncertainty I have. I'm trying to find out of the overhead and complexity of OO actually offers enough benefit to justify its use in that context, so someone like you is exactly who I'd like to hear more from. Email me offline if you like.
# Posted By Brian Kotek | 11/4/08 6:12 PM
@Hal -- The reason I don't go for "OO purity" is because I agree with you: for datacentric apps, OOP is usually overkill. Since most of my apps are essentially data management apps, it's not really worth it for me to go full-bore OO. So it's not really about me avoiding learning about it or thinking it's unattainable. It's about me deciding to what extent I apply OO concepts to the kinds of applications I USUALLY write. Maybe someday I'll have to write an app that's more about behaviors than properties and I'll book a flight to Sarasota and take your class!

@Brian,
I can't think of any concrete examples off the top of my head. But I just know that in general the encapsulation in my code has made it so much easier to make changes. I admit that one area I need to improve on is planning out my application before I start coding. As a result, I end up changing my mind about stuff pretty frequently as I'm coding. When I was just doing things procedurally, it was a pain because changes I would make would usually require me to make other changes throughout my app. It's much easier to make changes now that functionality is so well isolated in my objects. I realize this doesn't answer how OO can help datacentric apps specifically, but I'll try to come up with a more specific example. Also, I use a code generator (and lately more onMissingMethod) to offset the increase in the amount of code.
# Posted By Tony Garcia | 11/6/08 2:10 PM
Hi Brian,
It's great to read your thoughts here. I've been pondering the same things (especailly because I've noticed a big take up of OOP in CF land recently) - I'm learning it myself.
I think part of the probelm with getting CFers (or any programmer) to learn correct OOP is that there is so much terminology involved. What does anemic-domain-model mean? In fact what does domain-model mean? Then you've got all sorts of concepts: design pattterns, facades, inheritent, polymorphisum, loss coupling, cohesion, data-centric, inversion-of-control etc etc - there are just so many concepts to learn in the OOP areana it's just not funny (however most programmers are technical and enjoy learning)!
One other problem in this space is that people try to learn CF OOP through a framework. Perhaps frameworks should be only given to people who've proven they know OOP first (kdding but I think it's these people who are in the 1st group you mentioned).
Perhaps the solution is that we all need to work together to write a single article ("CF OOP the correct way"), us learners can keep you guru's in check with all the use of terminology and no explinations. But of course no one will agree on anything so scrap that idea.
One other point: I think many CFers try to learn OOP through frameworks but don't learn a thing about UML, design patterns etc. We're all busy people and can't justify with the boss to give us 6 months off to learn OOP. So we try to learn on our own time or slowly on work projects. The problem is we're so hungry to get stuck in and start writing CF OOP code that we don't stop and learn UML / design patterns first. I'm starting to see that the whole point of OOP is to do the planning, design and modelling first and then you're coding time is reduced. As Tony mentions in his comment that he wishes to spend more time planning his apps.

Brian; perhaps this is what OOP is all about: planning-before-programming in order to create an app which will be scaleable and flexible?
# Posted By Matthew | 11/6/08 6:23 PM
@Tony + Hal - Brief clarification. The "is this OO enough" rant was actually not about the idea that OO purity isn't attainable. I believe that it is, although opinions about what that looks like vary enough to keep it debatable for the foreseeable future. While I don't consider myself a purist (but rather a pragmatist) what I was trying to point out is that the way in which the question is framed often affects the outcome - the answer. Asking the question "is this OO" often results in a bad or bogus (read: totally incorrect) answer because of well known human cognitive biases. Asking about whether or not a piece of code addresses the goals of OO like cohesiveness and encapsulation on the other hand is much more likely to produce not only a more accurate answer, but an answer that is much more pragmatic. An answer that leads to insight about the code and what it does, as compared to "is this OO?" which generally only leads to thoughtless nay-saying.
# Posted By ike | 11/11/08 6:01 AM
First off, nice post, Brian. I like it and I've wondered the same thing myself.

I've been giving a lot of thought lately to the idea that OO is all about behavior and trying to apply tell don't ask (and even a bit of getter eradicator), because it's something that lots of people don't understand or misapprehend and think that having a controller call getFooList() on a service call getFooList() on a Gateway is behavior.

I started writing this comment last night and had a use case for the usefulness of pseudo-OO, but I forgot what it was. Suffice to say that, for smaller data-centric apps I have found it to expedite development, especially useful when budgets are tight. But I can't really say it's a good idea in general... I prefer robust domain objects to any alternative.

Thanks for the brain excercise! :)
# Posted By Jared Rypka-Hauer | 11/11/08 11:32 AM
BlogCFC was created by Raymond Camden. This blog is running version 5.9.1. Contact Blog Owner