By Bruno Skvorc

The Balance between Visual and Technical Debt in PHP

By Bruno Skvorc

This is an editorial of the SitePoint PHP Newsletter from May 30th, 2017. Subscribe here!

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.

A still screen from the referenced video

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.



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 everythingeven 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?

  • Cameron Junge

    Totally agree. Removal of type hints means that auto-complete in my IDE no longer tells me what types are expected – I’d have to look at the code if there was some strange behaviour, or add PHPDOCs, which I’m sure would be a lot more “visual debt”.

    The opinion doesn’t seem to take into account other people using the code, without the same level of understanding as the developer. While it’s great to have a deep understanding of libraries that are used, often it’s something that isn’t needed (understanding Guzzle is a task in itself!). I agree in trimming down interfaces if not really needed, but removal of public/type hints/etc is just making your (& others) life harder in the long run. IMHO.

  • Tony Marston

    I have agree with Jeff on this one. I have a minimalist approach in my coding where minimalism is described as follows:

    “The minimum could be defined as the perfection that an artefact achieves when it is no longer possible to improve it by subtraction. This is the quality that an object has when every component, every detail, and every junction has been reduced or condensed to the essentials. It is the result of the omission of the inessentials.”
    So if I can remove something from my code without causing a problem, then that something is not necessary and can be removed. I don’t use interfaces; I don’t use type hints as the parameter name is itself as hint; I don’t use the word “final”, and I don’t use “public”, “protected” or “private” as “var” will suffice. My code works as-is and would not be improved by the addition of all those inessentials, so I refuse to add them.

    • Jeroen Meeus

      I hope I never have to maintain or fix a bug in your code. Code that runs for more then a year, is a lot more fun with verbose comments, verbose code, type hints, …

      • Tony Marston

        Comments are necessary, type hints are not. When I type in a function/method name my IDE automatically shows its arguments, and the names themselves should hint at what type of data they should contain. As for verbosity I strive for “enough”, which sits between “too little” and “too much”.

        • Joeri Sebrechts

          Every time I’ve added static type checking somewhere, it has caught bugs. In theory you’re right that this stuff is superfluous, in practice people do dumb things and every reasonable obstruction you can put in front of them (or yourself!) to prevent those dumb things is a good idea.

          I agree that if you’re only using type hints to get IDE autocomplete you’re not getting the value out of them that you should.

          • Tony Marston

            My code worked perfectly well for ten years without type hints, and adding them retrospectively would involve a huge cost for no benefit.

    • Todd Zmijewski

      From what I recall Tony maintains his own hodge podge framework. Its riddled with legacy code. I wouldn’t recommend taking any advice from him unless you want to build a php application 10 years ago.

      • Tony Marston

        You seem to think legacy code is automatically bad. Code from 10 years ago that was well written will still be good today. From from today that was badly written will always be bad. The age of code is totally irrelevant.

        • Todd Zmijewski

          I disagree. You have this entire shift towards the JavaScript stack. That makes these things more relevant then ever. We all need to stick together. I can’t stick together with people using outdated practices. I rather move onto the next tech stack then do that.

          • Tony Marston

            Some people may be shifting towards the JavaScript stack, but I’m not one of them. I don’t develop public-facing web sites, I develop business-facing enterprise applications where the emphasis is on pure functionality rather than a sexy UI.

          • enterprise applications are not developed by one person..and no sane person would argue the same as you with enterprise experience. We have PSRs php-fig and all best practices, coding standards only to solve problems we face everyday..specially in enterprise..if you don’t face them you are not developing enterprise that is for sure

  • Kevin Nagurski

    My mantra has always been “reach for complexity only when you need it”. I work on a project with a mixture of super-legacy PHP-4 era code and way over engineered Symfony code and it’s sometimes maddening that a sensible, *simple* approach is hard to get passed. Do we really need a bundle, 5 interfaces, 15 classes, 3 libraries, factories and all the buzz words and all the acronyms just to call a simple web service and return the result?

    So no, don’t use an interface until the complexity is needed. Don’t use `final` because it treats future developers like children. But I see scalar type hints and `public` as an extension of the idea of code being so descriptive that it doesn’t need comments. And removing `public` just makes me think the class I’m looking at is PHP-4 era and screams for a refactor.

  • I am tapping on a tablet and unable to test the script with `define( strict_types =1);` and curious to know if warnings or errors would be shown.

    I thought the idea of using the extra syntax was to prevent ambiguous types, type checking and make PHP7 that much faster.

  • Leandro Antonello

    Totally agree with you Bruno. I like the minimalist code, but public/type hints/etc make the code much more legible and easy to understand and to use for any other developers. The PHP evolution itself is walking throught this way.

  • Todd Zmijewski

    I think the author is a moron for proposing that function should follow form. That is the complete opposite of how software should be built. Scope is a fundamental oop concept and programming to interfaces is a well established design pattern. Well written software balances simplicity and complexity with anticipation for the future evolution of the project including adequate testing.

  • Tony Marston

    I disagree with your usage of the word “should”. In the PHP language interfaces are entirely optional, so there is no “should”. If I have a huge code base that never used interfaces then the time taken to add them would not add any value, but would waste a huge amount of time.

  • Coding, like art is subjective. Yes, there are rules to make you a better and more efficient coder, but do you have to stick by them? No, you don’t. If you feel like something shouldn’t be done, then you don’t need to do it.

    However, when it comes to working with a team, you all need to find a middle ground and agree on the terms set, otherwise it will be hell working alongside your team mates.

    I say you should find what works for you and take what others say with a pinch of salt and even learn from their experiences and fine tune it to your experience. Always explore your paths and always find your own results that work for you. We need to remember that what gets added into our chosen language aren’t set in stone and we should use it when it makes sense to, as an individual and as a team member.

  • we were living fine in caves for so electricity, water, cell phones :) ..PHP is evolving because there is a need for it..when working alone on a small project..of course it doesn’t really matter if using type hints or whatever other finish the project and never come back..but this changes with long term projects and we can easily see Jeffreys experience, he is an awesome very knowledgable guy but we all know he is not working on enterprise, robust projects with huge teams to manage

  • I disagree here..enterprise application must be for an organisation and must be of certain size, robustness. It is alway a long term no 6months and involves teams and several applications. If you do a presentational website for an enterprise, it is not an enterprise application..enterprise usually involves connecting internal applications, several databases, entire teams starting from developers, designers, db architects to business analysts, product owners etc…so what you believe to be enterprise is for me a mid size project..and yes in a single man team, standards may not matter..although we still have PSRs and if you want to publish a public package people are looking for consistency and standards..if you can’t read and follow a few guides, people can’t really expect you to create quality software(this is not a rule but expectation of many many developers out there)..I for instance dropped YII 2 immediately after I have seen they don’t follow PSR’s

    • Tony Marston

      If size is so important to you then consider the following:

      I started writing my RAD framework in 2003. I released it as open source in 2006. It is comprised of 4 subsystems (RBAC, Audit, Data Dictionary and Workflow) each containing its own database and user transactions.

      I used this framework to start building my ERP application in 2007. This meant adding more subsystems – PARTY , PRODUCT, ORDER, INVOICE, INVENTORY and SHIPMENT – where the databases were obtained from Len Silverston’s Data Model Resource Book. It went live in 2008.

      Since that time I have been constantly updating my framework and its existing subsystems as well as adding new subsystems. Any subsystem can share data from any other subsystem.

      A USA based software company used my framework to build their own application consisting of two subsystems. In 2014 I demonstrated my application to them, and they were so impressed they invited me to join them in a partnership so that we could combine our subsystems into a single application.

      Since becoming partners I have also developed another subsystem, and there are more on the drawing board.

      At present my application has 17 subsystems with a combined total of 400+database tables, 750+ relationships and 2,700+ user transactions. Is that big enough for you?

      It has been in service with paying customers since 2008 – is that robust enough for you?

      It is not necessary to have a large development team when a competent individual can take advantage of the RAD capabilities of the framework to create working transactions in a short space of time.

      I am no longer a single man team as I now work with by business partner and his team of developers. Not only does he not have a problem with my programming style, it was precisely that style, coupled with the large volume of comprehensive documentation, which attracted him to my framework.

      My development standards evolved from working with numerous teams and languages in the previous 20+ years. I do not follow the standards proposed by the FIG group, or any other group for that matter, simply because they did not exist when I started developing my framework in 2003. While I am prepared to change my code to avoid a vulnerability that some wise person identifies, I
      absolutely refuse to change my coding style just to be consistent with someone who wasn’t even born when I developed my first framework way back in the 1980s

      You may refuse to use a framework that does not comply with FIG’s PSR standards, but that’s entirely your choice. There are many groups out there, each with their own standards, but none of those standards is allowed to call itself the “official” standards. The only “requirement” I recognise is that code be readable so that it can be understood and maintained by any competent developer. I draw the line when somebody tells me that I should be using CamelCase instead of snake_case as that is going beyond the reasonable into the obsessive.

  • Spaces take up more file character space then tabs. Must be visual debt

  • Psr-2 guidelines… More like actual rules then guidelines.

Get the latest in PHP, once a week, for free.