Avoid Refactoring Yourself Into a Corner

We have developer meetings twice a week at work, and we use these as a forum for people to show things they’ve been working on, ask for advice on how to approach solving a particular problem, share cool tips and tricks they learned, etc. This has been working really well and fosters what I think is the most important aspect of any development team: learning from each other. Regardless of the various skillsets and experience levels on a team, people have different areas of expertise and I learn something new or start thinking about something differently at every one of these meetings.

Today’s meeting was particularly interesting and since it’s not an uncommon situation, I thought I’d share a bit about it. A co-worker has been working on an application for the past few months and this application has a very hard deadline. Without going into all the specifics, based on the client’s own description of how things should work, this is a person-centric application, meaning everything in the application revolves around data associated with an individual person. Each person has basic demographic data but also a minute-by-minute timeline associated with them, and this timeline consists of events that may either be unique to the individual person or may be inherited from a parent group that is used to organize individual people.

We’ve discussed this application quite a bit at our developer meetings lately because it’s been an interesting exercise in developing with Mach-II, but more importantly it’s been a great case study for effective domain modeling in an OO application. It’s simple enough that it’s not overwhelming from a learning standpoint, but it’s also complex enough and has some interesting wrinkles that take it well beyond the level of the basic OO applications that we’ve likely all studied or seen in conference presentations a thousand times. It’s been great because even the people not involved with the application are learning a lot through the discussions at the developer meetings.

The basic overview of the domain model is there is a Person object, which is a typical bean, and one of the attibutes of a Person is their timeline, which for ease of use and efficiency is a query object. When a Person is instantiated they get their timeline, which is created from events explicitly associated with that individual person and potentially events they may inherit from their group timeline. This works very well in dealing with individual people and their individual timelines.

Just recently a new person on the client side was added to the mix. (If you’re saying “uh oh” at this point, you know where this is going.) This person looked at the application and from her perspective, everything was backwards. Because of her concerns with the data being managed by the application, it shouldn’t be person-centric, but rather should be timeline-centric since her role in things is to be focused exclusively on the high-level aggregate timelines as opposed to the timeline of any individual person.

Natually this was a bit of a “D’OH!” moment. While it would have been nice to have this perspective from the outset and potentially would have changed the approach taken in building the application, the reality of the situation is that we have to get the application done very soon and we have to satisfy the new requirement in order for the application to be useful. Such is life as a developer.

Since the application has been to this point entirely person-centric, my co-worker was going down the path of thinking of aggregate timelines as a grouping of all the individual timelines, which on the face of it might not seem like a bad approach. The issue is that there are a minimum of 1500 individual timelines with a potentially large number of events per timeline, and since they may change extremely frequently, caching isn’t a realistic option. Obviously instantiating 1500 objects just to get at query data would be a nice way to bring the server to its knees rather quickly.

Another great aspect of developer meetings is the chance to get a completely fresh perspective. It’s easy when you’re neck deep in an application to have your thinking get a bit rigid and not be able to see the numerous other ways in which the problem you’re facing might be solved. So you start going down straight-line path you see in front of you and figuring out ways to tweak what’s already there to handle a new requirement that may well be the antithesis of what your domain model was originally designed to address.

My co-worker described this situation as “refactoring himself into a corner” and I think that’s a really apt description of what tends to happen in these situations. Partciularly given the recent discussions about all things OO in the CFML world, this seemed rather timely because my co-worker was thinking all about the objects and the domain model and not about the data. I know, you can probably quote me from any number of my conference presentations saying that’s the way you should think about things, and I stand by that … for the most part.

In this situation, however, what we’re really after has nothing to do with the domain model (well, little to do with the domain model at any rate … more on that in a moment) and everything to do with reporting on aggregate data. These are two completely different ways of looking at things, and going down the object path when what we really want to do is produce a report starts to feel wrong rather quickly. If something feels wrong don’t ignore that feeling, because it probably feels wrong for a reason.

Luckily since my co-worker did focus on the domain model so thoroughly in the initial design of the application, the data itself was all nicely organized in the database. This was really is a side-effect of the domain model design as opposed to a data-centric approach to building the application. (Not enough time to go into detail on that point so I hope it makes sense at a high level.)

With the data sitting in the database, why worry about the Person side of things and all those objects? My suggestion was to forget about all that and focus on the end goal of what we need for the timeline/reporting side of the application. Clearly for Person and individual timeline management what has already been developed is important and will continue to be used as it always has been, but timeline reporting is a different requirement and needs a different approach.

Once you throw all the person-centric bits out the window it becomes a lot more clear. The data’s in the database, so rather than thinking of an aggregate/master timeline as being made up of individual people, why not just leverage the database to do the reporting? Maybe this calls for a view to be created, or maybe it’s a rather simple query/stored procedure, but since what we want is a big list of data, creating that from a huge number of individual objects just doesn’t make sense.

Now that doesn’t mean that OO goes out the window completely. Since this is a Mach-II application, chances are this will mean a Listener, a Service, and a Gateway in front of the raw SQL that does the reporting, which means the reporting functionality will integrate nicely right alongside the person-centric part of the application that’s already done and working well. More importantly, it gets down to using the right tool for the job. Databases are (shocker) great at managing data, so putting that work in the database will not only make things a lot more efficient than shoe-horning all the individual beans into a construct where they don’t belong, it just makes more sense overall. In short, think in objects unless you shouldn’t. 😉

I’m not sure there’s a real moral to this story other than to point out that when you feel like you’re refactoring yourself into a corner, stop, take a deep breath, and force yourself to think about things differently. Throw out all your preconceived notions and if that’s difficult, grab a team member or three and talk through the problem with them. It’s almost better if they don’t know much about your application because they won’t have the mental baggage that you do about things, and won’t have any concept of how much rework is involved to implement their approach. And once you have them sucked in you can always get them to help you build the missing pieces!

Comments

Nice! 🙂 That notion of having “baggage” that keeps you from seeing the simple solution applies to much of life. I don’t have any URLs handy right now, but I know that there’s been at least one study that shows that the more experience a person has in a given field, the less able they become to learn new or different approaches because there’s so much reinforcement behind the techniques they’ve already learned.

And in this case also dovetails rather nicely into a comment Adam Haskell made a while back about one of the nice things about Fusebox being that you don’t have to write objects for things like a report page where there’s not much behavior going on.

Posted by ike @ 11/4/08 12:36 PM

Very good read. I think the comment near the end sums up my feelings:

“More importantly, it gets down to using the right tool for the job.”

If refactoring is the tool that is called for, so be it. Just know that it isn’t the tool *in every case*.

Posted by Shawn Holmes @ 11/4/08 2:21 PM

Great piece, and definitely not a rare situation. Think it bears pointing out that just because the solution isn’t going to be use of the existing objects in the existing domain model, that doesn’t mean the solution isn’t going to be OO. As you noted, the solution to the aggregate reporting is still going to be handled in MachII. The issue really is that the domain model is being extended, right? Because it’s a new requirement, it can be handled by a new domain model, a set of objects that just happen to consume the same data as the original app is already capturing.

I think that can be such a key as well: simply understanding when a change really does impact an existing requirement and when it doesn’t. Often the ability to extend your model to add a B option to your existing A option is entirely reasonable, and that ability to extend without destroying is one of the biggest benefits to OO modeling.

Posted by Jason Fisher @ 11/5/08 5:34 AM

As I am trying to dive deeper and deeper into OO, I am definitely seeing that there is a serious difference between what one might consider as being part of the domain model and one might consider to be reporting.

Not too unlike your scenario, I was going through a thought-experiement in which I imagined a Library object. And I asked myself, Should object have a GetBooks() method that returned a collection of all books in the library (potentially millions of objects).

While months ago I might have said YES, I understand that this is a bad idea. Yes, this would probably crash the server, but that is not what actually swayed me. What made me realize the absurdity of such a method was the question:

Would this collection of data be more useful as objects rather than as a report?

When I was challenged to come up a feasible use case in which I would need to affect millions of objects, I realized that this is data that should be report oriented.

Then, I also came to the realization that there is a difference between domain-based actions and “bulk” actions. If I wanted to increase the price of all products in an ecommerce store by 10%, I certainly would instantiate each product, update the price, and then save it. I think what would make more sense is to have some object (maybe a gateway or a service) have methods that allow for bulk actions.

