Reading Path for Core Developer Skills
Redundancy must be strenuously avoided in our work. Redundancy increases the cost of maintenance, often by an order of magnitude. A good example of this was the Y2K bug. The problem was not that the issue was complex: 2 digits vs. 4 digits. It was that it was repeated in millions of places throughout systems.
Typically developers concentrate on duplicated state and functionality (code). However, equal care should be taken to avoid duplication:
Anything that is redundant in a system will have to be maintained in more than a single place. This introduces the possibility that one or more of these places will be missed during maintenance. Eliminating redundancy eliminates that possibility.
Also, redundancy reduces clarity. If duplication is permitted in a system, seeking an integration point or locating a bug is about trading time to reduce risk; after you find the first instance, you have to keep looking for potential duplicates. If no redundancy is allowed, one can cease the search after you find the first place you need to make a chance.
Eradicating redundancy increases the likelihood that your code will be easy to understand and modify.
A certain amount of redundancy cannot be avoided.
For instance, on a platform like Java or .NET, inheritors of abstract classes with constructors must call those constructors. In such a case, a change to the signature of the constructor will trigger a change to all the inheritors.
The limitations imposed by each language are different.
Fortunately, you don’t have to find all the places where the aforementioned coupling was repeated. At best, the compiler will do so and, at worse, you will find out at run-time.
You can also design around problems intrinsic to your chosen platform. You can create value-objects to encapsulate signatures of methods. You can hide constructors to ensure there are no redundant calls to them. Et cetera.