Not Now, Honey! I'm Trying to Compile This Code
Building The Right Thing vs Building The Thing Right
Building the right thing and building the thing right are the two goals of a successful tech company.
Growth will be low and retention lower if your customers don’t want what you sell. But you can’t stay in business too long if, once they sign in, your product isn’t good enough. A competitor will eventually take your place.
By talking to customers and doing things that don’t scale, you can mitigate the risk of not building the right thing. And by creating “moats”, you keep competitors at bay and facilitate building the thing right.
You can also build tech in a way that helps you build the right thing, and build the thing right. The problem, of course, is that figuring out what the right thing is and nailing down how to do it right are at odds with each other.
It’s a narrow path. One that every tech leader must walk if they want to be successful.
And you’re going to need all the help you can get.
Welcome to Money In Transit, the newsletter bridging the gap between payments strategy and execution. I’m Alvaro Duran.
Today’s post is the sixth installment on a series I’ve called A Sketch of a Payment Systems Protocol. These include an exploration of the causes of the demise of Java, why designing payments like ocean freight could be the key, and the advantages of persistence ignorance.
They’re all free to read.
Want to be notified when there’s a new post? Hit that subscribe button below.
I don’t know if this is true or not, but I once heard that Furqan Rydhan, Founders, Inc general partner, has a nickname for founders who don’t ship every day.
He calls them localhost.
Did you just try to google what that is? Were you surprised to find that your browser didn’t work as expected?
Don’t panic. Localhost is the name reserved for your own computer. That’s the joke: someone is a localhost if they leave what they build on their laptop, rather than share it with potential customers.
I really like this attitude. I come from a very competitive family. I am a very cheeky person. When I’m gone, I’ll be buried with my copy of How to Win Games and Beat People.
Cheekiness is the opposite of being a localhost. It’s the attitude you need to figure out if what you built is what customers want, however crude. A cheeky founder builds one prototype after another, shares them with potential customers, and asks for feedback.
Such a founder has no time for building things right. But once they find product market fit, cheeky founders must leave some of that cheekiness behind. From that point on, they must engineer quality.
And quality is elusive, just like product market fit. But the tools to achieve it are completely different.
When figuring out what the right thing to build is, crudeness is your ally. But to build the thing right, it is coherence that helps, because it lowers the number of things you have to keep in your head at any time.
Coherence minimizes opportunities for errors. Thankfully, there is a tool that guarantees coherence across your software product. It’s math in a bottle.
It’s called types.
We’ve all experienced math as symbol manipulation in high school. Move this, scratch that, etc. But math is more than that. It’s a concatenation of interesting observations. It’s true statements, one after another.
You can see software in that light too. There’s user input, it gets validated and morphed into more structured information, and gets piped into a series of steps that gets you the answers you look for.
The only thing missing is the QED at the end.
The mechanics of mathematical proof are what makes types valuable. Data gets stored in memory with some information as to what it is (a number, a piece of text). And as it goes deep inside the system, it interacts with other data, becoming more meaningful, more structured.
That’s what types are. A knowledge preservation engine.
Types keep you honest, but also slow you down.
Some programming languages enforce the use of a type system. These languages see types as a performance enhancement tool. When types are mandatory, it is so that the programming language can make the translation between what the engineer writes and what the machine executes more efficient.
A type system slows you down because it takes time to get everything coherent. Cheeky engineers can’t go around it.
Building a prototype? The language will not comply, nor compile.
Let me propose something radical: is performant code all that important now? It sure is, for videogames or machine learning. In those cases, efficiency is a deal breaker.
But for everything else, hardware is powerful enough to make optimization efforts a bit pointless.
It goes against most engineers’ nature, but I think we should trade efficiency and performance for any increase in convenience we can get early on. Some of the best software products were started by people who didn’t know what they were trying to do, let alone type it. A type system would have been arguably harmful for them.
Types put guardrails on how you write software. But guardrails are only good when we already know where we are going, and we want to get there fast, but safely. Downtown, guardrails are a nuisance. Inside of cities, two way streets are more helpful than highways.
Both in business and in technology, change is not only inevitable, but desirable.
You should only use types when you need to.
Thankfully, some programming languages allow the use of type hints. These languages see types as an extra check on top of your testing. You can ship code that doesn’t pass the tests (I’m not saying you should), and similarly you can ship code that doesn’t comply with your type hints.
Types being optional means that, if you use them, checking will work the way a type system would. That’s the power of optionality: it lets you make mistakes.
Type hints are better than plain comments, because you can drift away from the purpose of comments without noticing. No system can alert you if your comments are wrong, but a type checker can.
Compared to type systems, type hints are also superior. Type hints allow you to incorporate the benefits of types incrementally. You can start without them, and once you’re sure about some of the implicit rules governing your data, you can make them explicit with types.
Performance and efficiency be damned. Wasting programmers time is the real inefficiency.
Besides, such a way of doing things matches exactly how we should go about building software.
First, make sure that you’re building the right thing. Prototype, prototype, prototype. Be cheeky.
Then, make sure that you’re building the thing right. Type, type, type. Be an engineer.
Can I ask you a big favor?
I'm experimenting with a growth idea in public.
Every time I hit publish here, I send a summary of the post on social media. This week, I’m turning the tactic upside down: the summary is already out, and I’m letting you know here!
If you enjoyed today’s post, please show some love on LinkedIn or forward to your friends. It really does help :)