Posted by Ben Nadel @ 11/5/08 2:48 PM

What’s So Funny ‘Bout Peace, Love, and Understanding Design Patterns?

There have been some rumblings the last few days about the use of design patterns in the ColdFusion world, all of which seem to have been prompted by Brian Rinaldi’s post on the Gateway pattern and its use (some say misuse) in ColdFusion. As usual with things of this nature the discussion got rather heated so I thought I’d add some fuel to the fire. The building’s burning down anyway, so what the heck. Actually I love discussions like this because in my opinion anything that gets people this riled up is a good thing. When you question aspects of development at a very fundamental level you either come out of it with a completely different view, or it strengthens your beliefs in the way you’re already doing things. Either way much is learned through the process.

In any discussion of design patterns, we must first turn to The Holy Book of Design Patterns, namely Design Patterns: Elements of Reusable Object-Oriented Architecture by Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides, a.k.a The Gang of Four, The Four Wisemen, or the Four Horsemen depending on your perspective. I don’t think the Biblical comparisons are necessarily misplaced because, like the Bible, this book has many companion books that attempt to explain what the heck the contents of The Book actually mean, the most popular of which is Design Patterns Explained: A New Perspective on Object-Oriented Design by Alan Shalloway and James R. Trott. My copy even has one of those fancy attached ribbon bookmarks in it just like many Bibles. Also, as with religion people get extremely passionate (perhaps unnecessarily so–it’s just software after all) about their design pattern beliefs which makes the conversation all the more interesting and in some cases more than a tad bit irrational. Fun stuff.

As a backdrop for this discussion, I’d like to offer up the very first sentence in the introduction of the Gang of Four (GoF for short) book. I do this as a means of ensuring that none of us thinks there is a quick, simple answer to any of this.

“Designing object-oriented software is hard, and designing reusable object-oriented software is even harder.”

Now that we know we have an arduous task ahead of us, let’s get started with the discussion at hand, the shot heard ’round the world, namely the now-infamous Gateway pattern.

So what is a Gateway?

I think Brian covered this pretty well, and he made some very good points about how “Gateways” in ColdFusion don’t necessarily need to be the same thing as Gateways in Java, .NET, or any other language. I do find it funny that some of the same people that are saying ColdFusion shouldn’t become Java seem to get bent out of shape that we aren’t implementing Java-based design patterns exactly the same way in ColdFusion as they exist in Java. I suspect this may be a semantic argument at some level (how about we call the ColdFusion implementation of this pattern DataSucker and move on?), but I digress.

Many ColdFusion developers, myself included, use objects we call Gateways to encapsulate access to a database table, specifically to retrieve multiple records (meaning methods will typically return either query objects or collections of beans) from specific database tables. Is this a bad thing? Does it violate some commandment that states what a Gateway is? Let’s investigate.

To understand what a Gateway is, let us crack open the GoF tome. (Come on, admit it, you bought this book a while back but the binding still cracks when you open it. Mine sure does.) Turn to the index at the back of the book and look for the word “Gateway.” Nothing in your copy? Mine either. Must be a misprint. Let’s try “Table Gateway,” because I think I saw reference to this pattern using that name somewhere. Hmm … nothing there either. My point, specious as it may be, is that the word “gateway” isn’t even important enough to appear in the index of the Bible of design patterns. Either that or they hired a really cut-rate indexer.

We’re going to have to look through the entire book ourselves to find the mention of “Gateway” apparently. Go ahead. I’ll wait.

Didn’t find it? Didn’t think so. Me neither. That’s because–surprise!–it’s not in there. Why not? Well, my own personal theory is because the GoF are higher-level thinkers than something so specific as a Gateway as they’re currently implemented in any language. That being said, the Gateway pattern isn’t necessarily as concrete as many of us make it, but we’ll address that in a moment.

First, in the absence of any mention of Gateway, let’s look at an example of what the lofty GoF do consider to be a pattern important enough to be included in their revered book. I’ll just choose one more or less at random.

“Pattern: Bridge. Intent: Decouple an abstraction from its implementation so that the two can vary independently.”

Based on that definition, if I told you to go build a bridge right now could you do it? If you say “yes,” you’re either reading far too much into the pattern, you’re way smarter than I am, or you thought I meant for you to build a bridge for your Matchbox cars out of popsicle sticks. I suppose my point is that, in the GoF book at any rate, design patterns are so high level that while they’re very useful, the say nothing about any specific implementation details. If we could find the word “Gateway” in the GoF book, chances are it wouldn’t say anything about hitting database tables, what data types the methods should return, or anything of the sort. Their “intent” description for Gateway, if I may be so bold as to put words in their mouths, would likely be something like “Enapsulate access to an external resource.” Keep that high-level definition in mind because we’ll come back to it.

The GoF book does provide examples to accompany all their patterns, but remember these are examples that are designed to illustrate one potential implementation of the high-level design pattern. Furthermore, the examples provided are in the context of building a desktop document editor in Smalltalk. In my opinion their examples shouldn’t be (and I’ll go so far as to say weren’t intended to be) taken as gospel. The authors wisely provide examples because, as we see with the Bridge pattern, it’s a very lovely pattern but doesn’t become very concrete in the mind of developers until we see an example. Examples are indispensable to shedding light on the abstract intent statement of the design. But again, this is an example, not the example.

This brings to mind a bit of an aside, which is one of the key problems I have with the recent posts by Sean Corfield, Peter Bell, and some of the comments on Kola Oeydeji’s post (that itself was a response to Brian’s original post), namely that they seem to stop quite a bit short of being useful in any practical sense. Saying “people need to review things more” or “I do things completely differently” or “this is a pet peeve of mine” doesn’t illuminate anything. I know, we’re all busy people, but a specific example such as “I don’t use a gateway that way–here’s what I do” with some concrete details would add far more substance to the discussion.

I suppose these comments are useful in the limited sense that they urge us to think about what we’re doing. That’s fine as far as it goes. I think a lot about what I’m doing, however, and I personally find using the Gateway pattern as it has come to be implemented in ColdFusion by numerous developers quite handy. I like it. It’s cohesive, it’s easy to explain to others, it serves a clear purpose, and has a clear intent. Saying “but it’s not really a gateway” doesn’t much help the discussion, other than to cause the people who use this pattern and call it a “gateway” to defend their use of it, which as I mentioned at the outset of this post is actually useful for the purposes of facilitating discussion. Will I change my thinking on this in the future? Perhaps. It’s certainly happened before. The “it’s not really a gateway” comments don’t, however, tell me why I shouldn’t use it in this way except in an academic sense, and the validity of the academic argument itself is pretty dubious as well see momentarily.

This brings us back to the question concerning what a Gateway is. Since it’s not in the GoF book we have to look elsewhere. The obvious next avenue of investigation in my mind is Martin Fowler.

Gateway: A Definition From the Book of Fowler

For whatever reason, unlike the GoF, Fowler does grace us with a definition of Gateway, which comes from his book Patterns of Enterprise Application Architecture. I have to pat myself on the back just a bit, because Fowler’s definition is remarkably similar to the one I came up with above:

“An object that encapsulates access to an external system or resource.”

As we read on, things get even more compelling:

“Interesting software rarely lives in isolation. Even the purest object-oriented system often has to deal with things that aren’t objects, such as relational data-base tables, CICS transactions, and XML data structures.”

Relational database tables! Now we’re getting somewhere. At a high level this definition, which would be the “intent” section of the GoF book, seems to fit with getting data out of a database, and he goes so far as to give the scenario of retrieving data from a relational database as one possible implementation of this pattern. So far so good. I think at this point we can all agree that an object that retrieves data from a database, at least in Fowler’s view, is a perfectly legitimate implementation of the Gateway pattern.

Like the GoF, however, Fowler doesn’t drill down into specifics just yet. As we look further into Fowler’s pattern definitions we see that there’s another instance of the word “gateway” in his pattern definitions, specifically a pattern called the Table Data Gateway, which he defines as follows:

“An object that acts as a Gateway [he references his more generic Gateway pattern here] to a database table. One instance handles all the rows in the table.”

