Software development often reminds me of the “peanut butter and jelly sandwich” exercise. This is where two people sit back to back: one responsible for making the sandwich, the other responsible for providing precise instructions on how the sandwich is made.
Although it sounds like a trivial challenge, there is a twist to it: the person making the sandwich must interpret the instructions literally, even if they’re vague or incomplete. This usually results in silly outcomes like an entire jar of peanut butter being placed on top of a loaf of bread still in its bag. In one demonstration, I have even seen someone use a saber to “slice the bread”—that one was my favorite.
The purpose of this exercise (contrived though it is) is to show how difficult communication can be when you don’t have effective two-way feedback, shared context, and frequent reviews of a work-in-progress. Unfortunately, this sort of environment isn’t very far removed from what the typical software development team experiences day-to-day.
There is a unique aspect of our work in that eventually each instruction needs to be written up for a mindless automaton to follow. This is literally what the coding process is all about: converting human intentions into digital instructions. Much gets lost in translation because coding is a difficult task in itself, and it takes a continuous effort to keep an eye on the big picture while simultaneously working at the primitive level of modules and functions.
The solution to this problem is simple if not always easy to implement: drive up communications quality as much as possible.
There are many different tactics that can help create better feedback loops, but at the heart of all of them is the concept of reification: to take an abstract idea and turn it into something tangible.
Going back to the peanut butter and jelly sandwich exercise for a moment, think of a slightly more plausible scenario in which the person making the sandwich is reasonable about interpreting instructions, but simply has never prepared or eaten a PB+J sandwich before. A single picture and the right supplies would probably be enough to explain the entire ‘recipe’ to them.
Even in the cases where the instructions might conflict with the picture, it still provides a shared reference point for communication. This makes it so that relatively simple alterations like “remove the crust” or “toast the bread” would be far more likely to be carried out successfully without much confusion.
When building software, we can use wireframe sketches and mockups for similar purposes. For example, suppose someone asks you to build a music video recommendations feature for an application. The following sketch could serve as a useful starting point for further discussion:
Sometimes a sketch will confirm a shared understanding of the problem, where in other cases it’ll reveal fundamental misunderstandings. For example, a music video recommendation system might be designed to work as shown above, but it also might be set up to automatically play one song after another, using thumbs up and thumbs down buttons to give feedback that informs the next selection.
Reification is also a progressive process… once you make something even slightly concrete, it is natural to begin filling in some of the more specific details. For example, where are those thumbnail images going to come from? Will the video properly adjust its orientation and aspect ratio when running in full screen mode if the phone is rotated into landscape mode? Do we need a new sketch to confirm what that would look like?
The purpose of wireframe sketching is not nail down a picture-perfect view of the desired outcome, but just to bootstrap conversations. Eventually static visuals break down, because it is very difficult to communicate behavior and workflows through words and pictures alone.
This is where looking for examples in the wild can come in handy, but also where you need to be careful. When someone casually says “make Thing X work like how YouTube does,” it provides a very concrete example for you to look at, but interpreting that instruction requires a whole lot of context.
The heart of context begins and ends with purpose. A peanut butter and jelly sandwich made for a classroom demonstration on listening is different than one made to eat for lunch, which in turn is different from one made to look good in a stock photograph.
Why are you being asked to build a music video recommendations feature in the first place? Is your company providing a video hosting service like YouTube? Or is it selling band T-Shirts? Or are you developing the application as a demonstration for a blog post or a book? Context matters greatly: what is perfectly fit for one context would be disastrous in another.
I’m sure that for many, this blog post feels a bit basic, and it is! But it’s also fundamental: without an iterative process of progressive reification and ongoing two-way conversation with stakeholders, you many end up cutting a loaf of bread with a saber when you should have used a serrated knife.
For much more on this topic, see Chapter 1 of Programming Beyond Practices. 🙂