Improving code traceability with contextual mutations
Mutation is common in the world of business logic. Take StackOverflow as an example: a user can create a question and later change its content. However, when this concept is translated into the programming world without careful thought, it can lead to issues that affect maintainability, particularly in tracing mutations in the codebase.
Let’s consider a super simplified example of a fictitious StackOverflow clone. Imagine a REST API endpoint that allows the user to update their question:
In this example, updating the question's description requires mutating a public description field. This might seem straightforward, but imagine a codebase where this field is mutated in many locations. With multiple files editing this description field, various data sources updating the Question description, a codebase with 50k lines of code, and numerous other classes also containing a description field, how would you locate where the description of a Question is updated? Here are some approaches:
Let’s review each method and its drawbacks:
Ultimately, these methods of finding where the description of the Question class is updated are not specifically designed for this purpose. Fortunately, there are some refactors we can implement to improve traceability. The first refactor involves encapsulating the mutability of this field in a single function, such as a setter:
By searching for references to setDescription, we can precisely locate all the places where this field is mutated. While this approach solves the problem, it lacks context about why these mutations occur, which would be beneficial for understanding how our business rules align with our codebase. Here’s an enhanced approach:
Now we can clearly understand the context of these mutations and accurately represent the business rules. Of course, in a realistic scenario, there would be more data, code, and other classes involved in these mutations. However, adding context to mutations remains viable and significantly enhances the traceability and maintainability of our codebase.