Abstractions should be Extracted, not Designed

November 2, 2020

I attended RailsConf in 2019 and only the above quote has stuck with me since. David Heinemeier Hansson (DHH) said this in his keynote. Of all people, the creator of Ruby on Rails should have something to say about abstractions.

I've understood this to mean that when I'm writing code that will require an abstraction, I should write a first implementation without using any abstractions (even if this means repeating some code). Then once I've repeated myself once or twice or three times I should extract the abstraction from there in a refactor. This as opposed to designing the abstraction ahead of time and doing all the coding in this framework.

The logic here is that if I design the abstraction without digging into the implementations I'm very likely to get many things wrong. For example, I thought each implementation of the abstraction would need to configure a certain field, but really they can all share one. Or I thought some value would always be an enum, but really need the flexibility of a string. And now to make these changes I have to change the abstraction as well as the implementations.

I follow this pattern religiously now. The underlying insight is there's no better way to research and design the abstraction than by getting your hands dirty with some implementations. The design is the extraction.

I realized yesterday this pattern works for building a company as well. One of my friends co-founded Rentroom. He described how they built their application by automating the painful parts of their brick-and-mortar real estate management company. They are their own first, best customer. And, naturally, the problems they were solving (easier online payments, repair task management, security deposit holding) were being experienced by other landlords too. They extracted their SaaS product from their implementation.

My former company Flexport is another great example of this. Flexport started as a traditional freight forwarder (and in many ways still is one) but focused relentlessly on automating and streamlining the painful parts of the shipping process. Now Flexport needs to turn these internal automations into sellable SaaS products.

Finally, AWS might be the canonical example. Amazon realized they were duplicating much of their DevOps/Infrastructure work across different business units; different teams each managing their own severs and deployments. So Amazon created a team to offer DevOps as a service: just ask DevOps for a server or a database, get back an endpoint and some credentials in return. This duplicated work was extracted from the implementers and now the details are abstracted away from them. And since it turns out just about every other web-connected person on the planet would like to abstract away these details, AWS now accounts for over 75% of the Amazon's profit.