One of the common themes in the talks I’ve been doing over the last 5 years is about how we have carelessly over-decomposed and damaged software - and I think this is because of a fundamental conflict between the surface area - the observable “size” of a system - and the desire of organisations to parallelise and accelerate work.
Software has a fixed surface area - a maximum amount of humans you can fit around it. Capitalisms voracious desire for parallelism directly conflicts with this, because there’s always an insatiable desire for more. More teams, more concurrent work, more progress, more everything. The only way to satisfy this hunger is to make the surface area of the software bigger, and we do this by introducing seams. You can imagine this like cutting a dining table in half to introduce two more edges to sit people around - the area doesn’t get bigger, but you can fit a few more people at the table.
Seams in software come in lots of different disguises, modules, microservices, packages, applications, outsources SaaS solutions - but all of those things have the same intent to a business - to subdivide the working set into parts, to fit more people around those parts, to parallelise the work. Introducing seams come with technical overheads: repository management, documentation, and assorted other complexities.
Sometimes, often accidentally, those seams are “good seams” - they align with fault boundaries in your software (things that change together, fail together), or they align with domains (“Customer”, “Payments”), or they align with specific concerns (“File system access”, “I/O”). Unfortunately, they are often “bad seams”, especially in Enterprise software. The seams are synthetic, subdividing a logical module into unnatural boundaries. This most frequently manifests as nanoservices, single functions extracted from larger applications without semantic changes and packages that should be parts of their containing app.
The appetite for business productivity introduces seams in the software with the goal of parallelisation of work - and in a majority of cases damages the design, legibility and performance of the software directly. This is the root of Conway’s law - that your organisational structure and your software always reflect one another, and either you actively engage in software design, or you’re subjected to (often low quality) design by side-effect.
The cruel joke in all of this though is the perceived productivity gains of “bad seams” never happen. This was the central thesis of The Mythical Man Month - “it takes 9 months to make a baby? shit, better get 9 women on it, I need it done next month!”. Even when the seams in the software are good (domain bounded, modular, fault boundary respecting subsystems and libraries), organisational entropy normally kills the effectiveness of parallelism in the work - you replace the “I can’t fit enough programmers around this problem!” problem, with the “I can’t coordinate all of these teams and divide the work in a sufficiently non-blocking way” problem.
Most of the parallelism really just resulted in technical debt - frequently dragging organisations over the line owning brittle, broken, systems where the cost of maintenance was 100x the cost of initial creation, and directly contributes to that programmers sense of “if only I’d got this right the first time we wouldn’t be doing this subsequent half decades worth of work”.
There’s a very famous misquote that was never said by Shigeru Miyamoto - that “a delayed game is eventually good. A bad game is bad forever.” - he might never have said it, but I think it’s pretty true in design, that slower progress and more competent design is more evergreen than rushed haphazard systems, and central to my belief that the only good systems designs are the ones where their ability to change trivially is their central design philosophy.
One of the most liberating things about the current capabilities of model-assisted software development is that it brings with it the ability to reason about systems as a whole, rather than isolated pockets of software. Thinking about the system as a whole over the application isn’t a new discipline, but with the industry having spent nearly three decades subdividing and introducing seams, it’s been increasingly difficult to even perceive a whole system, let alone reason about it. Model-assisted development is now in a place where we can take these tools - that are good at processing large volumes of data - and use them to pull back together the unnatural seams in a system, because with the assistance of these tools we’re able to reason about the whole, rather than be damned into the artificial subdivisions of large software enforced by organisational structure and entropy.
I’ve always felt that the correct amount of software to build is “nothing” if you can get away with it, because the cost of maintaining software is so high, so it’s interesting to me that we might have a technique for undoing some of the damage done to system design by having tooling that can bring all these wayward parts back together.
A Practical Tool
I’ve recently experimented with mapping out the entire constellation of software I care-take, trying to map and comprehend the seemingly infinite seems in both the software and processes around them and I ended up building software that instrumented all of our tooling and systems to build a graph of HTTP, Event and package dependencies between components.
It’s an obvious and sound technique, but I’ve always struggled with finding a good tool to do this kind of thing because each organisations software ecosystem is different. I built a thing, a bunch of scripts that talked to the systems we use and produced a graph for me, but it’s not really a tool that can be generalised or shared because it’s specific to our organisation.
Inspired by OpenAI’s Symphony - I instead realised that with the current generation of tooling, that this software didn’t need to be generalised, and instead could be released as a specification. So I’ve written a specification, of a tool that I built, so you can build your own that’s specific to you that might get the same outcomes in your environment.
It’s wild to me that we’re in a place where we can release “software as a design”, but I think it’s a novel application of the current generation of tooling where actual software would be too difficult to generalise, but a model-assisted tool could trivially build something for your exact setup easily.
You can see the spec for my System Map generator here.