Boilerplate is just Tech Debt waiting to happen

Our goal as developers should be to write as much business logic as possible, and spend as little time as possible on anything else. Here's why that matters.

Boilerplate is just Tech Debt waiting to happen
Photo by Mykyta Martynenko / Unsplash

Maybe instead of business logic, which can put some people off for reasons I've never completely understood, I should say that our goal should be to write as much "problem solving" code as possible since if you're building an internal UI library your "business" customer might well be the developers next door.

What is boilerplate?

A good way to think about boilerplate code is that its everything that your non-technical Product Manager doesn’t care about. Its code that you’d expect to throw away if you changed the framework (but not the language) that your product was written in.  If you get it correct then nothing special happens, but if you make a mistake then you’ve introduced a defect.

That's worth stressing.  This is code in which there's no possible opportunity for a win, but lots of opportunities for a late night support call.  And ain't nobody got time for that.

If you’re a backend developer, for example, boilerplate might involve defining repetitive JSON configurations or correctly handling your use of a database connection so that it handles error recovery and network glitches.

On the frontend, it could be correctly handling AJAX calls, defining a date format for a particular screen, or specifying pagination behavior for a grid. Its making sure that you do the right thing when your backend API requires that you re-authenticate as a response to a random call, even though that almost never happens.

Some boilerplate is inevitable but its our job as architects to keep it to the barest minimum, without sacrificing functionality especially around the edge cases. In those previous examples that might mean that instead of handing out a database connection directly we write library code - once - to deliver a wrapper that respects the try-with-resources model.  That makes it easy to write good code.  Even better, maybe we change the model to require a lambda so there's literally no way to use it incorrectly.

In the client-side example, we might create a routine that owns (and hides the URL for) all communication with our own server and automatically handles the security protocols (even requesting re-authentication if needed).  Or writing a "too simple" 2 line component to put a date on the screen, which doesn't save much code but does make it much harder to output something with the wrong timezone. And so on.

Code generation considered harmful

Generated code can be one of the worst, most insidious sources of hidden technical debt.  To be clear, I’m not talking about anything generated by your build process, I’m talking specifically about files that are generated and then checked in to your repository.  You’re basically guaranteeing that you have a lot of “copy-paste” similar code that may have been slightly modified along the way - and if that’s not an anti-pattern then I don’t know what is.

I find that in the real world, almost all generated code can be replaced with package use.  Even if you wanted to generate the actual scaffolding of a microservice, you could, for example, require a package to be installed that exposes a new alternate entry point in your code.  Or (worst case) use the same approach and generate the scaffolding over and over again at build time, but I can't see why this would actually be useful.  Either way, your repo should only contain intentional code.

None of this is new

None of this is revolutionary.  Hell, none of the development advice here on the site is.  But adopted as a philosophy its an approach that's easy enough to follow, and lets you spend more of your development time actually writing code that makes a difference.