Spis treści
Open/closed principle
All classes should be open for enlargement and closed for modifications.
How to use OCP in practice?
You should use interfaces and abstraction, not to become dependent on implementation details.
Difficulties in using OCP
Sometimes is hard to decide, what is implementing detail and in which direction the application is going.
Example
To exercises OCP I took a simple example. We have Calculator, which calculates figure area.In first version I am using switch, to recognise a specific figure.
class AreaCalculator { private readonly List<object> figures; public AreaCalculator(List<object> figures) { this.figures = figures; } public double Calculate() { double area = 0; foreach (var figure in figures) { switch (figure) { case Square square: area += square.GetWidth() * square.GetWidth(); break; case Rectangle rectangle: area += rectangle.GetWidth() * rectangle.Getheight(); break; case Circle circle: area += Math.PI * Math.Pow(circle.GetRadius(), 2); break; default: area += area; break; } } return area; } } class Square { private readonly double width; public Square(double width) { this.width = width; } internal double GetWidth() { return width; } } class Rectangle { private readonly double width; private readonly double height; public Rectangle(double width, double height) { this.width = width; this.height = height; } internal double GetWidth() { return width; } internal double Getheight() { return height; } } class Circle { private readonly double radius; public Circle(double radius) { this.radius = radius; } internal double GetRadius() { return radius; } } class Program { static void Main(string[] args) { List<object> figures = new List<object>() { new Square(5), }; AreaCalculator areaCalculator = new AreaCalculator(figures); Debug.Assert(areaCalculator.Calculate() == 25); List<object> figures2 = new List<object>() { new Square(5), new Rectangle(5,3), }; Debug.Assert(new AreaCalculator(figures2).Calculate() == (25 + 15)); List<object> figures3 = new List<object>() { new Square(5), new Rectangle(5,3), new Circle(5), }; Debug.Assert(new AreaCalculator(figures3).Calculate() == (25 + 15 + Math.PI * 25)); } }
After refactoring, I have figure classes, which implement the interface to calculate figure area. The calculator only sums all figure areas.
class AreaCalculator { private readonly IEnumerable<IFigureAreaCalculator> figures; public AreaCalculator(IEnumerable<IFigureAreaCalculator> figures) { this.figures = figures; } public double Calculate() { return figures.Sum(x => x.GetArea()); } } interface IFigureAreaCalculator { double GetArea(); } class Square : IFigureAreaCalculator { private readonly double width; public Square(double width) { this.width = width; } public double GetArea() { return width * width; } internal double GetWidth() { return width; } } class Rectangle : IFigureAreaCalculator { private readonly double width; private readonly double height; public Rectangle(double width, double height) { this.width = width; this.height = height; } internal double GetWidth() { return width; } internal double Getheight() { return height; } public double GetArea() { return width * height; } } class Circle : IFigureAreaCalculator { private readonly double radius; public Circle(double radius) { this.radius = radius; } public double GetArea() { return Math.PI * Math.Pow(radius, 2); } internal double GetRadius() { return radius; } } class Program { static void Main(string[] args) { var figures = new List<IFigureAreaCalculator>() { new Square(5), }; AreaCalculator areaCalculator = new AreaCalculator(figures); Debug.Assert(areaCalculator.Calculate() == 25); var figures2 = new List<IFigureAreaCalculator>() { new Square(5), new Rectangle(5,3), }; Debug.Assert(new AreaCalculator(figures2).Calculate() == (25 + 15)); var figures3 = new List<IFigureAreaCalculator>() { new Square(5), new Rectangle(5,3), new Circle(5), }; Debug.Assert(new AreaCalculator(figures3).Calculate() == (25 + 15 + Math.PI * 25)); } }
Adding a new figure does not require any changes in the AreaCalculator.
All posts from mini project: Learn SOLID and OOP principles:
- SOLID
- SOLID exercises
- S like Single responsibility principle
- SOLID exercises — Kata
- O as Open-closed principle
- L jak Liskov Substitution Principle
- Interface segregation principle
- KISS — Keep it simple, stupid
- DRY — Don’t repeat yourself
- Dependency inversion principle
- SLAP — Single Level of Abstraction Principle
- Composition Over Inheritance
- Encapsulate what changes
- Lod — Law of Demeter
- ES as Exercises of Single responsibility principle
- EO as Exercises of Open/closed principle
- EL as Exercises of Liskov Substitution Principle
- EI as Eexrcises of Interface segregation principle
- ES as Exercises of Dependency Inversion Principle
- Object-oriented programming
- OOP — Object-Oriented Programming — Advice
- OOP — Object Oriented Programming
Sources
Main image
Materials
- Clean Architecture — Robert C. Martin
- https://hackernoon.com/why-the-open-closed-principle-is-the-one-you-need-to-know-but-dont-176f7e4416d
- https://code.tutsplus.com/tutorials/solid-part-2-the-openclosed-principle–net-36600
1
/
53
020/100| Przetłumacz Na Angielski - Translate to English| Bubble.io TUTORIAL
019/100| Wykryj Sentyment Zmień Głos na Tekst- Voice-to-Text Sentiment Analyzer| Bubble.io TUTORIAL
018/100| Rozpoznawanie Logo - Logo Recognizer| Bubble.io TUTORIAL
2025_01_17 Jak Ugotować Jajka? | Walka I Postępy
017/100| AI Generowanie Obrazów - AI Image Generation| Bubble.io TUTORIAL
2025_01_16 Rozmawiaj!!! Walka I Postępy
016/100| AI Chat Produktywności - Productivity Chatbot AI| Bubble.io TUTORIAL
2025_01_15 Świąteczne Prezenty Walka I Postępy
015/100| AI Trener Personalny - Motivational Coach AI| Bubble.io TUTORIAL
2025_01_14 Metoda Na Cele | Walka I Postępy
014/100| Połączenie przez API - API Connector| Bubble.io TUTORIAL
2025_01_13 Przerwa Świąteczna | Walka I Postępy
013/100| Rejestracja i Logowanie - Sign-Up & Login Page| Bubble.io TUTORIAL
012/100| Proces Tworzenia Oprogramowania - Transforming App Development|Bubble.io TUTORIAL
011/100| Debugowanie - Debugging| Bubble.io TUTORIAL
010/100| Reużywalny Element - Reusable Elements| Bubble.io TUTORIAL
009/100| Listy Tekstów - Lists of Text| Bubble.io TUTORIAL
008/100| Logika: Warunki - Conditional Basics| Bubble.io TUTORIAL
007/100| Edycja w Bazie Danych - Edit Database| Bubble.io TUTORIAL
006/100| Baza Danych - Database| Bubble.io TUTORIAL
Powiadom Osobę w Komentarzu - Notify Person via Comments| Bubble.io TUTORIAL
005/100| Działanie: Akcje i Wydarzenia - Workflows: Events and Actions| Bubble.io TUTORIAL
004/100| Animowany Przycisk - Custom Animated Buttons| Bubble.io TUTORIAL
003/100| Grupy - Group Elements| Bubble.io TUTORIAL
002/100| Teksty - Text Elements| Bubble.io TUTORIAL
001/100| Edytor Aplikacji i Układ Strony - Editor & Layouts| Bubble.io TUTORIAL
Zbuduj TODO Aplikację - To-Do App in 10 Minutes | Bubble.io Budowa Aplikacji
Wysuwający się Panel - Slide-in Panel| Quick Tip
Wykresy Wykorzystania Bubble.io - App Usage Charts | Bubble.io TUTORIAL
Własny Tymczasowy Stan - Learn Custom States in 5 min| Bubble.io Quick Tip
1
/
53