“What” instead of “How”

Leena
Continuous Delivery
4 min readDec 13, 2017

Imagine a restaurant kitchen. Customers order food off a menu. These orders come into the kitchen through a little window (the one with the bell beside it, “order up!”) and the food eventually comes out. To a naïve imagination, it may seem as if the kitchen is filled with magical plates of food that are waiting, pining to be ordered, but in reality the kitchen is full of people, food, and frenzied activity and each order triggers a new construction and assembly process.

The kitchen does many things but does not, thankfully, expose them all to its customers. It has a public interface that customers are expected to use; the menu. Within the kitchen many things happen, many other messages get passed, but these messages are private and thus invisible to customers. Even though they may have ordered it, customers are not welcome to come in and stir the soup.

This distinction between public and private exists because it is the most effective way to do business. If customers directed the cooking, they would have to be re-educated whenever the kitchen ran low on an ingredient and needed to make a substitution. Using a menu avoids this problem by letting each customer ask for what they want without knowing anything about how the kitchen makes it.

Sandi Metz — Practical Object-Oriented Design in Ruby

The above restaurant kitchen is relevant in many contexts, say the way we run our businesses or in general how we work with each other. We enjoy our work when we know “what” to do than getting instructions on “how” to do it. But it’s also true that we find it hard to design businesses in that way.

And it is relevant to our code too. There are two guidelines that the above example emphasises:

  • Public and Private Interface
  • Asking for “What”, instead of Telling “How”.

Each of our class is like a kitchen. Expose the responsibilities as public methods and keep the methods used internally for achieving the responsibilities, say the utility methods, as private. Most of these internal methods talk about the “how” of the responsibility and the public methods talk about “what” of the responsibility.

In the POODR book, Sandi talks about another example — automating the operations of a Bicycle Touring Company. Take a scenario that we need to implement the feature that the bicycles need to be prepared before each trip by a mechanic. Below are the two implementations of the same:

Compare this with the restaurant kitchen analogy, i.e., we don’t tell “how” to prepare instead we tell “what” we want, and it gets delivered to our table. It is violated in the above implementation, as the trip tells the mechanic to execute each step of the preparation. In case a new step gets added, the trip will have to tell the Mechanic explicitly.

The Trip is tightly coupled with Mechanic, and with Bicycle class. So a slight change in Mechanic can affect Trip.

The above is the updated design for the same where Trip tells Mechanic what to do, and Mechanic takes care of the same. The responsibility of the Mechanic is to prepare_bicycle, exposed publicly. And there are multiple steps the Mechanic executes to complete the preparation, not revealed publicly. The Mechanic interface is clean now and minimises the dependency with Mechanic.

Getting started with flexible design

How can we arrive at a similar design which is flexible and less-coupled? Identifying the domain objects in the application is easy. Usually, those are the nouns in the system. To identify the messages [it is better to consider each method as a message used for communication], we need to draw the sequence of events within the application.

The usual tendency is to start writing code, but it is better to spend some time thinking about what you are going to implement using a pen and paper. This works well with Test Driven Development [TDD] too, because it helps us to identify the first test to write and emerge our design.

Tell, Don’t Ask and the Law of Demeter principle, as written in my earlier post, is one of the fundamental principles for keeping the code more flexible. Similarly, the above guidelines by Sandi Metz help to keep the code more flexible. Continuous Design and Refactoring are the ways to apply these consistently.

--

--

Leena
Continuous Delivery

Co-founder/CTO @ PracticeNow, Bangalore, India. A strong believer of lean principles, an evangelist and practitioner of Continuous delivery