How do we make agile technology choices – especially those ones where we have relatively little information to use as input but our decision is likely to have a big impact on what we’re building? Here are 8 guiding principles.For several years now I’ve had a fairly strong gut feel for making technology choices. I’m talking about picking tools and tech stacks, yes, but also making larger, more influential architecture decisions. In many of these cases, we don’t have a huge amount of data to steer our choice.
I’ve normally made those decisions ‘by feel’. When presented with a set of choices to pick from, I’d have a feel for each one. My reactions would range from “No, that’s gonna go horribly wrong”, to an out-and-out “Eww”, to “Yea that might work pretty well”. But what was informing these hunches? I’d never stopped to articulate the underlying logic. That is, until recently, when one of Red Badger’s clients asked if we could capture a set of principles for making these choices, to help them make better decisions.
Initially I thought it would be a tricky task, since that gut feel is largely an accumulation of experience of what worked in the past. How do you translate that for others? But then I sat down and put my thoughts to paper, evolving and refining them as I wrote. I soon found there is actually a sound set of rules I follow.
The eight principles I penned have made a difference for our client and for the Red Badger team. Already, we’re using them to inform decision making across a range of projects.
We believe in sharing, so here are our principles for you to put to use:
1. Put your user first
Any technical decision should first and foremost be informed by our understanding of the user and their needs.
There are many possible business and ‘architectural’ reasons to go with a particular choice, especially one that’s considered tactical. For example, sticking with an existing vendor because your engineers are familiar with that option, or because it’s considered best practice.
All those motivations are valid inputs into a decision, but they must never be in conflict with meeting your users’ needs within a reasonable timeframe.
2. Minimise time to market
Pick the minimum viable toolset to get your product live.
Why? Because getting value to users is the main goal. Partly for obvious business reasons, and partly because launching something fast helps you learn what you actually need to build vs. what you think you need to build.
Investing more effort than is absolutely necessary before the product is live is just delaying that learning, which is very likely to radically change your perspective, including the assumed benefits, which made you consider higher-effort options. Here, speed is your friend.
3. Make your solution as simple as possible
Pick the simplest solution possible to meet the needs you know today.
Complexity is the main opposing force in software development. It slows us down, as we have to navigate around existing choices and their consequences. Strive to minimise it at every step, because it will only ever grow.
There’s complexity in the product itself, some of which is inherent, while some is based on assumptions. Always challenge those assumptions, to make sure you’re only building what’s actually needed. Challenge assumptions when picking tools, too. Every tool you reach for adds complexity. For each feature, the author had to make a number of choices, which will limit your options later. Don’t need those features today? Wait until you do.
4. Validate assumptions and adapt
Every assumption you make needs to be validated.
We should constantly be asking ourselves “Can we get away with not doing that?” And we should answer honestly. The sneakiest of assumptions are accepted best practices. It’s important to step back and identify the motivations behind then, then validate whether they apply to your situation.
Questioning everything all the time can be tedious. But it’s not as tedious as undoing work you didn’t need, or constantly paying the ‘tax’ for it. Identified an assumption? Great, now test it. Is the assumption false? Adapt immediately, rather than continuing down a road you know is built upon a false assumption. Don’t fall prey to the sunk cost fallacy.
5. Defer and minimise commitment
The best choice is one not made.
If nothing forces you to make a choice, wait and make it later. Or never. Let’s say you’re trying to decide which database to use. Actually, files or in-memory storage might serve you just fine.
When you do have to make a choice, go with one that leaves as many escape routes open as possible. And be prepared to change your mind quickly when evidence shows you were wrong.
6. Buy small
Avoid the lure of large feature sets.
When you decide a piece of functionality is not bespoke enough to warrant a custom build, try to opt for small, precise tools that deliver this functionality and nothing else. Choose such tools over large, complex ones that also give you all sorts of things you don’t currently need.
It’s generally best to assemble together a number of small tools, rather than relying on one huge one. We don’t want to be responsible for all the choices a tool’s designers made on our behalf.
7. Minimise long-term maintenance costs
All things being equal, look at maintenance cost – especially the price of ongoing developer effort.
Cost matters, but ideally you should consider all other principles first. Cost is the reason people go for software as a service and cloud infrastructure. But it’s important to consider the potential hindrances that come with a hosted service.
It’s a truism, but cost and value are not always the same thing. Sometimes it’s better to opt for a simpler solution, even if it means maintaining it yourselves.
8. Prefer open source software
Lean towards open source software with good community support over commercial software with paid support.
It’s better to see into the 3rd party software we use, because it lets us self-serve in solving issues. Community support and documentation for popular tools are typically better than vendor support, simply because more minds are investing effort.
Decision making is an art. There’s already enough riding on your choices, so adding contractual obligations on top is usually the last thing you need. Tempted to pick a technology because you already have a contract with the vendor? That likely tops the list of misguided motivations.
Some final thoughts on decision making
You probably noticed a lot of these principles overlap, articulating similar ideas and values in different ways. What do they all share? The understanding that making the wrong choice is inevitable.
We’re making a choice for the future. A future we don’t know, typically affected by an environment we can’t predict. Even when product requirements are clear as day and a roadmap stretches out for two years, there’s no guarantee things will stay that way. Management changes. Markets change. Users change. This is 2020, afterall.
The motivation behind all of this is acceptance of a humbling fact: we are wrong. It’s so much more likely that our understanding of the situation is incorrect, that the basis of all decisions should be the assumption that we’re wrong. On top of that, it’s rare that we know exactly how wrong we are. We’ll learn that later down the line, at which point we’ll need to adapt.
Assuming our understanding increases as time passes, here’s another handful of helpful principles:
- Not making a choice is better than making one
- Making a choice later is better than making one now
- A conscious choice is better than an implicit one
These are the same motivations that drive the Lean and Agile schools of thought, which teach optimising for course correction, not perfect planning.
Do these 8 guiding principles resonate with you? Have I made any assumptions that need to be challenged? Let me know.