I'll admit straight away that my background is in procedural code, way back before Object Oriented Programming (OOP) had not been dreamt up, or maybe just no one bothered to tell us humble COBOL programmers!
I started coding with ColdFusion on version 4.5 and the code I wrote was very much like this Form posts to action page that relocates somewhere that displays some links that show more Forms etc.
No framework no structure, spaghetti of the worst sort.
So I looked round and decided to adopt fusebox as a framework and this improved my code a great deal separating out data access, business logic , and display code.
Later versions of fusebox made this even better by forcing the use of XML in the flow of control from request to request, stopping the leak of business logic into the flow control.
Now like every good developer I'm lazy, so if I find myself coding something twice I start to wonder how I can make that code common and call it. The answer of course is to get data access and business logic which is liable to be called from multiple places into cfcs.
I learnt to make my functions as cohesive as possible (focused on as tight a purpose as possible) because that helps to make the API's clean and simple.
I found that making functions only dependant on their arguments, with no other dependencies on variables in shared scopes, made changing code much easier and more predictable. Not like the days of relying on variables passed up from nested custom tags!
So I started to believe that maybe I'm doing OOP already?
Well... NO because I'm still think procedurally.
If someone says to me we need a program that makes a cup of tea, my first thought is not
I'll call the kettle factory and the tea pot factory, inject the tea pot and the kettle into the cup of tea object and then call the makeTea service method which will know how to make a cup of tea by magic.
I expect that's how you guys make your tea, but us 'ol folk work through a process :-)
Kettle must be available
Teapot must available
Ingredients must be available from the 'Tescos' datasource.
Need to 'display' my tea to the user in a 'cup view'.
(work with me here ok?)
So since my system regularly needs to make tea I have Kettle and TeaPot cfc's instantiated in application scope with any init() method already run. But NO injection of other objects.
(gasps of horror already)
So earlier I said I didn't make my functions dependent on any shared scopes; well I lied because they do call other cfc functions by directly referencing functions something like this application.teaPot.openLid().
(more gasps of horror)
I don't have a service layer, data access layer and domain layer as such, but I do have functions grouped logically together in cfcs and by following the principles of cohesion and loose coupling the functions inside those cfcs start to adhere to that pattern automatically as you think through and re-factor code.
There is NO inheritance. So if I see a call to application.kettle.switchOff() I can open the kettle.cfc and find a function called switchOff and see what it does. I don't have to chase up some inheritance tree to find the actual function.
I have NO beans. CF gives us queries as a great way to pass around record sets. Sometimes a structure or an array might be more suitable, but either way CFQUERY and a bit more CF is all you need. If I need to maintain the code that saves an address record to add a new column because of a database change I want to see only a handful of SQL queries and the CF code that works with those record sets. I don't want to see multiple layers of code encapsulating the address record as a bean with bean factories and getter and setter for each column, too many additional lines of code to look at to understand, to go wrong or get wrong.
What about Aspect Oriented Programming (AOP) I here you cry. How do I handle cross-cutting concerns such as logging and security?
You know what? I would rather have the ugly but easily understood
application.utils.log(stuffToLog=stuff)
wherever I need it than the very clever but much more hidden and tricky to understand XML of ColdSpring.
Security can be nicely handled as a plug-in at the application.cfc or fusebox level.
I think much cleverer people than me have taken some very good concepts and developed them to their logical conclusions, but in so doing have lost sight of the wonderful speed and agility that makes CF such a great language in the first place.
Keep the principles foremost but also the KISS principle 'Keep it short and simple' or 'Keep it simple stupid!' And if it makes sense to break a rule once the pros and cons have been considered, then break it!
If this has enraged you mightily please let me know where I have gone wrong :-)
Jun 26, 2009 at 7:49 AM Kind of agree with you but not massively. I gotta say your thinking of occam's razor.
Jun 26, 2009 at 8:04 AM Having wrestled with OOP for probably the same number of years, I am totally sympathetic. But this objection to OOP because it over complicates an otherwise simple and straightforward application isn't really fair in the real world. It's a bit of a straw man you're attacking, because, at least where I work, a week later some manager is always going to wander in and tell me to port the whole thing to Oracle, or add a REST API against my service layer or fire me and put a new developer on my app which, not having been built in a recognizable framework, will offer him no bearings, etc. The thing is, taking a few extra minutes to break my app out into services and beans to my mind really does allow me to KISS. And it really is only a few minutes with ColdSpring and great code generators like Roobios and Illudium P-36. If an app is really as simple as the one you describe and is never going to evolve or scale or change, then I totally agree a framework is overkill. I personally only see apps like this in my own sandbox.
Jun 26, 2009 at 8:51 AM @Mark - yes Occam's Razor popped up as I looked up something else while writing this. Thanks for the comment.
@Jason - my main application does not make cups of tea :-) just in case any confusion. I certainly don't propose no framework - fusebox has served me well. but the additional structures which have crept in from the OOP world - those seem to me to be a step too far - in most cases. I absolutely agree about the need for an application to be scalable (in scope not performance I mean) and I think cfc's and fusebox give you that. I have writen very tiny apps and used fusebox, thinking as I did it that it was not really needed only to find exactly what you describe that the app grows and fusebox was definately needed! Thanks for the comment.
Jun 26, 2009 at 9:48 AM Well man, I'm sorry you feel that way. Sure sometimes not using OO can save some time. It might look more complicated with a service layer, DAO, beans, gateways, etc.. but really its organization. Separation of duties. In a multi developer shop having this type of organization really helps. I do not have to go looking to find something. One HUGE thing that helps you setup and wire your OO layer together is ColdSpring. As for beans, sure I can pass queries around but the minute that column changes, the data needs formatting, encryption, etc... it gets a bit messy. Having setters/getters really helps. I'm not saying every feature or project needs to be full OO but we've found that using more OO really does save time down the road both in getting other developers up to speed on the project and reuse.
Jun 26, 2009 at 9:56 AM @Ryan. Thanks for your comment. Good to hear this is help you guys out. I'm not completely closed to the ideas just yet to be convinced that it will save me and other developers time. We are doing some coding experiments to take a closer look at this whole area. Who knows I might become a convert :-) If I need to format a column or encrypt it can I not just modify the query returned from my function? How is a bean simpler or better?
Jun 26, 2009 at 10:56 AM You probably already realize it, but it's worth spelling out to your readers: you're actually doing OO. You're just not using some of the "patterns" that are preached as core to the ColdFusion genre. And that's the important part.
A lot of people "believe" in OO development without understanding the core ideas, and as Chris Rock said in Dogma:
"I think it's better to have ideas. You can change an idea. Changing a belief is trickier. Life should malleable and progressive; working from idea to idea permits that. Beliefs anchor you to certain points and limit growth; new ideas can't generate. Life becomes stagnant."
Jun 26, 2009 at 12:03 PM @Adam Thanks for your comment Adam. I regret my post title a bit because to be honest I don't really know how to define OOP - I am certainly using the principles and ideas that make sense to me and give me benefits - the concepts that seem to create more issues than they solve I have left alone. Wow can I put OOP on my CV? Will you give me a reference? :-)
Jun 26, 2009 at 1:04 PM Michael,
Thanks for describing your app & your coding practices. It's good to see inside what people are doing. Just know that what you are doing, contrary to Adam's thoughts, is not OO.
You've grouped utility functions into a few CFCs in a way that makes sense to you. Lately, I've been calling this the utility object anti-pattern. It's a heck of a lot better than nested cfincludes, and miles beyond copy and paste reuse, so I applaud your logical thinking.
Of course the danger here is to ward off the 'spaghetti with meatballs code,' where your code is unruly and mixed with objects. I'm not saying you're doing that, I just like to make pasta analogies.
For you, actually, if you plan to go more OO from where your 'tea' app is, I would actually warn you more against the anemic domain model problem, where you have these objects like services, passing out beans and communicating with DAOs, but all your logic is in the service layer, in the application scope. That's dangerously close to what you're doing now, and once you go there, it's a pain to make it work for you (instead, you'll be working for it).
There's actually a good mix of OO you can do with CF that's not too overblown (what you're afraid of) and not too underblown (what you've done). Layered architecture can fit well, especially once your application reaches a critical mass of cohesion and complexity.
You wouldn't need to 'go OO' for making a cup of tea (nor would you need Fusebox) and drawing the line is an art, as is beautiful code.
What you're doing isn't wrong, it sounds like a good structure, and hopefully it works for you, but it is not OO.
Jun 29, 2009 at 5:30 AM @Nathan
"There's actually a good mix of OO you can do with CF that's not too overblown (what you're afraid of) and not too underblown (what you've done)."
The problem ist that for someone new to OO this is terribly hard to find. You find many examples of Gateways, DAOs, Beans, Services, all put in CFCs. You find repeated warnings to avoid the anemic domain model. But, how to make GOOD use of OO, how to actually avoid the anemic domain model, that is the info that's hard to find.
I'm sure if you would point out one or two resources that actually help, many people would be grateful.
Jul 1, 2009 at 2:45 PM I agree that OOP tends to be overemphasized in some ColdFusion circles. For instance, I rarely use inheritance in CF apps because it's hard to reuse code that way even when following an MVC architecture.
For my own development, encapsulation is most important concept, followed by cohesion and coupling, followed by design patterns, followed by the other OO techniques such as inheritance.
You say that you use loose coupling, but by using the application scope in your CFCs you are effectively coupling your CFCs to _EVERYTHING_ in the application scope.
I see two big problems with application-scope coupling. The first problem is that when you change a CFC, it's difficult to determine which other CFCs are impacted by the change. The second problem is that it becomes impossible to perform true unit testing on a single CFC as you cannot remove the influence of the other application-scope CFCs from your tests.
Developers can often put up with with both of the above two problems as long as the number and complexity of the CFCs are low. Heck, most CF developers don't do _ANY_ unit testing. However, as both the number and complexity of CFCs increase, developers who ignore these problems will find themselves spending more time working on bugs and issues related to dependencies between CFCs.
I love dependency injection because by defining the dependencies explicitly through property relationships, I can see which CFCs use which other CFCs without having to scan the code. If I change a CFC, I can see which other CFCs depend on it so I know what to retest. I can also perform proper unit testing on a CFC by injecting mock objects into the instance I am testing to satisfy its dependencies without letting those dependencies influence the testing.
I also like design patterns like factories, but I don't use them for the sake of it. Design pattern newbies often miss the fact that every design pattern offers a trade-off: they reduce the costs of some aspects by increasing the costs of others. It is better to _NOT_ use a design pattern until you can see that the trade-off presents a net gain for you. Factory objects are often great, but in some cases a factory object may not buy you enough benefit to be worth bothering with.
To sum up my feelings on this, it's good to question and not automatically buy into all the "best practices" floating around the CF blogosphere, but consider that some of techniques mentioned might appear low-value to you now simply because you have yet to encounter the kinds of problems that those techniques are meant to solve. As you build larger and more complex applications you may encounter new problems and some of the techniques you've rejected so far may begin to offer more value to you.
Dec 21, 2009 at 9:07 PM cheap jordan shoes free shipping paypal
http://www.nikejordanstore.com
http://www.onlinebuyshoes.com