A question was asked on Reddit and showed up in my feed as I was browsing this weekend:
What does protocol oriented programming mean, and why is it better than OOP?
“Explain Like I’m Five” – A laundry service example
First, the example provided was very understandable. I highly recommend you jump over and just read through what the commenter wrote.
The theme was “laundry service”. Supposing that there was a
Laundry object that encapsulated certain laundry-related functions… “Launder my clothes, please” — “Okay, here’s your clothes!”. You as a client simply interact with
Laundry by saying “Launder, please!”. The
Laundry object goes off and does its thing, which could range from simple to incredibly complex – the beauty is that as a client, as a person needing laundry done, you don’t care. As long as the laundry gets done and you get your clothes back, life is great!
“Problems” with Object Orientation
In my guide on the Fundamentals of Callbacks for Swift Developers, I describe the scenario that we’re all in as developers:
When we’re building software, we’re either using code built by others, or creating code for others to use, are we not? We’re either using code that “hooks into” what other developers have designed and made available to us, or we’re creating code that other code will “hook into” and interact with, even if the “other code” is written by us in our own app.
We wear two hats at once, when it comes to being clients and creators of code.
But what if we’re working with a
Laundry object as a developer/creator, and not as a client (ie, someone who needs laundry done). What if we, as developers, get handed a
Laundry object in a library and we want to customize its behavior… maybe improve the performance of
launderClothes(), or override the implementation it to use some amazing new laundry service.
The way we’d do that is by crating a subclass. Here’s the beef with Object Orientation, according to the commenter:
[Object Orientation] encourages “encapsulating complexity” by exposing state and internals through inheritance.
Unpacking that: Software has innate complexity. Objects are “things” that encapsulate that complexity. They do it in a certain way though: They expose certain pieces of state and pieces of functionality. The way those abstractions over complexity get propagated and customized through the system is through this mechanism called inheritance.
But the commenter cites this methodology as “trouble” though. Why? Well…
“I may not want to know how my dry cleaning got done, but if I wanted to design a better route to go from dirty clothes to clean clothes, I would necessarily have to know every last detail of the steps that were performed so I can try to refine them in my subclass.”
So the commenter is coming at it from the point of a developer/creator. It’s pointed out that to truly be able to improve performance or refine algorithms in a subclass, we necessarily have to know every detail of the steps that were performed in the superclass. And it’s not always the case that we can discover that superclass implementation to improve upon it.
Shifting to Protocol Orientation
So… Protocol Orientation? If it’s better, how is it better?
I love how the commenter takes the object oriented example of laundry service, and refines it with nuances that come out of thinking in terms of protocols rather than just objects. Really. Have a look.
The primary difference we see is that rather than having a
Laundry object… a single one… that does laundry in its own particular way, a shift occurs: We begin to deal in terms of describing ways to get laundry done.
If I want my laundry done one particular way by one particular guy I go Object-Oriented and stop caring about how things get done. But if I want to generalize over the ways to get laundry done I need to go Protocol-Oriented and stop caring about everything else.
In Protocol Orientation, the only thing that matters is the interface… the things that clients will interact with. Describe that to the best of your ability with a protocol, and let something else come along and worry about the how.
In the end, the only thing that a person needing laundry done needs to know is what interface is available for them to accomplish the laundering they have need of completing.
Being able to sit down and think about how something would look if you removed state and inheritance from the picture and just thought about the bare minimum required interface to that particular task is a far more powerful and simple approach to programming that enables reuse far easier than OO ever did.
The take-away point for me in this thread on Protocol Orientation is this: Protocols are about generalizing. They’re about the interface. It’s about a mindset and a focus (an orientation) toward thinking of ways to do certain things, and describing them clearly in the form of a Type in Swift.
Once the way to do something is described, other things, concrete Types, can come along and implement those in an infinite variety of ways.