Open/Closed Principle
The Open/Closed (OC) Principle states that a class object should remain open for extension but closed for modification. The class should be able to be extended (to add new functionality, for example), but the original code should be open to change only to correct bugs.
At first glance, this principle seems to be contradictory. How is it possible to extend code that is not supposed to be modified?
Take a look at the following example:
public class TextWriter { public void TextWriter(string message, WriterType writerType) { switch (writerType) { case WriterType.Console: Console.WriteLine(message); break; case WriterType.File: // code here break; } } } public enum WriterType { Console, File }
What if we need to add a third way of writing a text message to the switch statement (to a database, for example)? According to the principle, this code should not be modified.
To change this code to no longer violate the OC principle, we can introduce an interface to create an abstraction for the different ways to implement writing the text message.
The refactored code looks like this:
public class TextWriter { IMessageWriter _messageWriter; public TextWriter(IMessageWriter messageWriter) { messageWriter = messageWriter; } public void Write(string message) { messageWriter.Write(message); } } public interface IMessageWriter { void Write(string message); } public class ConsoleWriter : IMessageWriter { public void Write(string message) { Console.WriteLine(message); } } public class PrinterWriter : IMessageWriter { public void Write(string message) { // Code to write message to a file } }
Now we can add new types of writers without modifying the class that handles the writing by using an interface and constructor injection, which is a type of dependency injection used by frameworks such as Java Spring or the Ninja injection framework for .NET.