As I shared two posts ago, our team has more than met our goal this year of reducing defects found outside our group by 25%. We did this by performing a root-cause analysis of defects from 2018 and devising strategies to counter the most frequent causes. Now new causes have risen to the top, with one being fallout from unrelated changes.
A fallout-type defect happens when a developer changes an area of the code to correctly produce a desired feature or fix a defect, but this change has the effect of breaking something else.
Here is an example. Our flagship software product stores data and images and then allows a user to search for them later. Among its features is the ability to store search criteria for future use.
As a recent enhancement, we provided a way to link data in one domain to data in another. We use a folder metaphor, and this feature is called Related Folders. For example, we can configure the system so when a user is viewing a record in the Accounts folder it can find related records in the Invoices folder by searching for invoices whose Account Number equals the one currently being viewed in the Accounts folder.
Whatever the criteria for relating a pair of folders, those criteria must be saved to the database so the folder relationship becomes permanent.
Cleverly, we reused existing search logic to implement both the search itself and to persist the criteria. Code result: the holy grail, right?
A further requirement was that the user who sets up a folder relationship must have administrative rights. That is where the problem came in. The developer added a requirement for administrative rights to the search-persistence logic. This made admin privileges a requirement for persisting all searches! Ordinary users could no longer save their search criteria. Oops.
That’s what we mean by fallout. The new feature worked perfectly, but it broke an existing one.
So how can we prevent this type of defect? In software engineering, almost all roads lead to the Single Responsibility Principle, and this was no exception. The developer gave a second responsibility (application security) to a module that already had a responsibility (storing search criteria).
A better design would have been to sequester the authorization and business logic into separate layers. The path of execution would first verify that the user had permission to do what he was attempting, whether saving an ordinary search or setting up a folder relationship, and then the business-logic layer would store the search criteria.
If you are getting many defects due to fallout from unrelated changes, it may be a sign that your code does not follow the Single Responsibility Principle!