So now we see what I consider to be a more specific instance of the generic Gateway pattern. A Gateway merely “encapsulates access to an external system or resource,” while the Table Data Gateway pattern explicitly defines the “external system or resource” as a database table. Again, there is no real discussion of the specifics of how the Gateway achieves what it does, but Fowler does provide some sample methods that might be contained in a Person Table Data Gateway such as find(), findForCompany(), insert(), and update(). Pay particular attention to the insert() and update() methods, because they’re key to the discussion that follows.

To summarize where we are at this point, we now know that the Gateway pattern (more specifically the Table Data Gateway pattern) is indeed a perfectly acceptable way to encapsulate access to a relational database. This of course isn’t the only way to do things, however, so now we’ll examine an alternative pattern, compare and contrast, and discuss how the two might not be mutually exclusive.

Data Access Objects (DAOs)

The other pattern many of you may have seen referenced in your OO trials and tribulations is the Data Access Object (DAO) pattern. The most thorough description of the DAO that I’ve come across, and the one to which most people point when they’re discussing this pattern, comes from Sun’s “Core J2EE Pattern Catalog.” So how is the DAO pattern different from the Gateway pattern? Let’s take a look.

After describing the issues with data access in general and the goals of abstraction and encapsulation, Sun’s proposed solution is to “use a Data Access Object (DAO) to abstract and encapsulate all access to the data source.” Sounds an awful lot like the Gateway pattern, doesn’t it? Sun’s definition continues, “The DAO manages the connection with the data source to obtain and store data.” So the basic idea is that the DAO encapsulates database access.

As a point of comparison, let’s prepend the term “DAO” to Fowler’s definition of the Table Data Gateway pattern:

The DAO is “an object that acts as a gateway [lowercase mine] to a database table. One instance handles all the rows in the table.”

Even by combining the two we see that the general definition remains consistent. So at this point, and considering things only at a high level, the Table Data Gateway pattern and the DAO pattern are essentially the same. They both are defined as objects that encapsulate access to a database table, so it’s really just a difference of nomenclature. Furthermore, if you scroll down to some of the examples that Sun offers on their DAO definition page, they also show methods that deal with both single and multiple records, meaning that just as with the Table Data Gateway, you see both an insert() method, which deals with a single record, and a selectCustomers() method, which handles multiple records, in the DAO.

Table Data Gateways vs. Data Access Objects (DAOs)

At this point you might be confused. Don’t worry. Whether or not everyone admits it, you’re not alone. To review, at this point both the DAO and the Gateway, from a pattern standpoint, serve exactly the same purpose. They both encapsulate access to a database.

So why in many ColdFusion applications do we see both Gateways and DAOs, for example both a PersonGateway and a PersonDAO? To review something I mentioned above, the Gateway pattern is used by many ColdFusion developers to contain methods that handle multiple records. The DAO, on the other hand, is used in many ColdFusion applications to deal solely with single records; many ColdFusion DAOs contain only create(), read(), update(), and delete() methods (affectionately referred to as “CRUD”). To elaborate, in this scenario the PersonGateway would contain methods such as search(), getAll(), and other methods that return multiple records. The PersonDAO would contain the CRUD methods and typically nothing else.

Since in the canonical sources mentioned above (i.e. Fowler and Sun’s pattern catalog) the Gateway and DAO are in essence the same thing, where did this distinction in the ColdFusion world originate? I know specifically where it originated for me, and likely for many others as well: the Macromedia Mach-II Development Guide. Since Mach-II was the first fully OO framework for ColdFusion, I suspect that many others (like myself) learned not only Mach-II from this resource, but the relevant OO patterns outlined therein.

Because in my opinion this particular point is so tremendously pertinent to the discussions happening in the various blogs mentioned above, I’m going to quote the relevant section from the Mach-II Development Guide nearly in its entirety. This is not intended to point any fingers at anyone, least of all Sean Corfield who authored the original Mach-II Development Guide, but I do think it answers the question of where the distinction originated for many ColdFusion developers, myself included.

— Begin quote from the Mach-II Development Guide —

There are two basic patterns of access to persistent data within most applications:

  • aggregated access – reporting, searching, listing multiple rows,
  • per-object access – creating, editing, working in depth with a single row (object).

ColdFusion has a great built-in idiom for dealing with the first type of access  – the query – which is an efficient way to manipulate (potentially large) sets of data rows retrieved from a database (or other data sources, since you can easily create a query object and populate it with your own data). When you are dealing with aggregated access, it does not make sense to convert every row returned into a fully-encapsulated object (CFC instance) when all you are likely to do with the data is display a few fields with a link to a detail page that will focus on the selected row.

On the other hand, when you are focusing on a single row it usually does make sense to work at the fully-encapsulated object level since you are usually interested in object behavior at that point. This is also the level where you need the standard CRUD (Create, Read, Update, Delete) operations.

Recognizing these two basic patterns, you should design your components accordingly by providing separate components for each pattern. This is best explained through an example:

  • If we have a business model object called Order, then we would provide an OrderGateway component for aggregate access and an OrderDAO component for per-object access (or build the per-object access into the Order object – but see below).
  • The OrderGateway component would provide methods like findAll(), findWhere(), findByID() and they would all return standard query objects (even findByID() which returns a single row).
  • The OrderDAO component would provide CRUD methods like store(), load(), update(), delete() and they would operate on a specific Order object exchanging data via getters/setters on the Order component or via some sort of snapshot of the Order’s data, e.g., a bean: the Order component could implement methods like getSnapshot() returning a bean and setSnapshot() taking a bean as an argument – the bean containing the core persistent data for the Order object. Sometimes a more direct data transfer between the business object and the data access object is needed for performance reasons (or because the application can ‘trust’ the components to exchange less encapsulated data, such as a struct or some opaque data structure e.g., the Memento design pattern). Such optimizations are beyond the scope of this document.

Separating out these operations from the business model object helps it stay persistence-neutral. The gateway components can be optimized for retrieving large record sets, caching etc. The DAO components can be optimized for dirty data updates, pooled object access and so on. Again, the details of these optimizations are beyond the scope of this document but providing for the two distinct patterns of data access will get you started on the right road.

— End quote from the Mach-II Development Guide —

To reiterate, the sole purpose for the inclusion of this quote is to point out where I suspect many ColdFusion developers got the idea to separate Gateways from DAOs in this way. Given the recent blog posts and comments, clearly Sean thinks differently about these things now. That’s perfectly fine. If we stop thinking about things and changing our minds about things, we stop increasing our knowledge and may as well find another line of work. I personally want to thank Sean for creating this guide not only because I learned so much from it, but because it served as a fantastic foundation on which to base an updated version of the Mach-II Development Guide (forthcoming) for the newer versions of Mach-II.

Also bear in mind that Sean’s intent with this guide was not, I assume at any rate, to attempt to provide ColdFusion developers with a design pattern Bible that should be followed to the letter, so it is incumbent upon all of us to study the design patterns on our own and make up our own minds about them. For me, the Mach-II Development Guide was a great starting point for my learning process. I’ve since learned a great deal more about numerous other design patterns and OO concepts, and I continue to learn more every day. Remember: this stuff is hard to begin with, and doing it well is extremely difficult. If we keep doing things the same way and don’t change our minds about things as we increase our knowledge, then we’re standing still as developers, so we shouldn’t see it as an error or failure on anyone’s part if they said something on their blog three years ago that they no longer agree with.

But Aren’t You Doing It Wrong?

Given everything I outlined above, specifically how both Fowler and Sun illustrate that methods dealing with single records and methods dealing with multiple records coexist in either the Table Data Gateway or the DAO design pattern, why do I still split out my data access methods into two separate objects? In short, because I can.

Blasphemy! Well, it’s actually not only because I can. It’s because I like to, and given Joe Rinehart’s recent blog post entitled “Defending the Gateway Pattern in ColdFusion,” apparently I’m not the only one.

Maybe this all stems from me latching onto Sean’s description from the Mach-II Development Guide at a formative stage of my OO ColdFusion development, but as my knowledge has grown I still think there’s a tremendous amount of validity to using the Gateway pattern for multiple records and the DAO for single records. No, you won’t find any real justification in any fancy books, but in my own real-world development I completely agree with Joe. It’s served me well, I’ve never seen any negative impact by doing things this way, I like the separation of the two concerns, and no one’s convinced me that it’s wrong to do things this way. Even if there are valid arguments to the contrary, they’re still just academic, because the bottom line is these patterns work and continue to work well in many of my applications.

