SOLID – część 4. Zasada Segregacji Interfejsów

SOLID – mnemonik, który mówi jak pisać poprawnie programy w językach obiektowych. Podążanie za tymi zasadami znacznie poprawia czytelność i możliwość utrzymywania kodu. Część czwarta: Zasada Segregacji Interfejsów.

Moim zdaniem jest to najprostsza zasada z wszystkich pięciu możliwych do wyjaśnienia. Spójrzmy na definicję Interface Segregation Principle.

Klasy nie powinny być zmuszane do zależności od metod, których nie używają.

Język zrozumiały. Ale co to może oznaczać w rzeczywistości. Spójrzmy na nasze karabiny:

public class SzybkoszelajcyKarabin : IStrzelajaceILadujacy
{
	public void Strzelaj()
	{
		Console.WriteLine("Pif-Pif-Pif-Pif-Pif-Pif-Pif");
	}

	public void LadujPocisk(ISiejacyZniszczenie pociskSiejacyZniszczenie)
	{
		throw new NotImplementedException();
	}
}

public class CelnyKarabin : IStrzelajaceILadujacy
{
	public void Strzelaj()
	{
		Console.WriteLine("Pif-Paf");
	}

	public void LadujPocisk(ISiejacyZniszczenie pociskSiejacyZniszczenie)
	{
		throw new NotImplementedException();
	}
}

SzybkoszelajcyKarabin oraz CelnyKarabin implementują interfejs IStrzelajaceILadujacy, który zawiera dwie definicje metod:

public interface IStrzelajaceILadujacy
{
	void Strzelaj();
	void LadujPocisk(ISiejacyZniszczenie pociskSiejacyZniszczenie);
}

Do karabinów nie ładuje się pocisków. Pociski w moim przekonaniu to coś dużego czym można zrobić dużo bałaganu w okolicy. Dlaczego nasze karabiny mają implementować metodę LadujPocisk? Co mówi ISP?

Klasy nie powinny być zmuszane do zależności od metod, których nie używają.

Karabiny łamią zasadę segregacji interfejsów. Można to w bardzo prosty sposób naprawić. W tym celu stwórzmy dwa mniejsze interfejsy.

public interface IStrzelajace
{
	void Strzelaj();
} 

public interface ILadujacy
{
	void LadujPocisk(ISiejacyZniszczenie pociskSiejacyZniszczenie);
}

Robiliśmy interface IStrzelajaceILadujace na dwa mniejsze: IStrzelajace oraz ILadujace. Poprawmy kod tak, aby nasze karabiny implementowały tylko IStrzelajce.

public class SzybkoszelajcyKarabin : IStrzelajace
{
	public void Strzelaj()
	{
		Console.WriteLine("Pif-Pif-Pif-Pif-Pif-Pif-Pif");
	}
}

public class CelnyKarabin : IStrzelajace
{
	public void Strzelaj()
	{
		Console.WriteLine("Pif-Paf");
	}

}

W ten sposób spełniamy zasadę ISP. Nasze karabiny implementują tylko te metody, które używają. Dzięki temu na przykład nie będziemy już przez pomyłkę na karabinie wykonywać metody LadujPocisk.
Ale musimy troszkę poprawić nasz kod w innych miejscach, aby mógł się komplikować.

public class Lufa : IStrzelajace, ILadujacy
{
	...
}

public class Czolg
{
	private readonly IStrzelajace _karabin;
	
	...
}

I gotowe.

SOLID – Zasada Segregacji Interfejsów. Linki.

CodeProject – przykład
UWR – Wykład z przykładem
Wysokopoziomowe metaforyczne wyjaśnienie ISP

1 thought on “SOLID – część 4. Zasada Segregacji Interfejsów”

  1. A jak teraz po modyfikacjach wywołać ładowanie pocisku z poziomu agregatu czołgu, jeżeli ładowanie odbywać ma się przez metodę naszego agregatu? Wydzieliliśmy interfejsy pod działanie karabinów ale czy teraz nie naruszamy zasady Liskov Substitution, ponieważ otrzymamy martwą metodę LadujPocisk? Czy nie ma tutaj błędu?

Leave a Comment

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *