I’d like to introduce a concept of “anti-tooling” – which is “tooling that makes it easier to make our situation worse”. There’s 2 main flavours of this that I’ve noticed: the first is tooling that helps us to do something that we shouldn’t be trying to do; the second is tooling that helps us with one, mild, problem, but introduces or aggravates a worse problem.
The objective of tools in general is to reduce the effort needed to do something, and that’s normally a good idea, because it frees up that effort to do other more valuable things. However, if we’re reducing the effort needed to do something that harms us, perhaps by removing constraints, then we get into a situation where we the tooling is accelerating the growth of a problem – we’d have been better off without the tooling, and better off still if we took a step back to understand the problem and find another way forward.
So for example, I’ve seen a bunch of tools cropping up around managing the dependencies between microservices. I can absolutely see how if you have a problem with too much interdependence that is a recipe for disaster, but the creation of these tools is making it easier to ignore the root cause and symptoms of the problem, and carry on without making the (real) change that’s needed. If we’re going to try to design independent services, we should at least start from a belief that it’s possible to avoid deep dependencies, and strive to achieve that; if we reach straight for tooling that helps manage the problem, then we’re implicitly admitting defeat as far as prevention or avoidance is concerned. To me, this is an anti-tool, because it is making it easier to do something that shouldn’t be done.
In this case, we should take a step back. We have identified a problem – interdependence… but instead of looking to solve the problem, we’re looking to smooth over it. Look instead at how the problem has come about, at whether there are other approaches that minimise or avoid the problem.
Another example I’ve been working with recently is tooling around the protocols between components. By definition, protocols should be lightweight, to make them easy to share. This particular tooling generates clients and servers – but not an interface… there is no lightweight piece that can be shared! The tooling is easy to use, it saves time… but it promotes a dependency structure that is incorrect, which is much harder to test because there’s no seams in the structure. This is an anti-tool to me, because it replaces a mild problem (boilerplate code) with a severe one (poor structure).
In this example it’s probably helpful to have some kind of tooling – because there is effort that is wasted. However, we need to select this tool with a bit more care, and make sure that the tool doesn’t come with hidden costs, which could far outweigh its value – because using the wrong tool will make things worse faster.