-
Lay Thick Pipes
One thing that has becoming increasingly important to me over the years when writing software was architecture and design. At first, there was no “architecture” in my code in any traditional sense. It was not laid out in any deliberate manner and once I got it working - it stayed.
Of course, its obvious here that the project quickly becomes a disorganized mess that is almost impossible to bug fix, test, or extend without introducing a million bugs along the way.
One thing I see time-and-time again is the lack of “thick pipes” to help combat these sorts of complexities. What is a thick pipe? To understand what a thick pipe is, we need to understand what a “thin” pipe is.
Here is a Javascript example of an API that searches for Foos. It will create a request and get back a JSON object that contains the Foos from the server.
var findFoos = function( bar, baz,callback ) { (new Ajax.Request('/foo/search', {method: 'get', parameters: {search_bar: bar, search_baz: baz }, onComplete: function(transport) { var myFoos = transport.responseJSON; callback(myFoos) }});) }Now for the sake of simplicity this great. This is the “less or more” or “less is less” mentality. This API allows you to search for foos by its bars and bazzes. Awesome.
But what if in the next revision (there is another release, right?), the Foo has a weeble property now. What changes? The API does, the code in the API does, the server code probably does too, along with every existing call to findFoos in the code base. Using this mentality, your API interface would look like this:
function findFoos( bar, baz, weeble, callback );But now, what if you don’t necessarily care about the bazzes for a specific part of your app, only the bars and weebles. Uh-oh, now your API calls start looking like this:
findFoos( 'the_bar', null, 'the_weeble', callback );What does null mean? What do the other parameters mean? If a new developer comes into the project and code like this is all over the place, they’ll spend a lot of time searching instead of reading. Even worse: every time the “Foo” object changes you will have to go through this mess and change all of the code it touches.
How to lay a thick pipe
All of this could have been avoided from the beginning. Instead of philosophically asking the question “how can I search for Foos on their bar and baz”, you could have asked “How do I search for any object on any number of parameters?” An answer to the first question does something, an answer to the second question enables you to do a lot of things. This is a thick pipe.
var search = function( objectName, parms, callback ){ (new Ajax.Request('/search', {method: 'get', parameters: parms.merge({objectType: objectName}) , onComplete: function(transport) { callback(transport.responseJSON); }});) }Notice how if you add another object to the server database you won’t have to change the API (or create a newObjectSearch() method). Notice how, regardless of what parameters you use or need to search by, the API doesn’t need any more parameters as you’ve passed them in as a hash. Look what this does for code readability in the case where we don’t care about bazzes.
search('Foo',{bar:'the_bar',weeble:'the_weeble'}, callback ); // we can also search for other objects with this search('Report',{id:5},reportCallback); search('Comment',{author:'skottie'},commentCallback);Once we’ve added these other objects and tables to the server-side, the client API enriches itself out of the art of the possible, without any extra code.
Through this example, its obvious that a “thick pipe” is a lot like abstraction. However, with abstraction alone you can still have 3-4 layers with a lot of very “thin” pipes. If one thing changes in your code and you find yourself changing a handful of interrelated pieces, your pipe is probably not thick enough.


