I am ACTUALLY good at programming

The last few weeks have shown me that OOP, types, static analysis, linting – good developer tooling! – is all really good and actually helpful on larger codebases and when working with teams. I had an inkling, but now I’m actually feeling it.

This sounds like a stupid thing to say, as I’ve been a professional programmer for 25+ years at this point. But hear me out.

Two caveats:

1) I’m the kind of person that is normally pretty down on myself. So when I find good things to say I like to say them and share them. You can call it bragging if you like. But I like to think of it more as marketing.

2) I’m also sharing because I think there are lessons to learn here for programmers.

Now some history:

Despite being a programmer for 25 years, most of my work in web development has been either solo as a freelancer, working on team projects but as the only developer, working on side projects by myself or working on teams with huge legacy codebases that are very hard to change and under pressure to deliver.

I have opinions about how software should be developed; about the tools and techniques that a team should use to make their work fast and reliable and accurate. But I’ve rarely had a chance to put my principles into practice and see the outcomes.

That is my context.

And the headline of why I’m suddenly saying I’m good at programming is that two things have happened recently where I saw the medium-term or long-term payoff of those opinions being put into practice. And the results are good!!!

Firstly, about 18 months ago, I was tasked with building a new interface to an external API.

Some things I did in this context:

  • Used an object-oriented approach that separated the API interface from the business logic and used data objects to define the data received from the API and stored internally in well-defined, well-typed structures.
  • Wrote unit tests and integration tests where it made sense to prove that things behaved as they should, to define what inputs and outputs should be, and to create a reliable basis for future change.
  • Used both code and written word to document what this all did, how, and why.
  • I may well have also used static analysis. I don’t remember.

I had to hand this work over as I moved to another team. But I recently had some feedback from one of my old team members to say that the work I did had really paid off, laying a “solid foundation” for the eventual completion of the project.

This was really great to hear as at the time I felt like I was working slowly, but that slowness was deliberate to build such a solid foundation as I thought this work needed.

So it was so good to have this validated.

Secondly, in my new team I’ve been working on updating developer tooling on the existing codebase.

There was linting and coding standards, but they weren’t up to date and configured correctly. We fixed that.

I’ve also been working on incrementally adding static analysis.

For PHP we have a codebase that needs strong backwards compatibility with older sites, so for this we are using PHPStan with PHPDoc docblock annotations rather than PHP’s own type annotations. We’ve also taken a baseline so existing errors are ignored.

For JavaScript we’re not adopting TypeScript as it’s just too much, but rather incrementally adding JSDoc annotations to new code and any existing code that we modify.

This is a process. I think all of these changes have been bigger than anyone thought they would be. But we persevered and got them in.

Add to that correct configuration of IDE’s, and that work starts to pay off.

Today I was working on some new PHP code. The editor was highlighting my errors be they formatting/code style, or static analysis issues. I was paying attention to the editor’s messages and fixing things up as I went. I was using the built-in reformatting command on the whole file to instantly fix all the formatting errors.

And as I was raising my pull request, I ran the linter and PHPStan and got green across the board, all ready to commit and have the checks run again by continuous integration for good measure.

The realisation today is that this tooling, when set up right, really does reduce friction. I wasn’t having to think about things that the machine could think about for me. I could focus on the logic of the task at hand. And when commit time came I didn’t have to go back and revisit a bunch of stuff.

I suspect the review time will be quicker too as the code style doesn’t even need to be looked at, and the DocBlocks make clear what the valid inputs and outputs are. There’s no guessing. No unnecessary type validation in the code. It’s clear what the code’s expectations are and breaches of those are reported by the tooling.

This stuff works! It makes you faster and better both as an individual as a team. Today was not friction-filled frustration, as so many days adding to a legacy codebase are. It was automation-enabled developer heaven.

So if you’re working on a new codebase: get this tooling in. Don’t worry too much about the settings/configuration/rules, especially for code formatting. What matters is consistency and automation. Format on save or on commit. Just don’t think about it.

If you’re working on an old codebase: try to find time to get the tooling in and then incrementally adopt it. Use it on new and modified code only. Use methods like JSDoc and PHPDoc to add documentation and typehints without tearing your whole project apart. I guarantee you will start to see flaws in your old code, and you will start to wish you had more automated help.

These things can take time to get in place. But advocate for them if you think they can help you. Because, done right, they probably can.

Finally, some words on types.

I’m known for my love of strongly-typed code. My academic, computer-science background and the first step of my career involved safety-critical software and formal methods. It’s deeply ingrained into my programming muscle memory. But also, I’ve never given it up because I see the value and utility of types.

BUT… I’m not actually a full-on type zealot. Types can hinder you. You can fight the type system or tooling. It shouldn’t be that way. Use types where they have value and utility. Avoid them where they make your life more complicated. Yes, this is why I don’t get on with TypeScript.

I hoped this was interesting and encouraged you in your craft.