Friday, January 19, 2007

Patterns in Software - Part 1

Patterns of Software: Tales from the Software Community (freely available in PDF format) is something I came across last time I was talking about design patterns.

First off, I think this book is very well written - style, language, structure - it's all good. I wish I could write as well as this guy. Christopher Alexander is in the preface (the guy who is attributed to inventing patterns).

Secondly, I'm going to cover the chapters that I've liked as I get to them. The first is "Abstraction Descant".

In this chapter he introduces the concept of compression which is: "...the characteristic of a piece of text that the meaning of any part of it is “larger” than that particular piece has by itself."

Examples are macros, function or class names. There is a danger though that compression and abstraction can be overused.

"The problem is that people are taught to value abstraction above all else, and object-oriented languages and their philosophy of use emphasizes reuse (compression), which is generally good. However, sometimes the passion for abstraction is so strong that it is used inappropriately — it is forced in the same way as it is with larger, more complex, and typically ad hoc abstractions."

"Another problem with complex abstraction arises from the observation that abstractions are about ignorance...Some complex abstractions, however, contain information about the implementation that is legitimately required, such as its performance, the algorithm, coding tricks, and resource usage—keep in mind that almost all interaction issues are about resource conflicts."


The next point is that software evolves through time, in little pieces by programmers not designers. The danger is the designers use abstractions (usually in ignorance) whereas coders should write code and design it in order to make it more habitable.

"...creating habitable software that can be effectively maintained, recognizing that the reality of software development is piecemeal growth and to plan accordingly, and to understand that the power of object-oriented programming is compression, which carries a terrific requirement for careful use of inheritance—relate to how we use abstraction and how much we use it."

"In programming, if a set of large abstractions does nearly the right thing, it is tempting to use them and to bend the structure of the surrounding program to fit them. This can lead to uninhabitable programs."

"Worse: You can fight this temptation and choose not to use them. This choice also can lead to uninhabitable programs because you will be using parts similar but subtly different from possibly familiar ones. The only way to avoid this is to use small blocks rather than large ones, or to use blocks well-designed and tested by experts."


He also has a comment on teaching programming where we need to "learn from the classics".

"How much time do we spend reading in our ordinary education? And from our reading we gain a foundation for writing...But in programming we just learn the language and solve a bunch of short puzzles. Sort of like writing 50 limericks and then off to write books."


The next point took me a while to digest but I think it's probably the most useful part of the chapter. It is that we rarely spend time creating new control abstractions (like loops) and most of the time creating abstractions of data. He argues that the two should go hand in hand.

"Let’s look at another problem with abstractions: Data and control abstractions are generally best when they are codesigned and this is rarely done anymore. Consider, for example, the Fortran abstractions of arrays and iteration. Arrays are abstractions designed to represent vectors and matrices. Iteration is a control abstraction useful for traversing vectors and arrays. Think, for example, of how easy it is to implement summation over the elements of a vector. This is because arrays and DO loops were codesigned."

"But an interesting thing happened to Lisp in the early 1980s: the use of macros to define control structures became forbidden style. Not only did some organizations outlaw such use of macros, but the cognoscenti began sneering at programmers who used them that way. Procedural abstractions are acceptable, but not control abstractions. The only acceptable control abstractions in Lisp today are function invocation, do loops, while loops, go statements (sort of), non-local exits, and a few mapping operations (such as mapcar in Lisp)."

"Regardless of what you make of this view of data versus control abstraction, it is certainly true that because almost every programming language does not allow any sort of meaningful user-defined control abstractions, there is always a mismatch in abstraction levels between control and data. If there is a good reason for allowing data abstractions, why isn’t that a good reason for allowing control abstractions; and if there is a good reason to disallow control abstractions, why isn’t that a good reason to disallow data abstractions?"


Finally a word on the general use of patterns.

"Common patterns are similar in nature though not detail to the patterns that Christopher Alexander uses in his so-called pattern languages. A pattern language is a language for generating buildings and towns with organic order. Patterns generally specify the components of a portion of a building or a place and how those components are related to other patterns."


More of this is covered in "The Failure of Pattern Languages" but the next part will be "The Quality Without a Name".

No comments: