On the growth team at Arcadia, requirements come at us fast. As a start-up, our strength is meeting these opportunities when they come along. And we all know, “The climate crisis needed to be solved yesterday.” But how do we incorporate these changes on a recurring basis without turning our code base into a morass of if/else statements?
We balance these considerations in a few ways:
- We apply an exacting eye to requirements to ensure the minimum part of minimum viable product for launch
- We split up project work into milestones and assess progress with milestone confidence ratings.
- We look for opportunities to make our codebase more robust and scalable when we have a clear motivation to do so.
- We QA all projects and apply quality assurance templates to streamline our process.
You have to act quickly in a growth environment, and streamlined processes can help you launch with confidence.
What’s on the chopping block?
As an organization, we know it’s crucial to get products to market fast, both to learn from our efforts “in the wild” and to meet contractual obligations. Looking for opportunities to reduce scope helps us get new experiences out more quickly without spreading ourselves too thin.
As engineers, we flag features that have a low return on investment and present this information to our product managers. When possible, we also provide solutions that may offer similar functionality but are significantly less effort than the full design. We then lean on our product managers (PMs) to determine which product and design features are critical for launching the project and which can be left for after launch. PMs can also make the call on whether to use a fully fledged spec or an alternative solution.
Milestones and milestone confidence
In a similar vein as the above example of “scope surgery,” we use milestones to split up major initiatives into smaller deliverables. While we may not launch until all milestones are complete, splitting up the work gives stakeholders a better awareness of how the project is progressing and gives engineers incremental reinforcement.
Additionally, we purposely slot functional work at the beginning of projects. Whenever possible, the largest and most complex features should start first. This gives us better insight into launch timelines, enables us to address dependencies and blockers early on, and allows us to cut less critical features or design recommendations as needed.
We recently began adding confidence ratings to each milestone. For example, I rated our last “first milestone” at 75% confidence we’d achieve everything in the milestone by the target finish date. Encouraging all engineers to proffer their ratings and explain the rationale behind them helps equalize team input. It also lends greater weight to poor or high confidence ratings.
If the ratings are significantly off, we can give early feedback to stakeholders and adjust the overall release date. This early feedback keeps stakeholders in the loop and helps prevent external pressures from driving a too-urgent launch date.
Help us drive the clean energy future — we're hiring!Explore open positions
Incorporating intentional code design
With tight deadlines, it can be easy to make shortsighted code design decisions, but this practice will end up hurting you in the long term. We cannot afford to go back and correct prior shortcuts while building new offerings. As engineers, we have to make the hard call on when a hack won’t cut it.
As an organization, and especially as an engineering team, one of our most important values is “build for simplicity.” To quote our values, “we turn complex challenges into simple, elegant solutions that enable individual action at scale.”
How do we put this value into practice?
Sometimes, the best thing for the product is to take a step back and see if there’s a more robust solution. Can we refactor this hook to pass in params based on the funnel configuration? Should we add a new attribute or database mapper table or new product to represent this new functionality? Should we extract out that growing class into subclasses or even build a factory to define which service to use when?
These detours take time away from launch, but often pay immediate dividends. We recently released a new signup funnel in a couple of days because we had previously built this kind of extensibility into our code.
Moving fast — but not breaking things
The trope “move fast and break things” generally does more harm than good. We of course need to move fast, but breaking things damages our relationships with customers and stakeholders and takes time away from making our applications and products better.
To hedge against accidentally breaking things, we rigorously regression test existing code and QA all major releases. We are working to build a QA checklist template to streamline and speed up our rollout process. We also lean on engineering managers, designers, and product managers for QA as much as possible, helping free up individual contributors to focus on writing quality code.
On the growth team, we strike a balance between product requirements, quick deliverables, and application resilience. We manage our work by applying care and consideration to every step of the development process, from scoping and building to testing product initiatives. We don’t always achieve perfect results, but our rapid feedback loops keep us nimble. We can course-correct based on changing business dynamics, code complexity, or experimentation results. You have to act quickly in a growth environment, and streamlined processes can help you launch with confidence.