Adaptable Design Up Front and the Open/Closed Principle

The Open/Closed principle is one of the SOLID principles of software design:

“The Open/Closed Principle states that the design and writing of the code should be done in a way that new functionality should be added with minimum changes in the existing code. The design should be done in a way to allow the adding of new functionality as new classes, keeping as much as possible existing code unchanged.”

camera with lensesThe picture on the right illustrates the application of this principle to an object we know very well: Professional cameras can be attached to several types of lenses. The camera itself does not need to be changed, it is simply extended. It is “closed” but also “open”.

The Open/Closed principle was originally proposed by Bertrand Meyer: “Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification.”

strategyA simple example of the Open/Closed principle is the Strategy design pattern. In this pattern, the Strategy is a component, and the same composite class may be associated to several types of strategies. The composite class using the strategy never needs to be changed to use a new type of strategy, and in this sense it is “closed”. But it is also “open”, because its behavior can be
extended through associations to new concrete strategies.

It is easy to understand the meaning of the Open/Closed principle in the context of relationships between pairs of classes, such as inheritance and composition. It is also relatively simple to use it in low-level design, and actually many design patterns apply this principle. But it is interesting to ask ourselves how the Open/Closed principle may affect the high-level design.

The Open/Closed Principle Applied to High-Level Design

The approach of Adaptable Design Up Front (ADUF) is an application of the Open/Closed principle to high-level design. It focuses on the early definition of the “closed” aspects of the design while at the same time allows easy evolution by making this design open to extensions.

The design is “closed” when it captures the essential aspects of the system: The main entities and relationships. These are the aspects that are not expected to change.

The design is “open” when it can be easily extended without changes. Through these extensions, the closed part of the design can be adapted to changing requirements.

ADUF starts with a domain model defining the main entities and relationships. We then design a framework for this model, in which the relationships among entities are implemented as associations among classes.

The associations must be closed: An object of type A must have a reference to an object of type B. But polymorphism allows this association to be also open: An object of type A can be associated to an instance of a subclass of B, even subclasses that did not exist when A was created.

ADUF also promotes the usage of Plug-ins as an application of the Open/Closed principle to high-level design. The same module may be associated to diverse plug-ins without any need of change. The module associated to the plug-ins may appear to be completely opaque and monolithic from the point-of-view of the plug-in developer.

Enough Design Up Front

Question: How much design should be done up-front?

Answer: The design up-front should capture all the “closed” aspects of the system. Besides that, we should invest to make this design “open”, in order to allow it to evolve through specialization. This may be done with appropriate Design Patterns.

Thus, there are several kinds of mistakes when doing the design up-front:

  • Too much design up front: Capturing aspects that are not essential as if they were such. The consequence is that the design may need to change, and if it needs to change then it is not really “closed”. This also happens when specific details are not generalized. If the details change, the design must be changed.
  • Not enough design up front: Leaving away some of the essential aspects of the system. The consequence is that these aspects will need to be added to the design when other parts of the system are already implemented. If the original design was not “open” enough, the new additions may cause conflicts.
  • Not enough openness: The design captures all essential aspects, but there are not mechanisms that allow this design to be easily extended. For example, if there are Interfaces or Abstract classes that represent the main entities, there should be also creational patterns such as Factories to instantiate specific subclasses.
  • Too much openness: The design is over engineered, resulting in complexity not really necessary. For example, it is always possible to reduce the coupling between modules through additional layers of indirection. However, if there are many such layers, it becomes more difficult to locate the places in the code where the business logic is actually implemented.

In summary:

According to the ADUF approach, the design up front should be:

  • Closed: Capturing the essential aspects that are not going to change.
  • Open: Allowing the initial design to be easily extended and adapted.

What do you think? Have you used similar approaches? Please share your experience in the comments below.

About Hayim Makabee

Veteran software developer, enthusiastic programmer, author of a book on Object-Oriented Programming, co-founder and CEO at KashKlik, an innovative Influencer Marketing platform.
This entry was posted in Adaptable Design, Design Patterns, OOD, Software Architecture, Software Evolution and tagged , , , , . Bookmark the permalink.

