Ducks Are Loosely Coupled

That's right, ducks swing that way, open marriages and all... Actually very few species of animals even have any pretence of monogamy, but that's not really what this is about.

This is something that didn't even come about until ColdFusion MX was released. With ColdFusion 5 and before, virtually everything was "duck typed". It was only with cfparam, particularly with custom tags, that it was even possible to declare a variable's type, but only built-in data types were available (string, struct, nueric, array, query). Functions hadn't even been introduced until ColdFusion 5 and at the time there was no cffunction tag, so functions had to be declared in cfscript and the syntax for declaring functions that way doesn't provide a built-in method of checking data types. If you wanted to check the type of an argument, you had to use the built-in type-checking functions like isStruct() or isSimpleValue() manually, so all function arguments at the time were "duck typed".

But perhaps I should back up. Once ColdFusion MX had been released, people started essentially "strict typing" the arguments to their functions (generally as CFC class names), instead of the "duck typing" they'd already been using for a long time. Why? Because it's better? Because it makes applications less error prone? Because it reduces the amount of coding needed? Nope... The ColdFusion community at large started strict typing things for two reasons: 1) it was available and 2) it's the way Java is written ("a real programming language" according to some). And then a number of people in the community started talking about "duck typing", and there was a big to do and a lot of people kept asking "what the hell is duck typing?"

Originally the explanation was "if it walks like a duck and talks like a duck, it's probably a duck", and so you don't have to specify the type of object being used. Which made sense to me, but not to everyone.

Duck typing is what we always did before the release of ColdFusion MX.

But it's easier to show what duck-typing is than to explain it:

Strict Typing:
<cffunction name="doSomething" output="false">
   <cfargument name="arg1" type="com.company.widget" required="true" />
   ...
</cffunction>

Duck Typing:
<cffunction name="doSomething" output="false">
   <cfargument name="arg1" type="any" required="true" />
   ...
</cffunction>

So there, obscure / spooky language clarified.

But this isn't just about clarifying the language, this is about going a little further and talking about why we even had any confusion in the first place. What is duck typing? Duck typing is loose coupling. If you aren't duck-typing, you're strongly coupling. Or at least, you're coupling stonger than you would if you were duck-typing.

Strict typing has one purpose and one purpose only: to create errors.

And some people feel that's a good thing. I don't. Why? Because I've noticed that ColdFusion applications written with CFCs aren't any more or less error prone than ColdFusion applications written on CF5 and prior, when CFCs weren't available and duck-typing was virtually required. What's that mean? Strict typing isn't making our software any less error prone.

In some other languages like recent versions of ActionScript, the use of strict-typing can result in improved mechanical performance due to the way the engine binds the language's type system, however aside from the fact that this falls for me into the category of sweating the small stuff (and therefore not worthy of your time), it also doesn't improve performance in current versions of ColdFusion. In fact, ColdFusion 8 recommends a setting that disables type checking entirely on production servers! Because type checking with this version of ColdFusion is less efficient. So mechanical efficiency isn't a concern.

Which leaves what I mentioned before, that the purpose of strict typing is to create errors. Creating errors in and of itself isn't necessarily a bad thing. In fact the onTap framework contains several cfthrow tags to create helpful, friendly error messages to help you debug it when something goes wrong. Strict typing on the other hand isn't really that kind of thoughtful error creation, it's indiscriminate error creation.

