Spis Treści
Trochę teorii
Kolejną zasadą kryjącą się pod literką „O” w akronimie SOLID jest tytułowa zasada otwarte-zamknięte. Treść zasady jest bardzo prosta i wydaje się wręcz trywialna:
Elementy oprogramowania takie jak: moduły, klasy czy funkcje powinny być otwarte na rozszerzanie i jednocześnie zamknięte na modyfikacje.
Zanim przejdę do podania przykładu napiszę po krótce w teorii dlaczego ta zasada jest ważna. Pisanie oprogramowania bardzo często wymaga wprowdzania różnych zmian. Wynikają one ze zmiany logiki biznesowej bądź potrzeby refaktoryzowania kodu. Jeśli wprowadzenie nowej funkcjonalności wymaga istotnych zmian w kodzie, może się okazać, że inna osoba używająca w innym miejscu danej funkcjonalności straci ją.
Trochę kodu
Kod niewłaściwy
Prześledźmy przykład kodu liczącego pole figury. Najpierw przykład kodu, który łamie zasadę otwarte-zamknięte. Tworzymy klasę trójkąta a następnie klasę która liczy pole figury.
public class Triangle {
public float baseLength;
public float height;
}
public class AreaCalculator {
public float calculateTriangleArea(Triangle triangle) {
return triangle.baseLength * triangle.height / 2;
}
}
Nasza aplikacja działa świetnie, ale pojawiła się potrzeba dodania opcji liczenia pola koła. Dodajemy klasę koła, a następnie musimy wprowadzić zmianę w klasie obliczającej powierzchnię nowej figury i w tym momencie łamiemy zasadę otwarte-zamknięte. Nasz kod wygląda następująco:
public class Triangle {
public float baseLength;
public float height;
}
public class Circle {
public float radius;
}
public class AreaCalculator{
public float calculateTriangleArea(Triangle triangle) {
return triangle.baseLength * triangle.height / 2;
}
public float calculateCircleArea(Circle circle) {
return 3.14 * circle.radius * circle.radius;
}
}
Zauważ, że dodanie nowej figury wymusza modyfikację innej istniejącej już klasy i implementację nowej metody liczenia powierzchni. Zapiszmy nasz program inaczej.
Kod poprawny
W celu uniknięcia łamania zasady wystarczy stworzyć interfejs, który będzie zawierał metodę liczenia powierzchni. Następnie ustalmy, że każda nowa figura będzie implementowała ten interfejs. Wówczas nasz kod będzie wyglądał następująco:
public interface Shape {
public float calculateArea();
}
public class Triangle implements Shape {
public float baseLength;
public float height;
public double calculateArea() {
return baseLength * height / 2;
}
}
public class Circle implements Shape {
public float radius;
public float calculateArea() {
return 3.14 * radius * radius;
}
}
Taka konstrukcja daje nam możliwość stworzenia kalkulatora niewymagającego ingerencji przy dodawaniu kolejnych figur:
public class AreaCalculator {
public float calculateShapeArea(Shape shape) {
return shape.calculateArea();
}
}
Można zatem stwierdzić, że nasz kalkulator jest zamknięty na modyfikację natomiast otwarty na rozszerzanie.
Podsumowanie
Jak widać zasada ta choć z pozoru prosta jednak nie jest tak oczywista w implementowaniu. Wymaga czasem przewidywania potencjalnych kierunków rozwoju programu, a także umiejętności wydzielania różnych abstrakcji. Zapraszam do lektury pozostałych artykułów odnośnie zasad SOLID.
Pingback: SOLID - podstawa programowania obiektowego – Wojciech Siwek
Możliwość komentowania została wyłączona.