SW engineering, engineering management and the business of software
Something I’ve had unclear thoughts about for years but only recently been put into succinct words is the programming and system design concept of “isolating complexity to one side of the seam”. In other words, keep simple at least one side of the boundary between two things (codebases, components, systems, API producers & consumers, etc.)
If you have an API or any kind of interface, You don’t want to make it difficult for developers on both sides. You want the majority of the complexity to rest on one side or the other.
The Seam Law: Isolate complexity to one side of the seam between two components
Typically this is because you have asymmetric relationship of some kind. Such as a single producer, but many consumers. By putting the burden of work on the producer side, this allows new consumers to be easily spun up and to work reliably with out a ton of learning curve.
Similarly, if there are many producers, you would typically put the burden of complexity on the consumer side. Handing all the ordering, fault tolerance, etc. on the consumer side means, you can trivially add new producers. An example here is logs or metrics aggregators.
If you have complexity on both sides, the system becomes hard to debug (defect rate and time to resolution go up). You also have extended learning curves on both sides. Here you can imaging an API server protocol that is hard to implement and requires a tremendous amount of developer skill to make use of the API payloads on the consumer side.
A typical REST API is an example of making one side easy. Relative to other technologies at the time of it’s invention, JSON-based REST APIs were originally designed to simplify client-side consumption. Contrast with SOAP, which has ridiculously complexity on both sides and didn’t last in the market.
Something like protobufs is an attempt to add a bit of tooling complexity in exchange for type safety across the seams.
If you want a particular technology to reach wide adoption, I think is is even more important. Think of how early wiki’s made publishing on the web relatively simple. USB was initially tough on manufacturers, but the consumer benefit of a single port won out. Stripe’s relatively simple-to-use API beat out not just old Wall Street behemoths, but even incumbent digital payment giants like PayPal.
Lastly, you want the complexity on the side with the fewest developers or users. Just about every successful example above (log aggregators, REST APIs, USB, etc.) follows this pattern. Make it hard for a few of your core developers so the majority of users benefit.
Regardless if you want good architectural design or need broad market adoption, you should strongly consider isolating complexity to one side of the seam.