5,445,109 members and growing! (15,183 online)
Email Password   helpLost your password?
Development Lifecycle » Design and Architecture » General     Intermediate

Open Close Principle

By svigano

Object Oriented Design
Windows, Visual Studio, Dev

Posted: 6 Jun 2006
Updated: 6 Jun 2006
Views: 11,284
Bookmarked: 3 times
Announcements
Want a new Job?



Search    
Advanced Search
Sitemap
18 votes for this Article.
Popularity: 2.57 Rating: 2.04 out of 5
9 votes, 50.0%
1
2 votes, 11.1%
2
1 vote, 5.6%
3
2 votes, 11.1%
4
4 votes, 22.2%
5
Note: This is an unedited contribution. If this article is inappropriate, needs attention or copies someone else's work without reference then please Report This Article

Introduction

One thing is certain in all software development, all software changes during its life cycle. So, it is imperative that developers design software that is stable (i.e. does not change) in the face of ever changing functional requirements. To aid in this development, Robert Martin gave us the open-closed principle, which states:

SOFTWARE ENTITIES (CLASSES, MODULES, FUNCTIONS, ETC.) SHOULD BE OPEN FOR EXTENSION, BUT CLOSED FOR MODIFICATION [Martin].

Software modules that satisfy the open-closed principle have two huge benefits. First, they are "open for extension". (the behavior of the modules can be altered to satisfy the changing requirements) Second, these modules are "closed for modification". (The modules, themselves are not allowed to change). In this article, we will describe the the open closed principle via a simple example.

Background

Consider the following example. We have an application that must be able to manage different kind of shapes (i.e. circles squares, polygon etc...) and draw them on a standard GUI. Using a techniques that do not conform to the open-closed principle, we might solve this problem as shown

    
    class Shape
    {
         private Point _center;

        #region Center Get / Set
    };

    class Circle : Shape 
    {
        private int _radius;

        #region Radius Get / Set
    }

     class Square : Shape 
    {
        private int _side;

        #region Side Get / Set
    }

These first classes encapsulate the shapes' data structure. The follow manager performs several operations on the shapes such as draw and serialize.

 class DrawManager
 {
        private List<Shape> _shapeList;
        
        public DrawManager()

        public void add(Shape s)
        
        // Serialize all registered shapes
        // This method is not conformed to the Open Closed Principle
        public void serializeShape(string fileName)
        
        // Draw all registered shapes
        public void drawShapes()
        { 
            // This method is not conformed to the Open Closed Principle
            foreach(Shape s in _shapeList)
            {
                if (s is Circle)
                {
                    _drawCirle((s as Circle));
                }
                else if (s is Square)
                {
                    _drawSquare((s as Square));
                }
            }
        }
        // The concreate implementations of these methods are not important in this discussion
        private void _drawCirle(Circle c)
        private void _drawSquare(Square sq)
        private void _serializeCirle(Circle c)
        private void _serializeSquare(Square sq)
  };

The method drawShapes walks a list of Shape, examining the Shape type and then calling the appropriate private draw method (either _drawCirle or _drawSquare). The problems with the above design is that it violates the Open Closed Principle because it cannot be closed against new kinds of shapes. If I wanted to extend this function to be able to draw a list of shapes that included triangles, I would have to modify the function. In fact, I would have to modify the function for any new type of shape that I needed.

Of course this program is only a simple example. In real life the switch statement in the drawShapes function would be repeated over and over again in various functions all over the application; each one doing something a little different (For example the method serializeShape has the same problem). Adding a new shape to such an application means hunting for every place that such switch statements (or if/else chains) exist, and adding the new shape to each. Moreover, it is very unlikely that all the switch statements and if/else chains would be as nicely structured as the one in drawShapes. It is much more likely that the predicates of the if statements would be combined with logical operators, or that the case clauses of the switch statements would be combined so as to “simplify” the local decision making. Thus the problem of finding and understanding all the places where the new shape needs to be added can be non-trivial.

Solution

