Add, Don’t Modify Pattern

Intent We want to be able to grow our domain models. They must be infinitely scalable. Growing an already large model should not be more difficult than a small model. Change comes in two forms: changing existing functionality, or adding new. We want there to be as little difference as possible between the two, regarding…

Intent

We want to be able to grow our domain models. They must be infinitely scalable. Growing an already large model should not be more difficult than a small model. Change comes in two forms: changing existing functionality, or adding new. We want there to be as little difference as possible between the two, regarding testing, validating, and modelling.

Also Known As

No known current variants of this pattern are known to me.

Example

A banking system has functioned for years but now an invasive change is necessary: the format of the account numbering system needs to change from a proprietary 9-digit number to a standardised 20-digit one. Since this change will impact all existing accounts it seems to be a daunting job: all accounts will be touched, and this change may have numerous side effects. It may even be impossible to cover all test cases completely.

Context

Large, interdependent systems need a change that has rippling effects.

Problem

Even a small change can have massive consequences, making the changes in large, interdependent systems more and more expensive.

Solution

Don’t change existing objects. Not for changing existing functionality, nor to add new functionality. Existing test cases should not need to be modified. Instead functionality is modified by adding more objects. Since the model has been created using the Active/Passive pattern it is a loosely coupled model that does not hinder us in doing this.

Structure

Existing objects will still be used by the existing part of the system. However new parts, those that need to work with the new format, will “enhance” those existing objects by reusing them. This is done by wrapping the existing bank accounts in a new bank account object, delegating all necessary behaviour to the existing object, but (as it were) enriching the object with the new behaviour.

Variants

The Decorator pattern from the Design Patterns book. In fact this is the possible implementation of this pattern.

Known Uses

Consequences

  • Changes do not lead to mandatory changes to existing components
  • Test cases do not need to be modified (same rule applies: change will lead to new components, in this case test cases, not to changes to existing components, in this case test cases)
  • The system may only grow, this is a possible adversary effect of the applying the pattern. As with any pattern, it is not applied in isolation: you will still need to audit your solution for legacy migration, which will phase-out obsolete parts of the system.

See Also

Tags:

Responses to “Add, Don’t Modify Pattern”

  1. Eddy de Boer

    Hi Rob, a question regarding this.
    Let’s say we want to add functionality to our object. When applying this pattern, it means more objects through inheritance. But that would mean strong coupling (I don’t want to use inheritance n concrete objects).
    Do you know how to deal with this?

  2. Dmytro

    Last time I felt the power of this pattern. Instead of refactoring existing (stable) functionality – it is easy to clone method, edit the body/parameters of method, and use it in necessary context. When activelly coding – next you will realize that new method also has very different context of invocation, diffetent call-time, sometime – different assembly.So there were no need of refactoring (reusing) effort.
     
    From evolutionary prospective – it is more efficient to have few copies (alternatives) of functionality in project. You will be able to monitor and track behavior, real cases – and basing on that experience – make a dicision about further reuse/refactoring.

Leave a Reply

Your email address will not be published. Required fields are marked *