Are you failing enough?
The process of creating software, compared to other manufacturing processes, is a little bit special. One unique property of a software product is that it can be changed easily and (relatively) cheaply.
Over in the physical world, changing a product is not so easy. Supply chains, inventory, machinery, whole factories, who knows what’s involved that is either difficult to change quickly and/or prohibitively expensive to change.
So what about this failing more often? Well if you have the ability to quickly change your software product, you can also run A LOT of experiments!
The ability to change whenever you want though, that’s something that needs to created and maintained. Running an experiment without some safety nets is quite the risk if you can’t undo the changes quickly. The best results from your experiments will come from real world use-cases with real users in the production environment. It goes without saying that accidentally messing up a live system that is used actively is something we all want to avoid.
The 10-minute build (but preferably faster)
I guess we can call this step one. Automate your entire build and deploy process and make it fast, like really fast. If you deploy something broken, you can quickly pave over it with a new version if you have to. So this will give you some agility. That thing you changed and deployed not really working out? Undo it (or fix it) and re-deploy.
The 10-minute mark has another advantage. If you can build fast enough (or fail really quickly), you can avoid context switching. If building and deploying takes long, you (or your team members) might want to pick up some other task while the build is running (switching contexts to this new task!). Build broken? Here comes that context switch again to get back to what you had built before that other task was picked up. Switching between tasks is very costly and getting back into the groove can take at least 15 minutes.
In short, context switching is pretty wasteful. Complete a task before picking up something else. Fast builds greatly help staying focused on the task at hand.
Testing
You are testing your code automatically in that pipeline right? Get that test coverage up and ensure that when you introduce changes, you’re not accidentally breaking something somewhere in your app.
Speed also applies to your test suite. Make it fast! Lots and lots of small unit tests that run in seconds complemented by some end-to-end tests but keep it fast. Especially while writing code, if you have to wait for those unit tests to complete, something needs improving.
Something broken? We want to know ASAP. Preferably before we commit anything, break the build and hold up someone else that also wants to deploy stuff.
Start failing!
Now that you have indicators for the condition of your product (using tests) and the speed to quickly deploy changes without breakage (“Go fast and break stuff” is terrible advice anyway…), you are able to change your product at any time, safely and consistently.
Try out some of the more “out there” ideas that you’ve collected from users or within the team. Break them down into small little experiments and test them out in the real world.
Don’t want to burden your whole user base with new stuff all the time? There’s A/B testing. Or even better, introduce a Beta program in your application that users can opt in to. Users that do will be able to see and use whatever you can cook up! Hide all the experimental stuff behind that Beta flag and let the curious crowd give you early feedback.
Things not working out? Instead of calling it a failure, call it a job well done, you’ve learned something new about how your application was used and the desires of your users.
And best of all, you can roll back whatever you’ve attempted and all is well again. Just keep an eye on those users. If you move things around all the time they’re going to get fed up and either leave if they can, or complain endlessly about it.
Software architecture also plays a part in this whole story, if you’ve somehow ended up with a big ball of mud, you might want to look into refactoring with the aid of some test-driven-development to create something more adaptable.
To conclude all this, a software product, given the right conditions, lets you experiment to your hearts content. Start putting that ability to good use by releasing small changes more often and faster. If you happen to stray away from your users needs and desires, you can always go back.