Give me six hours to chop down a tree and I will spend the first four sharpening the axe.
Abraham Lincoln
The key to completing e-commerce features on time isn’t working over time. It isn’t allowing buggy releases. And it isn’t adding people to the dev team. Before you try those things, try sharpening your dev tooling. The capabilities brought from good tooling and practices allow quick iteration, on-time delivery, and higher business value.
A Surprising Result
On my last client project, the task was to boost sales by simplifying checkout. The current version of our client’s site had too many clicks and pages in the way of checking out, and our client’s sales suffered for it. Their business couldn’t afford the poor checkout experience, and they wanted our help.
We needed to go fast. Our client had a product release coming soon, and they wanted the e-commerce site ready for the traffic. As we started making changes, we realized we couldn’t go fast enough for this deadline. We needed to improve our tooling. These improvements eventually allowed us to release changes the same day our client requested them, leading to more iterations, greater flexibility, fewer dropped sales, and an on-time project.
Refining our Testing
Automated testing is essential to moving fast as a software team. At Integral, we practice Test-driven Development, which ensures we can confidently and quickly make changes. But it’s rarely easy.
We made no exceptions regarding TDD when we began integrating with the Stripe API for the new checkout page. But, the Stripe API is so expansive, and nearly all of our business logic was inextricably linked to calls to their API, that TDD became difficult. Initially, we tried using dependency injection to make this easier. But that technique failed here. The Stripe API covered so much surface area, and we needed to use a large enough portion of it that any interface we wrote around it was far too big. This interface’s implementations resulted in a pile of code that nobody on the team wanted to maintain. But we weren’t willing to give up the ability to write our tests. We needed a better solution.
We used Mock Service Worker. MSW intercepts network traffic during unit tests just before it goes to the internet and allows you to mock the response. Using this technique, we updated our code to use the Stripe SDK directly instead of through an interface. Then, we updated the unit tests to tell MSW to return mock Stripe data – which we generated from actual responses from Stripe. This made our tests robust and allowed us to iterate faster, since we could now safely refactor our code.
We had sharpened our testing, which allowed us to make changes confidently. But other tools were still lacking, and they were quickly causing problems.
Refining our Deployments
Accelerate (one of the best-researched books in modern software engineering) makes it clear: high-performing businesses release more, and they release more frequently1, not less.
Our first iteration of the custom Stripe checkout page took longer than we wanted. Our team was new to the Stripe domain models, which are difficult to understand. And many Stripe domain models have surprising limitations, which we constantly ran into.
But, our team understood that we wanted to release our new checkout sooner rather than later, even if all the desired features weren’t there yet. So, we released version one of our checkout. It had been a few weeks since the last production push. Unsurprisingly, we had problems.
The codebase had stagnated long enough without a release that the configuration between environments had drifted. So, when we released the new checkout for the first time, we had multiple environment variables misconfigured and a few bugs that cropped up. But we knew this didn’t mean we should release less; it meant we should release more. And if we wanted to release more, we’d need smaller stories and a more stable pipeline.
After working with the product manager, we reached the point where most stories were thin vertical slices through the application. For instance, we made a story to view a single invoice. Then, we made one to view multiple invoices. Then, we added a story to remove cart items. These were easy to finish and release within a few days.
We also simplified the management of environment variables in the project and minimized the manual steps needed to release. With these changes in place, we were soon releasing every day.
The Results
After these tooling improvements, we were releasing small features incredibly quickly. Within 10 weeks of development time (that time including the tooling fixes) our team had a custom Stripe checkout page with a vastly simplified checkout flow, a user dashboard page where they could view their purchases, and new login and account creation pages. Along with these changes, we were frequently able to receive a request from the product manager in the morning and have it released before lunch!
We could work fast enough that once or twice a week, a few engineers would join the product manager and a designer for what we jokingly called a “beep boop session”. In these sessions, the designer and product manager would talk about what they wanted to change (usually these were stylistic changes) and while they discussed those changes, the programmer would implement them. In real-time, the designer and product manager were able to see what was feasible with their designs and settle on something new, which we then released the same day.
Needless to say, this type of immediate, real, usable feedback with the design of the website was invaluable. So, don’t leave it on the table! If your e-commerce teams are struggling to meet deadlines and provide a good user experience, consider simplifying your release process, releasing more frequently, and trying test-driven development. If you want Integral’s help with these changes, reach out for a consultation.
- Forsgren, N., Humble, J., & Kim, G. (2018). Accelerate: The science behind devops: Building and scaling high performing technology organizations. IT Revolution. ↩︎