The ideal Formula 1 car falls apart immediately after crossing the finish line.
It’s 2018 and my team has some incredible ideas and is funded too. Now it’s time to realise those ideas and execute on our vision. The trouble is, I have not enough product and too few customers. I need to create that product and prove that our business idea will work before our funding runs out — a familiar startup story. While I need to move as quickly as I possibly can, I don’t want to ship too many bugs or force future development to stall while a substantial re-write is undertaken.
Engineers are forever being told that ‘the thing’ is needed yesterday. Sometimes that’s more true than others. In this case, it really is. The companies survival is at stake, not the board’s new Ferraris. We need to optimise our processes for speed of delivery over all else. Over my time at early stage startups I’ve learnt a few tricks to keep development pace up, without inviting total chaos.
I’ve talked about the importance of software architecture in my post about technical debt. In it, I suggested that a good system will accommodate sloppy implementations if the architecture is good.
That means good enough for now will do.
Not a shithole.
You can cut the implementation corners and come back later. If the code is too far gone, it can even be ditched wholesale and replaced — so long as those boxes end where they are supposed to. A bad architecture has overlapping boxes and they can’t be removed or modified without breaking lots of things.
I’m bastardising a Colin Chapman quote here. The actual one is:
Simplify, then add lightness.
The 20th century Russian manned space programme outlasted the American one partly because they kept things simple. Simple things might not do everything you want, but they will do what they do well and do it reliably too. When they break, they can easily be fixed . Simple spaceships (oxymoron alert) are straightforward to fly and cheap to build.
You call your design minimal, but I me I call it simple.
This ties back into architectural considerations, simple monoliths are far easier to work with in early stages than complex microservice systems. If you are playing records at a party, you (probably) wouldn’t choose your loudest techno as the first tune; you’d work up to that over a few hours. Software is not so different.
Most great engineers will tell you that rigorous automated testing is the only way to build reliable software. They aren’t wrong either. It’s also true that time spent writing tests is money not being invested in achieving product market fit.
If I was building a flight control system, I’d be testing every which way I could as peoples lives depended on it. My side projects…well they aren’t tested at all. They don’t need to be because I’ll never finish them anyway. There is a middle ground and finding it comes down to two things: pragmatism and precision.
Let’s start with pragmatism; some things require more testing than others. The payment gateway needs to be tested more than the copyright date in the footer for example or perhaps your authentication mechanisms require more attention than your FAQ section. Having identified your testing priorities you can move on to precision.
Making extensive use of code coverage tools will give you the reassurance that you are testing the things that you need to, and chide you when things slip. The correct percentage of code coverage needn’t be 100%.
It’s also worth saying that bugs aren’t fixed until there’s a test that says it’s so. To ship bugs is human, but shipping regressions is a sin.
Anything involving security just can’t slip. In Europe the big bad General Data Protection Regulation will literally ruin your life in the case of major screw up. There are no security corners you can cut, this one needs to be done by the book.
If you have particular expertise in a technology, then that’s the one you should use. Even if it’s not cool — I’m looking at you PHP! For any given programming language or stack, regardless of what the zeitgeist says, there will be a highly profitable tech company built on top of it. The only caveat to this is where the tech so obscure that it would be almost impossible to hire a team, perhaps COBOL, Perl or Vigil.
There are hosted services for servers, databases, message queues and just about anything else you can think of. They might seem expensive, compared with doing it yourself but nothing is more precious than your time.
Sorry, but Amazon are much better at this than you are.
Delegating your infrastructure to a third party saves you the burden of a huge amount of operational work that would otherwise distract you from that vital but elusive product market fit. Most of them offer discounts for startups if you ask nicely too.
When considering a feature, do you really need all of it? Are there some parts of it which are much more complex to implement than others? If you left out those complex bits, would the feature still be coherent and work? There’s often times where you can leave out that last little bit and still have a useful feature. Get to market faster by delivering 80% of the value in 20% of the time.
Finding these shortcuts requires deep product insight into the nature of the problem you are trying to solve. If you, as an engineering team, think of features as designs to be implemented you won’t find the shortcuts. Instead think of them as proxies for problems that need to be solved. Leverage the product team / owner to grok the problems and then reflect how you could defer some expensive parts of the feature for a later sprint while still solving most of the problem.
Uncertainty needs to be treated with caution too. If you think a part of the feature could be difficult but aren’t sure, then ship the better understood parts of it first — so long as the feature is still coherent of course.
First make it work, and only then make it awesome.
Priorities done right .
Even if you nail all the software architecture and the rest, it’s of no use if you build the wrong features first. It’d be out of the scope of this post to go to the Build-Measure-Learn cycle, but I think it’s important to stress that getting it badly wrong will undermine every and any of your other successes. Don’t be that team.
Right now these principles are serving us well at Fluidly.com and code is getting out of the door. That’s not to say they will forever. Best practices exist for a reason, and bending the rules to get speed now will have a cost later on. Preparation for a shift to a mature team maintaining a complex system in production needs to be done too.
In the end, the old ways will reassert themselves, but as a technical leader in an early stage business your job is to prove that there’s money to be made in the idea. If you survive long enough to need to fall back to best practice, you are doing well.