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