Categories for non-functional requirements
Working with software includes many different types of activities such as maintenance and feature work. If we don’t focus on balancing different types of activities we risk neglecting one to the detriment of productivity and job satisfaction. To aid teams with this balancing act it can be helpful to visualize the distribution of tasks we create and solve, but first, we need to group them somehow.
This idea comes originally from the Flow Framework where we track features, defects, risks, and debts. However, I think this overlooks a crucial part of software development: learning. Therefore I suggest a new set of types. We define these four based on two questions:
- Does the activity reduce a negative effect or reinforce a positive effect?
- Is the result of the activity visible to the users?
Based on these two questions I define four categories of work:
The bottom row of this table is also known as non-functional requirements. Teams often prioritizing these. According to the DevOps Handbook, these should take up at least 20% of our capacity, however, that is not the scope of this post.
Bugs and features are what you expect. However, where the Flow Framework categorizes activities as security under risk, I consider security a feature of the product. More curious are the two user invisible categories which I now explain.
As I have posted earlier, I use the umbrella term “technical drag” instead of the traditional “technical debt” because I find the latter lacks nuance. The term “technical drag” includes everything that slows down development. This includes four subcategories:
- Technical ignorance. Sometimes solutions are more complicated than we have skills to implement. In these situations, we implement bad solutions because we simply don’t know they are bad.
- Technical debt. When we have issues in production and we are losing money we may need to implement a quick and dirty solution just to stop the bleed. Immediately after the situation is resolved we go back and reimplement a proper solution. Technical debt is when bad solutions are short-lived.
- Technical waste. When our bad solutions are not addressed and are allowed to embed themselves into our codebase, they are no longer “debt” they are “waste.” They are pollution and sabotage.
- Static content. Bad solutions slow us down but so do working solutions, documentation, tests, and everything else that is written down. The second we write something down we need to maintain it and include it in our mental models.
This is the most fluid category, as it covers any activity that we expect to increase our productivity over time. Common examples include:
- Experimenting with a new feature (unrequested)
- Studying blog posts, books, or videos
- Trying a new tool
- Automating manual process
- Increasing code quality by adding tests or error handling
- Improving our development process
- Sharing knowledge or experiences
In short, any unprioritized task can cause a productivity increase.
At this point, I recommend to our customers that they tag their tickets with category and visualize these four categories using “created vs resolved charts”, and visualize the distribution in a pie chart. This way, if we prioritize technical debt too little we should see that created and resolved are running parallel, or even worse moving away from each other.
The biggest challenge in doing this is usually centralizing all the necessary information in one system. Often organizations have one system for feature requests, a different one for incidents, and sometimes even a third for improvements or impediments. This practice makes it very difficult to get an accurate overview of the distribution of work.
If you like my writing consider checking out my refactoring and technical excellence book Five Lines of Code, where I cover many socio-technical challenges similar to this one.