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 back 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 which 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, each would have to be re-educated when 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.
Each of your classes is like a kitchen. The class exists to fulfill a single responsibility but implements many methods. These methods vary in scale and granularity and range from broad, general methods that expose the main responsibility of the class to tiny utility methods that are only meant to be used internally. Some of these methods represent the menu for your class and should be public; others deal with internal implementation details and are private.
The methods which make up the public interface of your class comprise the face it presents to the world. They:
- Reveal its primary responsibility
- Are expected to be invoked by others
- Will not change on a whim
- Are safe for others to depend upon
- Are thoroughly documented in the tests
All other methods in the class are part of its private interface. They:
- Handle implementation details
- Are not expected to be sent by other objects
- Can change for any reason whatsoever
- Are unsafe for others to depend on
- May not even be referenced in the tests
Responsibilities, Dependences, and Interfaces
Chapter 2 was about creating classes that have a single responsibility. This notion of single responsibility goes hand in hand with the idea of defining a public interface for your class. There is a correspondence between the statements you might make about your class's responsibilities and its public methods. Indeed, public methods should read like a description of responsibilities. The public interface is a contract which articulates the responsibilities of your class.
Chapter 3 was about dependencies and its take-home message was that a class should depend only upon classes that change less often than it does. Now that you are dividing every class into a public part and a private part, this idea of depending on less changeable things also applies to the methods within a class.
The public parts of a class are the stable parts; the private parts are the changeable parts. When you mark methods as public or private you tell users of your class upon which methods they may safely depend. When your classes use the public methods of others, you trust those methods to be stable. When you decide to depend on the private methods of others, you understand that you are relying on something that is inherently unstable and are thus increasing the risk of being affected by a distant and unrelated change.