With Enough Thrust...
Back during university, one of my software engineering professors often used a saying: “with enough thrust, even a brick can fly”. I still think about this a lot.
Flying a brick
He’d typically use it like this. A student would come to him for advice, halfway through a large programming project. Via much struggle and effort, they had gotten the project half-working, but it had a couple of tough bugs and was missing an important feature or two. The student would ask the professor how to proceed. The professor would note that the reason that it was difficult to squash the bugs, add the missing features, and generally proceed forward was that the project’s technical design had some foundational flaws that the student was fighting against; instead, the student should take many steps backward and reconsider the core design. The student would typically not take this recommendation — to go back and redo a lot of work — very well! It had been so much effort! And it was already half-working! Couldn’t the professor be more helpful and just get them moving forward from here? And did they mention it had been so much work to get to this half-finished state already?
“Well, with enough thrust, even a brick can fly,” he would say. The student had been applying an awful lot of thrust, and sure they had managed to get a little bit airborne… but that doesn’t mean that they weren’t trying to fly a brick, and instead of insisting upon applying even more thrust to make their brick fly better, had they considered building an aeroplane instead? Going back to the drawing board might sound painful, but the reason getting this far was painful in the first place was that their brick required quite an awful amount of thrust to get even a little bit airborne, and if they went back and built an aeroplane instead they might find it required quite a lot less effort to make it fly. Just because they had gotten this far doesn’t make what they had been doing a good idea!
A while ago I was working on an app with a user signup system that had become very unreliable. Over the years, user creation had come to span dozens of functions making dozens of writes across different databases, any one of which could fail. If that happened, we’d return an error to the user — but worse, we’d leave behind an inconsistent partially-created user, which often caused subsequent attempts for that person to sign up to fail! We tried to fix this by adding an error-checking function, which would try to detect these partial failures and delete the detritus. This helped, but also created problems where the cleanup function could itself fail and cause other inconsistencies, which it then had to be updated to deal with; as user creation continued to change, we’d inevitably miss a case and need yet more cleanup. We applied a lot of thrust to this brick of a cleanup function! The right solution, of course, was to build an aeroplane; we eventually consolidated our user objects down to just a couple and then refactored the code to create them so that everything could be done in one atomic transaction. Unsurprisingly, our user creation problems all went away, no cleanup function needed.
Making a brick fly
One of the reasons, though, that it’s stuck with me is that you can use it the other way too. Sometimes you find yourself with a brick, and for reasons beyond your control, you just need to make it fly. But with enough thrust, even a brick can fly! It might require an awfully large, truly gigantic amount of thrust — but it is always possible to make it fly.
I find this line of thought really helps frame discussions about tradeoffs in a system’s design. Different design decisions make certain features easier or harder to build — but it never makes things impossible. It’s never a binary “this design allows for feature X but makes feature Y impossible” — rather, “this design makes feature X cheap and makes feature Y very expensive”. But with enough thrust, feature Y is still possible! It’s all a cost tradeoff. How much thrust do we want to expend on feature X? On feature Y? How much thrust might we have available to expend on feature Y a year from now if we change our minds?
It’s also why I never say “no” when someone asks me if a feature is possible to build, even for difficult or absurd things. Sure, we can do that, but here’s an honest back-of-the-envelope analysis of the cost involved in doing so, and I suspect you’re not going to go for that. I find people very much appreciate being taken seriously, even for ill-conceived or off-the-cuff ideas, and that the resulting discussion often leads to interesting places or at the very least to a better understanding for everyone involved. And every once in a while, I’m surprised to be told that the cost doesn’t sound that absurd and could I please go take my informal remarks and put them together into a real proposal… because it turns out we have this extremely important brick which we very much wish were airborne and also we have really quite a lot of rocket fuel lying around…
And with enough thrust, even a brick can fly!