Liskov Substitution Principle – zastosowanie LSP

Liskov Substitution Principle – zastosowanie LSP

Przyjrzyjmy się teraz, jak możemy zastosować zasadę LSP w naszej aplikacji myjni samochodowej. Użytkownicy naszej aplikacji, zgłosili nam mały błąd który wprowadziliśmy, gdy modyfikowaliśmy nasz kod wprowadzając wzorzec fabryki DetailsPricingFactory do tworzenia różnych instancji typów mycia, teraz musimy to naprawić.

Pokazałem, jak możemy użyć refleksji i konwencji, abyśmy nawet nie potrzebowali instrukcji switch wewnątrz fabryki. I zgodnie z zasadą OCP oczywiście, jeśli nie znaleźliśmy pasującego typu mycia do utworzenia, zostałby wygenerowany wyjątek. My jednak w tym przypadku po prostu zwróciliśmy wartość null.

W klasie CarWash możemy pracować z tą wartość null, używając operatora warunkowego null w instancji wyceny mycia. Kod oczywiście działa i nie generują wyceny, ale jego zachowanie nie jest w 100% takie samo jak w oryginalnym kodzie. Teraz nasi użytkownicy zgłosili nam błąd i musimy to naprawić.

Przyjrzyjmy się oryginalnemu kodowi metody Pricing obiektu CarWash. W tym oryginalnym kodzie, jeśli typ mycia nie został rozpoznany, rejestrowaliśmy nieznany typ wyceny mycia.

switch (details.WashingType)
{
   case WashingType.Standard:
   ...
   default:
   Logger.Log("Unknown type of Washing.");
   break;
}

Teraz już nie ma wyświetlanie tej wiadomości w przypadku, gdy typ mycia nie został rozpoznany.

Ok, nie ma problemu. Możemy wstawić instrukcję if, aby sprawdzić to w CarWash.

Wróćmy do naszego kodu. I możemy po prostu zmień ten kod, aby dodać kontrolę wartości null i wyprowadzić oczekiwany komunikat w przypadku, gdy typ mycia nie został rozpoznany. Za pomocą kilku linijek kodu naprawiliśmy błąd.

if(pricing == null)
{
   Logger.Log("Unknown type of Washing.");
}
else
{
   pricing.Pricing(details);
}

Teraz, kiedy pricing będzie równy null, możemy zalogować nieznany typ mycia do konsoli, w przeciwnym razie po prostu wywołamy metodę Pricing, którą zwróciła nam fabryka. Teraz możemy uruchomić aplikację i przetestować że wszystko działa.

Działa. To świetnie, ale teraz naruszamy zasadę LSP, ponieważ musimy traktować wartość null inaczej niż traktujemy inne przypadki. Ponieważ jedyne zachowanie, którego potrzebujemy w przypadku nierozpoznanego typu mycia to rejestrowanie tego i nie podejmowanie innych działań, możemy to łatwo uzyskać, stosując wzorzec obiektu null.

Aby to zrobić, umieszczamy zachowanie, którego oczekujemy, gdy nie znajdujemy odpowiedniego typu mycia w nowym własnym typie, który nazwiemy UnknownDetailsPricing.

public class UnknownDetailsPricing : DetailsPricing
{
   public UnknownDetailsPricing(CarWash carWash, ConsoleLogger logger) : base(carWash, logger)
   {
   }

   public override void Pricing(Details details)
   {
      _logger.Log("Unknown type of Washing.");
   }
}

Następnie modyfikujemy fabrykę, aby zwrócić wystąpienie tego typu za każdym razem, gdy nie znajdziemy pasującego typu mycia. Oznacza to, że zamiast zwracać wartość null w naszym bloku try catch, zwrócimy nową instancję tego typu UnknownDetailsPricing.

public class DetailsPricingFactory
{
   public DetailsPricing Create(Details details, CarWash carWash)
   {
      try
      {
         var detailsPricing = (DetailsPricing)Activator.CreateInstance(
                       Type.GetType($"ExampleSolid.{details.WashingType}DetailsPricing"),
                          new object[] { carWash, carWash.Logger });
         return detailsPricing;
      }
      catch (System.Exception)
      {
         return new UnknownDetailsPricing(carWash, carWash.Logger);
      }
   }
}

Zauważ, że po tej zmianie DetailsPricingFactory już nie zwraca nulla w żadnym przypadku. Oznacza to, że możemy pozbyć się sprawdzenia wartości null w CarWash.

pricing.Pricing(details);

Ta zmiana zmniejsza złożoność metody Pricing tak aby mogła być wywoływana bez konieczności martwić się o wartości null lub inne szczególne przypadki.

To wszystko w przypadku zasady LSP, mam nadzieję, że podobało Wam się zastosowanie zasady i jesteście gotowi, aby zrobić kolejny krok w nauce zasad SOLID i zastosować czwartą zasadę ISP.

2 comments

Dodaj komentarz

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