It’s one thing to learn how to create an application using an object-oriented framework like Ruby on Rails.
It’s quite another to know how to create an application well, and by that, I mean that the code within an application is scalable, reusable, and flexible to change with minimal cost.
When constructing simple apps, developers new to OOD, myself once included, tend to have a
class-based perspective. “I know I need this class, what should it do?” is the foundation of this mindset.
message-based perspective, however, changes the question to, “I need to send this message, who should respond to it?”
As a concrete example, if I were to create an app for a cycling store that arranged bike trips, my initial programming might create a
Trip class that responded to a customer inputting the date of the trip, the difficulty of the course, and if they needed a bike, and if so, what type of bike and to check if that bike was ready to ride.
Instead of cramming many responsibilities into a single class, focus on the message, “Should
Trip class be receiving the message about the availability of bicycles? Should
Trip class be receiving the message about the condition of the bicycle?” Now the idea of creating a
Bicycle class or a
Mechanic class becomes a logical choice.
Having a message-based perspective in OOD doesn’t make you anti-class, rather it allows you to create the appropriate amount of single-responsibility classes based on the messages passed betweenÂ objects.
It’s important to delegate responsibilities in OOD. If your
Trip class has methods for having a bicycle’s frame cleaned by the mechanic, tires pumped by the mechanic, chain lubed by the mechanic, and brakes checked by the mechanic, you’ve overloaded your
Trip class with dependencies.
Trip class is dictating how your
Mechanic class should act. The message Trip is telling Mechanic here is “I know what I want and I know how you do it.” Not only that, if
Mechanic class were to ever change its preparation methods,
Trip class would break.
A key concept in OOD is to keep the messages as abstract as possible through “Duck Typing”. For example, instead of writing such concrete methods crammed into a single
Trip class, find the overarching simple message, in this case, “I want to prepare a trip.” From there, objects (i.e. classes) can collaborate without binding themselves to context and new objects can be introduced without re-tweaking every class created.
As opposed to the first example, this example has
Trip class telling every other class “I know what I want and I trust you to do your part.” This is a key component in OOD as there is more room for growth and for change.
If this example looks familiar, it’s because it was adapted from Sandi Metz’s work Practical Object-Oriented Design in Rubyâ€Š–â€ŠAn Agile Primer. I read this book outside of my usual regimen of coding exercises, algorithms, and Git commits because I wanted to move beyond focusing on the quantity of my coding. Rather my focus now is on the quality of my coding; coding that is scalable, reusable, and flexible to changeâ€Š–â€Šcoding that adheres faithfully to object oriented design.