sobota, 15 października 2022

Metoda Prywatna vs. Value Object

🔒 Metoda Prywatna

Na samym początku musimy odpowiedzieć sobie na pytanie dlaczego tworzymy metody prywatne:

  • potrzebujemy współdzielić kod w conajmniej dwóch innych metodach danej klasy,
  • chcemy zredukować złożoność i ukryć pewny spójny logicznie kawałek kodu,

Niewątpliwie są  to dobre powody, ale stosowanie metody prywatnej nie jest najlepszym sposobem na uwspólnianie kodu czy redukowania jego złożoności.  

 

💡 Narodziny Konceptu Domenowego

Mamy klasę ShippingService z metodą publiczną getCost zwracającą cenę wysyłki. W samym ciele tej metody zaczyna rosnąć ilość linii kodu weryfikującego czy dostawa powinna być darmowa czy nie. Logika nie jest banalna i na podstawie nowych wytycznych biznesu koncept darmowej wysyłki jest dopiero implementowany w kodzie.

1
2
3
4
5
6
7
8
9
10
11
12
final class ShippingService
{
    public function getCost(...): Money
    {
        // call private method
    }
 
    private function isFree(...): bool
    {
        // using class dependencies
    }
}

Nie wchodząc w szczegóły implementacji, skupmy się na samym fakcie powstania nowej metody prywatnej ShippingService::isFree - czyli zredukwaniu złożonoście metody głównej ShippingService::getCost. Metoda prywatna enkapsuluje warunki podejmujące decyzję czy wysyłka jest darmowa. Wyłonił się tutaj nowy koncept domenowy i niestety jest on zamodelowany za pomoca metody prywatnej.

Problem pojawia się gdy inny serwis również będzie musiał operować na koncepcie darmowej wysyłki. W tym wypadku potrzebny byłby refaktor - upublicznienie metody bądź wydzielenie jej do nowego serwisu nie wydaje się też dobrym rozwiązaniem. Więc jeżeli pozostawimy to w obecnej formie musimy liczyć się z następującymi konsekwencjami:     

❌ niemożliwe jest ponowne wykorzystanie metody w innym obszarze,

❌ istnieje ryzyko duplikacji logiki - świadomej (przez lenistwo programisty) / nieświadomej (trudniej odnaleźć logikę w metodzie prywatnej niż w osobnej klasie).

❌ modelowanie konceptów domenowych za pomocą metod serwisowych ogranicza nasze możliwości co do rozwoju konceptów które odzwierciedlają. 

Koncept domenowy jest ukryty

 

⚠️ Metoda jako wyrażanie Konceptu Domenowego

Przechowywanie konceptów domenowych w metodach jest bardzo ograniczające w ich potencjalnym dalszym rozwoju. Istnieje bardzo duża szansa, że sam koncept domenowy z czasem będzie się rozwijał nabierając pełniejszego kształtu. 

Jeżeli obecnie oczekujemy tylko odpowiedzi na to czy dla danej kwoty wysyłka jest darmowa to w przyszłości możemy potrzebować np. samego progu cenowego darmowej wysyłki. Wymagałoby to od nas utworzenia kolejnej wyspecjalizowanej metody. 

Co więcej przy nieznajomości projektu możemy mieć problemy z ustaleniem czy taki byt w ogóle istnieje w projekcie - z perspektywy katalogów jest on niewidoczny. 

Dodatkowo cementujemy logikę biznesową wraz ze sposobem pozyskiwania danych (pobieranie danych z repozytorium) co może prowadzić do ich parametryzacji bądź wydzielenia części logiki do kolejnych metod prywatnych.

 

🧩 Value Object

Nie jest to wpis o Value Object'cie samym w sobie dlatego tylko wypiszę jego przewagi względem stosowania metod serwisowych:

  • jest uniezależniony od kontekstu wywołania,
  • nazwa klasy może nadać mu bardziej abstrakcyjny charakter (metoda shippingDays na Value Object ShippingTime::days),  
  • bardzo łatwy w testowaniu,
  • jawna i niezależna jednostka przechowująca wiedzę domenową,
  • widoczny z poziomu katalogów,  
  • bardzo łatwy do ponownego wykorzystania w innym obszarze. 

 

♻️ Refaktoryzacja do Value Object

Pierwszym etapem refaktoryzacji do Value Object'u może być transformacja do prywatnej metody statycznej. W tym wypadku wszystkie parametry wejściowe stałyby się w dalszym toku przekształceń parametrami konstruktora Value Object'u.

Przenosząc odpowiedzialności do Value Object'u i powiązanej z nim Fabryki redukujemy złożonośc samego Serwisu w którym logika ta się wcześniej znajdowała. Zależności przechodzą z Serwisu do Fabryki i to właśnie ona od teraz jest wstrzykiwana do klasy Serwisowej. 

Przekształcenie metody prywatnej na Value Object


Brak komentarzy:

Prześlij komentarz