Why I Don't Do OO
This is an entry that I have been intending to write for some time. I keep putting it off. Perhaps because I don't think I will explain myself well, perhaps because I don't want to be flame-bait.
T.J. Downes recent entry "Why Aren't More CF Developers Using OO Methodologies and Frameworks?" made me decide that now is the time.
He asked those of don't use OO to explain why, so I will do my best to explain why I don't.
I Don't Need It
This is a bit hard to explain. More accurately, I have yet to run into a problem that I feel would be solved by moving all of my development to OO. I do use object from time to time. For example, my code generator makes pretty heavy use of objects. They make sense there and so I use them.
Generally, however, I hear about the benefits of OO and I think that I get all of the benefits that I care about without doing pure OO development (more on that later).
It Adds Complexity
For years, I have had great success in talking to developers who use other languages in getting them to take another look at ColdFusion. I have had two standby examples that I have used for years.
The first is <cfquery>. Any developer from ASP/ASP.NET or PHP that has to write SQL (all of them so far) that I have talked to has been really impressed with the direct simplicity of <cfquery>.
The next is <cfoutput>. Want to loop over a recordset and output an HTML list?
<cfoutput query="qMyRecords">
<li>#MyValue#</li>
</cfoutput>
</ul>
Done!
Want to make nested lists for categories?:
<cfoutput query="qMyRecords" group="MyCategory">
<li>#MyCategory#
<ul>
<cfoutput>
<li>#MyValue#</li>
</cfoutput>
</ul>
</li>
</cfoutput>
</ul>
Done again!
This compares with having to do a manual loop with some sort of check to see if you are at the end of the recordset. The nesting requires extra conditional logic to compare to previous values. It isn't hard, but it makes the code just a little messier. I see the same thing now in ColdFusion when people try to add OO-ness to the output instead of just using queries.
I Can Follow OO Principles without Using OO
I know this sounds strange and I don't think I will explain this part well, but give me a chance. I do use a service layer. I am very strict about encapsulation. I take advantage of inheritance and (occasionally) polymorphism within my service layer. I just pass around data instead of objects.
So, for example, I don't (usually) have a "User" object. Instead, I have a "Users" service. This would have a "getUsers" method that returns a recordset.
One of the criticisms about this is "What if need a property of a user that can't be calculated in SQL?" This belies an assumption that a recordset must come directly from the database. My view code doesn't care how my service puts together the recordset. It just knows that it will get a recordset from the service with the data it needs.
So, for example, it may have an "Age" column in the recordset. That column may be calculated and added outside of a query. The view code simply doesn't care how the column was created. It just knows what data it gets from the service.
Extra Rules I Can Enforce
One advantage that I get my using a service-based approach instead of an object-based approach is that I can enforce a rule of "no method calls in the view". The view can call UDFs, but it cannot call service methods directly. That is the controller's job. The view can only use the data that it gets from the controller.
The view does looping but it doesn't know what happens under the hood for any given method. Consequently, I don't what the view calling methods. The worst performance problems I have seen in ColdFusion come from looping over queries. How can the view knowingly avoid this when it doesn't know what happens under the hood for any method?
The Starting Over Problem
One criticism I hear of ColdFusion programmers who refuse to move to OO is that they don't want to give up their procedural expertise and start over with a new way of doing things. I certainly have to concede that is a factor for me. My development seems to be going well and I am not keen on going through a major slow-down to dramatically shift my development style.
This is especially true as I have a large tool-set built around my current practices. Currently, I use my tool set to quickly build stable but flexible solutions for my clients. It offers me a competitive advantage. In order for me to give that up, I would have to see major benefits for the cost.
That being said, if I do see those benefits, I am not opposed to going through growing pains to get them.
This is ColdFusion Specific
It is important to note here that I am not anti-OO. I remember being in a job interview where the people interviewing me said "OO is just a fad". I thought they were sticking their heads in the sand. Of course, they also told me that CSS slowed down web sites, so it clearly wasn't a good match for me.
When I write JavaScript, I do (try) to write OO code. It makes sense there. When I practice Flex coding (I am just barely learning), I definitely do OO there. It just makes sense there. When I write a façade for ColdFusion to talk to Flex, I will likely have ColdFusion return objects to Flex. Again, that just makes sense.
This is Me Specific
I am not here trying to advocate that everyone avoid OO. I'm just trying to provide my reasons for not using OO. Hopefully they show how a reasonable programmer can avoid OO and that OO need not be "The One True Path". Maybe this just shows that I am missing the boat completely.
OK. Those are my reasons for avoiding OO.
Flame On!
"Generally, however, I hear about the benefits of OO and I think that I get all of the benefits that I care about without doing pure OO development (more on that later)."
I am a pragmatist, at heart. If you get what you need out of your architecture, and your architecture helps you build maintainable applications in a rapid fashion, then it sounds like a sensible architecture to me.
One thing that doesn't get talked about enough is the amount of "oo-ness" that seems appropriate for the application is directly correlated to the complexity and number of developers. My personal guidelines change a lot between a website/cms project and an application with lots of business rules.
Thats why the right answer is most often "It Depends"....
DW
You are NOT avoiding OO. I haven't seen the code driving ColdFusion, but I assume it is Java, and I can 100% guarantee it is 00. You are simply abstracting it, even if you don't create a 'User' object, you are still creating a user object ;)
There is definitely a big learning curve when moving to OO development and you've got to ask yourself why you'd bother going through that. As applications continue to grow in complexity, things like being able to encapsulate the calculation of properties within the business object rather than getting a service class to do it can be easier to work with. I also find the whole #Order.getItems()# syntax very useful for traversing relationships. I also find re-use of code through base classes has worked for me well.
In the end I found that as I tried to generate more and more complex web applications, my procedural approach wasn't working very well for me. I was running into specific problems that I could solve, but maintenance became more of an issue. I spent a bunch of time, went through an experimentation phase and now have a richer set of tools to apply to problems.
I think there are two reasons to consider "doing OO" (specifically, learning all of the common patterns and getting comfortable enough with the forces behind each one to determine were and when they are a good fit for a given application - it doesn't mean any given app would use all or even any of those patterns - I still have one page forms with the processing at the top and the display at the bottom sometimes!).
The biggest reason is that if you see yourself as a programmer rather than as a CF programmer, you're going to be severely limited from a career perspective if you're not conversant in OO and design patterns. It's why I play with a little Java now and again (and keep reading up on new features in C#) - so I can talk with non-CF developers and understand what they're on about. I'd also argue that if you want the pick of the best jobs, it makes sense to become comfortable with a functional language (such as Haskell), keep up to speed with the "new coolness" languages like Scala and Cat (I think Groovy and Ruby are old hat now :-)) - at least well enough to chat about their relative type systems and the like, learn all you can about agile and lean, and get some familiarity with meta programming, DSLs and Domain Specific Modeling. Of course, that's my list - someone into biological computing would probably have a different list - as would someone into high performance systems or compiler theory.
The other reason to learn OO is to have more tools in your toolchest. Interestingly I don't find many people with both deep OO and procedural experience choosing procedural approaches over OO outside of specific edge cases. Certainly the more OO I learn the more I find ways I can use some of the patterns to solve specific problems more elegantly.
It seems to me that you ARE taking patterns from OO development and applying them to your use cases intelligently to solve specific problems which is what all this is about. The more legacy infrastructure you have around a specific approach, the less likely it is that a wholesale change in implementations will provide an ROI.
I think your approach also shows the benefits of starting with something that works and refactoring to solve specific problems. Of course, if you don't have the problems, you don't need to refactor. And if you DO have the problems, you know WHY you're using the patterns and will use them appropriately!
http://www.pbell.com/index.cfm/2008/7/15/The-Simpl...
@Jon, By that argument we all do procedural programming as it is compiled down into byte code that is executed sequentially. OO is about the way you construct the code you write in your language of choice - not about what it gets compiled down to.
Thanks for the encouragement.
Peter,
I should have clarified that my post is why I don't use OO for most of my ColdFusion development, not why I don't *learn* OO. I am learning OO. I'm not learning it as quickly as I would like, but I do read about Design Patterns and OO programming and I am planning to practice those concepts (mostly in Flex).
I'm not sure I follow what the advantage of having calculation in a "business object" rather than in a service. I do keep all of my business logic together and encapsulated, after all.
I do see the advantage of Order.getItems(). That syntax is certainly one of the things I like about OO.
I want to reiterate again that I don't do OO in CF because I don't think OO (usually) helps (me). I am trying to learn other languages where OO does make sense (to me) and use OO there.
Great point!
If the results are truly an attribute of the entity you are modeling, then I would think that the results of the web service call should be included with the original entry into the db. I would probably roll the web service call as a separate service object or UDF since it seems to me that I'm really fetching data from a different data source. We're sort of making a join across the internet.
Regardless, it's still a pretty good example.
It is also my opinion that there are many types of OO and levels of OO development. This is likely my bad to some... but there is a difference between complete OO and pure OO. The concept that OO is a pure implies that anything not "complete OO" is impure. It is a very anti-social term and is actually manipulative at it's base. We need to look at the trade offs and choose which trade offs are right for our applications. In fact if OO is so hard to learn then we reduce the sustainability of our applications in the area of man power when we move them to complete OO in many scenarios.
I disagree a bit there. I do use unit testing. Unit testing requires well encapsulated code where logic and output are separated. It doesn't require OO.
I haven't had any challenges using unit testing with my current approach.
As to the difference between "pure OO" and "complete OO", I have to confess that I don't follow you there. I am not familiar with those terms and didn't quite get them from context. Perhaps something I should research in the future.
http://www.google.com/search?q=pure+oo
I would love to see how you do your unit testing. We can generate our base test methods off the meta data of objects. Granted you can manually include a file and pre-set variables and check them after the fact. (That is the type of testing that was done in Fusebox years ago. Test stubs or some such thing.) I think FB4 was when it could not be done anymore. I am glad you found a way to do that... and it might be a good preso for you to share with others!
I don't really think I am doing anything unusual in my unit testing. I basically just call the methods of my components that I want to test and check the results, nothing special at all.
I may write a blog entry about it later, but really nothing special going on at all. I still use CFCs for business logic and .cfm files for views.
You ARE doing OO. You're just not doing PURE OO. To be blunt, you're using your head! Converting a query to an array of objects has questionable benefits as far as I am concerned. I've seen noticeable performance issues, which I've been meaning to blog about in more detail, but I touch on it here:
http://www.brianmeloche.com/blog/index.cfm/2008/1/...
ColdFusion is not a pure OO language, and I think a lot of developers make a mistake to treat it as such. If there's no reason to "set" a value after it comes out of the database, why convert a query to an array of objects and add all of that additional overhead? Just keep it simple. Return a query.
You ARE using sound application design principles. A service layer is critical to a good application design.
Thanks for the words of encouragement. Honestly, though, I don't think I am doing OO. The key thing being that I don't use any objects. I use components, sure, but not real objects.
I would say I am doing Service Oriented programming (assuming that term doesn't already exist). I do have services, after all.
Still, I did decide to write a service layer in part so that I could add objects in the background later if I see the need.
"really impressed with the direct simplicity of .
The next is ."
Thanks for the catch. That is fixed now.
I do OO cause I am used to but I have to admit that OOP make really more sense in AS or JS than in CF.
Cfc do not have the basic of a normal object in a real OOP language.
We all use init() but I can make instance of any cfc without that any constructor run etc....
But most important CF used in very stricktly OOP becomes terribly slow.
I use dataMgr to develop my personal service/data layer that return indifferently query / json or array of objetcs ( for flex development ) ......the point is that returninig a query is 30% of the time of making with that query population of objects and return them.
I had many test with framework like transfer; they are beautifull but if hibernate make sensi in java transfer do not in cf cause make performance very poor.
So I use OO all teh time in CF but no way to use it in a strict way....probably CF was not designed for that....honestly I cannot loose so much performances.
Andrea