The Fluencia engineering team highly values speed and correctness. Here are some techniques that we use to ship new features quickly and with high quality:
Reduce scope ruthlessly.
For a new product, we decided to shoot for an alpha version that sent one-off emails before building out a database and a UI. Smaller scope means more accurate estimation, smaller changes, and shorter code reviews. And the easiest code to maintain is code that isn't written!
By shipping a minimal product, we got real customer feedback faster. What we built after analyzing this feedback was different from what we would have built before it -- and the difference between the two represents significant engineering time saved.
Prove value with A/B tests.
A number of times we've A/B tested a proof of concept before fully implementing the feature to prove its worthiness. When it performs well, then we're highly motivated to see it through to full implementation. When it doesn't, we'll pull the idea so we don't throw good time after bad.
Pin engineers to projects for a couple of sprints.
This defers making everyone ascend the learning curve, and promotes focus. In the medium and long-term we want to distribute knowledge among engineers to avoid siloing. But for the short-term, a few weeks to a couple months, we can see a speedup by keeping certain engineers on particular projects.
For example, we have been doing this with the various independent pieces of our new product, which are conceptually very different: a client-side library that does a lot of DOM manipulation vs. an HTTP server that transforms and persists records vs. a single-page app that displays data graphically.
Optimize code reviews for the reviewer.
The reviewer has the burden of diving into new code and understanding it enough to give useful feedback:
- Open small pull requests frequently.
- Make clear in pull request descriptions what you are leaving out of this PR and intend to implement in future PRs.
- Leave comments in your own PRs explaining decisions that you think reviewers might want to know about, or highlighting areas for particular attention.
Use pair programming.
When multiple developers are focusing on a similar part of an application, join forces! Pairing on research can be inefficient, but pairing for knowledge transfer can be efficient, so in the future when two people working on similar code both know what's going on.
Manage large stories by grouping small stories.
We use Pivotal Tracker to manage our development effort, and it has a nice feature called epics that groups together user stories (aka feature tickets) that lead to a larger goal. We try to use epics for any feature that's larger than two or three days of work by one engineer. This prevents us from cramming too much into one ticket, and it helps us write tickets that are highly focused, tightly scoped, and easier to estimate and review. In addition, the epics interface in Pivotal gives us a visual indicator of progress towards each of the large-scale goals within a particular product. Whatever your preferred process/workflow software is, it likely has a feature equivalent to epics -- try it out!
Have an internal hack day.
We haven’t tried this one yet, but the idea would be to clear our minds of normal engineering requirements such as maintainability and scalability, and create only prototypes to put in front of coworkers and friendly testers very quickly. We’d gain knowledge about what parts of our idea work well and solve the user's problem, and what parts need to be rethought or dropped.
When we try this, we’d aim to avoid the temptation to think of hack week prototypes as finished products, though. Writing well-tested, maintainable code is usually a faster approach in the medium and long term because accumulated technical debt can slow you down later.
Improve developer workflow.
This can yield compound dividends over time, but there's a tradeoff here in that time you spend improving developer workflow is time you can't spend actually working on features. We try to strike the right balance.
Some workflow improvements we've benefited from: - Upgrading tooling when it speeds up common tasks such as builds or adds new metrics such as a code coverage. - Creating an engineering team playbook to consolidate our best/preferred practices into one place and give us a forum for discussions on evolving those practices. - Pivot technology choices to ease pain points. For example, our new product uses AWS Elastic Beanstalk, which provides a higher level of abstraction for managing infrastructure than AWS EC2 instances, reducing the level of effort we put into ops work.