Now I’ll get extremely geeky (and getting geeky while writing about OO design patterns is no small feat!) and quote one of my all-time favorite shows, The X-Files:

Deep Throat: “Mr. Mulder, why are those like yourself … not dissuaded by all the evidence to the contrary?”

Mulder: “Because all the evidence to the contrary is not entirely dissuasive.”

Ah, such wisdom from my hero of the 1990s. So why is this seemingly random quote appropriate? Because even given the definitions of such giants of the design pattern world, I’m not convinced that separating data access into two objects is “wrong.” Conversely, I’m definitely not convinced that taking these two separate objects and combining them into one is the right thing to do. Many of my thoughts echo what Joe already said, but I’ll put them in my own words and expand on them a bit.

First and foremost, I like knowing that my DAOs deal with CRUD and that’s it. Once those objects are done they’re done, and these types of objects are also fantastic candidates for code generation precisely because they are so singular in purpose and prescriptive in nature.

Gateways, on the other hand, are far more nebulous and end up changing much more during application development. CRUD operations are easy to define. As you build out an application, however, typically you’ll find yourself coming up with methods that need to be added to the Gateway that you didn’t know about at the outset. Maybe the requirements change as the application evolves, maybe you figure out different or better ways to do things, who knows. Regardless of the reason, in my development I find that I add, remove, and alter methods in my Gateways pretty regularly right up until the application is complete. My DAOs, on the other hand, are built at the outset and they just sit there doing their job.

I also like knowing that when I call methods in my DAOs, they take in an instance of the object with which they are concerned (i.e. the bean) and don’t return anything since they’re operating directly on the objects passed in. Gateways, by contrast, typically return query objects or, when necessary, collections of beans. It’s been lamented in some other recent blog posts that if we don’t return a collection of objects, again we aren’t using this pattern “properly.”

Says who? Fowler? Sun? Now maybe in Java the convention is that you return a collection of objects, but this is ColdFusion, not Java. In ColdFusion we have a wonderful little object called a query that is extremely efficient and darn easy to use. So why not use it? If all I want to do is loop over a query and display the data, and I don’t need to interact with each individual object, why on earth would I make things more complex and less efficient just so I’m better meeting another technology’s definition of how a Gateway is supposed to behave? Pure nonsense. When I need to deal with each individual object in an aggregate dataset, I can quite easily return an array of CFCs. When I don’t need to do that, I won’t bother. Some call that bad programming; I call it practical.

Some might argue that having two objects where one will suffice is a bad thing. In one of Sean’s comments to Kola’s blog post, he makes the point that by combining some of the concerns via “responsibility-driven design” as opposed to “data-driven design” (I take issue with calling the way I do things “data-driven,” but I’ll leave that for another post), that he winds up with “28-46 CFCs + Transfer compared to 100-150 CFCs which the ‘5:1’ process [meaning controller, service, bean, DAO, and gateway for each object type in the system] creates.” In some cases less is more. In OO design this argument doesn’t necessarily hold water. First of all, Transfer eliminates the need to create many of these objects because it does it for you. They still exist in some form or another, it’s just handled by Transfer.

Regardless of the details, I personally would rather have more objects with fewer methods in each as opposed to fewer objects with more methods in each, and worse, methods that may not be as related to one another as they are in smaller, more cohesive objects. I realize I’m speaking in generalizations a bit here, but I hope you see my point. The “work” of the application needs to be done somewhere. Fewer objects doesn’t necessarily mean you’re saving any work because if the applications behave the same and contain all the same business processes, then in general terms the same work has to get done regardless of how you organize the objects.

There are also those who believe that based on the strict definition of these design patterns, or maybe just their personal preference, that there should be a single Gateway or DAO as opposed to both existing and serving different purposes. In my mind there’s nothing wrong with that approach, it’s just not my preference. Again, if the only argument is “fewer objects means easier maintenance,” that’s not a valid argument in my opinion. Either approach will achieve the goal of abstracting and encapsulating data access, I just prefer having slightly more cohesive objects, and Mulder’s statement holds true: all the evidence to the contrary is not entirely dissuasive.

If I’m Doing It Wrong, I Don’t Want To Be Right

Maybe that’s overstating my case a bit, but as of the time of this writing I still like having both a Gateway and a DAO in the mix, and I have yet to see a convincing enough argument to make me change my mind. Maybe I will at some point, or maybe I’ll figure out another way to handle all this that I like even better. Then everyone can point out how gosh-darn eloquent and convincing I was in this post and call me a flip-flopper. I see a career in politics in my future.

I think the biggest problem I had with the recent discussions occurring on the various blogs I mentioned earlier is that many developers who haven’t been working with these concepts very long, and particularly those who are just getting into OO development, may be scared off. To anyone who was scared off, don’t be. Be brash. Do things completely and utterly wrong and ask for help. Use an utterly inappropriate design pattern and make someone tell you why your implementation isn’t right. Crash and burn miserably, then get up and try it again. That’s the only way to learn.

The other thing to remember is that the end goal of development is not to use design patterns “correctly,” it’s to put a functional application into the hands of your users. If your applications work, no one (especially an end user!) is going to know whether or not you’re using the “right” design pattern, and they’re certainly not going to know if you’re using something like a Gateway “incorrectly.” If the application works and the objects are cohesive and well-organized, you’ve likely done your job well, and even another developer can jump in and immediately understand your code.

If you’ve stuck with me to this point, here’s the one pearl of wisdom I was really trying to get across in all of this: overanalysis leads to paralysis. What? I just made you read several thousand words for some cliche fortune-cookie quality wisdom? You betcha. In all seriousness though, it’s very easy when reading academic discussions such as those referenced above to get caught up in the right and wrong of it all and not try anything. You’re only wrong if you don’t try.

I’ll wrap this up by saying that while none of the blog posts and comments therein caused me to change my mind (yet …), I truly appreciate the discussion. It gets all of our minds going, it makes us justify our opinions, offer alternatives, try new things, and grow as developers. And with this post you have yet another person to target if you do things differently or think that my analysis or the way I do things is utterly wrong. Comment away!

Comments

Link to a Google doc of this post:

http://docs.google.com/Doc?id=dhshbm3s_126fhh6ks

Posted by Matt Woodward @ 7/27/07 8:38 AM

Another great post Matt, you are on a roll. You offer some excellent detail and exposition on many of the points I was trying to make. I think it is great if people learn more patterns and can apply those, but not at the expense of blindly thinking there is something wrong with the bean/dao/gateway structure. It has and continues to work well for me in so many cases. This isn’t about making new CF-specific terminology but about adapting patterns to suit the specific advantages and drawbacks inherent in ColdFusion development.

Posted by Brian Rinaldi @ 7/27/07 10:14 AM

What is all this “Tolerance” stuff? I’m ok, You’re ok? You’re a real rule-breaker!

Posted by Michael White @ 7/27/07 10:41 AM

Great post, Matt. One of the hardest thing that folks new to (or even very experienced with) OO have to get past is that there usually is not a single “right” way to do things — instead just a series of options, the value of each dependent on their context. I know that kind of ultra-modernist subjectivism can drive people up the wall, but it’s one of the realities of OO. Sometimes there aren’t easy answers that apply every where, and you really have to train yourself to always ask “Why am I doing it this way? Is there a better way to do it, or is what I have now actually a good solution for this problem?”

Posted by Brian Klaas @ 7/27/07 12:29 PM

Interesting read, thank you. I was reading Software Architecture With ColdFusion:

Design Patterns and Beyond

Topics Outline Prepared by Simon Horwith for CFUnderground 6 (PDF, google it). Something caught my eye:

———-

Pattern: Row Set DTO

Purpose: Improve

performance by

returning recordset

data to the

presentation tier.

Description: Queries are

returned directly to

the presentation

tier for use rather

than returning

Objects.

———-

It does sound a lot like “Gateway”, what do you think?

Posted by Henry @ 7/27/07 5:00 PM

Good post, Matt. Thanks for putting the time into this topic and identifying the role that preference plays in software design. I think preference is extremely important topic that is often overlooked (although the post you’ve linked to may not convey that 🙂 )

