Daj Się Poznać Programowanie SOLID

SOLID #2 – ZASADA OTWARTE-ZAMKNIĘTE

W poprzednim wpisie opisałem pierwszą zasadę w mnemoniku SOLID czyli zasadę pojedynczej odpowiedzialności. Kontynuując, dzisiaj przyszedł czas na drugą literę tego skrótu czyli O, a wraz z nią zasadę otwarte-zamknięte (ang. Open-closed prinicple).

CO TO JEST ZASADA OTWARTE/ZAMKNIĘTE

Zasada otwarte-zamknięte  — jedna z zasad programowania mówiąca, że elementy systemu takie, jak klasy, moduły, funkcje itd. powinny być otwarte na rozszerzenie, ale zamknięte na modyfikacje.

Na pierwszy rzut oka wydawać się to może sprzecznością, szczególnie jeżeli chcemy przełożyć tą regułę na życie codzienne. Nie uda nam się powiesić nowej szafki na ścianie (rozszerzanie), nie montując w ścianie wcześniej śrub na której tego dokonamy (modyfikacje).

Jednak, gdy zostawimy w tyle życie codzienne i zastanowimy się jakie mechanizmy oferuje nam programowanie obiektowe (delegaty, polimorfizm, wyrażenia lambda), to zastosowanie powyższej zasady stanie się tylko formalnością.

Zasada ta wymaga myślenia perspektywicznego, dlatego może sprawiać duże kłopoty początkującym adeptom programowania.

 

PRZYKŁAD

Posłużmy się przykładem, aby rozwiać wszelkie wątpliwości. Załóżmy, że produkujemy system, który będzie dobierał typ treningu w zależności od poziomu zaawansowania osoby.  Utworzyłem prostą klasę Person oraz type Enum TrainingType  definiujący typ treningu.


enum TrainingType

{

    Beginer,

    Intermediate,

    Advanced

}

class Person
{

     public TrainingType type { get; set; }

     public string Name { get; set; }

}

 

Teraz czas utworzyć funkcję, która będzie dobierać odpowiedni typ treningu.

public void SelectTraining(List<Person> persons)
{
  foreach (var person in persons)
  {
   if (person.type == TrainingType.Beginer)
     Console.WriteLine
     ("Należy zastosować program treningowy dla początkujacego");
   else if (person.type == TrainingType.Intermediate)
     Console.WriteLine
     ("Należy zastosować program treningowy dla osoby średnio zaawansowanej");
   else if (person.type == TrainingType.Advanced)
     Console.WriteLine
     ("Należy zastosować program treningowy dla osoby zaawansowanej");
   }
}

 

Na pierwszy rzut oka wszystko wydaje się być poprawne, ale warto zwrócić uwagę, że klasa TrainingType jest bardzo podatna na zmiany. Być może będziemy ją chcieli w przyszłości rozbudować o inny typ treningu  i zmusi nas to do przebudowanie funkcji SelectTraining, co złamie zasadę Otwarte-Zamknięte.

Popatrzmy jak można zmodyfikować funkcję SelectTraining, tak aby dodanie nowego typu treningu nie powodowało konieczności modyfikowania klasy.

public void SelectTraining(List<Person> persons, Dictionary<TrainingType, string> training)
{
   foreach (var person in persons)
   {
     select(person, training);
   }
}

public void select(Person person, Dictionary<TrainingType, string> training)
{
   string trainings;
   if (training.TryGetValue(person.type, out trainings))
   Console.WriteLine(trainings);
}

 

Dodałem kolejny argument, w którym definiowane będą rodzaje treningu. Dzięki takiemu podejściu nie ma ryzyka, że zmiany w publicznym API spowodują nieprawidłowe działanie kodu i oszczędzamy sobie pracy w przyszłości.

PODSUMOWANIE

Dzisiaj poznaliśmy kolejną zasadę z kręgu SOLID.  Zasada otwarte-zamknięte pomaga tworzyć takie oprogramowanie, które będzie otwarte na nowe funkcjonalności bez potrzeby modyfikacji istniejącego kodu. Zasada otwarte-zamknięte wymaga od programisty dobrego zrozumienia treści którą programuje oraz wykazania się swego rodzaju intuicją, aby zaimplementować tę zasadę w miejscach podatnych na rozszerzanie.

Do następnego!

 

Dodaj komentarz