Sunday, 25 March 2018

Discuss: Recipes vs. Patterns

Link: blog.fitterwork.org?id=Recipes-vs-Patterns

Abstract:


Recipes are a great way of handling complexity. You don’t need to know how they work, you just need to know how to wire them up; it’s a black-box solution. Software patterns also help you handle complexity, but they do this by generalising a solution to a particular class of problem. This means that you do need to understand how it works as you must implement your own code; it’s an open-box solution. Implementing software patterns takes time, effort and some experience. In contrast software recipes can often by dropped into your code without too much thought. This might explain why recipes are so pervasive in modern software. The problem with recipes is that their quality and format is variable presenting a real challenge for anyone trying to develop reliable software. We might improve the situation by adopting a similar approach to their documentation as used for software patterns. This is what we’re hoping to achieve in the FitterWork cookbook.

About Recipes


What’s a recipe? Don Lancaster’s TTL Cookbook[1] contains a collection of projects each describing how to build an electronic device from chips like the 74C73 or the 74C00. These are recipes in the sense that they give you a list of ingredients as well as the steps needed to make them into something useful. Software recipes borrow from this idea, but typically help you implement a feature for a computer system. Therefore if you want to provide your website with input validation for a form you can just Google to find a suitable recipe and then follow its instructions to implement it.

Recipes are a great way of handling complexity. When building Don Lancaster’s electronic stopwatch you don’t need to know anything about how CMOS logic chips work, instead you just follow his recipe. Similarly, when validating an input field you just the appropriate Tag Helper to the HTML in your form and then add a suitable data annotation to your model. You don’t need to know anything about how these components work. Instead you just need to know who to wire them up; that’s what the recipe gives you.

About Patterns


Software patterns provide another way of handling complexity. They do so by generalising the solution to a particular class of problem. For example, the ‘Observer’ pattern provides a way of allowing a change in one part of the code to be communicated to many other parts of the code. Once you’ve learnt how the observer pattern works you can implement a solution using standard code constructs. However, introducing such patterns into your code has another key benefit. It makes your code easier to understand, for rather than describing the system at its code level you can describe it much more succinctly in terms of its higher level patterns.

The idea of documenting reusable software patterns was popularized in 1994 by the book ‘Design Patterns’[2], but it was inspired by the work of Christopher Alexander who originally documented common patterns for architecture his book ‘A Pattern Language’[3]. These   patterns generalise complexity by presenting the essence of the idea in a form that invites adaptation. For example, he describes how adding slit windows into a building can draw people towards a beautiful view. Alexander documents each of his patterns with a name, a statement of the problem and its context before he presents a solution together with implementation details. In this way the patterns can be easily understood without the need for the reader to have any background as an architect.

The authors of Design Patterns followed Alexander’s approach when documenting their patterns, but unfortunately didn’t manage to achieve the same degree of accessibility. Consequently Design Patterns isn’t a book for a novice. You can’t just drop a stock solution into your code base. Instead you’ll probably need to look at several implementations and then use parts of each for your own solution. This takes time, effort and a degree of experience. For these reasons software patterns are typically found in the work of expert developers (or computer science students looking for extra credits). It is also rare for software patterns to occupy more than a small percentage of the total code base. Certainly, the early promise of building entire systems by assembling a collection of suitable patterns is yet to become common-place.

Using recipes to build reliable code


In contrast to software patterns, recipes are pervasive in modern code. Indeed we now operate in the era of the mash-up in which much software is little more than code from multiple sources cut and pasted according to various forms of recipes. Let’s take a step back and recall the world late last century. Programs in those days were a mixture of your own team’s code and third-party code; typically libraries with an application programmers interface (API). Vendors like Rogue Wave took responsibility for maintaining the library, documenting the API and providing samples to demonstrate its use. Therefore the recipes (samples) came from one authoritative source; the library vendor. Furthermore in order to sell more of their product the library vendors competed to provide useful recipes as well as good API documentation.

Working in the Mash-up World


