For the past four months, Sindhu, Mustafa and I have been doing a Fellowship with Infoxchange — a not-for-profit social enterprise that has been delivering technology for social justice for over 40 years. You can read more about our Fellowship here.
We have been tasked with building Ask Izzy Plus, a brand new website that helps social service workers and volunteers to find help for their clients. For example, a volunteer at a homeless shelter who is helping someone fleeing family violence could go on our site and search for family violence support services nearby.
Ask Izzy Plus is the evolution of a very popular website called Ask Izzy, which is targeted at the help seekers themselves. The folks at Infoxchange noticed that around half the people currently using Ask Izzy were actually not help seekers, but people working in the social services industry (helpline operators, social workers etc.). This is what prompted the idea of creating a site specifically catered to these users, Ask Izzy Plus.
By using Ask Izzy as our foundation, we have a unique situation where, on the one hand, we are like a startup trying to validate a new value proposition and find product market fit, and on the other hand, we are building an extension of a mature product with thousands of daily users, which will be ultimately handed over to Infoxchange devs to maintain.
A key challenge from an engineering perspective is finding the right balance between working fast, and building something robust and maintainable.
Some of the areas where this tradeoff exists include:
- Time spent planning vs time spent building
- Test coverage
- Code readability and structure
- Where and how we deploy
In our case we’ve tried to get the best of both worlds where we can, and prioritised speed over robustness.
When building a new product with a lean mindset, the goal should be to find product-market fit as soon as possible. This means prioritising activities that maximise the rate of learning and iteration. There’s no point spending ages gold plating your code if it’s not actually the product your customers want and need.
A few ways this mindset has played out for our project are listed below.
Some developers think of comprehensive testing as a non-negotiable aspect of writing code, and that skimping on tests is lazy and bad practice. However, there’s an alternative (slightly controversial) opinion that under some circumstances, you don’t need Test Driven Development or even many tests at all.
When building a brand new product with lean startup methodology, the cost of writing tests is higher (because they need to be re-written more often as the product changes) and the benefits are lower (fewer users means lesser consequences if a minor bug makes it through). This calls for a slightly different approach to testing.
Firstly, we focus on the core functionality of the product by prioritising solid end-to-end tests. This gives us peace of mind that the core functionality of the website is working, which is the most important thing. Only a small number of tests are needed to cover most things a typical user might want to do. These tests are written after the features are implemented because this is faster and requirements are constantly changing.
For visual/UI testing, we use Storybook (with Chromatic), which has the simultaneous benefits of generating a design system for the UX team and automatically detecting visual changes in the UI.
Code Readability & Structure
There is a difference between writing clear and readable code (a.k.a. writing good code) and obsessing over details that don’t really matter. Sure, it would be nice to have a perfectly consistent code base with strict adherence to a style guide, and this is important in some circumstances, but when speed is the priority, this is hardly a good use of time.
Planning vs Building
The team working on the original Ask Izzy work on a six week iteration cycle, with two weeks planning and four weeks building. In contrast, for our work on Ask Izzy Plus, we’ve adopted a shorter three week sprint cycle, with detailed feature planning occurring during a single sprint planning session, and higher level planning occurring on a more ad-hoc basis as we feel it is needed.
Working in this way has forced us to make tough product decisions on the fly with limited information, and can be more stressful because there is not a well defined roadmap. It also runs the risk of having us build the wrong thing, because certain assumptions were wrong.
The upside however, is that we can progress at a very fast pace, which means we get the product into the hands of users sooner, and start validating the assumptions we made in planning.
There’s a fine line between just enough planning and not enough planning, and we’re still working out the best way for us, but our focus on building has enabled us to make great progress and ship a working MVP much sooner than we would have otherwise.
We have chosen to use Platform as a Service wherever possible to greatly reduce time spent on DevOps. Platform as a Service (e.g. Heroku, AWS Elastic Beanstalk, Azure Container Instances) and Database as a Service remove the need to configure servers, and allow deployment of a new app in minutes, not days. They can be scaled up with the click of a button and are typically either free or very inexpensive at small scale.
There are two main downsides to Platform as a Service: they typically cost more at scale than self-managed infrastructure, and there is less control over server configuration. These issues may mean that it will be necessary to transfer to self-managed infrastructure at a later stage. In the case of our project, we need to transition to on-premises hosting at some stage.
Fortunately, because we are using Docker, the process of moving our production servers will be relatively straightforward and painless.
When developing new software, there are many decisions to be made that come down to a tradeoff between more work upfront and more work later. In most cases the conventional wisdom holds true: it’s better to spend time up front to save a lot of headaches later. With a new product, the cost of upfront work is higher (it delays launching and receiving feedback from users) and the cost of rework is less important (there may not even be a product to rework!). This calls for careful consideration of the costs and benefits when making decisions about how we build the product, and sometimes using approaches that might not be considered ‘best practice’, but will get the right product built faster.