Object Oriented Programming And ColdFusion - What's The Point?
Posted October 27, 2008 at 9:10 AM
Last week, while covering the events at Hal Helms' "Real World OO" class, I had several inquiries, both direct and via my blog comments, asking what was the point of all of this was? How pure does object oriented programming need to be? What size does my project need to be in order to best leverage object oriented programming? I am very new to OOP, so I can't necessarily answer these all that well; but, here is the best explanation / exploration of these topics that I can offer.
The biggest hurdle that object oriented programming faces is the simple fact that many of us have been building successful procedural-style web applications for years. I've been a web developer for a good 8 years and have been programming ColdFusion for about 6 and I am just now starting to get into OOP. That means that I've spent the last 6 years building web applications with procedural code. And you know what? I don't think any of the applications have died horrible deaths. In fact, I'd bet that many of the procedural-style web applications that I've built will go on to be used for years.
So this begs the question: why do I even need object oriented programming? If what I am doing is working, then why bother changing it?
The most honest answer that I can give you is that I generally don't need it [OOP]. For many of the applications that I have built, object oriented programming is simply not the best tool for the job. That's not to say that I wouldn't benefit from some more object-based programming like a Service / API layer; but, when it comes to the very data-centric style applications that I have built over the years, pure OOP doesn't really provide a huge benefit.
See, pure object oriented programming is all about behaviors - what does it mean to be this or that object and what should this or that object know how to do? When you have a lot of behaviors on your objects, you want object oriented programming because it is fantastic for delegating responsibilities and subclassing for specialization. However, most of the applications that we build are not about behaviors - they're about data. When all you care about is data management, I think you'll find that pure OOP systems offer a lot of overhead with little benefit.
While pure OOP can be a bit much for many of us, I think that we can still gain a lot from the principles of object oriented programming. At its core, object oriented programming helps to create reusable and more maintainable code; I can't think of a single application that doesn't need to have those features in the bag. At the end of the day, even if we don't go pure-OO, I think all of our applications should be heavily object-influenced. Objects help us to cut down on repetition and can encapsulate code in such a way that it keeps maintenance costs to a minimum.
I know that I have taken a lot from my class with Hal Helms. I am enamored with the idea that an object can only exist in a valid state and that data persistence should not be the responsibility of the domain entities. I just need to go figure out how that fits in with everything else.
What about OOPhoto? I built OOPhoto in order to learn more about object oriented programming. The problem with it, however, is that it has no behaviors. Again, it's just another application that is focused on data management. Photos don't know how to do anything. Galleries don't know how to do anything. They simply contain data that gets displayed or persisted. As such, it probably isn't the best application to learn from. I think what I am gonna do next with it to apply some of the better principles that I learned last week and see how well I can understand them on my own outside of the classroom. I am really just learning this stuff for the first time, so I am not sure how it will go.
I hope this answer didn't dishearten anyone. I think that learning the purest OO first is a great thing. Just as we must learn to walk before we can run, I think that we must learn the best practices of OO before we can learn how, when, and why to break them.
Post Comment | Ask Ben | Permalink | Other Searches | Print Page
Newer Post
Ask Ben: Redirecting Users To A Random Page
Older Post
Hal Helms On Object Oriented Programming - The Summary
Reader Comments
I don't see pure OO as a goal or a target. It is one way of looking at an application that may help you to do a better job of putting behavior alongside your data (which typically is good from an encapsulation and information hiding perspective).
Some of the stuff like domain objects not being able to persist themselves, I just flat out disagree with. I think it's great you took the course, and Hal is incredibly smart and knowledgeable. I'd just look at all the material you covered from a programming, first principles perspective (will this create a more maintainable app, etc) and then ask yourself which of the principles will make your app better and why.
It's important to understand we're not in the business of modeling real world objects - that is not what OOP is about. However, we may pretend that we are doing that to help us with designing parts of the domain model.
http://www.pbell.com/index.cfm/2008/10/27/I-Dont-Care-What-An-Object-Is
@Peter,
I definitely agree that we are not in the business of modeling real world objects. I think that is an OK way to start, but I think it gets way too muddy way too fast. As you have read in my previous posts on using Human as a model. When we come at it from a real world standpoint, its starts to become a philosophical discussion on what is really Human.
But, really, we are not concerned with existentialist debates - we are concerned with what an object is in terms of the System or Domain in which we are working. In such an environment, we cannot have nuances of correctness or validity. So, I agree that modeling real world objects is not our goal.
I think also what makes pure OO so hard to wrestle with is the fact that one of the big payoffs of it is that we can reuse our code in different systems within in the same domain. This is great - but how many of us actually do that? How many of us have a catalog of domain-specific CFCs that we can swap in and out of applications.
I think you've told me that you have like 4 physical CFCs in your SystemsForge stuff right? So, for you, the concept of reusing CFCs in different applications within a single domain is laughable as a goal - it would be very complicated for you to port a CFC to an application without also requiring LightWire and all the other aspects of your framework.
And don't get me wrong, I am not dumping on your strategy at all. If anything, this is a perfect example of where you are optimizing for your own goals: How can I most efficiently and easily create software that works. This is an awesome goal and I think the one that we are all striving for. What I need to do now is take the principles that I have learned in the class and see how I can apply them to my software development whether in whole or (most likely) in part.
At the risk of sounding quite naive here, what are some examples of applications that have behavior (and thus are more suited for OO)? The majority of web sites I visit are simply there to show me some data. Online banking, email, shopping, news, blogs, forums, facebook, ... are all just UIs for different kinds of data.
I could possibly see how video games or virtual reality UIs begin to get into behaviors. In a lot of OO intro materials you get example of a Dog object that has a bark method or a Car object that has a start method. That's good for getting the concept, but unless you are building a video game, you probably don't need a dog that barks in your application.
What are some common behaviors I would see in non-video game apps?
@Matt,
I think it's hard to find a system that is 100% behavior based. However, I think that most systems have *some* aspect that is behavior based. For example, in an eCommerce site, your Shopping Cart should probably be a CFC that can handle cart behaviors. In a banking system, you must have work flow systems that have decision logic that can be encapsulated.
I am new to this, so my examples are pretty weak :) But, I think that many systems can be heavily object-based without it being a totally OO system.
@Ben, A few comments!
> one of the big payoffs of it is that we can reuse our code in different systems within in the same domain
I completely disagree. Just because you are modeling the same class of real world object in two systems it is quite likely that they'll actually have different behaviors and properties as the two different systems will often implement different subsets of possible real world behaviors or will even use different conceptual approaches to the same real world objects. In my experience, reuse of domain objects between distinct projects is a fairly rare and limited situation.
> I think you've told me that you have like 4 physical CFCs in your SystemsForge stuff right? So, for you, the concept of reusing CFCs in different applications within a single domain is laughable as a goal
Well, actually I DI reuse objects between projects (notwithstanding what I've said above, because I have a lot of fexibility to direct the implementation details of my projects, I actually can quite frequently reuse domain objects between projects with fairly modest changes to their behavior, relationships and properties) - I just describe the objects using XML rather than coding them using CFC's.
> What I need to do now is take the principles that I have learned in the class and see how I can apply them to my software development whether in whole or (most likely) in part.
+1!
@Matt, I find my objects start getting behavior when the data isn't quite enough to describe everything. It starts simply when I need a DisplayPrice for my Product. It might encapsulate simple logic (If DiscountPrice > 0, return DiscountPrice, else return BasePrice). In my cart, the ItemTotalPrice is probably ItemUnitPrice * ItemQuantity (or even Product.UnitPrice * ItemQuantity depending on when product price updates affect the items in the cart). Those are the simplest possible behaviours as they're really just encapsulating the business logic required to get a property that doesn;t exist in the db. Same thing with a User.getAge() that'll calculate the age (which is not persisted) from the dob (which is).
Other more obviously behavioural behaviors would be things like Newsletter.Publish() or even site.Publish(). Project.generate(). page.display(). These are examples of methods I have in my apps.
You could also have things like message.send() and I find it perfectly acceptable to have things like NewProduct.validate() or NewProduct.save().
You could have a User.upgrade() method which would validate the request, change their status and persist their new status in the db (some composition would probably be involved - you probably wouldn't want to be writing SQL in your domain objects directly).
The common thread is that we're putting behavior and properties into one place to hide as much information as possible and to minimize coupling, so if I decide to change how I calculate my Product.displayPrice() logic, I change it in the Product object and because all of my screens just call that one method, I don't have to worry about changing the code in other places, hence making it easier to maintain my app.
@Peter,
>I completely disagree.
I agree with you in practice; I have never really reused objects between systems other than copy-paste-modify. But, I think one of the goals of pure OO is stop people from copy-paste-modifying. Think about something simple like a Float or something fairly complex like and Xml Document - these are classes that you want to be able to reuse across domains. I think having a float mean something in every system would be very confusing.
Of course, floats are very simple, and even XML Documents are very simple - but that is why they are the most reusable. Not *all* objects are supposed to be reusable across the domain. Some objects must be system-specific otherwise, our apps couldn't work :)
To me, I think one of the hardest parts to grapple with as I learn is the trying to discern which objects are meant to be reused and which are meant to be app-specific. And quite fankly, I don't really have enough experience here to argue one way or the other.
@Matt
. . . continued . . .
I never ask myself whether a real world page will know how to display itself or whether a real world newsletter will know how to publish itself. Why would I care? Why would that be important to me? What value does asking that question provide me with? Rather I ask whether the behavior is cohesive with the objects other behaviors, whether the class file is getting too big, whether it'll help to make the app easier to maintain., whether it'd be easier to test if I delegated the behavior to a composed object, whether adding a composed object might cause major performance problems if there were arrays of the object being displayed in my ColdFusion apps. Those are the kind of things I'm thinking about and I'll often trade one heuristic off against another. But I never worry about what a real world object would do as I don't usually find that to be relevant to the process of creating maintainable apps.
To each their own, however.
@Ben, I hear what you're saying, but my argument has for a long time been that in practice OO provides for greater maintainability but NOT for greater reuse and this seems to be a pretty common opinion. I wrote something about this a while ago:
http://www.pbell.com/index.cfm/2006/6/26/Maintenance-and-Reuse-One-Out-of-Two-Aint-Bad
Of course, in the domain of programming there are objects you'll be able to reuse. As you pointed out an XML document or a float will probably be the same across the majority of applications. So are generic DAO's and Service classes and IBO's which is how I get a good level of reuse of my base framework classes across web applications, because they are the same domain and I have control of the business rules I choose to implement within that domain of web applications. However, in my experience, the behaviors, properties and sometimes even the relationships between domain objects in rich OO apps are seldom reusable as is between applications.
Think of it this way. You could create a standard e-comm app and sell it to four people. procedural or OO, you'd be reusing code which is generally a good thing. But now try going to Amazon, Chevvy, Lenovo and a PriceWaterhouseCoopers. Ask each one what a product is in their domain and see how easily you'll be able to reuse your domain objects.
Typically the benefit of OO programming comes as the domain model becomes richer, and in my experience of building hundreds of web projects, the richer the clients domain model is, the more likely it is to be full of business rules that are unique to the way that they see the world and therefore the less likely they are to be reusable across apps.
There is no question that for simpler domain models you can reuse code. We often reuse page, user, newsletter, product, cart and a bunch of other items (we usually have to tweak a few properties as each client has slightly different needs and believe me - the solution is NOT to have a set of uber objects with every possible property and behavior - been there, done that, got the t-shirt). However, the richer the domain model, the more likely it is to be specific to the world view of that particular customer and the less likely it is that you'll be able to reuse the code.
@Ben,
I think another important point to make here is that not only are we not modeling idealized real world objects because of technical considerations (we need to model the behavior required to implement the essential user stories - not the whole universe of possible behavior), but in addition to that, our clients actually have their OWN conceptual model of what a product is or what a customer is or what another object is, and those conceptual models often vary widely between businesses. In some businesses a contact is a type of person that may or may not be associated to a company. In others, a company simply has a ContactName property. You can model the true real world relationship however you want, but what really matters is the conceptual model that the client has underlying their domain objects and often the same domain objects are thought about differently in different companies. That is what really kills the general re-usability - we're not modeling the same objects and the different clients conceptions of those objects vary - stopping us from reusing the same objects between those clients.
So when you say behaviors, I am not sure I understand. Take OOPhoto. Let's say you had functionality to:
- order in album, rank (favorite), print, resize, rotate, write caption, move, copy, make album cover, write on top of picture, tag, declare face-recognition, download, share, blog, embed, zoom, undo, next/back, replace, delete.
These are "some" of the things you can do in Picasa, for example.
So are you saying, none of these are behaviors? Wouldn't a picture know how to rotate itself? How to write a caption for itself? How to validate that the caption is acceptable?
OOP Does make alot of sense to use if you are coming from the systems analysis and design approach rather than just sit down and start coding.
OOP has come intuatively from UML.
With most large companies the senarios are planned out with use case diagrams and use case class diagrams. so from these you create your classes which are your objects.
so from that angle it is the easiest way to go about it.
if you are making a basic application then there is not really much need, but once you start to think in OOP they you just start to use it weather you need to or not.
Generally it just makes it easier to add extra functionality and for future developers to understand your code.
I just want to make sure that the anemic data driven apps that we are so often confronting are appropriate for OOP. There is a lot of overhead for object-relational mapping (even though CF9 will supposedly have it built in). And, to be frank, OOP breaks some of ColdFusion's Rapid Application Development tools as we know.
I'd like to see an honest discussion about the "it depends". I've seen everything but the "it depends" clarified.
@Peter,
I am leaning towards agreeing with you - OOP is more about maintainability rather than reusability. That is where I am seeing the real payoff, and if you go that route, I think the rules definitely change in the way you model your domain.
Also, when I considered reusing things cross-app, I never really thought about it in terms of cross-company. I meant really different apps in the same company.
@Glen,
Yeah, but OOPhoto doesn't do that :) But, yes, I think those are behaviors. I thought about the idea of resizing because photos in OOPhoto *do* get resized. In fact, they get resized three times:
* Original
* On Screen
* Standard Thumb
* Square Thumb
Now, here's one of the issues that I wrestled with - a photo *should* know how to resize itself; however, my photos need to be resized in a particular way (the square one needs to resize and crop). Resizing can be generic, but once you resize and crop, now we are talking application-specific behaviors.
This is OK, but to have a photo resize itself with a sort of GenerateSquareThumb() method or something, we have to get rid of the idea of reusing this "Photo" object in other applications. OR, we need to sub-class it and add special behaviors for just this app.
But, that seems a bit excessive to me. That is why I am starting to move to the Peter Bell camp that OOP is more about maintainability and less about reuse.
Still sorting this stuff all out.
Peter makes sense because he is a pragmatist.
He wants to make the most money, which means completing projects that meet every objective as quickly as possible. While pure theoretical OO is nice, you can spend a whole lot of time preparing for something that is a guaranteed flat result.
Why object-oriented programming? I think the benefits to decomposing your application's functionality into discrete pieces are almost too numerous to list. You can isolate changes to one part of the application, reuse components, unit test one tiny piece at a time, etc, etc.
But object-oriented programming is only one way to chop up your application. We've been inventing and refining ways to do this since the 1970s, when David Parnas introduced modular programming. Paradigms from functional to object-oriented to aspect-oriented have this goal in common.
As others have said, it is not a choice between OOP or nothing. Any way to modularize your code will improve your life and the lives of those maintaining your applications in the future.
@ Matt Williams
I just spent the last three weeks rewriting the core spidering robot for my website, WoW Lemmings. It is a multi-threaded CF app that is composed of two key parts:
- The main object that contains a list of spiders, and has methods that manage the spiders across threads, as they touch URLs, scan data, and update/refresh/delete a database.
- Multiple spiders that derive from a base spider class, which inherit common functionality that all spiders use. Derived spider objects implement an interface that requires them to supply certain methods back to the main object, which are either declared in the base spider or are overridden and implemented in a new and specific way in the derived spider.
The spiders themselves, and the parent object that manages them, all have properties, behaviors, etc. The application as a whole demonstrates common OO fundamentals, such as encapsulation, polymorphism, and inheritance.
This may be a more appropriate "concrete" example of an application as it pertains to OO-development in use within ColdFusion.
I think the struggle procedural CF developers often have with embracing OO is that it causes you to approach the development of an application from an entirely different point of view.
Ben's original quote: "Photos don't know how to do anything. Galleries don't know how to do anything."
I wager that with a bit of rethinking on the part of the developer, it wouldn't be too long before you had the following lines of code in your application:
galleryObject.DisplayPhotos();
galleryObject.DisplayPhotosByGrid(4, 3);
and
photoObject.Display();
photoObject.DisplayThumbnail();
Suddenly, photos and galleries now know how to do something.
As one of the people who sent Ben and email asking "What's the point?", I am happy he wrote this post. I didn't ask "What's the point?" because I think OOP is bad, but I wanted to hear from someone who had put for the effort to learn OOP to see if there is something I am missing, and to evaluate weather I should put forth a similar effort.
I appreciate how David said:
>...it is not a choice between OOP or nothing. Any way
>to modularize your code will improve your life and the lives of those
>maintaining your applications in the future.
I have done a lot of reading into OOP, and it seems like "Maintainability" is usually the primary reason the OOP experts give for implementing their chosen programming paradigm. However, it seems to me that in ColdFusion, OOP really just makes developing things more complicated, and sometimes adds unnecessary processing overhead. Also (as someone that regularly has to hire CF developers), it seems that the majority of CF Developers out there are more comfortable developing in a procedural fashion, and CF developers who actually are comfortable with OOP are almost always comfortable working with well organized procedural code as well. Threfore, it is easier to maintain a staff of people to maintain a CF application if it is procedural.
That is why, while I have implemented some OO-ish principles to my programming style, I continue to program procedurally, and I have not put forth a lot of effort in training my mind on how to turn everything I program into in an object.
I think if you do a good job of identifying the parts of the application that can be modularized with a generic CFC, or Custom Tag, or UDF, and you do a good job of organizing your code (so it doesn't turn in to a pile of spaghetti with 1000 .cfm files all in one folder), then maintainability is not an issue that should decide weather your do OO or Procedural.
The main reason I can see for choosing one programming paradigm over the other really boils down to simple personal preference.
@Shawn,
I definitely do need to rethink the way I envision an application. My concern with display-related logic is that it ties the model a bit too tightly to a particular view.
It almost sounds to me like we're discussing two different issues here. Ben and Scott seem to be thinking about OOP as an all-or-nothing thing, and they seem to be asking if they should make *everything* in an application an object.
Many of the people responding, I don't think are answering the question - or even really hearing the question. The question that people are hearing you ask is, "should I use any objects at all ever?" and so of course, they're answering that yes, you should, quite obviously you should.
That's my take on this discussion. Except for Peter, it looks like people are answering a question you didn't ask.
Here's my answer: should you make everything an object all the time without exception? I say no. But on the other hand, you should be intimately familiar with the power of OOP so that you are able to use the best tool for the job at hand. Many of the applications I write are *not* entirely OO, but in almost everything I write, I find that some part of it is best implemented as an object.
A quick example: I'm doing some integration with the google calendar. I get an authorization token from google and then use that token on subsequent reads and writes. This can be implemented procedurally. Procedure A gets an auth token, which the calling program stores in a global variable and passes to proc B and C, which read and write calendar entries.
But if you have that OO tool in your bag, you see this setup as tedious and needlessly complex. Ten years from now when I have to maintain this code, I don't want to have to think about auth tokens. I shouldn't have to remember rules like how long the token is valid.
An OO solution encapsulates the token and the read/write methods, and ten years from now when I have to make a change that tedious detail is hidden from me. Also, if I need to work with two calendars simultaneously, I don't have to juggle auth tokens in global variables. I simply instantiate two objects, and they handle themselves. Finally, when I start working with resource calendars, I'll find that the code is almost exactly the same - but different enough that I would need new procedures if I had implemented it that way - with OO, I can use inheritance and have the resource class make use of the calendar class' auth method.
The bottom line is, this is an incredibly power tool. You don't have to use it all the time, but you should be ready to use it when appropriate.
@Christopher,
I think that is well said and very accurate.
@Chirsopher,
As I mentioned in my last post I use some "OO-ish" principles in my programming style, and I have developed CFCs to create "objects" for certain parts of applications when I think they are appropriate similar to your google api example, and instantiate the object into a memory scope to maintain it's state and use it's properties and methods to handle events in my application. However, I have always been under the impression that there is a difference between writing objects that can be used by a procedural application and writing applications that are truly "OO".
Are you saying if I use a few objects in a generally procedural application, does that make it Object Oriented? Or is there perhaps a magical ratio of objects to procedures in an application that must be attained before I can call an application OO? =)
Nice discussion guys. This kind of topic would be a great round table discussion, recorded for podcast oh course.
By the way I do lean towards the OO side. Even at times when I seem to be creating more code than I would normally, in the end it comes together better and I do think it makes a more maintainable application. Overall I can't say that I think that I have ever made an application less maintainable by making to OO.
This may not be a good comparison but our admin side of one main portal application is its own entirely different site written using a different framework but we do re-use objects between them when we can. It usually works better if you know about the re-use up front. Some have xml (coldSpring) config files that load them up differently. Yes there are times when the needs are so specific we write completely different cfc's for the same objects.
@Jonny - you said 'OOP Does make alot of sense to use if you are coming from the systems analysis and design approach rather than just sit down and start coding.'
I have to disagree.
Using an Agile approach you may start off with a unit test and an empty cfc, write a few lines of test code then make the test pass with a few lines of code in the cfc.
You may well have a vague grand design sketched out on a whiteboard and have a good use case in front of you for the focused task at hand but I think OO works better using an Agile 'bottom-up' approach rather than a clasic 'top-down' approach.
I have always found my top-down design is completely different by the time I finish the project so tend to not spend as much time on it these days and just develop things, bit by bit



