Nick Arora

Practical Object Oriented Design by Sandi Metz

Practical Object Oriented Design

After spending enough time in the software industry, developers come to embrace a single, enduring truth: most applications are a complete mess. It doesn’t always start that way. Many successful businesses are built on the backs of perfectly acceptable code.

However, as time ticks on, that software endures a constant barrage of new requirements, feature requests, and bug fixes. These changes are often implemented under time pressure. Developers add hack after hack, and the software becomes harder and harder to change. The code calcifies - it’s rigid, brittle, immobile.

The problem with poorly designed small applications is that if they are successful, they grow up to be poorly designed big applications.

The Problem

Developers absolutely hate working on applications like this. But their distaste is not the real problem. The real problem is that the time and cost necessary to change the application have considerably increased. When a business has a hard time responding to changing market conditions, it can fail outright.

This paints a dire picture. Thankfully, Sandi Metz’s book, Practical Object Oriented Design, demonstrates how this bleak future can be avoided. The trick is learning to design code so it remains easy to change.

The purpose of design is to allow you to do design later, and it’s primary goal is to reduce the cost of change.

An Object-Oriented Approach

When developers first learn to write code, they start by writing procedurally. It comes naturally. The developer writes a list of steps. The computer executes them in sequential order. For simple applications, this can often be the best solution.

However, as the complexity of the application increases, the problems with procedural code start to surface. What was once a simple list of steps has transformed into a complicated, condition-laden, duplicative knot that is hard to understand and almost impossible to change.

An object-oriented (“OO”) approach offers a countermeasure to this problem. With OO, the code is organized into small, interchangeable units (objects) that collaborate by sending messages to one another. This offers several benefits:

However, it is important to note that OO is not a silver bullet. When used correctly, complex applications become easier to understand and change. But in the wrong hands, OO can be just as convoluted, calcified, and frustrating to change as a procedural code itself. This is why it is so important to study object-oriented design.

Object Oriented Design

Good design ensures code is arranged so that it is changeable in the face of unpredictable requirements. Designing for changeability is all about carefully managing dependencies.

A dependency is created any time one object collaborates with another object. They are a necessity as soon as your application starts doing anything relatively complex. The problem with dependencies is that when they change, things that depend on them may also have to change. In the worst case, even the smallest change can cause a cascade of failures through the codebase.

To tackle this, Sandi Metz prescribes several battle-tested strategies:

A class should do the smallest possible useful thing; that is, it should have a single responsibility.

Design experts notice domain objects without concentrating on them; they focus not on these objects but on the messages that pass between them

The choices you make about the direction of dependencies have far reaching consequences that manifest themselves for the life of your application. …if you get it wrong then the dependencies will gradually take over and the application will become harder and harder to change

You don’t send messages because you have objects, you have objects because you send messages.

Composition contains far fewer built-in dependencies than inheritance; it is very often the best choice.

Tests are your record of the interface of every abstraction and as such they are the wall at your back. They let you put off design decisions and create abstractions to any useful depth.

Conclusion

In recent years, OO design has received increasing criticism. Developers argue that it becomes bloated with complex class hierarchies and that alternative approaches (like functional programming) are easier to maintain. Sandi Metz reminds us that, when done thoughtfully, OO design remains a powerful way to keep software understandable, maintainable, and, crucially, easy to change.