I did have a question about your take on the difference between the DAO and a Table Gateway pattern. If the Table Gateway pattern is specific to a database table and the DAO pattern “implements the access mechanism required to work with the data source” (from the link to Sun you provided), can you really use the Gateway pattern on a relational model where a business object doesn’t map directly to a single table? If so, could you give me a brief example of how you’d do this? If not, what pattern, in your experience, would you recommend using for this problem? It seems like Fowler’s definition for Table Gateway isn’t flexible enough for more than a single table, but I could be wrong.

I work with a lot of legacy applications where we don’t want the relational model to dictate the object model, so I’ve always wondered what other developer’s perspectives are about this problem.

Posted by Brian LeGros @ 7/27/07 9:13 PM

Absolutely wonderful post Matt! I updated my blog entry to add a plea for everyone to read your blog entry!

It’s interesting to see the Mach II Development Guide held up as the possible source of this DAO/Gateway separation so I feel the need to provide some background there.

The original public release was early October 2003 and later that month, in response to “various requesters” I “Expanded Data Access Objects section to better explain DAO, gateway and memento machinery – and added example code” (according to the Revision History – and the memento example code was later removed because too many people followed the example slavishly without understanding it!).

A few months later I “noted that example code takes some shortcuts with the Memento design pattern”.

A few months later still I “rewrote confusing DAO/memento paragraph and commented out example implementation of DAO/gateway”.

That was early 2004 and that page has not been updated since although a *lot* has changed since then.

Do we disagree on the patterns? No. I still maintain that in ColdFusion it makes sense to keep per-object operations separated from aggregate operations because ColdFusion provides a wonderful abstraction called “query” 🙂

With the rise of ORM frameworks, it makes even more sense to keep “DAO” and “Gateway” separate because the ORMs replace the DAOs completely but only partially replace Gateways, if at all.

I suspect the only place we differ is in ratio of DAOs and Gateways to the underlying business objects. I offered a 1:1 ratio in the Mach II guide because it was the simplest thing to explain. In reality, I rarely had such a 1:1 ratio but it’s much, much harder to explain why, when and how to decide what ratio to use!

Brian Klaas makes a critical point in his comment: “One of the hardest thing that folks new to (or even very experienced with) OO have to get past is that there usually is not a single “right” way to do things”. I know I get teased about saying “it depends” but, unfortunately, it’s absolutely true. There is no “One True Way” but a lot of people want a black and white, right or wrong answer.

Henry, no, Simon’s “Row Set DTO” is merely giving a fancy name to the query object that ColdFusion provides. Nothing to do with gateways specifically, merely describing the return value.

Posted by Sean Corfield @ 7/27/07 11:32 PM

Awesome post Matt. Looking back at my “Mach-ii for newbies” tutorials I see that must be the point where I started separating my database access layer into Gateways and DAOs (only then I called them CRUD components) – and to this very they that is what I do, and feel just like you about this way of doing it.

Posted by Trond Ulseth @ 7/29/07 7:02 AM

….”to this very they” should of course be “to this very day”

Posted by Trond Ulseth @ 7/29/07 7:04 AM

I find the particular excerpt very intriguing:

“… in my own real-world development I completely agree with Joe. It’s served me well, I’ve never seen any negative impact by doing things this way, I like the separation of the two concerns, and no one’s convinced me that it’s wrong to do things this way.”

Isn’t that what its all about? That’s all design patterns really are; re-usable solutions to common problems. Until you find an anti pattern that destroys your technique then its a great pattern. The beauty is someone else could do it differently, as long as they do it differently consistently, and have it work just as well for them, still a fine design pattern.

Posted by Adam Haskell @ 7/29/07 5:17 PM

Someone bottle what Matt’s been drinking and ration it out to others..

Insightful, useful and I even read the entire X pages of this post 😀

You almost made me turn back to CF Fulltime Matt 🙂 (almost) heh.

Scott Barnes.

Developer Evangelist

Microsoft.

Posted by Scott Barnes @ 7/29/07 7:45 PM

Incredible post, Matt. I just came back for my second read and I find your writing style pleasing, humorous, and enjoyable — Not to mention very informative and insightful. When’s that first book coming out?

Posted by Fitz @ 10/25/07 7:13 AM

Thoroughly enjoyed — and mentioned in this blog entry here: http://ontap.riaforge.org/blog/index.cfm/2008/2/6/Devil-Went-Down-to-Silicon-…

Posted by ike @ 2/8/08 12:16 AM

Yorum yazmasak ayip olur

Link to a Google doc of this post:

http://docs.google.com/Doc?id=dhshbm3s_126fhh6ks

Posted by mp3 download @ 6/23/08 10:11 AM

thnks very good post

Posted by Prefabrik Ev @ 9/8/08 2:50 PM

Wow, what a insightful read. You hit the head on the nail when you talked about cohesion. I believe separating the two makes more sense and provides a more cohesive approach.

Often times, my gateways do not only reference databases, but also web services or other external resources. In that regard, a gateway makes a lot more sense.

Posted by Stewart Gateley @ 1/23/09 10:58 AM

Duck Typing: Stop the Insanity

If you pay attention to the ColdFusion blogs at all, or if you were at CFUnited, you’re well aware of the new-found duck typing craze in ColdFusion land. While I agree with some of the sentiments behind advocating duck typing, as with most things that become a veritable feeding frenzy, there’s quite a bit being lost in the insanity in my opinion.

First and foremost, just because you can do something doesn’t mean you should. Let me state that again and extend it a bit. Just because you can do something doesn’t mean you should, and it certainly doesn’t mean it’s appropriate to do it all the time. My fear with all the blog postings I’ve been reading the past few days is that people will take on an attitude along the lines of, “Typing? Who needs it! This is ColdFusion!” Personally I think that’s exactly the wrong approach.

Let’s stop and think about why typing exists in strongly typed languages such as Java. Yes, I know ColdFusion isn’t Java, but kindly stick with me for a moment. Typing exists in Java for numerous reasons, not the least of which is that type checking makes for safer software. Why? Because in Java if you’re doing something wrong, either on purpose or inadvertently, the compiler won’t let you get away with it. If an object’s expecting a Person to be passed in as an argument and you try to pass it a ShoppingCart, that simply isn’t going to fly. No worries about weird runtime errors based on typing because you can’t even get that far. From my years as a Java programmer I’ll say this much: once you get the darn thing compiled, you’ve won well more than half the battle. Java feels solid precisely because of this aspect of the language, and many other languages both before and after are strongly typed for many of these same reasons.

Is dealing with strong typing a bit of a headache? Sure, particularly when you’re in a situation where duck typing is actually necessary. Re-read that last part. “… where duck typing is actually necessary.” Now given the fact that there isn’t, strictly speaking, a way to even do duck typing in Java, and there are plenty of Java applications out there running just fine without it, “necessary” might be a bit strong in this case. So let’s downgrade that to “… where duck typing sure would come in darn handy and I’m doing it because I know what I’m doing and actually mean to remove type-checking and all the benefits that go with it.” One of the ways Java addresses cases in which duck typing would come in handy is to use interfaces, which–and the discussion of interfaces is a topic for another blog post altogether–ColdFusion doesn’t have. (As an aside, BlueDragon 7 adds a cfinterface tag, and it was rumored at cf.objective() that CF 8 may add interfaces as well.)

Now back to ColdFusion. As many have pointed out over the past few days, ColdFusion is not Java. Fair enough. What I take issue with is the extension some folks seem to be applying to this statement. Specifically I find statements such as “ColdFusion isn’t Java, so don’t worry about typing at all” extremely problematic. ESPECIALLY if people are new to OO and they’re bypassing the proper learning of OO and jumping straight to going typeless everywhere in all their applications, this is utter madness.

Granted, because all the type checking in ColdFusion is done at runtime, we don’t get the same compile-time checking that Java developers enjoy. (Take “enjoy” with a grain of salt there; the Java compiler is a rigid taskmaster yet we are forced to seek its approval and are generally elated when we receive such approval via a successful compilation.) That doesn’t, however, completely negate the value of typing in ColdFusion.

First let’s think about the development process. ColdFusion checks type at runtime, but during development, when you change a file and fire things off again, behind the scenes things are getting compiled and subsequently they are immediately executed. So this is really a compilation step with automatic execution thereafter. Not so different. If you’re passing something an object of a type it’s not expecting, ColdFusion throws an error. During development you may absolutely want this to happen, and it can save you some headaches because you get no further than CF saying, “Hey pal, wrong object type. Try again.” This can be great for debugging purposes.