Contrast how we worked in the past with the present. Open-source projects staffed by part-time volunteers are typically interested in developing code not recipes or good documentation. This work is left to the community who use their library and for this reason it’s difficult to find high quality sources of information, even from the library’s own forums. Typically, searches for information generate hundreds of hits which may resolve to dozens of recipes of varying quality and format. Therefore you select your black-box solution using a combination of gut-feeling about the skill of its author, the credibility of the site and the effort needed for its implementation. Sometimes the solution works, sometimes it doesn’t, and sometimes the solution seems to work but hides a serious flaw. Clearly this last situation is the most worrying if you are trying to develop reliable software. It can be argued that with open-source you can always look at the library source code. However, that negates one of the key advantages of using a library API; it’s a black-box and others take responsibility for what happens inside. In order to handle the complexity of modern software development we just don’t have the time to start delving into the guts of libraries. Instead we need good API documentation and reliable recipes.

Better Working with Recipes


The best cooking recipes are passed from generation to generation. They are tried, tested and also improved. Poor recipes, like bad furniture, simply don’t survive. However, waiting for software recipes to mature in this way isn’t an option. Therefore we need to find alternative ways to create reliable and well documented recipes.      

Community websites like Stackoverflow (https://stackoverflow.com/) provide a good starting point for software recipes. You might post a question like ‘how can I validate user input in ASP.NET?’ then wait for responses, hopefully including fragments of the code you need. If one of responses solves your problem then you should mark it with a tick so others subsequently searching for the same solution can know it works. People also comment on each other’s solutions so allowing iterative improvement. Adopting this simple approach has allowed Stackoverflow to build-up a vast collection of coding recipes in a wide range of topics. However, the flexible format of the responses means that sometimes important information is missing, like the version of ASP.NET that the solution was tested upon. It also means that improvements in the recipe are often missed as they appear in responses far removed from the original question.

A better way of working with recipes might involve following Christopher Alexander’s approach of giving them a name, a statement of the problem and its context before presenting a solution together with implementation details. We might then follow with a discussion section and a means of voting to improve the given solution. It would also be important to give the solution some provenance in terms of a reference to its source such as the Blog of a well-known authority, or a solution posted elsewhere. I intend to test these ideas in the cookbook section of FitterWork in the hope of encouraging debate and thereby helping others to provide better recipes elsewhere.

Summary:


Software patterns and recipes are both ways of handling the complexity which is inherent in modern software. Patterns are more focused on learning and understanding. They teach you good ways to code by showing you how expert programmers go about solving common problems. Using this knowledge you can then start designing your own solution. In contrast recipes are more like black-boxes. They provide a solution that you can just drop into your code without knowing much about how it works.

The big advantage of using a software pattern is that you will end-up understanding exactly how the code works, but this takes time and effort. The big advantage of using a software recipe is that you solve your problem without much effort, but this comes with the risk that it might not be entirely suitable for your application.  

Given that so much contemporary software relies on recipes, we need to find better ways of identifying the ones we can use to build reliable code. The FitterWork cookbook will explore ways of making better recipes by documenting them in a similar way to software patterns. In  this way it is hoped that people can more easily decide whether a particular recipe is a suitable solution for their specific problem. We can’t avoid recipes, so let’s make the best of them.

References:


1.      Lancaster DE. CMOS Cookbook. 1st edition. Indianapolis: Sams Publishing; 1977. 412 p.

2.      Gamma E, Helm R, Johnson R, Vlissides J, Booch G. Design Patterns: Elements of Reusable Object-Oriented Software. 1 edition. Reading, Mass: Addison-Wesley Professional; 1994. 395 p.

3.      Alexander C, Ishikawa S, Silverstein M, Jacobson M, Fiksdahl-King I, Angel S. A Pattern Language: Towns, Buildings, Construction. New York: Oxford University Press; 1977. 1171 p.

4.      Freeman E, Bates B, Sierra K, Robson E. Head First Design Patterns: A Brain-Friendly Guide. 1st edition. Sebastopol, CA: O’Reilly Media; 2004. 694 p.




No comments:

Post a Comment