Good Abstractions are Timeless, and Now also Critical | Tom Kennes

Good Abstractions are Timeless, and Now also Critical

TL;DR
Claude Opus 4.5 is powerful, until it isn’t. AI-assisted coding thrives on clean abstractions and falls apart when things are ambiguous. Slow builds, unclear APIs, bad docs? That friction is no longer just annoying, it’s now actively blocking your AI from being useful too.

Yes, Claude Opus 4.5 is pretty powerful! Especially when applied to well-defined use-cases where there is not that much room for interpretation or different implementation methods. Less ambiguity. But it also falls apart sometimes, and more often than not we still end up taking our “super-intelligent” companion by the hand to feed a simple solution it failed to see.

When does AI-assisted development work well? And when does it not? Organizations are rushing to push for adoption, but there is a lot of noise when it comes to judging the overall effectiveness.

On the one hand there is this is horde of vibe coders pushing their work, these companies were “everybody is a builder” and the occasional benchmark crushing of newer models. But on the other hand we also see academic research that notices the overall time to produce software together with an AI-assistant to actually increase!

Looking at the development process overal, 2 things are starting to emerge:

  • AI-assisted coding is speeding up the development process: Friction in the Developer Experience now suddenly has grown into an impediment!
  • AI-assisted coding is not speeding up the development process: your building blocks / abstractions are not that easy to work with, as inspired by this blog post
 

Developer Exerience: Friction becoming an Impediment

In an earlier post, I wrote about Developer Experience following the book Frictionless by Nicole Forsgren. That really hits the nail when it comes to the developer process. Even if the part of the process where code is implemented takes less time, it still needs to be reviewed, tested and deployed.

If those parts of the process do not speed up similarly, your overall process might not be faster at all! A 20 minute build-time is becoming much more painful if the development time drops from 2 hours to 2 minutes. Suddenly you’re spending not spending 15% of the total time waiting for a build, but 90%!

Responsive image  

What are Good Building Blocks / Abstractions

A good abstraction continues to behave the way you expect, even when the things underneath it change: Predictability under change

This comes down to:

  • Parnas’ Information hiding
  • Robert C. Martin’s Stable Dependency Principles
  • Modern Platform Engineering Practices
 

Parnas’ Data Hiding

  • Each module should hide its internal data and design decisions that are likely to change, exposing only what is necessary through a stable interface

So this also means hiding design secrets so the system can change safely

Hide the things most likely to change

This also makes the interaction predictable, which is in the end what abstractions serve for. Predictable interaction between loosely coupled components.

 

Stable Dependency Principles

Robert C. Martin, credited for the SOLID principles, the Agile Manifest and author of several books on coding craftmanship (like for example: # Clean Code: A Handbook of Agile Software Craftsmanship ), defines stability as a lack of change and advocates that a module that is hard to change should not depend on a module that is easy to change but rather the other way around.

If the dependency direction goes wrong, small changes can cause global incoherence. This means in practice that in order to implement a feature on top of other abstractions, the lower-level abstractions also need to be changed.

For an AI-assistant this means that a larger context-window is required to properly understand the codebase, which in turn also increases the risk of unexpected code changes. That’s perhaps a bit vague, but I like to lean on Bayesian Statistics in my thinking a bit here: the stability of the posterior distribution over all the code samples the AI can generate are considered robust if the prior distribution and likelihood distribution.

 

Modern Platform Engineering Practices

Modern platforms explicitly separate out internal products that absorb volatility for application teams. The platform takes care of lower level changes and exposes them into a stable interface towards applications that are built on top of the platform. This provides clear decoupling.

Good platforms limit what teams can do on top of it, thereby eliminating entire classes of invalid or unwanted states and encoding acquired knowledge into the technical implementation.

Note that the industry shows that this is not easy. We are seeing various typical failure modes:

  • Interfaces that are defined by its implementation, where changes are shaped by how the current implementation happens to work rather than by the needs and invariants of its customers.
  • Hidden coupling through shared mutable abstractions
  • Platforms that expose internals (dependency inversion), where application teams are still required to understand the underlying APIs
  • Flexibility over stability, meaning the platform is optimized for future change rather than stability
 

The Timeless Case for Good Abstractions

If you think about it, a lot of what we do within IT comes down to automating processes, whether they’re human- or IT-driven already. And in order to do so, we rely on domain-driven generalisations and abstractions that translate these processes into steps for a machine to execute.

This is such a prevalent problem, that we keep on coming back to it from various different angles. There has been so much thought-piecing on what empirically constitutes a good abstraction, and how to handle conflict arising from bad abstractions, or when different abstractions meet.

As we are gearing up to speed up our software development cycle through AI, the need for good abstractions is taking up more and more center stage as the question shifts from “Can our developers work with this?" to “Can anyone, human or AI, work with this without hand-holding?”

If the answer is no, you’ve found your next refactoring target.