Next, let’s think about deploying an application to production. Do you care about typing once the application is complete, has been thoroughly debugged, and you’re absolutely, positively sure everything’s going to work correctly? Probably not. You don’t really care about it at that point in Java either. Once all the bugs have been ironed out you know the correct types are being passed, so conceptually at least, it probably no longer matters. Of course there are special cases where it might matter, such as if you’re writing an API and people interact with your API by throwing objects at it, a good old-fashioned “wrong object type” error might be better than something that could be much harder to debug.

The other advantage of duck typing people seem to be going nuts over is performance. In Java, type checking is done at compile time so even if you could do straight duck typing in Java, there’s no performance benefit. In ColdFusion on the other hand, type checking is done at runtime, meaning this is an additional step ColdFusion has to perform. No huge surprise then that if you don’t make ColdFusion perform this additional step, things are going to be faster. How much faster? Depends on the application. My real concern here is performance gains … at what cost? Duck typing for the sake of performance should only be done in very specialized circumstances, and I’ll probably have more to say on this point soon.

Before I ramble further, I’ll cut to the chase and summarize by saying that duck typing is darn handy when you need it, but eliminating typing altogether because it’s the new, hip thing to do, or because you think it’s the top-secret weapon that will make your CF apps lightning fast, is a big, big mistake. If you listen to ColdFusion Weekly you’ll probably recall the call we had a couple of weeks ago asking for our thoughts on the Hal Helms and Jeff Peters Out Loud episode where they discussed “GroupThink.” Duck typing is another case in point in my mind. Please, please, please, for the love of the OO gods, think about what you’re doing when it comes to duck typing. Don’t skip typing because all the cool kids are doing it.

So where do I think this is all going? I hope that we’re in another Hegelian phase of our collective development knowledge. Thesis: ColdFusion has a type attribute now, so use it. Antithesis: forget typing–duck typing all the way. Synthesis: use duck typing only when you need it. We’re currently still in the antithesis phase which is why I thought it was a good time to do my own personal brain dump on this topic.

I’ll conclude with a few bullet points that you can use as food for thought.

  • Duck typing is great when you need it, but in the vast majority of cases you care about an object’s type (at least philosophically).
  • Duck typing for performance is a very bad reason to do duck typing, except in specialized circumstances.
  • Duck typing throughout your application can make development and debugging much more of a hassle.
  • Just because ColdFusion checks type at runtime doesn’t entirely negate the benefits of typing.
  • OO is to a large degree about discipline. Don’t duck type at all until you’ve done it the “right” way for quite a while.
  • Learn Java. I’m not saying learn it to the point of expertise, but play around with Java and learn how Java thinks. You have to know the rules before you can intelligently (and hopefully judiciously) break them.
  • Make up your own mind. Don’t duck type until it makes sense to you to duck type, and even then, only do it when you need it. (Yes, I know I repeated that point, but it’s and important one.)

That’s all my quacking (har har har) on duck typing for now.

Comments

Matt – Great article. But what I think some of us need, is a real BASIC tutorial on duck typing. This whole duck typing, OO, etc. talk is like listening to the Gods talk on Mount Olympus, but us little people down the mountain don’t understand.

Examples of duck typing and the explanation of what an Interface is. WTF is and interface?

Posted by @ 4/17/07 3:04 PM

Well said Matt. I’m always amazed at how the ‘sound bit syndrome’ gets ingrained into peoples brains. The brief exchange about how Duck Typing **in specific portions of 2 frameworks** significantly increased the performance of the frameworks got turned into ‘Duck Typing = Fast Code’. Sean Corfield had a nice follow-up on his blog about this same issue and addresses the performance issue as well.

BTW, re-listen to Helms & Peters Out Load’s “7 Habits of Highly Ineffective Programmers” podcast. One of the 7 ‘ineffective’ habits was putting too much weight on performance.

Posted by Jason Daiger @ 4/17/07 3:04 PM

Hi Matt,

Great post. There is only one thing I’d add. Once you’ve learnt Java, go play with Ruby!

I agree 100% that duck typing is a specific, advanced solution to a specific problem. For me the best thing about duck typing was that it forced me to spend the time to really “get” interfaces and nulls – and the implications of not having them.

If you have to do duck typing for performance (pretty unlikely), you can do it as a production build stage with a Regex so you can keep better documentation and still have the benefits of the slightly earlier and easier to debug errors that psuedo static typing provide during development and testing.

However, once you’ve done all of the above, start to really play with mixins. I think they’re as dangerous as a goto – but really – the ability to copy and rename methods at runtime like any other variable?! Dangerous – but very cool indeed!

Best Wishes,
Peter

Posted by Peter Bell @ 4/17/07 3:04 PM

For the person who asked, Rob Gonda posted a good list of links on Duck typing recently:
http://www.robgonda.com/blog/index.cfm/2006/7/4/PostCFUN-Must-read-links

I’d personally recomment Vy a Duck (and getting a subscription to Fusion Authority Quarterly Update – it looks like being quite a magazine – especially with articles on cool stuff like flash forms :->).

Also, as a practical matter, unless you’ve had a problem with the lack of interfaces or nulls in CF, you probably don’t need to worry about duck typing. It’s like any design pattern – very hard to understand until you come across the forces that drive it in your latest app. And then it becomes an obvious solution to your real world problem!

Best Wishes,
Peter
Best Wishes,
Peter

Posted by Peter Bell @ 4/17/07 3:04 PM

Matt,

I agree 100% with your article. I worry that all of this discussion will cause some developers to abandon typing altogether, without understanding what they are doing or what problems it can cause.

Also, there’s a point I’ve made before that is worth restating: with typed parameters, type mis-match exceptions are thrown at the START of a method. With duck typing, exceptions are thrown in the body of the method when the offending line of code is executed. THIS COULD BE IMPORTANT! Consider the case where a method commits some atomic action: it must either all succeed or all fail. Sure you could do all kinds of nasty type checking by hand and use liberal amounts of try/catch blocks, but typed parameters do it for you.

Plus, typed parameters provide a bit of self-documentation that I think is pretty valuable.

Bottom line: I think we use typed parameters in CF *unless* there is a clear cut reason not to. Don’t duck type just because its the going fad.

Seth

Posted by Seth Petry-Johnson @ 4/17/07 3:04 PM

Just out of curiousity, why are so many cf developers trying to make cfml into java, when it isn’t?

I mean if you like java, then code in java. I am not saying cfml doesn’t have room for improvement, but java and cfml have two seperate and different purposes.

And what exactly is duck typing?

Posted by Craig M. Rosenblum @ 4/17/07 3:04 PM

Hi Matt:
This is the best posting on the subject I’ve read so far (and, yes, have read quite a number of them in the last few days).

Good work.


Adam

Posted by Adam Cameron @ 4/17/07 3:04 PM

Craig–this isn’t an issue of Java vs. CFML. This is about writing good, solid code, which in my opinion in the vast majority of cases means you should type your objects. That doesn’t mean I’m trying to turn CF into Java, it means that I’m taking full advantage of what type safety does exist in the language.

If you don’t know what duck typing is I’d suggest wikipedia as a starting point:
http://en.wikipedia.org/wiki/Duck_typing

Judith Dinowitz also has an excellent article on Fusion Authority:
http://www.fusionauthority.com/Techniques/Article.cfm/ArticleID:4588

That should help put the discussion in context.

As for the question on interfaces, I’ll try to post again on that topic at some point, but again wikipedia might help in the mean time:
http://en.wikipedia.org/wiki/Interface_(computer_science)

Posted by Matt Woodward @ 4/17/07 3:04 PM

Matt,

I am honored to have you lead our CFUG. Well done, and I fully agree.

Mike.

Posted by Mike Kelp @ 4/17/07 3:04 PM

In a conversation I had with Joe Rinehart at CFUnited (at least I *think* it was Joe!) he mentioned that his approach wasn’t the nuclear option of just stripping out every single “type” and “returntype” as was suggested by at least one presenter at CFUnited. His suggestion was to find particular bottlenecks, and if ducktyping can be a benefit in those places, then by all means implement it. The example he gave was in the XML parsing of Model Glue in which ducktyping gave considerable gains. This is not a black and white subject in my opinion, and I don’t believe the answer is simply to strongly type *or* duck type. There is a middle ground.

