Technical Debt in Product Lines – on the trouble of differentiation

Traditionally, technical debt research (implicitly) takes a single-system perspective. However, what happens in product lines? Is there also technical debt (you bet) – are there further forms of technical debt? Probably..

In our recent research, my group also addressed the notion of (code) smells in product lines. There is already some research in this direction, but very often from the perspective of: how do existing smells translate to the product line situation. We were more interested in the perspective: what are novel types particular to product lines.

What is particular about a product line is that it typically contains a variability model (describing possible features and their relations) and the code that is related to these features. For a specific feature combination that is selected then the corresponding code is extracted / generated / composed, etc.
We grounded our studies in Linux, a well-known reference case, as it is with about 15.000 features and industrial-size product line. (There code is C-code with pre-processor statements, while variability is expressed using the special language Kconfig)

So what are the kinds of problems that arise there? And are they REALLY technical debt items – or are they defects? (Kruchten argues very strongly on this blog – and I think correctly – that these two are actually very different)

Typical problems relevant for product lines are for example:

  • dead features,
  • dead code (or the inversion),
  • or where we was interested in: over-constrained code

But what are these beasts and if we use the following definitions

“Technical debt = non-user-visible issue in the system implementation that creates a problem for evolution”
“Defect = user-visible issue that leads to a problem for the user (unexpected / unintended) behavior”

are they defects or technical debt?

A dead feature is a feature that cannot be selected, although it is described as selectable. It is probably a safe bet this is a defect. For dead code, it is more difficult: this means that some code is not used in any variant, although it is described as variable in the code. This may have many reasons like added constraints in the build system or in the variability model that interact.
At first sight this may seem clear: certainly the problem is now not activated in some situations for which it was intended. This is surely a defect! – On the other hand, it may be due to the fact that these variants do not even exist any more, making it simply some code that is maintained, but effectively dead code, i..e, technical debt.
The situation of over-constrained code is even more complex as simply in some cases where one might expect this code to be present it won’t be. Whether this qualifies as a defect or technical debt requires a deep analysis of which code should be integrated under what circumstances and what would be required for correct functioning. We found in our analysis that there was hardly any difference in amount of effort spent between identifying whether s.th. had a user-visible effect (i.e., defect) or was technical debt and actually proposing a change for solving the problem altogether. Hence, while the differentiation between technical debt and defect seems rather obvious and intellectually appealing, we also saw that it sometimes is of rather little practical use.

Apart from this specific question of technical debt vs. defect, I am also looking forward to discussing special forms of technical debt like product line technical debt or debt handling in software ecosystems.