Abstractions and Vacations
One of my favorite questions to ask other programmers is:
“In the years you’ve been writing code, what principles have you seen rise to the surface and how do they inform the decisions you make today?”
The answers to this question say a lot about where the person is in their progression as a developer.
At this point in my career, the answer I give most commonly relates to properly executed abstractions. If you are a new programmer, the term “abstraction” may not mean much to you. Given time, however, you will undoubtedly experience the effects of abstractions, both good and bad.
What is an abstraction?
Let's tease out abstractions with an example from the real world. Say you’re taking a vacation with your family. Would the first step be to go to your local airport and get on a plane? Of course not. You must know where you are going, with whom, and for how long.
Once you’ve determined the destination, participants, and duration, you breakdown more specific details. Details like finding the best price on a plane ticket, deciding which Airbnb to reserve, or scheduling a rental car all need attention.
An abstraction in this example might look something like this:
In my case, I'm good at purchasing plane tickets, so I would handle those details along with the car rental. My wife would care for the lodging and finding local attractions. The kids will be responsible for packing a book or stuffed animal to keep them company during the journey.
See how no one person is tasked with more than they can handle? It wouldn’t make sense to have the kids buy the plane tickets; they would have no idea what to do. But bringing a travel toy is completely within their realm of understanding (hopefully).
Abstraction is a kind of organization accomplished by delegating responsibilities and information so that each segment isn’t overwhelmed or doing more than its fair share.
What an abstraction isn’t
An abstraction isn’t simply dividing something into X equal parts and distributing it among the participants.
It also doesn’t need to be complicated to be effective. Surely there is more complexity in knowing when and with what airline to purchase tickets than there is with selecting a toy, but each is important when factored into the big picture. (Do you want to sit on a plane with a toddler who has no toys? Me neither.)
Putting all the responsibility in one place isn’t an abstraction at all and will probably result in details being missed.
What are signs of a bad abstraction?
Abstraction is a dangerous tool if wielded improperly. A bad abstraction can keep you hopping back and forth in a codebase, scratching your head saying, “Where does this thing happen?”
Here are a few clues that might indicate you have a bad abstraction:
1. You need multiple sentences to describe what a section of logic does:
- This task includes logging in to multiple travel websites, providing destination and dates, comparing pricing, and saving potential flights for later review.
- This code creates a new user record, hashes their password, saves their email, sends a verification check, subscribes them to the newsletter, and charges their credit card.
2. The logic has both high- and low-level responsibilities:
- This task must book flights (high-level) and make a reservation at Giovanni’s on Friday evening at 6 (low-level)
- This code registers a new user (high-level), verifies API keys, connects to the mailing service provider, and sends a welcome email (low-level)
3. The logic handles unrelated concepts at the same time:
- This task is reserving a rental car (concept A) and purchasing new travel luggage (concept Z)
- This code registers a new user (concept A) and runs database migrations (concept Z)
How can abstractions help you?
As a younger programmer, I used to get frustrated when I would look at a section of code and not grasp all it was doing. It led to me questioning my ability to even program at all.
As time went by, however, I found that this “shortcoming” resulted in better abstractions. Because I couldn’t understand 100 lines at once, I was forced to break down the logic into smaller pieces, each of which made sense to me.
While I couldn’t digest code that did A, B, C, and D all at once, I could understand what A did by itself. This meant I could break A out of the larger flow, test it in isolation, and not have to consume such large sections in one sitting.
Back to our vacation example… a good abstraction would be dedicating focused time to the purchase of plane tickets. This way you can find the right combination of flight times and price without being distracted by things you can decide later (or have already decided).
Another benefit of abstraction is the freedom it gives to change the internals of a section of code without the fear of breaking larger application logic. If feature A is given input and returns specific output, does it really matter what happens while the logic is inside feature A? That gives me the freedom to design and adjust over time.
Does the airline you choose have any bearing on which attractions you visit? No, as it shouldn’t.
Bon voyage!
As we’ve seen with our vacation example, a proper set of abstractions will allow you to keep the big picture in mind, delegate the pieces down the hierarchy, and continue breaking concepts down to consumable ideas.
Being able to identify and implement proper abstractions will help you and those whom you take on vacation!
Want to read more tips and insights on working with a website development team that wants to help your organization grow for good? Sign up for our bimonthly newsletter.
By Jesse Schutt
Director of Engineering
Jesse is our resident woodworker. His signature is to find the deeper meaning in a project and the right tool for the job.