Object-Oriented Sandwiches — Part 2
Welcome to part two of my series explaining Object-Oriented Design (OOD) through the metaphor of a fictional sandwich shop. In this part we’ll examine communication, the importance of trust and why everybody hates a micromanager.
These examples build on the previous post, so if you haven’t read it yet, check out part one first.
Welcome back to the Rubytown Sandwich Shop
We’ve discovered that the sandwich shop is not just a single thing, it’s a collection of things: sandwich-makers and sandwiches, recipes and rooms. But that could just as easily describe a bankrupt business, with its windows shuttered and its doors locked. A thriving business like RSS requires these objects to do things. To interact. To communicate.
How to order a sandwich
Ordering a sandwich requires communication between the customer, Jane and Bob. It looks like this:
- The customer gives Jane the name of a sandwich and enough money to pay for it.
- Jane writes the name of the sandwich and the cost on an order slip and hangs it in the window where Bob can see it.
- Bob gives her back a sandwich that matches the order.
- Jane calculates the customer’s proper change on the order slip and returns the change and the sandwich back to the customer.
Take a moment to notice what’s not being passed:
- Jane doesn’t pass in the money, because Bob doesn’t care about money.
- Jane doesn’t pass instructions on how to make the sandwich or what ingredients to use, because Bob already knows how to take a name and turn it into a sandwich.
- Bob returns the sandwich and nothing else.
- Jane gives the customer the correct change without explaining about things like taxes and she gives them the sandwich without mentioning anything about Bob.
When Jane orders a sandwich from Bob, she hangs an order slip in the window. Jane knows the slip can hold a sandwich name, an amount, a tax amount and a grand total. All Bob cares about is that the slip will already contain a sandwich name: he ignores the rest. Bob and Jane use the slip for different purposes, but what’s on the order slip gives both of them everything they need.
In programming, communicating through a standard form with clearly-defined rules is called a “protocol” or a “contract”. Order slips are “data transfer objects” because we use them to transfer data — sandwich names, etc. — from one object to another.
The other benefit of this approach is that the exchanges are so simple: the customer tells Jane “I want” and Jane tells Bob “I want”. Jane and Bob each have a single call in their public interface, making it clear how they can interact. All the details of how sandwiches are made and how taxes figure into the final total are hidden from the other players.
It’s about trust.
How not to order a sandwich (a.k.a., nobody likes a micromanager)
Now let’s imagine a different world: a world where the customer doesn’t trust Bob and Jane. Our untrusting customer is named Richard. This is how Richard orders a sandwich.
- Richard decides what sandwich to get and notes the price: $6.95.
- Richard asks Jane how much sales tax is in this state and she tells him 5%.
- Richard multiplies $6.95 by 0.05, adds it to $6.95 and comes up with $7.30.
- Richard gives Jane a $10 bill and tells her he wants $2.70 back.
- Richard goes back in the kitchen and tells Bob “Toast 2 slices of dark rye. Put 3 thin slices of ham between them. Put 2 slices of swiss cheese on top of the ham. Slice it diagonally and wrap it in 1 sheet of wax paper.”
- Richard takes the finished sandwich and leaves.
In the real sandwich shop, this story would end with Bob chasing Richard down the street waving a bread knife, but believe it or not, this is how a lot of people write object-oriented programs. In this style, the “customer” object — which would be Richard — is making all the decisions and manipulating the other objects to accomplish the task. The other objects are merely extra sets of hands that know how to juggle or give a thumbs-up or tie a pair of shoelaces.
Without trust, your customer object becomes the most dreaded of bosses: the “micromanager”. Micromanagers don’t trust anyone but themselves to get the job done right, so they make sure the only things their employees do are so trivial and brutally-simple that there’s no chance of failure. Any sort of decision-making, problem-handling and result-verifying is too important to be entrusted to the low-level morons who work for them. Micromanagers operate under the principle that they are the only member of their team with a functioning brain and this disrespect makes it very hard to keep employees, who head for the hills at the first glimpse of daylight.
The practical downside is that the micromanager needs to know and be involved in every single detail about every single job his “team” might be expected to do. Any time the details of something change, he needs to know. If the toner runs low in the printer, he needs to tell someone to order more. If a supplier changes addresses, he needs to update his forms. Micromanagers are not calm, relaxed people. They also can’t ever get sick or go on vacation or even take a long lunch because their “team” is helpless when left to its own devices.
In programming, we call this a “dependency”: every member of Richard’s team depends on him for the details of how they do their job. If he is ever promoted, quits or gets run over by a bus, they are helpless. Highly-functional teams have dependencies that run in the other direction: the manager knows she can depend on her team to get work done with little to no supervision, because they’ve been trained to do a complete job, not just the trivial parts.
In addition, notice how complicated the exchanges have become. I count 7 different calls being made, all from Richard to either Jane or Bob. The order slip has disappeared and so have Bob and Jane’s private interfaces, because everything is now public. If any of those details change, the customer will have to change as well, increasing the hassle of maintenance and the opportunity for error.
So how do we get trustworthy “employees” to rely on? Bob and Jane are forced to investigate this in our next installment when Bob gets bad news from his doctor.
- The most important part of your application is not the objects you have, but the messages they pass between them. The interaction between objects is what makes your application come to life.
- Trust is the key to communication: tell an object what you want, not how you want it done. Nobody likes a micromanager.
- Trust also keeps public interfaces simple, hiding most of the complexity in private interfaces that only the object itself needs to care about. Objects need their privacy.
- Wrapping the details of your message in a data transfer object creates a standard “form” that every object understands how to use and simplifies message-passing.
- Dependencies in your application should be inward: the object that interacts with the outside world should depend on internal objects to accomplish tasks, not the other way around.