Posted by Dave Shuck @ 4/17/07 3:04 PM

Amen!

Posted by Kurt Wiersma @ 4/17/07 3:04 PM

Well written (golf clap). You went to university didn’t you.?! By the way: ‘Typing: Why do you care’ (the name of my new book… on bookshelves when coldfusion becomes typed, (that’s ‘never’ folks) classic…

There’s better ways to do things, yes sure, so go do them and stop being so flipping academic.

Coldfusion is fun, that’s why academics want to change it. It doesn’t fit their limited mindset. Everything has to be definable (or typed) or it’s wrong.

Posted by Chris Dawes @ 4/17/07 3:04 PM

Chris,

No offence, but that was a poor troll, a very poor troll indeed. I suggest reading this and trying again tomorrow.

Cheers,

Kurt

Posted by Kurt Neldegaard @ 4/17/07 3:04 PM

Matt, good summary. I don’t think many people advocate taking out typing entirely (myself included) but for people new to the subject I think it was good to reiterate that point. And I think before people try tackling a subject like duck typing they should first gain an understanding of object oriented programming, object oriented design, and design patterns – just some advise for the people out there new to the subject.

Zach

Posted by Zach Loch @ 4/17/07 3:04 PM

Another thing to keep in mind when considering optimizing some code by using duck typing is to remember that is likely that the next version of CF will likely correct some of the speed advantage currently provided by not having types.

Posted by Kurt Wiersma @ 4/17/07 3:04 PM

Java can do Duck Typing, as of Java 1.5.

Please see Duck Typing in Java and no Reflection

Posted by Ricky Clarkson @ 4/17/07 3:04 PM

I strongly protest against the term duck.

I am a duck myself and al my life i am mocked at.

See for your self

LOL

Posted by Donald Duck @ 4/17/07 3:04 PM

Matt,

I, like you, am a big fan of static typing in Java where we have a compiler to check errors and can achieve some decent degree of type safety. When I began advocating for duck typing, it was not for performance reasons, at all. In fact, I had no idea that duck typing would result in performance gains.

Instead, I advocate duck typing because (a) a pseduo-statically typed language generates almost no benefits and (b) without some form of multiple typing (either multiple inheritance, interfaces, or something), static typing will force people into bad, convoluted inheritance chains in order to gain the benefits of polymorphism.

So, I *do* advocate duck typing extensively. The benefits are minimal and the risks of forcing architects into bad design is great.

Posted by Hal Helms @ 4/17/07 3:04 PM

Errr…I meant the benefits of pseduo-static typing are minimal, etc.

Posted by Hal Helms @ 4/17/07 3:04 PM

Of Factories and Databases

While working on MachBlog we debated how best to handle the multiple database conundrum. When creating an application such as this that needs to support potentially numerous databases there is a fork in the road. Either a single single set of database access code is created that has conditionals throughout to handle database-specific functionality where needed, or database access code unique to each database platform can be created, but this runs the risk of having redundant code where the more mundane SQL is identical across database platforms.

In the end we decided that for the sake of maximum flexibility and future extensibility we would have a set of data objects (DAOs and gateways) for each database platform. Out of the box MachBlog will have two complete sets of data objects, one for Microsoft SQL Server, and another for MySQL. Make that three, actually, since for the sake of object typing we have a set of base classes that are extended by the database-specific objects. The base classes are never instantiated directly. They exist only to provide a common object type that the rest of the application will use, and they also provide a bit of generic documentation for future database implementations.

Either way you go there’s some potential maintenance headaches involved. In our case since we have separate objects for each database platform we do have a fair amount of SQL code that is identical between MSSQL and MySQL. The tradeoff here is maximum flexibility. For example, right now views and stored procedures aren’t used in the objects for either platform, but let’s say I get the crazy notion I want to implement stored procs for SQL Server. MySQL 5 has stored procs but MySQL 4.x doesn’t, so to make the MySQL objects compatible with both versions I decide not to implement stored procs for MySQL. No problem, I can change my SQL Server objects all I want and the MySQL objects won’t know or care, and I don’t have to create potentially messy conditional logic throughout my database objects to do so. Maximum isolation, maximum flexibility, with the downside of potentially having to make the “generic” changes that aren’t specific to either platform in multiple places.

The specifics of how this is achieved is through the factory pattern. It’s a simple enough concept, but extremely powerful in practice. In short, rather than instantiating specific objects for MSSQL or MySQL directly when the application starts up, the application simply asks the DAO and Gateway factories to return the appropriate objects for the database type that is indicated in the application’s configuration file. Because the data objects for both databases extend the same base class, the rest of the application can expect to receive an object of the “generic” type even though the specific instance is suited to a particular database platform.

This also makes it trivial to add support for additional database platforms in the future. In fact a new datbaase platform could be added simply by creating data objects for the platform in question and that’s it, other than literally a one-line edit to the application’s XML configuration file. The rest of the application’s code is happily unaware of this entire process.

There are of course pros and cons to any architectural decision, and this is no exception. As my music theory teacher always used to say, “You pay your money and go either way.” Personally I think the independent data objects that are platform specific give maximum flexibility while making the code far easier to deal with and maintain, not to mention extend through the addition of new database platforms in the future. Each database can take advantage of its individual and potentially unique strengths and any weaknesses of particular platforms can be avoided. Meanwhile the rest of the application isn’t concerned with what database is being used so long as the data it asks for is returned.

Comments

Hello Matt,

I’m probably missing the subtleties, but I’m doing something similar. The only difference is that any methods that are either identical between children (in your case MySQL vs. MSSQL, in my simpler case it is between different entities – UserDAO, PageDAO, ProductDAO, etc.) or have only simply parameterizable differences, I put those methods in the base class with the option to overload in the children if necessary. So if MySQl.Delete() and MSSQL.Delete() are identical (or the only differences can be parameteized in the extending childrens variable scope), you simply have a Base.Delete(), but then when you want a more sophisticated MSSQL.Delete(), you can then add it to that one child class.

Not sure if this matches the details of the problem you were solving . . .

Best Wishes,
Peter

Posted by Peter Bell @ 4/17/07 3:04 PM

Thanks Peter–we actually do have things like EntryDAO, EntryGateway, etc., with a base object, MSSQL, and MySQL version for each. They’re separated into different directories but the file names are the same between them. I’ve done things in the past as you describe with the common SQL in the base object but decided to take a bit different approach here and so far I like it. At this point anyway I prefer having fully implemented objects for each type and not really relying on anything from the base object in terms of specific implementation. I’ll see if this opinion holds up as we add a few more databases to the mix.

Posted by Matt Woodward @ 4/17/07 3:04 PM

cf.Objective() Presentations and Code

If you believe in the saying “better late than never,” then here for the patient among you are my materials from cf.Objective() 2006. Enjoy!

Head First Mach-II (presented with Peter Farrell)

head_first_mach-ii_cfobjective.pdf
Download this file

OOP for Noobz

oop_for_n00bz.pdf
Download this file

 

Migrating Legacy Apps to OOP with ColdFusion

migrating_legacy_apps.pdf
Download this file

Comments

Matt,

I am picking apart your OOP for NOObz code examples, trying to wrap my mind around OOP.

I don’t see anything in your examples that jumps out at me and says, “I’m the controller (as in MVC).”

Is the ooForm2.cfm or chooseForm.cfm acting as your controller (I thought controllers were supposed to be cfc’s, but I’m a noob, what do I know)?

This example is helping me more than anything else – thanks a lot!

Posted by Aaron Roberson @ 4/17/07 3:04 PM

Hi Aaron–actually that specific example wasn’t MVC. It was just designed as a gentle (hopefully) introduction to objects in general so it doesn’t necessarily follow an MVC pattern. The goal with that example was to focus on the bean and data access objects in order for people to get a grasp on how objects work overall.

If you have any other questions feel free to ask!

Posted by Matt Woodward @ 4/17/07 3:04 PM

Head First Mach-II Captivate Presentation

For those of you who can’t attend cf.objective() and see me and Peter Farrell present “Head First Mach-II” live, here’s a rough cut of me doing the presentation solo (49 MB) in Captivate. This is my first real shot at doing this sort of thing in Captivate so please be kind. 😉 If you want to follow along with the code here’s a zip of that as well.

Some general comments:

  • I used a cheap headset mic on the PowerPoint portions and a much better one on the code portions, hence the sound quality difference. I think both sound pretty good, with the “worse” of the two making me sound a bit like I shoved the mic up my nose. This is also the lowest audio quality setting in Captivate, but don’t let all my hemming and hawing scare you off; it actually sounds quite good.
  • The Captivate slides that involved the web browser and in one case the code didn’t seem to refresh properly when I went from one screen to another or scrolled the code. Not a major deal, just realize that at the end when I said “you successfully logged in” and the screen still shows “your login failed,” I’m not losing my mind.
  • It’s a big file, but it’s about an hour long so it’s a pretty reasonable size considering how much I rambled.
  • I’ve had plans to do this for months but never found the time to write up a formal script as I wanted to, so I decided to wing it and get it out there rather than wait for time that was never going to come to perfect the prose. What’s a few “ums” among friends anyway?

I had fun doing this and already have plans to do a few more, so I hope those of you interested in Mach-II find this useful. I’ll keep the future ones a bit more focused and therefore shorter or I’ll split long ones out into sections to keep the file size smaller. Let me know what you think!

Comments

What hit me first thing this morning that I need to add is a diagram at the end of the code section to show how all the objects relate to one another. I’ll get that added tonight and integrate it into the presentation but also make it available as a separate download for those who have already downloaded the 49 MB beast.

Posted by Matt Woodward @ 4/17/07 3:04 PM

Hey Matt,
I’m in the middle of your presentation right now and I have to say that I’m in love with the idea so far. I am on of those top down coders but I’m looking to branch out. Thanks for putting this together!

Ryan

Posted by Ryan @ 4/17/07 3:04 PM

I just finishing watching your “Head First Mach-ii” presentation all the way through, and I plan on watching it again. It was very well done, and I would like to add that I am GLAD you decided not to script everything out. I prefer the style you presented in — it was a nice conversational tone. Save yourself the time of worrying about scripting things out in the future and just let’em rip!

I’ve been on the look out for additional Mach-ii captivate presentations so I look forward to the next one. Keep up the great work, and honestly, thank you very much for your efforts.

Posted by Fitz @ 10/17/07 6:40 AM

MachBlog: A Mach-II/ColdSpring Blog Application

Quick sneak peek screenshot of MachBlog, the Mach-II and ColdSpring blog that Peter Farrell and I have been working on (rather leisurely) over the past few months.

Machblog_lg

So why another blog application? It started out as me wanting to have a good, semi-full-blown sample app for Mach-II. Then I got into ColdSpring so I thought I better include that. Then I thought, “Hey, this is turning into an actual blog app!” Then Peter got his hands on it and went to town so we’re committed to making this far more than just a sample app at this point.

More soon–we’re hoping to have a beta available around cf.objective() time.

Comments

Cool, Matt. I’m looking forward to seeing the MachBlog in action.

Posted by Ben Edwards @ 4/17/07 3:04 PM

Matt,

Have you thought about tying in Reactor?

Either way, I’d love to start on my blogging venture (to start soon) with MachBlog!

Will this be a free blog?

Sami

Posted by Sami Hoda @ 4/17/07 3:04 PM

It looks great! If you need a tester, let me know! 🙂

Ryan

Posted by Ryan @ 4/17/07 3:04 PM

Ben–thanks, and we’ll of course be very appreciative of any comments you may have after we make the application available.

Sami–I thought about including Reactor in the mix as well but that’s not on the roadmap at this point. One reason is because at first this was meant to be a sample application that people could study, so being able to see how things like DAOs work is still kind of important to me. We may reconsider in the future.

Ryan–thanks for volunteering to test. We’ll need lots and lots of testing I’m sure! 😉

Posted by Matt Woodward @ 4/17/07 3:04 PM

Should have mentioned a few more things. This will be an open source, free application that we’re distributing under the Apache 2.0 license. It will be i18n ready out of the gate and we’re making it darn easy to skin as well. We have some other neat features planned and we’ll detail those as we get closer to a beta release.

Posted by Matt Woodward @ 4/17/07 3:04 PM

FYI, my blog is in desparate need of an upgrade and thus one reason why I’ve been trying to put a couple of hours in on the weekends to get this done. When I say deparate, I mean it. Between MachBlog, ColdFusion Weekly, preparing for the cf.Objetive() conference and “real” work — I got a lot on my plate. Hopefully Matt and I will get a beta done by the conference.

Secondly, I have a lot of content on my blog in BlogCFC – so I hope to write a conversion script…(Matt, I’ll add that to the To-Do list)

Next on the plate is an updated website for Mach-II…Matt shall we?

(Matt you’re going to have to get up an Amazon Wishlist 😉

Posted by Peter J. Farrell @ 4/17/07 3:04 PM

I’ve been looking around at different blogs while I wait on the powers that be to finish working on my laptop. 🙁 It looks great so far and I’m anxious to see it in action!

Posted by Donna French @ 4/17/07 3:04 PM

Still Loving ColdSpring

As I’ve been working on MachBlog (which should be done in the next few weeks sometime), I’m extremely glad I decided to use this as my opportunity to learn ColdSpring. Now that most of my objects are built and I’m actually putting things into action, I ran into several cases this morning where I found myself needing objects within other objects, and these objects weren’t already in there.

Before ColdSpring this might have been a bit of an “oh crap” moment, and I would have had to traverse back through the object dependencies and figure out what all I needed to get Object B into Object A successfully. As you might imagine this can get a bit nasty when Object B also has its own dependencies, and maybe those dependent objects have their own dependecies … you get the picture. With ColdSpring all I had to do was add a property or argument (depending on how it’s being used) to the CFC in which I need this other object, add about three lines to the ColdSpring services.xml file, and that’s it! The dependency maze is handled for me by ColdSpring. This is VERY cool stuff that has saved me numerous headaches thus far in my experimental app.

Comments

mmmm… coldspring rox0rz j00..

Its a very cool framework.

Posted by Scott Barnes @ 4/17/07 3:04 PM

 

ColdSpring: Better Model Management

I’ve been working for a couple of days on MachBlog, which I hope will become a great real-world sample app for Mach-II and maybe even something people will actually use. 😉 I’m also using this as my opportunity to dive in and learn ColdSpring, which if you haven’t looked into it yet is an Inversion of Control/Dependency Injection framework for ColdFusion that plays very nicely with Mach-II.

Even in something as relatively simple as a Blog app when it’s built with a domain model things can get semi-messy rather quickly. Just as a very simple example, numerous objects in the app of course use a datasource, and I’m encapsulating the datasource information in a simple datasource bean. The datasource bean in turn contains information such as the ColdFusion datasource name, the database type (SQL Server, MySQL, etc.), and the database user name and password in the event the app is used in an environment that requires this information.

Even if the datasource bean parameters are stored in a traditional configuration file of some sort, having to construct that datasource bean every single time I need it within my other objects can get rather cumbersome. Now imagine nested objects, for example a UserService that contains a UserGateway and UserDAO, and each of these objects needs a datasource bean. Managing even that simple scenario is already getting nasty.

Enter ColdSpring, which manages all this junk for you. By using a simple XML configuration file and in my case the Mach-II plugin, I don’t have to worry about all that stuff. I just tell ColdSpring how the objects related to one another and in my CFCs I indicate that these dependent objects are arguments to an init method, and that’s it. I don’t have to worry about nested objects within my CFCs or even calling CreateObject() for the objects I need. Using the example above, if my UserService needs a UserGateway, and the UserGateway needs a datasource bean, all I have in my UserService’s init method is the UserGateway indicated as an argument to the method. Then I can set that argument to the variables scope or do anything else I want to with it, but ColdSpring “gives” the UserService the appropriately configured UserGateway object.

I’ll post more as I build this app out but I’m already seeing a huge benefit to doing things this way. It reduces complexity and increases flexibility, and your model doesn’t have to know a single thing about ColdSpring to take advantage of this. In Mach-II’s case the only objects that have to know about ColdSpring are the listeners. Bravo to Dave Ross and Chris Scott–keep up the great work on this!

Comments

I’m currently developing a Mach-ii application where each database record is stamped with the username and date-time when modified. I’m thinking that injecting my session facade into the DAO objects with ColdSpring might make this process a little easier.

Posted by Joel Cox @ 4/17/07 3:04 PM