Współtworzę kurs SSJ: Super Senior Java — powiedz nam, czego potrzebujesz.Wypełnij ankietę →
📦 Ten wpis pochodzi z 2020 roku i jest częścią archiwum. Treść może być nieaktualna. ← Wróć do archiwum
architektura

SOLID - Open/closed principle

#programowanie#rozwój#it

Druga zasada mnemoniku SOLID. Praktyka mówiąca, że klasy powinny być otwarte na rozszerzenia, ale zamknięte na modyfikacje. Opracował ją Bertrand Meyer w 1988 r. Według niej dana encja powinna mieć możliwość zmiany swojego zachowania bez ingerowania w kod źródłowy. W ten sposób wytwarzamy system, który potrafi dostosować się do zmiennych wymagań.

Open/closed principle

Klasa zamyka się na modyfikacje, ale zawsze powinna być otwarta na rozszerzenie.

Tą zasadę można zilustrować następująco:

public class Manager {

  private Task task;

  public Manager(task) {
    this.task = task;
  }

  public void work() {
    switch(task) {
      case ORGANIZE_MEETINGS:
        organizeMeetings();
        break;
      case MOTIVATE_TEAM:
        motivateTeam();
        break;
      default:
        haveDayOff();
    }
  }
}

public enum Task {
  ORGANIZE_MEETINGS, MOTIVATE_TEAM
}

Przy tworzeniu obiektu Manager przekazujemy parametr odpowiadający pracy jaką ma dzisiaj do wykonania. W przypadku, gdyby doszedł nowy typ zadania niezbędna byłaby ingerencja w kod źródłowy. Z tego powodu należałoby w instrukcji switch obsłużyć nowy rodzaj pracy. Jest to uciążliwe dla programisty i zdecydowanie łamie zasadę Otwarte-Zamknięte. Rozwiązaniem tego zagadnienia jest przechowywanie wspólnego, niezmiennego zachowania w abstrakcji (klasie abstrakcyjnej albo interfejsie). W efekcie odmienne części kodu źródłowego należy zamieścić w klasach konkretnych rozszerzających daną abstrakcję.

public class Manager {
  private Task task;

  public Manager(task) {
    this.task = task;
  }

  public void work() {
    task.getTheJobDone();
  }
}

public interface Task {
  void getTheJobDone();
}

public class OrganizeMeetingsTask implements Task {

  @Override  
  public void getTheJobDone() {
    // do task - organize meetings
  }
}

public class MotivateTeamTask implements Task {

  @Override  
  public void getTheJobDone() {
    // do task - motivate team
  }
}

Taki sposób zapisu jest o wiele przyjemniejszy w utrzymaniu. Dzięki czemu dodając nowe typy zadań nie istnieje potrzeba zmiany implementacji klasy Manager. W rezultacie nasz kod źródłowy na pewno jest otwarty na rozszerzenia i zamknięty na modyfikacje 👍.

Podsumowanie

Osobiście uważam, że zasada Open/Closed Principle jest bardzo przydatna. Dzięki niej nasz kod jest mniej ze sobą powiązany i nie uzyskujemy zależności pomiędzy elementami. Trzymanie się tej reguły naprowadza nas na bardzo przydatny wzorzec architektoniczny jakim jest Strategia. Zachęcam do dyskusji na temat zasady Otwarte-Zamknięte poprzez napisanie komentarza pod postem lub wysłanie do mnie maila. Czy posiada ona same zalety, a może jednak ma jakieś wady, które nie przemawiają za nią? Może jesteś w stanie lepiej zilustrować tą regułę? Z chęcią się zapoznam z Twoim punktem widzenia!

Znajdź mnie na