The Beauty of Short Methods
Writing short methods is one of the pieces of conventional wisdom that have been passed around as a form of agile technique. Many programers adhere to the use of short methods without thinking too much about it, while others disregard the idea altogether, more concerned with the practical activity of creating usable code.
There is, however, a number of surprising reasons why writing short methods can improve the quality of software. Some of these reasons have nothing to with just writing auto-commenting code, as some people describe it. One of the main issues is the distinction between the static description of code provided by a set of classes, as compared with the dynamic and complex view provided by algorithms.
Dynamic Properties of Algorithms
When we start on Computer Science at college, we discover a new world of scientific pursuit in the area of computational systems. Students are then presented to algorithms, and taught that this is the foundations of programming. We are lead to believe that using correct algorithms is necessary and sufficient to write good software.
There is no question that algorithms are a foundational concept, but they give programmers the false sense that explicitly writing an algorithm is the best way of solving complex problems in programming. Throughout my experience as a software engineer, I have found that combining small methods from several classes and libraries is a far more common way of solving problems – a technique that covers the huge majority of programming tasks available nowadays.
Despite all the ideas about the simplicity and elegance of small methods, I believe the main reason to use them is to transform the complex dynamic nature of algorithms into a static description of a solution in terms of classes and methods.
Complex Algorithmic Methods
The main advantage and liability of thinking in algorithms is that you learn to reason in terms of complex logic. It is true that, after you really understand an algorithm, its logic become clear enough that you may use it in several other contexts, as with any other mathematical concept.
There is a problem with this, however: whole algorithms are not so easy to recognize at first sight, especially by someone who hasn’t been educated in computer science. Even if you have good training, it is not always clear that an algorithm can be recognized when it is used in the context of a larger method. If that is the case, a programmer needs to document that a particular algorithm is being used, and the reader needs to believe that the implementation is correct.
Also, it is not easy to verify that an algorithm implemented as a large method is correct. This is a big problem encountered when moving from algorithms in a classroom setting to their concrete implementation. While in a classroom, an algorithm can be proved as a mathematical entity. It can be shown as correct by simply proving its mathematical properties.
However, when an algorithm is converted into software, all kinds of mundane issues happen that directly affect its result. For example, Knuth once mentioning that a very small percentage of implementations of a particular quick sorting algorithm appearing in the literature are actually correct.
Small Functions as a Vehicle to Algorithms
Small methods are a much more fruitful way to express complex algorithms, because they have an important property: they are able to convert the dynamic world of algorithms into the static world of classes and their associated structures. This is not a small feature, and it is the root of the power of the Smalltalk approach.
In a Smalltalk program, every method is just a few lines long. Incidentally, that is why they have such a simplistic editor that can display only a small number of lines. When one sees this kind of program, there is the feeling that every method does very little. However, this allows a number of important features that are core to the philosophy promoted by the language.
First, it is very easy to determine how a single method works. The two-to-five-lines rule used when creating new methods makes it simple enough to understand their contents just by inspection – unlike anything you could do with long methods or functions. As an example, a number of static analyzers for languages such as Java and Objective-C fail when a method is too long. If a computer has problems when considering the branching possibilities in large methods, imagine how difficult it is for humans!
As another advantage, all the complexity of an implementation can been moved from the leaves of the system (the methods’ contents) to the internal nodes composed of classes and their methods. As a result, there is a large number of self documenting methods that can be analyzed by just looking at a class diagram or class browser. This is exactly the reason why the class browser is the standard tool in Smalltalk systems.
Finally, all the dynamic aspects of a program are stored in the code either using polymorphism (which further reduces the complexity of each individual method) or as part of the methods themselves, using selection and repetition structures. However, since these control structures are used in very small pieces of code, the resulting interactions are also very easy to understand.
Small Methods in Traditional Languages
Small methods can be a powerful weapon when trying to reduce the complexity inherent to software programming. Looking in this way, it is hard to understand why this kind of methodology is not more widespread in the programming field.
The first reason is the belief that programming with short functions/methods is bad from a performance standpoint. This kind of view is less relevant each year due to the increasing performance of computer systems, but is still around. The best answer is that doing otherwise is a premature optimization, and code quality should be the number one priority for a software engineer.
Another valid reason is the increase in class complexity when a large number of small functions or methods are used. This can justify the idea of using longer methods and a smaller number of methods per class. The solution for this problem, however, is already in place with modern IDEs. Each on of them allow programmers to traverse the hierarchy of classes in a system, most frequently using graphical tools to simplify the task.
When using this kind of system, it is important to emphasize the complexity shift from single methods to the whole class, while moving from analyzing the contents of a method to looking at class names and connections between classes. Modern IDEs also provide tools for moving methods around, using refactoring techniques that have been significantly improved during the last decade.
The good news is that, although Smalltalk is built around the idea of very short methods, it is not necessary to use Smalltalk to benefit from that concept. It is nowadays possible to use the same techniques in any object oriented language. In fact, it is possible to do this even on traditional languages such as C or Pascal, although this will result in losing the benefits of polymorphism and encapsulation – which can even be a reasonable tradeoff depending on the type of application being written.