Trading quality for time
Any serious business aims at having paying customers. In the software world, they do this by providing software solutions that customers can actually use. In business terms therefore, software is means to generate revenue, which is needed to create profit. Software development is therefore no more than a very expensive tool.
When a software solution is requested, the business wants it as soon as possible for two reasons: 1) longer development times means higher cost, and 2) the sooner the product is on the market, the sooner it starts generating revenue, so the more profitable the company will be.
Therefore, as a software engineer, it is no exception to deliver with tight deadlines. The classical response is to either do this at the cost of functionality or quality. However, trading quality for speed is an illusion.
Good – cheap – fast
Something like this picture is always in the mind of business people (and many developers): it presumes that time, functionality and quality can be traded against each other. Make it a little less good and you can have the product sooner. And, as stated before, the business always demands cheap and fast. So good has to suffer.
Let’s explore the three terms a bit more for a good understanding. Time is easily measurable. You can pick a date and measure the amount of time left, or make an estimate of the required work. Functionality is also not difficult to measure: for each piece of functionality, you can validate whether it is present or not in the solution. Quality is the difficult one however. How can you measure it? What is quality anyway? It seems we need a definition first to make the term a bit more manageable.
Definition of quality
Wikipedia distinguishes between two different notions of software quality:
- Functional quality, which tells to what extent the software fulfills its intended function;
- Structural quality, which tells to what extend the software is usable (does not crash, is easy to operate, can be installed etc.)
For the course of this article, I will focus mostly on the functional quality. To clarify my point, I will specify software quality a bit more concise as the absence of bugs.
What to give up?
Suppose the project deadline is really tight and you know you cannot make it in time. Suppose also that you are planning to give up on quality instead of features. What quality item will you give up? And what are the consequences when doing so?
Often, the first thing to go are automated tests. People argue that this might save the time to write and debug these tests, so it will save on time considerably. However, there is a consequence. Consider the worst case, where you ship the code immediately as soon as it compiles: in that case you actually turn your end users into testers. They have all sorts of problems of the software and start complaining. Each bug they report needs to be verified (you need to know what exactly is going on), repaired and delivered. The sad thing is, since you have no automated tests, there is no guarantee that existing functionality still works. So either you must perform regression tests by hand, or the end users start complaining about fixes that introduce new bugs.
It is also tempting to take shortcuts in the code: don’t take time to think of an appropriate design, or couple parts of the code that should be decoupled. The code base will be come a mess as a result. This consequences are even worse as the previous point, because it makes automated testing almost impossible (except on end-to-end level, which are the most brittle and slowly running tests possible). Over time, such tangled code will become unmaintainable and riddled with bugs.
A common consequence to these two approaches is that bugs are found (and fixed) very late in the development cycle. This makes fixing them very expensive. It also reduces the amount of feedback during development, so it looks like things are going well from the start, but only because the actual problems are not visible yet. The result is that removing these quality measures actually makes the project take longer and make it difficult to manage.
The bottom line is: you won’t gain anything when giving up on quality. A minimum quality level is required so that you get early feedback and are able to deliver with confidence.
A better approach
Since you cannot trade quality, the only thing left is to trade time for functionality. If there is insufficient time, you can only give up on features. However, normally you cannot drop features because that would make the solution unusable. The good thing is, that is also often unnecessary.
It is good to realize that functionality can be seen in two dimensions: which features are required, and how much of each feature is essential. Note that a feature is meant to solve a problem for some stakeholder. Having just enough to solve the stakeholder’s problem is sufficient, and this almost never would require the complete feature to be implemented, gold plated and all.
That is also the foundation of a much better approach: start by implementing just enough to deliver the most basic version of each feature. For example, a feature to export data might save to a csv file with a fixed name first. In later increments the feature can be given more body. Like: let the user select the file, export to multiple formats, allow the user to select what is exactly being exported and so on. Those are sensible additions because, although not essential, they still add value for the user.
This approach has two great benefits:
- Risks become clear as soon as possible. You get feedback very early, because even the most basic features can already be deployed. Therefore, there is ample time to find good solutions for any problems that occur.
- By having a working solution already, stakeholders get a much better feeling for the solution. They are able to better judge what is important and what not.
That a feature is initially delivered in the most basic way does not mean that it should be of low quality. To keep with the export example: the export function should do what is promised, and do that well. Also, since you intend to expand on this feature, you should take care that the code and design are sufficiently flexible (but not more). Automated tests are essential to avoid continuously manual regression testing. When you follow this approach, you adhere to a quality level because you know that will save you time.