solId…ne programowanie!

W tym wpisie „na warszatat” bierzemy 4 z zasad SOLID, „I” (eng. Interface Segregation).

O co kamannnn…?

Nie spotkałem się dotychczas ze złamaniem tej zasady w pracy. Zdaje się, że wszyscy wiedzą, jak jej nie łamać. Złamanie opisywanej zasady jest bardzo klarownie widoczne w kodzie. Mianowicie o czym mówi nam zasada segregacji interfejsów?

Klient używający interfejsu nie powinien być zmuszony do implementacji metod interfejsu, których nie będzie używał.

Aby lepiej zrozumieć zagadnienie, przypomnijmy sobie, co nieco o interfejsach (zerknij na wpis). Wiadomo, że każda klasa implementująca Interfejs jest zmuszona do implementacji metod, które interfejs ze sobą niesie.

Tło historczno-programistyczne SOLID…. 🙂

Załóżmy, że mamy interfejs który definiuje operacje na koncie w naszej aplikacji bankowej, w postaci jak poniżej:

interface FinancialOperations {
	void deposit();
	BigDecimal withdraw();
}

Klasa, która będzie odpowiedzialna za operacje na koncie, implementuje interfejs, a co za tym idzie, musi użyć metod interfejsu i dopisać do nich logikę. (PersonalAccount będzie wykonywała również inne czynności np. wywoła persystencję transakcji).

class PersonalAccount implements  FinancialOperations {

	@override
	void deposti() {
	    System.out.println(“depoist some amount”);
	}

	@override
	BigDecimal withdraw() {
	    System.out.println(“withdraw some amount”);
	}
}

Jak zapewne wiecie z doświadczenia lub śledząc LekcjeKodu. Zazwyczaj jednak okazuje się, że należy nasz program rozszerzyć. Dochodzi nowy rodzaj konta. SavingAccount.

Wymagania są takie, że oprócz metod deposit() i withdraw() musimy mieć metodę save().

Przejdźmy do solid..nych rzeczy!

W pierwszej myśli można stwierdzić, że rozwiązanie jest trywialne. Mianowicie dodajemy do Interfejsu metodę save() i implementujemy ją w klasie SavingAccount. Niestety rozszerzając w ten sposób, wymusimy też implementację metody save() w klasie PersonalAccount. Wymagania biznesowe konta osobistego nie przewidują możliwości implementacji systemu oszczędzania.

Idąc dalej tym tropem, można powiedzieć “a co tam.. zaimplementuje metodę, która nic nie robi”. To jest właśnie moment, w którym złamaliśmy zasadę “I”. Klasa PersonalAccount implementuje metodę (nie ważne, że nic nierobiącą), której nie potrzebuje!

Rozwiązanie

Jak nie łamać zasady “I” i wybrnąć z powyższej sytuacji. Należy przypomnieć sobie, że interfejs można rozszerzać o inny interfejs, używając słowa extends.

interface SavingOperations extend FinancialOperations {

	BigDecimal save();
}

Wykonaliśmy segregację interfejsów. Teraz klasa PersonalAccount będzie implementowała interfejs FinancialOperations, a SavingAccount, SavingOperations. Oczywiście dzięki temu, że SavingOperations rozszerza FinancialOperations, klasa SavingAccount wykorzysta także metody deposit() i withdraw().

P.S.

Za tydzień już ostatni wpis dotyczący solid. Do poczytania!

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *