That's where you'll also find the forums, wiki, source code repository and bug tracker. The blog also has a link to the new mailing list if you'd rather use that instead of the forums.
What is FW/1? Read the RIAForge project description and introductory blog post there.
Why create FW/1? Again, read the project blog on RIAForge!
I've left comments on a few of the blog posts but several people have asked me to go into a bit more depth about my thoughts on this issue (since I'm one of the people sometimes accused of "pushing" OO and insisting it's the "right" way to do things).
I said it in a post to the cfcdev mailing list and Henry Ho felt it deserved a mention on his blog.
The topic came up because John Whish, manager of the Devon CFUG over in England (where I spoke last September on design patterns), is running a series of presentations on OO and patterns for the group. He wondered how to approach the fact that CFers tend to have separate DAOs and Gateways whereas that distinction does not exist in non-CF languages or pattern literature.
I feel responsible for that distinction so I replied with my thoughts and an explanation of why I had suggested it nearly six years ago but why I don't think it's good advice these days (and, frankly, hasn't been good advice for years - I no longer had access to the guidelines document that enshrined the advice!).
I recommend you read the thread on the Google Group (cfcdev). Henry quotes part of my reply and links to the thread for more detail.
That particular chapter is available as a PDF and it's a really good read. It starts off explaining the problem to be solved and then presents the "obvious" object model that most new OO students come up with. Then he takes it apart, explaining why it's a poor design, and goes on to construct a much better model (with fewer objects) that is very elegant and easy to understand.
If you're struggling with the OO design process, you need to read this PDF and absorb the lessons laid out within it. Even if you think you're an OO 'guru' you'll probably learn something from it!
John Whish (Devon CFUG) has a version of all the slides (with builds but no notes) which was how I presented it on Monday because my laptop wouldn't drive the projector (first time ever!) and I had to present from John's laptop.
For ease of reference I just wanted to post a quick note highlighting Bob Silverberg's excellent series on using Transfer ORM and OO architecture:
- How I Use Transfer - Part I - Introduction
- How I Use Transfer - Part II - Model Architecture
- How I Use Transfer - Part III - Abstract Objects
- How I Use Transfer - Part IV - My Abstract Service Object
- How I Use Transfer - Part V - A Concrete Service Object
- How I Use Transfer - Part V.1 - A Comment and Response
- How I Use Transfer - Part VI - My Abstract Gateway Object
- How I Use Transfer - Part VII - A Concrete Gateway Object
There's a lot of good information here although it may be a bit overwhelming on first read so be prepared to keep coming back to these posts!
We hear a lot of talk about using individual Java objects within ColdFusion but the reality of enterprise development is that entire subsystems tend to built entirely in Java. Software teams that serve the enterprise often build large, complex systems using Spring and Hibernate. How do you go about using ColdFusion with such systems? I haven't seen any presentations on this subject so I was pleasantly surprised when I started reviewing Andrew Powell's slide deck to find that he was focusing on how ColdFusion can provide the web front end to enterprise class Java systems.
He introduces Spring (the Java version) with a demo and then introduces Hibernate (the industry standard ORM for Java), again with a demo. After that, he will walk you through solutions to the problem of connecting ColdFusion on the front end to Spring on the backend and, using Mach-II as an example, he then shows how to create an MVC web application that allows you to leverage the entire Spring-powered, Hibernate-persisted Java backend.
If you work along a Java team - or you are considering using more Java for your backend systems - this talk will provide you with a lot of good information about how well ColdFusion plays in this space.
Of my other two clients, both are ongoing rearchitecture projects along similar lines but with slightly less impending deadlines. It doesn't look like I'll be anything less than insanely busy for several months tho'. January was a record month for me in terms of hours worked and I expect that will continue for the next few months.
The downside of that is I'm less available on IM than usual (sorry) and never on IRC (so folks have to ping me if the cfmx7bot goes offline). I'm also behind on getting articles and columns and presentations written - but I am almost completely caught up on reviewing cf.Objective() presentation outlines!
- Model-Glue (two clients), Mach-II (other client)
- ColdSpring
- Transfer
All three clients are on - or imminently moving to - ColdFusion 8 (as most of my clients have been) so we can take advantage of AJAX, performance, array/struct syntax, enhanced operator syntax, onMissingMethod() - which powers ColdMock - and many other recent enhancements.
These three clients have been keeping me pretty busy - I was even on-site with one of them for three days this week which, as folks who know me will realize, is pretty unusual since I've mostly kept to remote work since I left Adobe. I think they're going to be keeping me busy for at least the first quarter of 2008.
I haven't been blogging much this past two weeks but I've been posting to a few mailing lists, covering decorators (Transfer), dependencies (ColdSpring) and various OO design issues. I've also been writing an article for FAQU which will be in issue 6 (issue 5 is at the printers and should be in readers' hands soon). The article covers the whole "beans + DAO + gateway + service" object stuff, looking at four possible ways to structure your code and examining the pros and cons of each.
I'm also reviewing a new ColdFusion book that is in the works. It's a great introductory book that covers a lot of best practices and focuses on CFCs up front. It's target market means that it probably won't get on most American developers' radars but I think it will be worth tracking down and reading if you're a novice (to ColdFusion).
I'll also be writing a regular column for [name withheld] on my favorite subject: architecture.
As you can tell, 2008 has started off busy and looks likely to stay that way. I think the year will offer me some interesting challenges and some interesting opportunities - and maybe some big changes too.
Let me know if you have questions or comments!
Event-Driven Model Framework for ColdFusion. The name? EDM = Event-Driven Model, Mund = mouth (German), Mund = ancestral rule over the family / disciplinary power over members of the family / responsibility to protect the family (Old English). Edmund is also one of my cats :)
This is based on two things (in my opinion - putting on my flame-retardant suit)...
As folks who attended my session in Chicago and/or Barcelona heard, I'm still offering that caveat today and people still think it's news...
Brian Kotek has a great post about data vs content in the context of AJAX and frameworks. He emphasizes the benefit of having your model in CFCs as the easier way to expose data-centric functionality to AJAX and notes that for data calls, you should not be trying to go through the MVC framework. It's a good read.
Please also take the time to read Matt Woodward's (very long) post about our use of design patterns in ColdFusion. It's an excellent read and makes some very important points about there being no "One True Way" and the fact that patterns are high-level and therefore can have multiple implementations in different languages.
Of course, as those folks who've struggled with Model-Glue: Unity (or Rails or any other framework) know only too well, it's not quite that simple!
So why do some people struggle when others find these frameworks so easy and so productive? The answer is blindlingly obvious, unfortunately, but it isn't an answer most people want to hear.
Sammy Larbi asks "is Rails easy?" and points to Venkat's blog entry "Can your cat code my Rails App?". The answer to both of these might seem obvious. The answer to the second question is clearly "no". The answer to the first question is, unfortunately, "it depends".
As Venkat says:
I asked why she thought developing with Ruby/Rails is so darn simple. She said she had seen a demo of a fully working app being created within minutes without much effort or code.
The videos are, of course, somewhat misleading because they show what someone can do once they already know the framework really well. It's the same reason that experienced OO developers find OO so liberating and productive: they already know OO really well!
Venkat compares C++ and Java, saying the latter is more productive with the following caveat: "I doubt anyone would say that Java makes an ignorant programmer more productive. You did have to take the time to learn the details of the language, the platform, and the API."
The point behind all this is that there really is no silver bullet. Using a framework doesn't automatically make you more productive from day one. You have to learn how to really use your tools and sometimes that learning process is non-trivial to the point of seeming endless (and being a lot of hard work!).
I post this because I got into a somewhat heated discussion at CFUNITED a few years back with someone who thought OO was dumb because they'd tried to use it and it made a mess of their application. I said that it takes time and effort to learn OO in order to be able to apply it properly. They got offended, thinking I was telling them they were too stupid to learn OO. I've repeatedly said: this stuff is hard. I started doing OO in January 1992 and I'm still learning. OO has mostly become second nature to me now but that doesn't preclude me from learning new techniques - often from people with less OO experience - that help make me more productive.
So don't think that Rails is going to turn everyone into super-productive programmers overnight - most people coming to Rails already have a fair bit of Java and OO experience so pick up the concepts easily and, once they've learned the Ruby and Rails specifics, they can be more productive than they were in Java.
It's the same principle that applies when you learn a new framework in ColdFusion. It may seem strange at first and may look like extra work but once you understand most of the specifics, you can be much more productive. Just be prepared for a learning curve.
Andrew Shebanow has a good post about this tradeoff in relation to Twitter, which is powered by Ruby on Rails. Alex Payne, of Twitter, has talked about their experience with the massive scalability explosion that the site has seen and some of the "friction" that they've encountered trying to refactor the abstractions out.
I worry about this in the context of most every framework I use - and there's certainly been plenty of noise on mailing lists and blogs over the years about the performance of frameworks. One of the reasons I've settled on Fusebox for the Scazu website is that it compiles all the circuit files down to inline CFML on the first request so the abstraction is compiled out (this is one of the core messages in my "Extending the language of Fusebox" presentation - see slides and sample code under 'SOFTWARE' on my blog).
I've also been a fan of Transfer for ORM, lately because of the TQL - Transfer Query Language - component that lets me write complex database queries using an object / property abstraction. It looks much like SQL but lets you use the terminology of your application instead of the terminology of the database. It does add overhead but refactoring methods that use TQL into methods that use the underlying raw SQL is pretty straightforward and can be done on a method by method basis (and, in fact, I recently refactored one performance-critical method in exactly this way).
Going back to Andrew's post (and the underlying comments from Alex), I'd say that Transfer has a low friction coefficient that contributes to why I like it so much.
Brian Kotek picked up on my response and posted that you don't need to go that far - just considering that you might have to put a Flex front end on your application is enough. He's right, of course, and that harks back to my Mach II advice post back in May.
In particular, I was taken by this comment from the Flash Coder:
A development framework is useful when your workforce is disperately or poorly skilled. Perhaps 'poorly' is the wrong word - maybe 'intermediate and below' is a better description.
To be fair (to both Simon and to the Flash Coder), the blog entry is mostly focused on code size and performance in regards to frameworks and is specific to Flash (therefore the context is more about cell phones and set top boxes).
However, the underlying sentiments expressed by the Flash Coder threw up much the same "red flag" that some of Simon's comments have: namely that frameworks are not appropriate for "good" developers and that if you're really good and really know OO and patterns, you just don't need frameworks.
Here's another quote from that entry that is almost exactly what Simon has said when justifying his Sensible Assembly Methodology over using a standardized framework:
The best solution of course, is to have skilled developers creating good pattern based OO code in a more project bespoke manner and adhering to accepted best practices.
I don't really want to start up the whole framework vs no-framework debate again but I thought it was interesting to see this message - and the subsequent pushback in the comments - coming up in Flash. I would bet we could go look in the PHP or Java community and see the same thing.
This post hits a nerve for me because as a senior software architect for most of the last decade, I've often found myself in situations where I've ended up quite distant from the code. And I don't like that much. I don't want to just write code but I do find writing code to be both very therapeutic as well as a good way to experiment with some of my ideas and evolve better practices.
I realized recently that, although I created the engineering team that rebuilt macromedia.com (now adobe.com) using ColdFusion and Flash, I hardly wrote any of the code on that site! The RSS feeds on LiveDocs are powered by code that is based on an initial prototype I built but that's about it, in terms of live code. I wrote quite a bit of back end infrastructure code for our ERP integration project (lots of XML processing and JMS messaging). That was a while ago.
My new team is smaller and is trying to be more agile in style so architects write code too. It's really good to roll up my sleeves and write code again - it's really helped me confirm some of my architectural ideas about what we're building (both good ideas and bad ideas!).
BTW, this lack of coding at work is what fuels my contributions to open source projects outside work, such as Fusebox 5!
Apparently I can be "quite blunt" but that was enough to kick Brian's butt into actually trying OO etc.
What I really like about Brian's post is that he realizes that there is no "perfect" OO solution and that it's OK to move toward the light, step-by-step, and it's OK to make mistakes and take shortcuts and make things better later.
Excellent post Brian - lots of good lessons to be learned here. No one should be afraid to take those steps!
His employer, AboutWeb, has just released the second in a series of podcasts. This second one talks about SAM, Simon's "Sensible Assembly Methodology". I'm looking forward to listening to it (as soon as I get caught up on my podcast backlog!).
He also said on blog today (July 7, 2006) that "I plan to have the first round of SAM documentation done and available within the next several weeks - probably before the end of the month".
For a bit of fun, I thought I'd search his blog for mentions of his methodology and see just how long he's been promising us the SAM documentation. So here, for some Friday fluff entertainment, are quotes from Simon's blog over the last year:
January 13, 2006: "The methodology I use, which I promise you'll all be able to read very soon".The suspense is killing me... :)December 24, 2005: "I have begun documenting the methodology that I use for developing applications and do promise to make that available very soon".
November 1, 2005: "I will begin the documentation of my methodology sometime in the next couple of days".
October 20, 2005: "I will begin documenting the methodology I use for planning and developing software with CF".
October 1, 2005: "I will officially be releasing my methodology, most likely I'll make the files and documentation available off of horwith.com, possibly on aboutweb.com as well".
September 26, 2005: "the book I've mentioned from time to time over the past year, which is still in the works, will be a definitive guide to my methodology".
September 21, 2005: "So far I still feel this way and I plan to do just that (document and release my methodology) sometime after MAX".
August 12, 2005: "I will document and develop a better alternative! I already have a methodology I use and it does include certain files I've written".
Simon started out with an overview of what object think is about. The key concept is "object personification" which is the basic way that I teach people about object-oriented design: I make people play at being the various objects in the system. I make them write notes to each other to reflect the message passing that objects do. Object think is all about creating an expressive but accurate domain model where every object handles all of its own responsibilities - it sounds obvious but it has some deep implications.
Peter has some very interesting ideas on code generation and is very passionate about it. You can always guarantee a good (and often heated!) discussion on a range of topics that includes frameworks, design patterns and metaprogramming.
Welcome to the blogosphere Peter!
And then you need to put a Flex front-end on your application. That means you need to expose your model as a set of remote methods. If you got your application design right, that'll be easy: just open up your model CFCs and change the access attributes and you'll be done, right?
First off, while I think the tests are interesting, I've always been one to say don't worry about performance too much because "fast enough" is almost always sufficient. Very few websites get the sort of traffic to need heavy load testing and tuning, frankly, and as we know there are some very high traffic sites out there running on various frameworks. macromedia.com runs (about a quarter of its applications) on Mach II and the performance under load testing met all of our criteria.
My comments about the tests Webapper ran were meant to say:
- It's no surprise Fusebox is "faster" because it is more of a compiler than anything else (the framework doesn't really "do" anything at runtime, once your XML is compiled to CFML)
- I was pleasantly surprised that Mach II was not slower than a hand-coded CFC-based application - a lot of people complain about the "overhead" of Mach II but this shows that is not necessarily true
The point of the original (Webapper) article was that JVM tuning can have a dramatic effect on performance, as can Trusted Cache.
Those wonderful folks over at Webapper have been doing some load testing on various frameworks using the ColdFusion PetMarket application (featured in the February CFDJ). They tested Fusebox 4.1, Mach II and Simon Horwith's "no framework" versions of PetMarket. Fusebox 4.1 was the fastest which really isn't much of a surprise since it compiles everything down to straight line CFML on the first request so subsequent requests just process a single file. What surprised me was that the Mach II version outperformed Simon's version (albeit, not by very much). Overall, Simon's version was 100% slower than the Fusebox 4.1 version. Unfortunately, Webapper couldn't test the Model-Glue version because "the PetMarket Model Glue application was not fully functional". Based on my experiences, I'd expect Model-Glue to fall somewhere between Fusebox 4.1 and Mach II performance so I hope they get a chance at some point to show that.
I just want to know your thoughts on this question... Which is the best Framework you think to adapt? (Fusebox or Mach II)Even assuming they mean "adopt", it's certainly not a straightforward question. I'd recommend folks download my frameworks comparison presentation and take a look at the accompanying sample application code. This covers Fusebox, Mach II and Model-Glue and gives pros and cons for each framework as well as some broad recommendations based on your skillset and the type of application you want to build. The sample code has nine variants of a single application, showing various flavors of Fusebox, Mach II, Model-Glue, Tartan and ColdSpring in various combinations.
I'm currently running around CFUGs with a talk about "Objects & Persistence" that briefly covers four of the ORM frameworks that have appeared lately: Arf!, objectBreeze, Transfer and Reactor. I'll soon also be giving a talk about factories and covering ColdSpring. Both of those talks will be accompanied by more variants of more applications.
However, I get the impression that some of the people asking me this question want me to specifically recommend a framework or a combination of frameworks for them so they don't have to digest the presentation and code. The short answer is that there is no "One True Answer™".
Here's part of another email - which has a lot more background the question - but here's how the question was phrased:
Anyway, I'm looking for some guidance with frameworks. I am involved in a project that I know could benefit from using a framework. I just don't know which one would be best. The more I read, the more confused I get. I think I've narrowed it down to Fusebox or a Model-Glue / ColdSpring / Reactor set up. I really like the MVC concept, but am new to that as well, so I'm not sure if it would be easier to go with something that forces the implementation or trying to implement Fusebox in an MVC pattern.This person has done their research and understands some of the tradeoffs involved which is great as far as I'm concerned. I sympathize with this part "The more I read, the more confused I get." - it's not a simple choice. They will get a long, detailed response - as soon as I find time. The other email shown above will get a short recommendation to read my presentation and look at the sample code.
The point of this (somewhat long) blog entry is that if you want me to offer advice on the choice of frameworks, I'm more than happy to do so - but the quality of the answer you get will be directly proportional to the amount of information you provide me with (and the amount of "homework" you show you've done).
And yes, I do have a personal preference - if there is no overwhelming reason to use a different specific framework combination. Just remember that what works for me might not necessarily work for you. What is my personal preference? Don't read too much into someone's personal preferences...
I was a little surprised he didn't go into more depth and talk about how frameworks can often provide standardized way to manage user login security and logging and auditing. Plugins and extension points (such as Model-Glue's standard broadcast messages) allow login / security to be built into applications in a nice, clean standard way. Auditing and logging can also be added more easily: Model-Glue allows a logging listener to be easily added that tracks all the messages without interfering with the existing application flow; ColdSpring AOP allows pretty much any application behavior to be logged without touching the application code.
Using a framework can save you a lot of work - tedious, boilerplate work.
So, what's the difference between the two? With factory method, you generally provide a key of some sort and the method yields an object of that type. We see this with hand-coded factories that we give a text string to and get back an object - the text string is either a simple key, the name of a component type or the ID of some object described elsewhere (e.g., an XML file). ChiliBeans and ColdSpring are two good examples of factory methods.
With abstract factory, you usually have multiple factory implementations and each factory implementation is responsible for creating objects that are usually in a related hierarchy.
We typically just say "factory" and we mean "factory method". Want to see an abstract factory in all its glory (gory?)... check out this 1996 article I wrote about building a compiler. I didn't call it an abstract factory design pattern because back then I didn't know the names of those patterns very well (the "Gang of Four" Design Patterns book appeared only two years earlier).
If you're feeling masochistic and want to understand a bit more about what makes me tick, feel free to read the entire compiler writing series (six parts, written between 1994 and 1996 and published in Overload).
My response was "Of course not!"... Now, it may surprise you to hear that someone who is so evangelical about coding standards and, in particular, design patterns, will actually build code that does spring fully-formed and cleanly architected out of its crib and into the world at large. Before you paint me as a hypocrite, let me explain...
I tend to build my code to be as simple as possible to start with. I may well write just one or two CFML pages (sometimes fairly long ones), just to get some machinery down and working. Then I'll refactor for a while, pulling code out into CFCs, for example. Then I'll add some more functionality - again using the straightforward approach - and then I'll stop and refactor. And so on.
I refactor to make the result maintainable or to prepare for a new round of functionality to be added. I try very hard to not attempt both at the same time: fix the functionality, change the code, test, add new functionality, test, repeat. Of course, I should be writing test cases before adding each new piece of functionality (I'm still supping away at my TDD kool-aid).
Anyone who has been watching the development of the IRCBot will have seen similar changes across releases (and the next release, when I get around to it, will continue that trend). I started with a monolithic CFC and refactored before adding each new round of functionality.
Sometimes attempting to both solve the basic problem before us at the same time as attempting to shoehorn design patterns into our code gives us writer's block. I can't count the number of posts on framework lists that say "How do I do X in framework Y?" when it's not totally clear that the poster could solve X outside the framework. My advice is always: implement X (away from the framework) and then refactor that code into framework Y. That way you're only solving one problem at a time.
Furthermore, don't feel forced to use design patterns "just because". They're intended as templates for solving problems you would have in your code - they are not solutions to business problems. Solve your business problem, then solve your code problem. Sometimes, you'll realize the cleanest solution to a given business problem will involve using one or more design patterns to create the code. Good for you - you just saved yourself a bit of refactoring.
Don't over-engineer your code either. Keep It Simple Stupid and You Ain't Gonna Need It are both reasonable bits of advice. Sure, sometimes a potential future enhancement is so blindingly obvious that refactoring in advance to support it is worthwhile.
And where does that leave frameworks? A lot of people argue that frameworks break the KISS / YAGNI principles - you don't need a complex XML config file, an MVC framework is overly complex for my simple app. Well, maybe, but think of the process of adopting the framework as just refactoring for maintenance. You might not need it for a one or two page app. You will need it for a hundred or two hundred page app. Refactoring a small amount of code to use a framework is a lot easier than refactoring a lot of code to use a framework. And a good framework won't get in the way - it won't really add any complexity. The tipping point is actually very low and the inherent complexity of a given framework is small in comparison to the likely complexity of your application.
At the end of the day, it comes down to what you feel comfortable with and how far you want to push yourself. Don't try to "boil the ocean" and cause your project to fail - don't try to learn a new framework for a tight deadline, mission-critical project. Use what you're comfortable with. After the deadline, look at refactoring the code to make future enhancements easier.
When you have an object model, you tend to use whatever types are most appropriate for the in-memory execution model, e.g., boolean. When you have a database, you use data types that are native to that particular database. In some (most?) cases, those will differ. Whose job is it to map between those representations? I hoped it would be obvious that the data layer (DAOs and gateways) 'own' that transformation but it appears to need re-stating:
It is the job of the data layer to perform the necessary mappings between the persisted database schema types and the in-memory object data types.
So a boolean in an object might be mapped to / from a varchar(1) 'Y' or 'N' value - in the DAO.
What about validation? Well, the DAO doesn't (shouldn't!) know anything about your business logic beyond knowing what in-memory data types you use. It might know a date of birth field is mapped to / from a datetime or date column but it doesn't care about valid date ranges or any such business stuff. Validation belongs somewhere in the business layer.
Now, whether you have smart beans with their own validation or dumb beans with external validation is up to you. The point here is that the business logic 'owns' the task of applying that validation to the bean before using the bean in additional business logic (and, therefore, before passing the bean to the data layer for persistence).
Here's an interesting use case tho': your application wants to store unvalidated data (because an object can be in many states, perhaps, and you're following a principle of enterprise robustness of persisting all the data you receive for audit purposes). By definition, this means your persistence model must support untyped (i.e., string) data. That also means your DAO must do no transformation. And that in turn means that it is the job of the business layer to decide whether the data is 'valid enough' to operate on. All the same, the business layer still owns validation (although it's now optional), the data layer still owns transformation (although it's now an identity operation).
The layers and responsibility are always the same. The details may change.
Here's the rub: most of our day-to-day ColdFusion applications are simple data entry stuff... display a form, user enters data, create a new entity from the form data... display a list of entities, user selects an entity, display pre-populated form, user changes some data, update the entity from the form data... we have an anemic domain model because, well, the domain model doesn't actually have any behavior!
Our controller loads beans to pre-populate the form and updates beans from the form data and persists the data. There's no behavior there. Our bean isn't smart - at best it might do a bit of validation for us. The controller isn't doing much either beyond orchestrating the CRUD operations on the bean.
We're caught between a rock (an example simple enough to explain in a few sentences) and a hard place (an example complex enough to show why we might use these patterns at all). No wonder some folks try to use these patterns (in simple apps) and can't see the point of it - and it can be hard to take the advice on trust that it's worth it for when your app grows.
Perhaps we need more KISS (Keep It Simple Stupid), YAGNI (You Ain't Gonna Need It) and XP-style refactoring?
Download my frameworks presentation and the accompanying code examples (see "Software" pod on my blog) and look at the first five variants as a progression from procedural to simple OO to refactored OO and see how it sits with your comfort level for such a simple application. The fifth variant has an anemic domain model because the domain is very simple - but consider how much easier that version would be to use as a basis for a much more complex task management app than the fourth variant....
Thoughts?
Martin Fowler voiced the opinion that he prefers the latter, using the term humane interface and he sparked something of a religious war between two factions. Check out the links he gives at the bottom of his post, especially to Elliotte Rusty Harold's piece on Cafe au Lait and James Robertson's response to Rusty which also has some very revealing comments.
Back when I was on the C++ Standards Committee, we had this argument about the string class. One group wanted a small, narrow API; one group wanted a broad, rich API. Neither side ultimately won so the class is a bit of a mess. It isn't quite a compliant container class (conceptually a string is a sequence of char) but it isn't quite an atomic string class either - it has bits of both. At my insistence, it does have both size() and length() however, for exactly the reasons that Martin Fowler mentions. In C++, size() applies to containers but most people are comfortable with length() for an atomic string. I fought hard for that change but I'm not - in general - a fan of large complex interfaces such as those Fowler would characterize as "humane". In fact I fought the addition of numerous "helper" methods for string (and failed to defeat their addition in many cases!).
Anyway, definitely some good reading for background on what people view as both good and bad class design.
They went through each of the major pattern collaborations in a Cairngorm-structured Flex app and emphasized the benefits of an event-driven architecture, using named, high-level business events rather than just the low-level click / drag type events in Flex.
The design patterns include Front Controller, Command, Service Locator, Business Delegate, Value Object and a Model Locator. Together they provide a powerful and compelling structure that makes it easy to scale applications as features grow. To demonstrate that, Alistair did a live enhancement to the demo application (the Cairngorm-structured Flex store) in just five minutes that would have taken substantially longer without a framework in place.
Definitely sparked my interest in doing more Flex development - and using Cairngorm!
Well, assuming your application is built with ColdSpring in the first place - which is reason enough to start looking seriously at using ColdSpring to assist in managing objects in your Model.
ColdSpring AOP lets you "re-wire" the objects in your Model so that your code ends up calling proxy objects (which in turn call your original objects), and the proxy objects can execute "advice" code before, after or around calling the original methods. This lets you add logging to all or any part of your application, simply by configuring the XML file that defines the objects that ColdSpring manages. Or security. Or...
Back in November last year, I posted an entry about data-driven design and pointed to responsibility-driven design which has essentially replaced it. Mark Kamoski just posted a (long) comment on that entry which points out, quite rightly, that a database is important and that some (many?) RDD evangelists speak as if the database can almost be ignored.
I just wanted to clarify that, yes, the database is an important part of most applications because, well, you need your data to persist and preserve its integrity. However, starting to design an application from the database tables forward to the UI is not going to create a maintainable, easy-to-use application. The UI is the most important part because that's what your users see and interact with. The interaction use cases drive the functionality your application must have. Those use cases should drive the design of the model, since it must support all the interaction use cases - and often more if you plan for growth and change. The model determines the data the application requires and that in turn drives the database design.
Database design is important. Your tables should not just be mere shadows of your objects. Objects (classes, really) are designed to satisfy dynamic interactions and represent a variety of entities and relationships in your domain. Databases represent those entities and relationships too but usually in a different form - due to normalization and efficiency concerns (or sometimes just the simple practicality of representing something complex using just columns and rows!). Therefore there is nearly always a mapping between object data and tables.
If you start with the database, that mapping will not be obvious until you get closer to the UI and that's the wrong place to do the mapping - you need the model first and that means focusing on responsibilities, not data.
So Simon doesn't like Fusebox and is already tired of it - after spending four days learning "all about it" so that he could give the talk at the conference... He thinks frameworks in general get in the way and wants to tell you about his methodology instead which "requires stronger application development skills" and if you think you can discuss frameworks with him, he says "I'm begining to care less and less as people continue to try and convince me".
I'm sorry I'm not going to the conference because I'd really like to talk to Simon more about frameworks and why he is so down on them. Like everyone else who has been involved in the discussion, I'm looking forward to seeing what Simon releases in terms of methodology and code since he believes it's so much better than what most of us are doing today.
I'm not tired of talking about frameworks tho' and I'll be doing just that on Friday at the Salt Lake City CFUG.
He also slips in a couple of common design patterns and explains them in very natural terms, showing how they benefit maintainability.
Make sure you also read his follow-up post about state management.
I may have additional comments once I've read all of that (and I may post them in his threads if I feel they're more appropriate to RIA discussions or I'll post them here if I think they're more appropriate to HTML application discussions!).
"One comment I saw in a news group just after patterns started to become more popular was someone claiming that in a particular program they tried to use all 23 GoF patterns. They said they had failed, because they were only able to use 20. They hoped the client would call them again to come back again so maybe they could squeeze in the other 3."
"... the truth is that almost none of us "pick up" OO in a few weeks or even months."
When I joined Macromedia, I joined as Senior Architect, part of a dedicated team of architects that were tasked with overseeing web infrastructure, data modeling activities, globalization issues, business processes and so on. I think there were seven of us, including our manager. She went on to set up a situation where all projects had to be approved by the architecture team and each project needed an architect associated with it to "tell them how to do things" (effectively). This was very adversarial, as you can imagine, and over time the team became rather unpopular.
She left, the team transitioned to a new manager who was more concerned with her program management team than her architecture team. The program management team folded and she left, leaving me in charge of the architecture team, which by this point had lost a couple of members - these were dot-bomb times.
I tried to integrate the architects more deeply into projects, making sure they were involved in implementation issues rather than just academic decision making. In the Summer of 2001, I formed the Web Technology Group and the architecture team disbanded, with architects being embedded in various IT teams.
Since then, various people have tried to resurrect the architecture team in various guises with varying degrees of success. As things stand today, we have a 'virtual team' - an architecture council that is made up of senior engineers from each division within IT. I chair the group and, after several experiments, we're now meeting only rarely but we keep each other informed of projects within our divisions and we discuss technical and architectural aspects of these projects whenever we need to.
This arrangement ensures that we're not an isolated 'decision-making' think tank - we're fully integrated into our primary teams - but it also recognizes the 'go to' people who need to be involved with complex projects and, in particular, cross-team projects.
We're still working out the kinks and learning from our mistakes. Read Hacknot and learn from the mistakes that Mr Ed has witnessed.
She gave some specific recommendations for dealing with untrusted collaborators: pass a copy of your data - don't share it by reference; after a request (to an untrusted collaborator), check that the request was actually executed (by calling some status test on the collaborator); employ alternate strategies when a request fails.
However, she also noted that redundant checks are a source of errors, inconsistency and brittle code as well as a performance problem. Don't fall into the trap of validating data that has already been validated for you.
Then she moved on to exception strategies and had some very good advice, including: name exceptions for what went wrong, not who raised it; recast the exception when you cross a boundary / abstraction level so that it makes sense outside the boundary (i.e., catch an internal exception and throw a translated, external exception). Some of the suggestions she had make me realize I need to revise the exception handling section of the CFMX Coding Guidelines!
Next up was Java's checked exception. Basically, they suck because they cause you to write reams of unnecessary code (see my other recent posts on this subject, referencing Bruce Eckel's articles).
Finally she covered a variety of strategies for robust handling of exceptions and called out the common practice of simply retrying operations: there's no point unless you really think the service state will change and a future operation will succeed!
Another key takeaway is that none of this is new but today's open standards (e.g., XML, SOAP) make SOA easier to achieve.
- Business layer only uses abstractions of technological services. 14/0
- Layers should be testable individual. 12/0
- Layers are a logical artifact that does not imply distribution between layers. 11/0
- Separation of concerns. 11/0
- Low coupling between layers, high cohesion within them. 10/0
- User interface modules should contain no business logic. 10/0
- Inbound external interface modules (eg web service handlers) should not contain business logic. 10/0
- Business logic layers contain no user interface and don't refer to user interface modules. 8/0
- Layers should be shy about their internals. 8/0
- No circular references between layers. 8/0
- Layers may share infrastructural aspects (eg security) 7/0
- Lower layers should not depend on upper layers. 6/0
Another good introduction is on Kennesaw University's website
Thanx to Jared Rypka-Hauer for the for the pointers to these articles.
Like I say, this stuff is hard!
Hal Helms touched on this in his "Bad OO" newsletter (which I also mentioned a little earlier).
If you're new to OO or struggling to come to terms with it, you should subscribe to his occasional newsletters. He started this current series with an article about bad OO design and in the second article goes on to examine what "customer" really means which is the heart of OO design (in this example).
Anyway, here's the list of links he sent me - read them through in order and see what you think. I hope it will increase your understanding of MVC:
- What was MVC?
- MVC as a J2EE pattern
- Implementing Smalltalk's MVC pattern
- More on MVC
- MVC really has two models
- MVC is not OO
Right now it's my one big criticism of both Mach II and Fusebox: they are geared very much toward an HTML presentation tier and it's really not easy to use either framework to build either a Web Services API or integrate it easily with Flash or Flex. Once Blackstone arrives, the pressure will increase because event gateways fit into the same pattern of needing a CFC-based way to interact with the framework - and get a well-defined result back.
Like it or not, knowing OO principles may help you get a job over someone who doesn't. Web development has grown up.
This question just popped up on the Fusebox forums but I figured my response there ought to get a wider audience.
Sally Shlaer and Steve Mellor are usually attributed with this approach which focuses on the data an object contains to drive the overall design. It was a relatively early approach to OO analysis and design and things have moved on quite a bit since.
Google turned up this nice little piece about it - see the original webpage (thanks to Scott Taylor for the updated link):
2.1 Responsibility-driven versus data-driven approachesIt is often said that data are more stable than functions and so data-centred approaches are to be preferred in most cases. However, one of the greatest dangers in adopting a method based too much on structured techniques is that of data-driven design. Two software engineers at Boeing (Sharble and Cohen, 1994) conducted an experiment with internal trainees with similar backgrounds. One group was taught the data-driven Shlaer/Mellor method of object-oriented analysis - a method consciously and deeply rooted in traditional entity-relationship modelling - while the other group was instructed in the Responsibility Driven Design techniques of Wirfs-Brock et al. (1990). The two groups were then asked to design a simplified control application for a brewery. The Shlaer-Mellor group produced a design wherein most of the classes represented static data stores while one class accessed these and encapsulated the control rules for most of the application: in much the same style as a main{} routine in C would do. The other group distributed the behaviour much more evenly across their classes. It was seen that this latter approach produced far more reusable classes: classes that could be unplugged from the application and used whole. It also demonstrated vividly that the method you use can influence the outcome profoundly. It is our firm conviction that data-driven methods are dangerous in the hands of the average developer and especially in the hands of someone educated or experienced in the relational tradition. Furthermore, We hold that the approach taken to requirements engineering can have a huge influence.
The study by Sharble and Cohen shows convincingly that data-driven methods do influence the thinking of designers and that they tend to produce un-reusable classes as a consequence. The usual effects are that:
In our commercial practice we insist upon or encourage responsibility-driven design and analysis. We will be concerned throughout this text to emphasize this in all we do, just as we shall stress adherence to the basic principles of object technology: encapsulation and inheritance. This is not the pedantic reaction of a purist but a stance of immense practical significance.
- behaviour is concentrated in controller objects that resemble main routines; this makes systems much harder to maintain due to the amount of knowledge that these controllers store about other objects;
- other objects have few operations and are often equivalent to normalized database tables: not reflective therefore of sound object-oriented design.
I made Joshua a Breeze presenter - his first time! - and he worked on the diagram while we all watched and discussed different design choices with him. Joe Rinehart (East Coast?) and Daniel Brown (New York) were active participants in this design session and also present was David Manriquez from Chile and a couple of others who were not posting so I assume they were away.
I've saved the entire chat log and the final XML from gModeler and will be writing up a more detailed entry of the discussion shortly (probably as its own page, rather than a blog entry).
At the end of the session, folks felt a lightbulb had gone on for them as far as OO modeling is concerned.
Overall, I think it showed the power of Breeze as a collaborative tool as well as just how gosh darned hard this OO design stuff really can be!
Many thanx to Joshua for being a Breeze guinea pig and to Daniel for extreme patience while we were playing devil's advocate and arguing with every suggestion!
What I want to draw attention to here is a key point in the conclusion of his Inversion of Control Containers review:
"In particular, I salute Howard for resisting attempts to twist HiveMind into something it's not - a rare quality, particularly in open source. HiveMind does (mostly :-) ) one thing and does it well."
Mike comments that PicoContainer looks like it followed the XP YAGNI (You Ain't Gonna Need It) principle and each new release seems to have haphazardly added those features which - guess what? - you did need them after all. He also comments that "Spring's just a bit took kitchen-sinky for me."
My point? Frameworks work best when they are cohesive, focused. That usually means tightly-controlled rather than being open source free-for-alls and it also usually means that the creator(s) started with a coherent vision of the whole.
So, when you're asking for Fusebox or Mach II to be opened up so y'all can contribute code, think about Mike's comments on why some frameworks work better than others.
Now, passing functions around as arguments isn't something that might spring to mind for many developers (unless you have a background in functional programming) but it is very powerful. And, guess what, you can do it in ColdFusion!
Yes, if you have a function argument with type="any" you can pass a UDF or a CFC method as an argument and then call the argument (function) that is passed in... I'll leave this as an exercise for you readers but if you get stuck I'll post a follow-up showing some examples!
When I put up some code examples in the Mach II Development Guide that used the Memento pattern as a simple way to pass data between the business layer and the persistence layer, some people assumed that was "the way" and just copied it wholesale. I removed the examples because - whilst they were representative of how certain persistence was done at Macromedia - they were not general best practice.
The same thing is true of DTOs - you'll see them used in relatively simple examples where they really add no benefit and then you'll see them used in code written by people who just copy the examples without learning about the pattern.
As Fowler says, patterns have two equally important parts: how to implement them and when to implement them. Most examples show the how but are not good representations of the when. So make sure you read up on the background of a pattern before you slavish implement it all over your code.
The classic "mixin" approach typically starts with an interface and a "common" implementation. Extensions to the model work by extending the interface and then implementing with a single class that also extends the common implementation class. Phew! You get a diamond-shaped inheritance diagram. You can see an extended example of this in part 4 of my compiler writing article (published in "Overload" many years ago).
Anyway, Laurence Middleton posted a comment on Robin's blog which points readers to an newsletter by Hal Helms on implementing Person-Role in ColdFusion. This refers to problems such as Employee-Manager where a lot of people mistakenly try to have Manager extend Employee instead of recognizing that Manager is-a Role and Employee (a Person) has-a Role.
Both Robin's article and Hal's newsletter deserve close reading for the techniques they discuss.
Is it really something new or is it just a buzzword for stuff we've known about for years?
In the latest (John and Ted, Round 3), John Cavnar Johnson makes a good attempt at defining a "service" (in the comments) which shines more light on the issue than most of what has gone before in the discussion and he shows just how much hype surrounds SOA when he says (in an earlier entry's comment) "I will grant you that much of what passes for SOA today doesn't live up to these principles, but I don't think that invalidates them".
Ted Neward quotes (with a little additional commentary) a post by Rockford Lhotka about Service-Oriented Architecture. Rockford offers some sanity checkpoints and warns of the potential for a train wreck. He's right that there's certainly too much hype around this topic (as there is around several other 'hot' topics these days). After all, cross-application integration isn't exactly a new concept and, so far, almost every attempt to standardize such integration has failed to deliver fully on the promises made...
Is SOA another case of the emperor's new clothes? In the context of being touted as a 'solution', yes I believe it is. If you treat it as a guiding principle (which, after all, is what an architecture should be), then it makes more sense. In other words, don't expect to buy "an SOA" off-the-shelf - but do expect it to cost you $$$ and be prepared to work hard on your business case. There's ROI to be had if you know what you're doing.
A recent question on the Mach II forum asked how to model applications with UML and there is, of course, no simple answer to that. The question has cropped up in a different form on the Mach II mailing list: "Can someone share some good examples of UML diagrams for planning my application?". The answer is not simple - what works for one person might not work for another because there is no "one way" to use UML...
For a long time, my UML tool of choice has been TogetherSoft's Control Center CASE tool. I started using it back in '97 (or early '98) when it was called Together/J. I've introduced it into every company I've worked at since then and for Java developers, it really is an impressive productivity tool - combining full visual (UML) software design with full EJB development and deployment, as well as software metrics and code auditing functionality. I introduced it to Macromedia back when I was part of the original Architecture Team and then the Web Technology Group picked it up to design and develop their applications. In fact, both Flash and ColdFusion developers use it, every day, to help them visualize their OO design.
And now I'm using it again. On a Mac. Even tho' we're still using version 5.5 (we weren't doing enough Java development to make it worthwhile upgrading) which was Windows-only. But it's a Java application and so, likely many pure Java apps, it can be persuaded to run on pretty much anything. I installed it on Windows 2000 using Virtual PC and simply copied the installation back to my Mac file system and tweaked the startup script to match the OS X Java install (the Windows install comes with both
.bat and .sh startup scripts). I'd forgotten how much I enjoyed using UML! I love how consistent the notation is and how you can describe systems at so many different levels, no matter how complex they are. And I love Together Control Center - I've tried a lot of different UML design tools but I keep coming back to this one as the most intuitive and most useful. I particularly like the integration of design patterns and refactoring tools and, when I'm using Java, the code audits and metrics.
TogetherSoft was bought by Borland a while back. You can find out more about the product on Borland's Together Control Center website.
Just read your comment on Ben's site. There are certainly cases where custom tags can still be used in Mach-II and Fusebox. I was actually asking whether people felt that by putting business logic into CFCs and common display into customtags, we can get away from using any kind of framework because all the real hard stuff is completely separate.This raises an interesting question about the nature of frameworks: are they really there to handle the "real hard stuff" in an application design? My sense is, no, they exist to provide a standardized way to structure your application and, to some extent, provide certain common low-level functionality. The "real hard stuff" in my opinion is designing the right (business) model objects.
I used Fusebox 3 when that was common, warts and all, because it seemed quite popular and worked in our case. I'm uncomfortable with Fusebox 4 - even though it is very *very* fast - as the XML syntax just seems really messy. Those condition tags look nasty :), and it doesn't really integrate with CFCs that well. I know it can be done, but doesn't look like a snug fit IMO. I welcome being convinced otherwise.I'm not going to take on the Fusebox question here except to say that Fusebox 4 seems like a good upgrade path for Fusebox 3 - it provides performance benefits, it replaces the nested layout model with a more flexible system and it clearly delineates what logic should be in the "fusebox" by using a well-defined set of XML commands instead of allowing developers to put arbitrary logic in their switch files. Fusebox (both 3 and 4) work for a lot of people because it provides structure.
Mach-II looks good too, but sometimes feels like an overkill. I don't know if it's really necessary for a web application. However, it works very nicely with CFCs, is buzzword compliant, and seems to becoming the de facto standard.I'm naturally pleased that some people see Mach II as a developing de facto standard. I'm surprised Tony thinks Mach II is overkill - it's about as lightweight a framework I've seen that still does something useful.
In the Java-world, I used a framework known as Webwork, which is incredibly simple and powerful. It just made sense to me, and I'd recommend anyone doing J2EE development to look at it in place of Struts. I'm really after a CF equivalent.I hear good things about Webwork but Struts appears to be the de facto standard in the Java world (and increasingly looks very compatible with JSTL and JSF as they emerge). My feeling is that Struts is unnecessarily complex, albeit very powerful. I don't know enough about Webwork to comment on it directly, but I'd say Mach II is substantially less complex than Struts and, from what I've read, about in line with Webwork.
Erm, this is a long post :) but I'm just wondering whether by putting all the business logic in CFCs and with plain old .cfm pages being so simple anyway, is there any benefit with using a framework?Well, if Webwork provided value because it was a Java framework and, presumably, Fusebox 3 provided value because it was a ColdFusion framework, then I'd say that question is already answered - good frameworks add value and therefore they are worth using (on all but the smallest projects). I find myself using Mach II for pretty much any ColdFusion project now - even simple, "one-off" things - because it provides a simple, standardized structure that allows an application to grow and because it helps reduce coupling between components.
I remind you, this isn't a theoretical question - I have to make a decision soon, so my livelihood depends on the replies! Haha :)Hopefully, this answer is useful and will draw further answers from other folks as comments on this entry!
Sometimes I feel very wary about dissing something that a lot of very smart people obviously think is a good thing, so I was heartened to read Martin Fowler making somewhat disparaging comments about MDA. Now, I'm quite a fan of CASE tools but only when they genuinely support your development lifecycle and make you more productive - hence my support over the years for Together Control Center with its simultaneous round-trip (re-)engineering for Java code. It's a CASE tool that can be used as a Java IDE. I don't adhere to the manifesto that you need to model everything in your application however and so, like Fowler, I tend to use UML as a sketch. To use MDA effectively seems to mean rigorous modeling with UML which in turn seems overwhelming to me, especially with talk of UML 2, and that just seems to 'price' MDA out of consideration for many folks in the trenches. If you've used MDA successfully, feel free to disagree...
You can refine this architecture somewhat further by splitting the business tier into three more tiers, which I would call: business-presentation, business-facade and business-model. The business-model tier contains the generic business logic for your application (that does not depend in any way on the presentation technology). The business-facade tier provides a Web Services or Flash Remoting interface that exposes key business methods from the business-model tier. The business-presentation tier is in Flash and provides a controller / manager layer for the UI (presentation tier) to use, wrapping the calls to the business-facade tier.
If you need both a Flash version and an HTML version of your application, you can write two presentation tiers (one Flash, one .cfm ColdFusion pages) and two business-presentation tiers (one ActionScript, one Mach II / CFCs) and then reuse the business-facade (CFCs), business-model (CFCs) and lower tiers. If you don't need the RIA, you can collapse the business-presentation tier (Mach II / CFCs) and the business-facade tier (CFCs). It's still worth keeping the business-model tier separate tho' (as discussed in the Mach II Development Guide).
For more information on n-tier architectures, you can read these articles:
- Application Architecture: An N-Tier Approach - Part 1
- Benefits of Using the N-tiered Approach for Web Applications (about ColdFusion)
- Extending Design Patterns into RIA (about Macromedia Flex)
- Macromedia Flash Communication Server MX Application Model


