In the second live session of my object oriented design class, The Object Oriented PHP Masterclass, I show my students domain modeling, both with slides and with a live coding demonstration.
In my demonstration, I show them how I break the single model they’ve been using into three component parts: a value object, a data layer object (usually that talks to the database), and a gateway object that stands between the other two.
This is a classic implementation of the Mediator pattern, but almost always draws a predictable question from my students: why are you abstracting this to that level?
The temptation to “Abstract All The Things”(tm)
Abstraction is a bedrock principle of object oriented design. The concept that large tasks are broken into smaller, more manageable objects is fundamental. Blog posts about the single responsibility principle draw a yawn, because nobody bothers to question it’s validity.
That’s because abstraction makes sense, once you understand it. Breaking large tasks into smaller objects works, because it improves maintainability and modularity. It encourages reuse. When done correctly, it reduces code duplication. These are all great things.
Of course, when we’re new at object oriented programming, the principle of abstraction is really hard to grasp. It’s why I teach it first in my class; I want my students to grasp that principle over almost every other.
But once it’s learned, do we ever learn when and where to stop abstracting? Too often, I come across code that is so abstracted it’s nearly impossible to follow or understand (unless, of course, you’re the original author). This is clearly not what the developers of object oriented design had in mind.
Code as communication (and not just with computers)
Code spends 80% to 90% of its life in maintenance. And in my own experience, the people maintaining the code are not always the same people who wrote it.
That means that another developer is going to have to understand your code, and be responsible for maintaining it.
Developers don’t like maintaining existing code. With a dollar for every time I hear “this code is crap” when someone takes on a new project, I could retire comfortably. Developers like to write code, but they don’t like to work on someone else’s code.
But the truth is that they’re going to be maintaining your code. They’re going to be struggling to understand what you meant, what you intended, and why you made the design decisions you did.
This means your code is going to have to communicate with more than just a computer processor. It’s going to have to communicate intent to developers who have never seen the code before. This is much more challenging than writing code that “just works.”
Abstraction to the most reasonable layer
My students ask a poingient question when I show them abstraction of the database layer to allow for new or different data storage options. They ask, “if my application is never going to use anything but a database, why do I need to possibly support other database types?”
Of course, my answer is almost always the same: following best practices isn’t about what you may or may not do in the future, its about enabling you to do something more easily later on. Of course, I almost always temper this with saying that it’s up to the individual developer to decide when, where and how far to take abstraction.
Just because you can abstract something doesn’t mean that you necessarily should.
Instead, you should abstract only to the most reasonable layer. If you can abstract something, but doing so would make it less readable, less usable, or less testable, don’t do it.
Want to boost your career and your OO chops?
I’ll be offering a new section of The Object Oriented PHP Masterclass in June. Registration will open mid-May. The first class sold out, so don’t miss out on your opportunity to finally put your object oriented programming problems to rest! Sign up in the box below to get updates about the class, including notification when registration opens!