Optimising For Rapid Iteration
Humans can only focus on a few things at a time and there are only so many hours in a day. So we can’t do everything and we need to choose carefully , so that we spend our time on the most important things.
FireWorks is a small team of only 6 people. Over the last 2 years we have launched more than 12 products. That means that we have to create a new product every 2 months without losing momentum on supporting the existing ones.
We use a few principles to make building new products both easy and fast.
- Increasing confidence,predictability and consistency
- Minimise configuration
- Assume code will be open sourced,shared or handed over at some point
- Automating repetitive tasks
- Increase visibility into the systems
Increasing confidence, predictability and consistency
The best way to improve productivity is to focus on predictability which leads to confidence. It’s easy to miss the little details, but with programming they matter. One of the best examples I know is PHP’s needle / haystack problem. This is one of the single points that every developer brings up when speaking about PHP.
Regardless of the reasons for the choice consistency is almost always better than correctness.
All code needs configuration. But all those tweaks come at a cost. Let’s say that, for example, you want to configure how many items are displayed per page. You now have to test your CSS/design with all possible configurations. Imagine actual logic/flow loops with varying configuration. Even if you have tests it’s still one more thing to care about. So unless you have 100% test coverage you need to manually test everything. The more there is to test the less you want to do it. Which in turn lowers Predictability.
Assume code will be open sourced or shared at some point
Our aim is to hand products over. We can’t afford to have secrets or credentials hidden in our code. We actually aim to make our source code shareable without needing to care about security.
Removing private and environment configuration has a nice side effect. It allows you to set up additional servers almost instantly and they will function exactly as the existing setup. If you need a staging environment spin up another one and call it -staging. Will be exactly the same as production just on different environment.
Automate repetitive important tasks
Humans are good at creating new things but very bad at repetitive tasks. On the other hand computers are totally the opposite.
We focus on what we are good at and leave the rest to the machines.
All our products are continuously deployed to production, often many times a day. In order to do this we need a very predictable deployment pipeline.
Tests are great if you have them. But focus on things you can do first. Often just checking that code compiles is a good start. If you have good test coverage and minimal configuration differences between environments it’s easy to be confident that if something works in development it will work in production.
Increase visibility into the systems
All the automation in the world doesn’t help if no one knows what’s going on. The best thing you can do to increase visibility is to build it into development flow. We use simple git workflow of feature/branch -> pull request -> master -> production.
Since github allows you to tag change sets it highlights if your changes are releaseable or not. Our automated tests feed back into our development workflow.
We also email the whole team on deployment failures. So there is a little incentive for developers to not break the build.
Our aim is to increase visibility everywhere, not just in deployment. To do this, we monitor everything:
- Bugsnag for exception reporting
- Papertrail for remote log viewing
- Pingdom for uptime checks
- Newrelic for performance monitoring
Automating all the boring things frees people up to focus on the important stuff. But if you want people to consistently use a system you need to make sure that the system is less effort to use than not to. So make sure that you put in place systems that are simple to use and easy to support and maintain.