Avoiding object oriented overkill

« »

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!

Learn all about abstraction, single responsibility, developing interfaces and more with The Object Oriented PHP Masterclass. New section starting in June. Get updates and be the first to book your seat!

* indicates required

Brandon Savage is the author of Mastering Object Oriented PHP and Practical Design Patterns in PHP

Posted on 5/1/2013 at 7:00 am
Categories: Object-Oriented Development, Learning, PHP, Refactoring, Best Practices, PHP 5

KingCrunch wrote at 5/1/2013 8:21 am:

> If you can abstract something, but doing so would make it less readable, less usable, or less testable, don’t do it.

Well, in my experience abstraction usually makes code more (re-)usable and testable. Of course only when it is made right ;)

However, with more abstraction you usually must test more and yes, the readability (especially the execution flow) can get harder to track. Oh, and of course performance :) Every abstraction layer introduces a new level of complexity (See nearly every ORM) Several currently existing “micro-frameworks” shows, that there are others aware of this too.

I for myself like to write some CLI-tools from time to time and I use SQLite as the only database. Here it doesn’t make sense to use anything else than native (optimized) SQL-Queries.

Hikari wrote at 5/3/2013 1:29 pm:

Indeed. There are some Design Patterns like Dependency Injection that are kinda complex to read and follow the workflow.

These kind of patterns are meant for complex softwares that require complex architectural and design solutions, that will bring real benefits like maintainability, testability, scalability, etc.

But for simple softwares they bring a level of complexity that’s not needed. In these cases they should be used only when the software may evolve to become more complex or for didatic reasons.

Tony Marston wrote at 7/18/2013 5:21 am:

The point to note about a database abstraction layer is not so that you can switch from a relational database to a totally different file system, but so you can switch from one RDBMS engine (eg: MySQL) to another (eg: PostgreSQL, Oracle, SQL Server). You may think that all SQL is the same, but there are subtle differences – MySQL and PostgreSQL use LIMIT and OFFSET for pagination, but Oracle and SQL Server use something totally different. All these differences should be handled within the specific database object so that the domain object can remain database-agnostic.

The idea that you may want to switch your persistent data store from a DBMS to CSV or flat files is never going to happen, so don’t bother trying to deal with it.

« »

Copyright © 2023 by Brandon Savage. All rights reserved.