This is an editorial of the SitePoint PHP Newsletter from May 30th, 2017!
Laracasts recently published a very interesting non-Laravel video about something called visual debt. It’s only 3 minutes long, so please, take the time to watch it before reading further.
Done? Okay, spoilers below.
In the video, Jeff starts out with with a bit of verbose event-based code with some listeners, fire methods, an interface on which to base the various classes, and quite a few type and return hints all over the place.
As he scrolls through the code, he claims it’s full of visual debt. Jeff then goes on to explain that while PHP does offer type and return hints, they aren’t necessary, and promptly removes them from all method signatures to reduce the amount of code. “We were doing fine for a really long time without them”, he argues.
He then reaches for interfaces and removes those, too. He argues that people reach for them too often, too soon, and add unnecessary weight to their code.
In what seems like a final cut, he removes the “final” keyword from a class arguing that it’s silly to protect a developer from themselves, but then unexpectedly, he also cuts out even the public
keyword in front of the remaining methods, leaving them at the language default (which, incidentally, is an implied public
).
The end result? About 25% less code in this simple example. But is the debt gone?
If you’ve followed my rants to any extent, you know that I’m very anti-legacy, and pro-verbosity. As such, I was thrilled when proper type hints arrived in PHP.
The number of bugs I had run into and the amount of time I had wasted when working on other people’s code because they didn’t make it obvious which type of value is expected as input or output of a method is tremendous, and just having the ability to get good, automatic static checking done, and proper, verbose IDE autocompletion tips while working was worth the transition to the newest PHP version across the board for me.
When working in teams, more control over code means fewer human-caused errors, and I’m all for that. Time is precious, and wasting it on predictable mistakes is downright sinful. I cannot agree with Jeff in removing these from his code. We were doing fine without them for a long time, but we were doing fine without a lot of things that now make our lives much better. To me, they don’t present visual debt – I feel in debt without them, because I know I could benefit from them in a way which prevents technical debt.
I do agree with him in removing the interface. In the case in the video it provided no tangible benefit, though this may have been because of the example code itself. He picked Events as an example, and his Event class as described in the video was in fact quite the decent interface on its own.
In general, I think interfaces are okay if you’re either building something that’s meant to be developed as an extension or a drop-in replacement for something, or when the package you’re using uses an interface to make sure the signature matches, but otherwise they do add quite a bit of code weight. I remember my old Zend Framework 1 days when 20 levels deep into the framework’s directory structure there were core interfaces with no body – just a class and empty braces. Code bureaucracy, in a word.
The removal of final
was completely justified. Preventing people from extending a class (which is easy to circumvent anyway) does seem pointless, and if it’s meant as an in-team preventative measure to keep colleagues in check, it’s just as effective as a memo. Some will disagree passionately, but I say down with final
. I don’t necessarily see its presence as visual debt, or its absence as the possibility of technical debt – I just don’t see the usefulness of it.
Finally, there’s the removal of public
in front of methods, i.e. from this:
public function fire( ... ) { ... }
to this:
function fire ( ... ) { ... }
I can’t say I agree with this. While it does remove some characters from the file, I believe it does more harm than good. First, as someone with a mild case of OCD, I’d be incredibly bothered by the fact that other methods have protected
and private
, but public
ones are naked.
function fire ( ... ) { ... }
protected function log ( ... ) { ... }
Secondly, almost all examples everywhere use the public
keyword even though it’s unnecessary – they do this to teach people who are just starting to explore PHP what it means, and to train them to use one common approach. Imagine where we’d be had everyone been trained to use spaces from day 1? Third, while the public
declaration isn’t necessary now, most people use it and it may very well become obligatory in the future, much like PHP4-style constructors worked up until version 7.0 and then no more. What this removal of perceived visual debt leaves you with, then, is technical debt.
Conclusion
In general, I’d say I strive for common sense (no need for final, or for interfaces when they’re obviously not needed) and err on the side of verbosity: static type hints even on solo projects and verbosity over visual freedom in teams, because verbosity makes things clearer to everyone and reduces misunderstanding.
In conclusion, I don’t have a die-hard preference in this case. My opinion here is a mixture of yes and no to each of his arguments, but I do fully agree with his final sentiment: question everything – even the person who tells you to question everything.
The curse of knowledge is strong, and the argument from authority even stronger. Don’t let yourself be carried by the wave of perceived expertise just because the surfboard feels safe. There be sharks in the form of both visual and technical debt, and good code is always a balance of both.
How do you feel about the visual freedoms presented in the video? Which ones bother you, and which ones would you adopt?
Bruno is a blockchain developer and technical educator at the Web3 Foundation, the foundation that's building the next generation of the free people's internet. He runs two newsletters you should subscribe to if you're interested in Web3.0: Dot Leap covers ecosystem and tech development of Web3, and NFT Review covers the evolution of the non-fungible token (digital collectibles) ecosystem inside this emerging new web. His current passion project is RMRK.app, the most advanced NFT system in the world, which allows NFTs to own other NFTs, NFTs to react to emotion, NFTs to be governed democratically, and NFTs to be multiple things at once.