The last code quality that we’ll discuss in this series, the “N” in CLEAN, calls for code to be nonredundant. On its surface it seems pretty straightforward but there is some subtlety to redundancy as well.
It’s easy to see why redundancy in code is a bad thing. It’s a duplicated effort. It means that when a business rule changes, there are multiple places where that change has to be applied and that significantly drives up the cost of maintenance. It also makes code harder to read and understand.
Unfortunately, there is a lot of redundancy in code. I see it all the time when I review the code from my clients. Sometimes it’s obvious and you can spot the duplication immediately. Other times, it’s less obvious but upon close examination we find that we’re basically trying to do the same thing in more than one place in the code.
We like to use the “once and only once rule.” When defining processes or business rules, we want to define it in one place so it’s easy to reference and access in the future.
Redundancy also has a subtle side that can be very difficult to pick up on. Perhaps we’re doing two processes that are mostly the same but some of the steps are different or one process has some extra step. There are design patterns that help us manage these types of variations and often, when we can see the pattern and apply it in our designs, we can get rid with the redundancy and improve our code quality.
I can tell you as a writer and an author that redundancy is death. There is no quicker way to bore, shut down, or shut off your reader than to repeat yourself. The same thing is true in code.
In good object-oriented programs there should be one authoritative place where each decision is made. These decisions often happen in factories, which are objects responsible for the creation of other objects. By moving business rules to object instantiation time rather than object execution time, it allows us to centralize decisions and limits the number of permutations that code can take so that behaviors are more reliable and software is more testable.
There are several creational design patterns that help eliminate redundancy in code. One example is the Gang of Four’s abstract factory pattern. The intent of the abstract factory pattern is to “provide an interface for creating families of related or dependent objects without specifying their concrete class.”
For example, let’s say I have an ecommerce system and when a sale is generated I want to create an invoice, a packing slip, apply tax, etc. but I want to do these things differently depending upon which country I make the sale in, so I want to work with families of objects. My abstract factory will return one set of objects if the sale happened in the United States but another set of objects if the sale happened in a different country, say the Netherlands.
If I set things up correctly, then as I begin to do business in new countries, I only have to update the abstract factory and add new variation to existing structures. All of the code that uses these variations—invoicing, accounts payable, and so on—can work without any modification as we start to do business in new countries. This technique not only helps eliminate redundancy but also allows for systems to be extensible to new variations in the future.
But not all redundancies are easy to spot. Some get hidden behind the best of intentions. If I have the time, I’ll try to figure out these subtle forms of redundancy because when I do I often find that the code becomes much clearer and I discover patterns I didn’t see before, which helps me improve the design of the code.
This is the worst part of redundancy, that it hides the truth, that it creates a barrier to understanding. If we want our code to be clear, we should strive to remove redundancy at all levels.
Previous Post: « Assertiveness and Testability
Next Post: Pathologies of Redundant Code »