Object Calisthenics: write better object-oriented code
“Object Calisthenics” is supposedly an exercise to get you to write better object-oriented code. If you want me to sum-up in one sentence I will definitely say:
“That which obscures my code is bad.”
We’ve all seen poorly written code that’s hard to understand, test, and maintain. Object-oriented programming promised to save us from the old procedural code. And it promised allowing us to write reusable software incrementally. But sometimes it seems like we’re just chasing down the same old complex, coupled designs in any OO-capable language (Java, PHP, …) that we had in C.
It’s well understood what are the core concepts behind good design, any software engineering book will hightlight seven code qualities that matter: cohesion, loose coupling, no redundancy, encapsulation, testability, readability, and focus. Yet it’s hard to put those concepts into practice there are some other rules that could help us.
Anyway, Object Calisthenics is an idea suggest by Jeff Bay in The ThoughtWorks Anthology , and lists 9 rules to writing better Object Oriented code. Among those rules are:
- Use only one level of indentation per method
- Don’t use the else keyword
- Wrap all primitives and strings
- Use only one dot per line
- Don’t abbreviate
- Keep all entities small
- Don’t use any classes with more than two instance variables
- Don’t use any getters/setters/properties
- Use first-class collections
This is not intended to do it in a production code but for example in a code kata. In fact, I found it a little difficult to completely apply all of the rules to any code. Particularly the 7th rule, as in many situations your working model could be a little more complex than this particular rule allows.
The Challenge
Rule 1: One level of indentation per method
This is really easy as you only has to ensure that the method you are writing only performs one simple tasks: one control structure, or one block of statements, etc. The way to achieve this is to split methods up.
Rule 2: Don’t use the ELSE keyword
Nearly every programmer has seen a nasty nested conditional that’s impossible to follow, or a case statement that goes on for pages. Object-oriented languages give us a powerful tool, polymorphism, for handling complex conditional cases. You can take this to avoid the ELSE keyword. Or if you want an easy approach you can perform “early return” for the particular situation of handling only two conditionals.
Rule 3: Wrap all primitives and Strings
This rule tries to encapsulate all the primitives with in objects for allow our programs to work in all our code in a OO-way. For example you can wrap the int primitive like this:
class IntegerNumber
{
private $number;
public function __construct($number)
{
$this->number = $number;
}
Rule 4: Use only one dot per line
In the case of PHP, my language of choice, only one arrow after $this->, since the former arrow cannot be omitted. Respecting the Law of Demeter was not an issue but it forced you to continuously avoid foreign methods, substituting them with methods on the right class.
Rule 5: Don’t abbreviate
It’s often tempting to abbreviate in the names of classes, methods, or variables. Please, resist the temptation – abbreviations can be confusing, and they tend to hide larger problems. The most common example in PHP are C-like languages could be the next one.
public function isTrue($boolean)
{
return ($boolean == true) ? true : false;
}
Rule 6. Keep all entities small
This means no class over 50 lines and no package over 10 files. Classes over 50 lines usually do more than one thing, which leads to be harder to understand and harder to reuse. In fact, they have the added benefit of being visible on one screen without scrolling. By reducing the size of classes and packages you’ll start to see that packages represent clusters of related classes that work together to achieve a goal. Packages, like classes, should be cohesive and have a purpose. Keeping those packages small forces them to have a real identity.
Rule 7: No classes with more than two instance variables
Obviously this will force you to do decomposition, but I think this this will make all the package harder to understand.
Rule 8: No getters/setters/properties
Well I find this rule really coupled with previous one. If your classes become simpler and try to encapsulate only one of two instance variables you don’t need getters or setter methods. The idea behind strong encapsulation boundaries is to force programmers working on the code after you leave it to look for and place behavior into a single place in the object model. This has many beneficial effects, such as a dramatic reduction in duplication errors and a better localization of changes to implement new features.
Rule 8: Use first-class collections
Application of this rule is simple: any class that contains a collection should contain no other member variables. Each collection gets wrapped in its own class, so now behaviors related to the collection will not be mixed with behavior related with the elements. This collection class will include filter methods, and handle activities like joining two groups together or applying a rule to each element of the group.
Conclusions
These rules allow us to move us towards object-oriented good habits, or at least to force us to think when we are about to break them. However, design cannot be enforced just by a few rules. Almost all the rules are simply ways to visualize and implement the holy grail of object oriented programming – encapsulation of data. Anothers force you to use the appropriate use of polymorphism, and another is a naming strategy that encourages concise and straightforward naming standards. The entire challenge is to craft code that has no duplication in code or idea. Code which concisely expresses simple and elegant abstractions for the incidental complexity we deal with all day long.
If you want to a real example of Object Calisthenics applied to one real example visit the next link: http://www.markhneedham.com/blog/2008/11/06/object-calisthenics-first-thoughts/