Immutabilita je jeden z nejdůležitějších návrhových konceptů pro budování stabilních aplikací. Základní princip říká, že jednou zapsaný stav může být později už pouze čten bez možnosti jeho modifikace. Pokud potřebujeme stav změnit, musíme vytvořit novou instanci a celý objekt vyměnit za jiný.
Datové typy lze proto velmi hrubě rozdělit na dvě velké kategorie:
Mutable objekty lze vnitřně změnit. To znamená, že poskytují operace, které při různé kombinaci volání způsobí, že dostaneme různé výsledky. Immutabilita se tomuto chování snaží zabránit.
Třída je immutable právě tehdy, pokud po vytvoření instance nejdou data instance žádným způsobem změnit.
Všechna data jsou tedy zafixována v konstruktoru. Všechny skalární datové typy jsou také automaticky immutable.
Navrhovat aplikace s immutable stavy přináší zásadní výhodu v bezpečnosti provádění operací. Pokud víme, že jednou zapsaná data nebude možné později změnit (mutovat), můžeme například velmi spolehlivě debugovat, nebo rozdělit aplikaci na dílčí funkce bez rizika, že zapomeneme na některý z mezistavů.
Myšlenka immutability je obecně proti principu ukládání stavů do properties v objektu/entitách a spíše vystihuje funkcionální přístup, kdy data pouze "protékají" přes aplikaci, jako to dělá například javascript.
Z pohledu výkonu můžeme o immutable objektech automaticky říct, že je lze cachovat na neomezeně dlouhou dobu, protože nikdy nebudou neaktuální.
Zdaleka nejčastější použití immutable objektů v PHP je objekt DateTimeImmutable
, který jednou vytvoříme a už nad tím lze volat pouze formátovací metody. Pokud bychom vnitřní nastavení modifikovali, metoda vrátí novou instanci. Tato vlastnost je klíčová například při použití ORM, které využívá tzv. identity pattern - to nám umožní například při čtení data vytvoření objednávky garantovat, že bude všude v aplikaci stejný a nedojde k poškození referenční integrity.
Konkrétní příklad muttable objektu:
$date = new DateTime('2021-05-14');$tomorrow = $date->modify('+1 day');echo $date->format('Y-m-d'); // 2021-05-15echo $tomorrow->format('Y-m-d'); // 2021-05-15
Stejný datum se vypsal z toho důvodu, protože metoda modify()
pouze změnila vnitřní stav objektu DateTime
a vrátile stejnou instanci. Došlo tedy z tzv. mutování vnitřního stavu, což je základní chování objektově orientovaného programování. Aktualizace proměnné změnila i tu původní.
A nyní příklad immutable objektu:
$date = new DateTimeImmutable('2021-05-14');$tomorrow = $date->modify('+1 day');echo $date->format('Y-m-d'); // 2021-05-14echo $tomorrow->format('Y-m-d'); // 2021-05-15
Objekt DateTimeImmutable
je immutable, což znamená to, že se nikdy jeho vnitřní stav nezmění. Do proměnné se po zavolání metody modify()
uloží nová modifikovaná instance (také immutable). Pokud bychom novou hodnotu neuložili do proměnné, nebude ji možné později použít.
Na originální hodnotu se nikdy nesáhne a zůstane bezpečně uložena.
Pokud nemáte velmi dobrý důvod, aby byla mutable, pište vždy třídu nebo funkci jako immutable. Do budoucna vám to zjednoduší návrh.
Mutable třídy by se měly měnit co nejméně. Chování immutability doporučuji vždy zdokumentovat.
S immutabilitou se pojí snad jediná nevýhoda, a to ta, že se s každou změnou atributu musí vytvářet nová instance, což má drobný dopad na výkon. Pokud vaše aplikace (stejně jako většina aplikací) data spíše zobrazuje a méně často mění, tak je tato nevýhoda s výkonem dnešních počítačů spíše bezvýznamná.
Co by naopak nemělo být immutable:
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:
Nabízím trénink vývojářů, konzultace, školení a analýzu návrhových vzorů. Osobně v Praze nebo online.
Napište mi, pokud si nevíte rady.
Lektor: Jan Barášek
Články píše Jan Barášek © 2009-2024 | Kontakt | Mapa webu
Status | Aktualizováno: ... | cs