Let me take a brief example from ColdBox, just because I've been working with it lately. Though this is just an example, it's not specifically a ColdBox thing, it applies equally to any application or framework. (And as a matter of fact there's an example of an event handler on the ColdBox wiki right now that uses duck-typing.)

<cfcomponent extends="coldbox.system.eventhandler">
<cffunction name="dspForm" access="public" returntype="void" output="false">
   <cfargument name="event" type="coldbox.system.beans.requestContext" required="true" />
   <cfset event.setView("theForm") />
</cffunction>

<cffunction name="save" access="public" returntype="void" output="false">
   <cfargument name="event" type="coldbox.system.beans.requestContext" required="true" />
   <cfset rc = event.getCollection() />
   <cfset rc.errormessage = validate(rc) />
   <cfif len(trim(rc.errormessage))>
      <cfset event.setView("theForm") />
   <cfelse>
      ... save the form data ...
      <cfset setNextEvent("theHandler.saveComplete") />
   </cfif>
</cffunction>

<cffunction name="saveComplete" access="public" returntype="void" output="false">
   <cfargument name="event" type="coldbox.system.beans.requestContext" required="true" />
   <cfset event.setView("saveComplete") />
</cffunction>
</cfcomponent>

Now let's say hypothetically that I wanted to modify my copy of the ColdBox framework. Let's say I wanted to make changes to the Event object because I think it's "bloated" and I want to remove some things to make it more efficient. (I don't -- I haven't looked closely at it, this is just a hypothetical situation.) In that case I likely would want to create a new CFC and in this case because I think the original is too "bloated", I don't want to use the extends property to make my new CFC a derived class of the ColdBox framework's Event CFC (which also rules out the flavor of the day "decorator" design pattern). If I created mine as a subclass then I'd just be opening myself up for a number of problems like the parent component bloating up my component, needing more work to bypass what I see as "bloat" in the original component and changes to the core component in later versions of ColdBox being incompatible with my methods of modification.

With all my event handlers (some of which may have come that way from other vendors) insisting on "coldbox.system.beans.requestContext", what will happen when I modify the ColdBox application to use my new Event CFC (say for example "com.mycompany.coldboxEvent"), is that the server will throw an error because my CFC isn't of the type specified in the handler. Since it's not a derived class either (using the extends attribute), it also can't be automatically promoted by the ColdFusion server's type system to a parent or ancestor class matching the specified type. I'm liable to use a multi-file search and replace in the handler directory and replace all instances of "coldbox.system.beans.requestContext" with my new class name ("com.mycompany.coldboxEvent"), or possibly with "any" if I want to move to duck-typed events.

It may not ultimately be a huge amount of work for this single example. I may only do it once, etc. On the other hand, it was still unnecessary work. The server doesn't need to know that the object is of type "coldbox.system.beans.requestContext" -- the only thing the server needs to know is that it implements the handful of functions required by the event handler like setValue() and getValue(). As long as those functions exist and "play nice", the application is golden. So using strict-typing in this case hasn't accomplished anything other than to generate an error that needed to be resolved via a multi-file search and replace.

Now the recent introduction of the cfinterface tag provides us with the opportunity to use interfaces to resolve this problem in another way. And some folks like the idea of interfaces. I don't. Why? Because the use of an interface provides an opportunity for someone else to introduce strict-typing for me. The interface is essentially a blueprint -- it defines a pattern for other objects, but doesn't do any actual work, just like an architectural blueprint defined a pattern for a building without necessarily specifying any of the materials. Given the previous ColdBox example, assuming that Luis Majano created an interface for the event object, I could specify that my new replacement event object implements his interface. Great! Until his interface specifies strict-typing in its method arguments, and then I'm back to square one, or I may have to implement those interfaces as well. This could turn into a fair lot of work pretty quickly. And what does all this work accomplish? The server throws an error if any of my CFCs aren't found to be of the given type or to implement the given interface. Which isn't what the application really needed to know. The application only needed to know that it could reasonably use the expected functions.

I say the application didn't need to know those things because applications that are duck-typed as far as I can tell aren't any more or less error prone than applications that use strict-typing. So the only thing actually being accomplished by strict typing is "tighter coupling", i.e. more work and the opposite of what is generally considered OO "best practice". You probably work in an environment that uses some (if not a lot of) strict typing, or you have worked in one or more of those environments. Do those applications break down less as a result? I would bet that they don't. But you're probably doing more typing -- or in some cases, using bean generators.

And really if we look at other software, often enough what makes a given language or platform truly compelling ultimately boils down to the same kind of "duck-typing" we all used in ColdFusion prior to the release of MX. What happens with an HTML page if you specify a tag the browser doesn't understand? It's ignored and the browser moves on to the next thing. What happens if you specify a CSS property it doesn't understand? It's ignored and the browser moves on to the next thing. Well what are these tags & CSS properties? They're "classes" of nodes - an "input" node is a class of node with a different type of appearance and behavior than a "select" node. A "background" property is a different class of CSS property than a "border" property. In both cases the browser simply accepts a "node" or a "property", does what it can with it and ignores the rest. This is not by accident.

In the world of JavaScript at one time it was commonplace to check the browser version within scripts, searching the string for "MSIE", etc. to determine which browser was running the script. This was called "browser sniffing". These days it's become much more popular to avoid sniffing and instead perform a "duck-typing" analysis of the browser by testing for the existence of specific features needed, such as DOM methods like document.getElementByID(). If the function exists, then the browser can support the script and the version is irrelevant. That's precisely the same phenomenon that "duck typing" in ColdFusion relies upon.

And now there's even more duck-typing in ColdFusion since recent versions have added the ability to include "metadata" attributes in tags like cfcomponent, cffunction and cfproperty that are ignored by the server, allowing you to use them for your own purposes later via the server's getMetaData() function. And ColdFusion 8 goes even further by adding the onMissingMethod() feature similar to missing-method handlers in Ruby and Python. Implementing a similar feature in Java would be at best a challenge because Java requires strict typing (the reason why java needs overloading instead of dynamic arguments for object methods).

But I'm not going to stop there, I'm going to draw one last parallel. It's become popular in the ColdFusion community in recent years to create stronger coupling in another way - with beans. The typical bean has a collection of functions called accessors and a collection of functions called mutators. Typically these would be named getXXX() and setXXX() respectively and for the most part, all they ever do is return "instance.xxx" or set "instance.xxx" within the private variables scope of the CFC. For example:

<cfcomponent displayname="product">
   <cfscript>
      variables.instance = structNew();
      variables.instance.price = 0;
      variables.instance.shipping = 0;
      variables.instance.productname = "";
      variables.instance.categoryid = "";
   </cfscript>
   
   <cffunction name="init" access="public" output="false">
      <cfreturn this />
   </cffunction>
   
   <cffunction name="getPrice" access="public" output="false" returntype="numeric">
      <cfreturn instance.Price />
   </cffunction>
   
   <cffunction name="setPrice" access="public" output="false" returntype="void">
      <cfargument name="Price" type="numeric" required="true" />
      <cfset instance.Price = arguments.Price />
   </cffunction>
   
   <cffunction name="getShipping" access="public" output="false" returntype="numeric">
      <cfreturn instance.Shipping />
   </cffunction>
   
   <cffunction name="setShipping" access="public" output="false" returntype="void">
      <cfargument name="Shipping" type="numeric" required="true" />
      <cfset instance.Shipping = arguments.Shipping />
   </cffunction>
   
   <cffunction name="getProductName" access="public" output="false" returntype="string">
      <cfreturn instance.ProductName />
   </cffunction>
   
   <cffunction name="setProductName" access="public" output="false" returntype="void">
      <cfargument name="ProductName" type="string" required="true" />
      <cfset instance.ProductName = arguments.ProductName />
   </cffunction>
   
   <cffunction name="getCategoryID" access="public" output="false" returntype="string">
      <cfreturn instance.CategoryID />
   </cffunction>
   
   <cffunction name="setCategoryID" access="public" output="false" returntype="void">
      <cfargument name="CategoryID" type="string" required="true" />
      <cfset instance.CategoryID = arguments.CategoryID />
   </cffunction>
</cfcomponent>

Now this is a pretty small CFC honestly... With only four properties, it's freakishly tiny... and look at all that REPETITION! Oh my god! Holy crap, if I have to repeat myself that much, just kill me now!... which is a large part of the reason why some folks have taken to using bean generators to write out these CFCs for them, which imo isn't a great idea because then you're just moving from manually creating more work for yourself to using a tool to create more work for yourself in an automated fashion. Especially given that in the present tense (and for many beans) this component is at best only marginally different than just using a structure by itself. Indeed, the "instance" structure is the bulk of the object and the only thing that's been added to it (at least yet) is that it will throw errors if you try to set price or shipping to a non-numeric value or any other property to a non-simple value. But just as "duck typing" (or at least the principal of it) can help with HTML and CSS, it can also help here.

<cfcomponent displayname="product">
   <cfscript>
      variables.instance = structNew();
      variables.instance.price = 0;
      variables.instance.shipping = 0;
   </cfscript>
   
   <cffunction name="init" access="public" output="false">
      <cfreturn this />
   </cffunction>
   
   <cffunction name="getValue" access="public" output="false" returntype="any">
      <cfargument name="property" type="string" required="true" />
      <cfset var methodName = "get_" & arguments.property />
      <cfset var theValue = "" />
      
      <cfif structKeyExists(variables,methodName)>
         <cfinvoke method="#methodName#" returnvariable="theValue" />
      <cfif structKeyExists(instance,arguments.property)>
         <cfset theValue = instance[arguments.property] />
      <cfelse>
         <cfset theValue = "" />
      </cfif>
      
      <cfreturn theValue />
   </cffunction>
   
   <cffunction name="setValue" access="public" output="false">
      <cfargument name="property" type="string" required="true" />
      <cfargument name="propValue" type="any" required="true" />
      <cfset var methodName = "set_" & arguments.property />
      <cfset var theValue = "" />
      
      <cfif structKeyExists(variables,methodName)>
         <cfinvoke method="#methodName#">
            <cfinvokeargument name="theValue" value="#arguments.propValue#" />
         </cfinvoke>
      <cfelse>
         <cfset instance[arguments.property] = arguments.propValue />
      </cfif>
      
      <cfreturn this />
   </cffunction>
   
   <cffunction name="setValuesByStruct">
      <cfargument name="struct" type="struct" required="true" />
      <cfset var x = 0 />
      <cfloop item="x" collection="struct">
         <cfset setValue(x,struct[x]) />
      </cfloop>
   </cffunction>
</cfcomponent>

Now I've even added a function in this example (setValuesByStruct()) and yet, this example is still only a mere five lines longer than the original bean example... and infinitely more flexible to boot. Other part of the application would now set and fetch properties of the bean in a slightly different fashion:

<cfscript>
   // before
   x = bean.getPrice();
   bean.setPrice(5);

   // after
   x = bean.getValue("price");
   bean.setValue("price",5);
</cfscript>

This is more flexible because only the two functions are needed in the new bean and unknown properties are handled by convention.

Let's say hypothetically that I decided the product bean needed an extra property, for instance a "description" property. Using the previous bean example, the one most common in today's ColdFusion environment, I would be obligated to add not just the one line in the bean's soft constructor but also to add a minimum of eight additional lines of code just for that one property (lines of code that are likely to be coppied and pasted). Those eight extra lines of code would be doing nothing for me other than referencing the instance structure just like all the other properties. If I ever want to use some object other than a product bean in place of the product bean (say a "fakeProduct" object), I have to know that the new fakeProduct component implements all those methods too. The common bean example has no less than nine functions, all but one of which do the same thing - that's eight functions that must be maintained and accounted for if extended or substituted, etc. All these things are because the standard bean doesn't know how to ignore irrelevant instructions -- it demands to know precisely what's going on, whether it needs to know or not.

In the subsequent example, I have only four functions. If I want to add another property to the component, the number of functions may or may not grow - most of the time they won't. A "description" property for example would likely not increase the number of functions that would need to be maintained. I'm only obligated to add a specific accessor (getXXX) or mutator (setXXX) if the specific property in question needs special handling (this is the same principal that's made Ruby on Rails phenomenally popular in the past few years). If I want to substitute another object, say the "fakeProduct" object, I don't need to know that all eight or ten accessor and mutator functions are replicated in the substitute object, I only need be concerned with two or possibly three methods - getValue, setValue and setValuesByStruct. Further the setValuesByStruct (and/or similar setValuesByQuery) method is a convenient shorthand that in most applications would eliminate huge amounts of additional repetition in the form results events where all the same property names would be repeated, yet again! For example:

<cfscript>
   set rc = form; // or event.getCollection() for ColdBox types
   // Standard Bean
   product.setPrice(rc.price);
   product.setBilling(rc.billing);
   product.setProductName(rc.productName);
   product.setProductDescription(rc.productDescription);
   product.setCategoryID(rc.productCategoryID);

   // Modified Bean
   product.setValuesByStruct(rc);
</cfscript>

Examples using the technique of the 2nd bean save me huge amounts of work because they're more flexible. And all this added flexibility boils down to one thing - it treats the properties in the same duck-type-like way that a browser treats unknown HTML tags or CSS properties, by ignoring them.

I'll call this 2nd example a "ducky bean", because it saves me a lot of work and I think it's just ducky! :)

The idea of "loose coupling" ultimately is to reduce the amount of knowledge that parts of a system have of each other, i.e. the "black box". The less coupled parts of the system become, the easier it is to maintain or modify the system because each individual component can be moved or swapped out more easily because they require very little exchange of information between them. Loose coupling reduces the opportunity cost to maintain or modify an application, by reducing the amount of code needed to write it. The standard bean on the other hand actually requires that other parts of the system know quite a lot about that bean.

Typically we store the data that goes into a bean in a relational database like MySQL, SQL Server or Oracle. These databases store the data in tables, with each table containing a series of named columns. You can measure in part the amount of coupling (and work) in your application by counting the number of places each column name is replicated in your application. In a typical application, the column names are replicated MANY times. Five times per bean, at least four times per DAO, plus probably a couple times per form and maybe a few times in the event handlers. Which means that each time you want to add a column to your database, there are at least TWELVE places in the application where you are required to add code that references that column name. By comparison in a typical onTap application, using something very similar to this "ducky bean" code, when you add a column to a database table, there is typically ONE place where you need to modify the code after adding the column in your database - in the CRUD form. Occasionally, you might need to reference it as many as four or five times if you need special handling in the "ducky bean".

In the application I've been working on recently it's even worse because not only are there those twelve places, we're using standardized insert/update stored procedures in the database, which aside from not adding any utility also adds another 4 places per column that need to be updated when a column is added (2 per procedure) bringing the total to a minimum of 16 items that need to be updated per column.

So to recap:

Common ColdFusion Bean
WorkloadSlowFast
Create a BeanX
Substitute a BeanX
Add a PropertyX
Maintain a BeanX
Process a FormX
Ducky Bean
WorkloadSlowFast
Create a BeanX
Substitute a BeanX
Add a PropertyX
Maintain a BeanX
Process a FormX

See a pattern here? Doing it the standard way is hard work. Doing it ducky is easy. And to date I've found no compelling reason to do it the standard way, simply because I've found no significant advantage to all that extra work. The only thing I've found it does for me is slow me down.

(And in spite of this, many of the components I've written recently, even in my own work, end up using hard-coded accessors and mutators -- not for any significant reason other than that they're for things I perceive as being different than typical "properties" like when I created the flyweight for my contact manager and I don't want to store the composed object in the instance variables structure.)

Related Blog Entries

Comments
BlogCFC was created by Raymond Camden. This blog is running version 5.5.006. | Protected by Akismet | Blog with WordPress