11 Responses to Adaptable Design Up Front and the Open/Closed Principle

  1. Yonatan Lehman says:

    Hi Hayim. I think that what you say here has a solid basis, but is simplistic in the real world and on the long term – which in nowadays can mean a year or less.

    My problem is in the statement
    quote : “Capturing the essential aspects that are not going to change”

    In real systems – including cameras, Inevitably you won’t always anticipate the changes, and you may well make assumptions – explicit or implicit – based on an existing understand of the technology and the market,

    quote : “The design up-front should capture all the “closed” aspects of the system..”

    IMHO – the design up front should capture our understanding of what isn’t closed, and our understanding of where we are making pragmatic or unconscious assumptions.

    Using your camera example.

    A new model of a camera – based on the same firmware – needs to be adapted to deal with 64 GB flash memory.

    Even if the architects did some up front design and created an abstract memory storage with plugins for different memory. Would they anticipate that accessing a 64 GB chip might need 64 bit arithmetic ? Would they be willing or even correct to force the design to use a 64 bit math instead of long integers ?

    How would you classify this type of “mistake” ?
    How would you classify the “year 2000” bug.

    I agree with what you are saying – but I think that when designing for evolution, an important driver of the design is making an intelligent guess as to how solid our assumptions are.

    An API and inheritance model exposes what changes we anticipate.
    We try to hide assumptions in classes, so that upper levels are not impacted by changes (yes – the existing lower level code are DESIGNED to be changed..)

    .

    • Thanks for your comments, Yonatan. I agree with you, and I didn’t mean that the “closed” aspects of the design should be less abstract than the “open” ones. I propose that we should start with a domain model that is then implemented as a framework.

      In the example of the Strategy design pattern, the closed aspect is the relationship between the Context and the Strategy, defined through an association and an API. The open aspect is the possibility to adopt diverse concrete strategies, using inheritance and polymorphism.

      If I understand you correctly, that is what you mean by “An API and inheritance model exposes what changes we anticipate.”

  2. AA: The principle of “Extensible but NOT Modifiable” is simple and direct. One can understand it without explanation. Open / Close is NOT as simple and direct. It needs explanation. This is the essential principle of modular design of various products and services.

    BB: In OOAD the concept of class hierarchies, one class one responsibility, polymorphism, orchestrating instantiated standard objects to create dynamically create new configurations and services are all great and practical without even invoking any concept of design patterns.

    CC: It is not clear if there is any real / practical advantage of knowing AA to improve software design over and beyond what BB already & anyway gives.

    DD: The kinds of mistakes pointed out are likely to occur. They can be detected and classified after making the mistakes and running into problems but I do not see how a designer can detect and avoid those mistakes. They are too general and relative.

    EE: I think that Yonatan is also saying CC and DD in his own words.

    FF: IMO this line of thinking is good and needs to be pursued but it is too nebulous without any distinction and value in the present form. I would be following your blogs closely and hope to contribute.

    Best wishes,

    • Thanks for your comments, Putcha. I’m proposing Adaptable Design Up Front (ADUF) as an alternative to Big Design Up Front (BDUF), No Design Up Front (NDUF) and Enough Design Up Front (EDUF). BDUF and NDUF are opposite extremes, and EDUF does not define how much design is “enough”. ADUF defines how much design should be done up front according to clear guidelines, and makes sure this design is extensible. I think ADUF is particularly suited to iterative software development as proposed by Agile methodologies.

      I’m aware that ADUF is still bit “nebulous”, and I will continue writing about this subject, but I will do so incrementally in order to collect feedback. Thanks.

  3. Tom Haley says:

    Excellent article and well thought out. I agree completely with you comments about Agile and ADUF. I have often wondered why some people believe that Agile and software design are somehow in conflict. They’re really not.

    Regarding the statement: “Capturing the essential aspects that are not going to change”
    I think at some point in the design phase decisions regarding aspects of the system that are unlikely to change need to be made. Your comments and the article imply, to me anyway, that domain experts will make a big difference in arriving at a quality design.

    I really like how you illustrated your point with a design pattern. It gives the reader a good insight into your ideas about design.

  4. Pingback: Avoiding Technical Debt: How to Accumulate Technical Savings | Effective Software Design

  5. Pingback: The End of Agile: Death by Over-Simplification | Effective Software Design

  6. Pingback: The End of Agile: Death by Over-Simplification | Effective Software Design

  7. Pingback: Re-Post: The End of Agile: Death by Over-Simplification | Youry's Blog

  8. Pingback: On Agile Architecture, Emergent Design and Framework-Based Design | Effective Software Design

  9. Pingback: Manifesto for Adaptable Software Development | Effective Software Design

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s