Niezmienność jest jedną z najważniejszych koncepcji projektowych przy budowaniu stabilnych aplikacji. Podstawowa zasada mówi, że raz zapisany stan może być później tylko odczytany bez możliwości jego modyfikacji. Jeśli potrzebujemy zmienić stan, musimy stworzyć nową instancję i zastąpić cały obiekt innym.
Typy danych można zatem bardzo zgrubnie podzielić na dwie szerokie kategorie:
Obiekty mutowalne mogą być zmieniane wewnętrznie. Czyli dostarczają operacji, które wywołane w różnych kombinacjach powodują, że otrzymujemy różne wyniki. Immutability próbuje zapobiec temu zachowaniu.
Klasa jest immutable właśnie wtedy, gdy dane instancji nie mogą być w żaden sposób zmienione po utworzeniu instancji.
Tak więc wszystkie dane są ustalone w konstruktorze. Wszystkie skalarne typy danych są również automatycznie niezmienne.
Projektowanie aplikacji z niezmiennymi stanami zapewnia fundamentalną przewagę w zakresie bezpieczeństwa wykonywania operacji. Jeśli wiemy, że raz zapisane dane nie mogą być później zmienione (zmutowane), to możemy np. bardzo rzetelnie debugować lub podzielić aplikację na podfunkcje bez ryzyka zapomnienia któregoś ze stanów pośrednich.
Idea niezmienności jest ogólnie przeciwna zasadzie przechowywania stanów we właściwościach w obiektach/podmiotach i raczej opisuje podejście funkcjonalne, w którym dane po prostu "przepływają" przez aplikację, tak jak robi to na przykład javascript.
Z perspektywy wydajności możemy automatycznie powiedzieć o niezmiennych obiektach, że mogą być buforowane w nieskończoność, ponieważ nigdy nie będą przestarzałe.
Zdecydowanie najczęstszym zastosowaniem obiektów niezmiennych w PHP jest obiekt DateTimeImmutable
, który raz utworzony może być wywoływany tylko przez metody formatujące. Jeśli zmodyfikujemy wewnętrzne ustawienia, metoda zwróci nową instancję. Cecha ta jest kluczowa w przypadku korzystania z ORM-a wykorzystującego tzw. wzorzec tożsamości - pozwala nam np. zagwarantować, że gdy odczytamy datę utworzenia zamówienia, będzie ona taka sama wszędzie w aplikacji i integralność referencyjna nie zostanie naruszona.
Konkretny przykład obiektu mutowalnego:
$date = new DateTime('2021-05-14');$tomorrow = $date->modify('+1 dzień');echo $date->format('Y-m-d'); // 2021-05-15echo $tomorrow->format('Y-m-d'); // 2021-05-15
Ta sama data została wydrukowana, ponieważ metoda modify()
zmieniła tylko wewnętrzny stan obiektu DateTime
i zwróciła tę samą instancję. Nie było więc tzw. mutacji stanu wewnętrznego, która jest podstawowym zachowaniem programowania obiektowego. Aktualizacja zmiennej spowodowała również zmianę oryginalnej.
A teraz przykład niezmiennego obiektu:
$date = new DateTimeImmutable('2021-05-14');$tomorrow = $date->modify('+1 dzień');echo $date->format('Y-m-d'); // 2021-05-14echo $tomorrow->format('Y-m-d'); // 2021-05-15
Obiekt DateTimeImmutable
jest niezmienny, co oznacza, że jego stan wewnętrzny nigdy się nie zmienia. Nowa zmodyfikowana instancja (również niezmienna) jest przechowywana w zmiennej po wywołaniu metody modify()
. Gdybyśmy nie zapisali nowej wartości w zmiennej, nie dałoby się jej później wykorzystać.
Oryginalna wartość nigdy nie jest dotykana i pozostaje bezpiecznie przechowywana.
O ile nie masz bardzo dobrego powodu, aby uczynić go mutowalnym, zawsze pisz klasę lub funkcję jako niezmienną. To uprości twój projekt w przyszłości.
Klasy mutowalne powinny zmieniać się w jak najmniejszym stopniu. Zawsze polecam dokumentowanie zachowania niezmienności.
Być może jedyną wadą niezmienności jest to, że nowa instancja musi zostać utworzona przy każdej zmianie atrybutu, co ma niewielki wpływ na wydajność. Jeśli Twoja aplikacja (jak większość aplikacji) ma tendencję do wyświetlania danych i ich rzadszej zmiany, ta wada jest raczej nieistotna przy wydajności dzisiejszych komputerów.
Co nie powinno być niezmienne:
Jan Barášek Více o autorovi
Autor článku pracuje jako seniorní vývojář a software architekt v Praze. Navrhuje a spravuje velké webové aplikace, které znáte a používáte. Od roku 2009 nabral bohaté zkušenosti, které tímto webem předává dál.
Rád vám pomůžu:
Články píše Jan Barášek © 2009-2024 | Kontakt | Mapa webu
Status | Aktualizováno: ... | pl