Devloger

Refaktoryzacja z Value Objects

Refaktoryzacja z wykorzystaniem Value Objects

Refaktoryzacja kodu z wykorzystaniem Value Objects.

Jest to kolejna świetna opcja jaką mamy, kiedy naszym celem jest refaktoryzacja wielkich klas. W tym przypadku wyabstrahowanie tzw. Value Objects Emotikon uśmiechniętej buźki.

Na czym to polega?

Polega to na wyniesieniu jakiejś konkretnej wartości typu prymitywnego do jej własnej klasy, która będzie przechowywała całe zachowanie z nią związane Emotikon uśmiechniętej buźki.

Wyobraź sobie, że masz kilka metod które służą jako gettery, dla przykładu: revenue(), revenueInDollars(), revenueAsCurrency()... Napisałem tylko trzy. A potencjalnie będzie ich dużo więcej. A klasa ciągle rośnie. I tutaj właśnie jedną z opcji do których możesz się uciec, jest wyodrębnienie value object.

Spójrz na nazwy tych metod, każda z nich zaczyna się od słowa "revenue". I fakt, że ciągle powtarza się to jedno słowo, może być (ale nie musi) oznaką tego, że coś ci tu umyka. Jakiś rodzaj abstrakcji, który z całą pewnością w tym przypadku by był mile widziany Emotikon uśmiechniętej buźki.

Jak tego dokonać?

Oto co możesz zrobić w tym przypadku. Utwórz nową klasę o nazwie "Revenue". To będzie nasz value object.

Po przeniesieniu do nich wcześniejszych metod powinieneś zauważyć, jak prefix "revenue" w nazwie tych metod stał się kompletnie redundantny i bezużyteczny. To dobry znak Emotikon uśmiechniętej buźki. Jesteśmy na właściwej drodze.

Odtąd będziesz operować na value object, zamiast na suchej wartość Emotikon uśmiechniętej buźki. Cała dedykowana klasa, która enkapsuluje wszelakie zachowanie i własności tej wartości Emotikon uśmiechniętej buźki.

Kiedy stosować?

Powinieneś stosować tę technikę tylko dla ważnych wartości należących do twojej domeny, konceptu, idei. Wtedy, kiedy zmiana tych wartości na value objects naprawdę poprawi coś w twojej pracy, w twoim projekcie Emotikon uśmiechniętej buźki. Dla przykładu: aplikacja do ćwiczeń - value object masy ciała.

Warto to rozważyć, jeśli jakaś konkretna wartość ma (lub będzie miała) dodatkowe zachowanie z nią związane. Jak w poprzednim przykładzie - konwersja na wartość w dolarach czy formatowanie jako waluta. Jeśli więc jest w tym jakieś dodatkowe zachowanie - warto zastanowić się nad przeniesieniem tego do dedykowanej klasy, która będzie właśnie value objectem.

Nie w każdym przypadku stosowanie tej techniki ma sens. I warto o tym wspomnieć, ponieważ wiele osób ma w zwyczaju nadużywanie tej techniki. Poznają ją i nagle wszędzie ją stosują, nagle każda rzecz staje się value objectem. A jest to głupie, ponieważ są przydatne tylko kiedy to naprawdę ma sens. Ale z całą pewnością nie powinniśmy jej stosować domyślnie, od razu, dla wszystkiego. Skazujesz się wtedy tylko na większą ilość zbędnej pracy.

Niemutowalność

Value Object powinien być niemutowalny. Co to oznacza? Oznacza to tyle, że nie powinieneś być w stanie zmienić istniejącego value object. Nie powinno być możliwości nadpisania jego wartości. A co kiedy musisz zmienić tę wartość? Nie zmieniasz istniejącej, tylko tworzysz i zwracasz nową Emotikon uśmiechniętej buźki (nowa instancja value object).

Eloquent i Accessors

Warto wspomnieć o ciekawej możliwości jaką daje nam Eloquent - a którą możemy tutaj fajnie wykorzystać Emotikon uśmiechniętej buźki.

W Eloquencie możemy zdefiniować metodę dostępową (tzw. accessor). Metoda ta zostanie automatycznie wywołana kiedy odwołasz się do wskazanego przez ciebie w nazwie tej metody atrybutu modelu. Przykład: "getFirstNameAttribute()" - nazwa metody będąca accessorem atrybutu first_name.

I kiedy odwołasz się do tego atrybutu, zwróci ci dokładnie to, co zwraca zdefiniowana przez ciebie metoda Emotikon uśmiechniętej buźki.

I możesz to wykorzystać, do zwrócenia właśnie twojego value object, do którego w metodzie tej przekażesz ten atrybut modelu (tę wartość) Emotikon uśmiechniętej buźki. Przykład:

public function getRevenueAttribute($revenue)
{
    return new Revenue($revenue);
}

Wówczas przy odwoływaniu się do tego atrybutu zamiast dostawać czystą wartość, to dostaniesz obiekt klasy Revenue - czyli twój value object Emotikon uśmiechniętej buźki.

toString()

Warto również zaimplementować w tej klasie metodę toString(). Dzięki której będziesz mógł zachować funkcjonalność odwoływania się do tej wartości jak do stringa Emotikon uśmiechniętej buźki.

Możesz również sam zdecydować jak powinna wyglądać domyślna reprezentacja tej wartości przy odwoływaniu się do niej jak do stringa. Bardzo fajna możliwość.

Kod klasy z omawianego przykładu

<?php

namespace App;

class Revenue
{
    private $revenue;

    public function __construct($revenue)
    {
        $this->revenue = $revenue;
    }

    public function inDollars()
    {
        return $this->revenue / 100; // 86
    }

    public function asCurrency()
    {
        return money_format('$%i', $this->inDollars()); // $86.00
    }

    public function __toString()
    {
        return (string) $this->AsCurrency();
    }
}

Zalety

Warto wspomnieć, że poprawie uległo również twoje API.

A nie tylko to, bo również kod został oczyszczony, twoja architektura uległa poprawie.

I ważny koncept w twojej domenie z którym związane było niestandardowe zachowanie zyskał własną, dedykowaną klasę Emotikon uśmiechniętej buźki.

Podsumowanie

Kolejna świetna technika którą nie raz pewnie zastosujesz Emotikon uśmiechniętej buźki. Niesie ze sobą sporo dobrego. Jednak pamiętaj, używaj jej tylko wtedy, kiedy ma to sens. Nie rób nagle na siłę ze wszystkiego value objects.

Kończąc

Dziękuję ci za lekturę i proszę cię o zostawienie komentarza, podzielenie się nim z innymi oraz zerknięcia na inne moje artykuły Emotikon uśmiechniętej buźki. A nie jest to jedyny artykuł z serii o refaktoryzacji.

A tymczasem życzę ci dobrego dnia, bywaj Emotikon uśmiechniętej buźki!

Krystian Bogucki

Podobał Ci się ten artykuł?

Jeśli tak, to zarejestruj się aby otrzymywać powiadomienia o nowych artykułach. Nie ujawnię nikomu Twojego adresu!