The follow code is a possible solution to the shapes problem that it conforms to the open-closed principle. In this case the abstract Shape class defines a single pure-virtual function called Draw. Both Circle and Square override the function in a different way.

    abstract class Shape
    {
        private Point _center;

        // Define an abstract way to draw a shape
        public abstract void Draw();
    };

    class Circle : Shape 
    {
        private int _radius;

        // Override the abstract method to draw a cirle
        // The concreate implementation is not important in this discussion
        public override void Draw()
    }

    class Square : Shape 
    {
        private int _side;

        // Override the abstract method to draw a square
        // The concreate implementation is not important in this discussion
        public override void Draw()
    }

    class DrawManager
    {
        //......
        //......
        
        public void drawShapes()
        {
            foreach (Shape s in _shapeList)
                s.Draw();
        }
        
        //......
        //......
    }

    

Note that if we want to extend the behavior of the DrawShapes function to draw a new kind of shape, now, all we need do is add a new derivative of the Shape class. The DrawShapes function does not need to change. Thus DrawShapes conforms to the open-closed principle. Its behavior can be extended without modifying it.

In the real world the Shape class would have many more methods. Yet adding a new shape to the application is still quite simple since all that is required is to create the new derivative and implement all its functions. There is no need to hunt through all of the application looking for places that require changes. Since programs that conform to the open-closed principle are changed by adding new code, rather than by changing existing code, they do not experience the cascade of changes exhibited by non-conforming programs.

Points of Interest

As you could realize The Open Close Principle is referring to using Abstract Classes and their Concrete SubClasses to extend behavior. This essentially means using something like the Template Method Pattern or Strategy Pattern to delegate either part or all of an algorithm in a Concrete SubClass [Gof]. A Template Method is a Method in an (abstract) base class which calls one or more HookMethods to fulfill parts of its tasks. You can easily extend or change the behavior of the abstract base class by creating new subclasses that implement a new version of the Hook Method. This fulfills the requirements of the Open-Closed Principle.

Conclusion

It should be clear that no significant program can be 100% closed. For example, consider what would happen to the DrawShapes function if we decided that all Circles should be drawn before any Squares. The DrawShapes function is not closed against a change like this. In general, no matter how “closed” a module is, there will always be some kind of change against which it is not closed. Since closure cannot be complete, it must be strategic. That is, the designer must choose the kinds of changes against which to close his design. This takes a certain amount of prescience derived from experience. The experienced designer knows the users and the industry well enough to judge the probability of different kinds of changes. He then makes sure that the open-closed principle is invoked for the most probable changes.

References

    Robert C. Martin - http://www.objectmentor.com/courses/pood

History

June 2006 : Initial Version.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

svigano


Simone Viganò is from Milano, Italy. He has been in the programming career since 1999, when he was 20 years old.
He has filled a variety of roles ranging from Junior Developer to Senior Software Engineer and Consultant.
For the last 5 years he has worked extensively on Artificial Vision System programming VC++/MFC, ATL/COM and DirectShow.
Simone is also experienced with C#, VB.net and Java (J2EE - J2ME).
Actually He is working as a Team Leader for a company involved in the building automation systems (HVAC-BAS).
He has his Degree in Computer Science from Milano-Bicocca University, Italy.
He has a Master in ICT (Information Technology and Comunication) Management
from Milano-Bicocca University, Italy.
Simone is just a passionate cool-dude about Software Enginee.
Occupation: Team Leader
Location: Italy Italy

Other popular Design and Architecture articles:

Article Top
Sign Up to vote for this article
You must Sign In to use this message board.
FAQ FAQ Noise ToleranceSearch Search Messages 
 Layout  Per page   
 Msgs 1 to 6 of 6 (Total in Forum: 6) (Refresh)FirstPrevNext
Subject  Author Date 
GeneralWHY CONFUSE PEOPLE????memberMr.Programer6:07 8 Jun '06  
GeneralWhy confuse people ?memberMaximilien7:09 6 Jun '06  
GeneralRe: Why confuse people ?memberleppie7:48 6 Jun '06  
AnswerRe: Why confuse people ?membersvigano13:52 6 Jun '06  
GeneralRe: Why confuse people ?memberKevin McFarlane7:18 8 Jun '06  
AnswerYou are confusedmemberSilentSilent1:14 7 Jun '06  

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

PermaLink | Privacy | Terms of Use
Last Updated: 6 Jun 2006
Editor:
Copyright 2006 by svigano
Everything else Copyright © CodeProject, 1999-2008
Web20 | Advertise on the Code Project