Does quality always mean speed loss?
We believe that the more time spent on software development, the better the result, and vice versa. But is that really true?
The speed can be achieved by skipping testing or sacrificing architecture clarity. This way, the app would likely have a lot of bugs and issues, including fundamental ones. However, this isn’t the only way.
The following tips significantly improve MVP quality so that it might become a foundation for the final app and could be maintained for many years.
Every MVP solves just one or several major customer problems. Let's think about whether all the backlog features are so important.
Many creative options could significantly reduce the required development time. Let's look at some low-hanging creative examples:
mailto:
link. Moreover, mailto:
links support a predefined subject and body by the same query arguments.
These temporary solutions are much faster to implement and usually won't affect a hypothesis check. Besides, most of these features are rarely used by customers, so they probably won't be disappointed.
Research your customers to find their common platforms or common patterns of how they work. It would help you define the primary scope: releasing only the MacOS app might be a good option.
However, keep your technical design common and return a "not implemented" response when it's possible. It will give you both benefits simultaneously: you may speed up development without losing the ability to extend. Here is a perfect example:
def normalize_image(filename):
if not filename.endswith(".jpg"):
raise NotImplementedError()
...
The most popular way would be to completely refuse to test since it doesn't provide any customer-facing benefits (especially low-term). However, missing tests could be a serious blocker for further support and also for quality generally.
A great option perfectly matches the 20/80 rule: design the test cases for your code without implementing them. Like the following example:
test.todo("login form displays error message for invalid credentials")
test.todo("success login redirects to the home page")
test.todo("success login redirect supports _next query param")
Although it doesn't test anything, it helps find all possible cases that must be supported and tested manually. Moreover, the generation process itself improves code and app quality.
In my experience, the simplest ways are always better, even in the further development processes. But it's essential to choose the simplest ones during MVP design.
Microservices, complex queues, or several data sources are usually bad ideas for MVP. Consider using a simple monolith app; just try to keep its modules decoupled.
There are two major rules that help to design sustainable architecture:
The correctness of the decisions themselves is not so important as the ability to change them later.
The more fundamental component requires more quality, and vice versa.
Remember that an MVP is as much a hypothesis test as it is often an initial app. So, balancing business expectations and technical quality is pretty important. Basically, both extreme points aren't good ideas: MVP without essential features isn't valuable, as well as an MVP that couldn't be adapted to any customer requests because it's always too difficult.