The example I'm about to give is for the PHP language, but I think this scenario applies to most languages.
Diciamo che ho un oggetto chiamato Response
e voglio che sia immutabile. Ogni metodo dovrebbe restituire una nuova istanza piuttosto che modificare lo stato dell'istanza corrente. Response
s ha intestazioni, quindi creo un metodo chiamato withHeader($name, $value)
che crea una copia del mio oggetto risposta, imposta l'intestazione e restituisce la nuova istanza. È piuttosto semplice da usare:
$newResponse = $oldResponse->withHeader('Content-Type', 'application/json');
Quindi decido che le intestazioni in realtà abbiano alcune proprietà e preferisco separarle in un oggetto separato chiamato HeaderBag
. Ora voglio che il mio Response
tenga un HeaderBag
ma voglio comunque che sia immutabile.
Non posso rendere la borsa una proprietà pubblica, come $response->headers
perché anche se l'oggetto $headers
è immutabile, la proprietà può ancora essere riassegnata. Quindi forse aggiungo qualcosa come $response->getHeaders()
che restituisce il mio oggetto HeaderBag
, ma ora come lo manipolo?
Se sposto il mio metodo withHeader
in questo sottooggetto, allora finisco con qualcosa come $response->getHeaders()->withHeader(...)
. Il metodo withHeader
restituirebbe presumibilmente un nuovo HeaderBag
poiché anch'esso è immutabile, ma allora? Credo che finirei con qualcosa di simile:
$newResponse = $oldResponse->withHeaders($oldResponse->getHeaders()->withHeader($name, $value));
Che sembra un po 'ridicolo; per aggiungere un singolo valore dobbiamo clonare due oggetti e scrivere questo abominio di una linea. Certo, possiamo scrivere un metodo di supporto sull'oggetto Response
per accorciarlo, ma l'idea era di spostare tutti i metodi relativi all'intestazione nella classe HeaderBag
.
Domande:
- C'è un modo migliore per farlo?
- Se non c'è, vale anche lo sforzo / il costo per rendere gli oggetti immutabili?
- Se potessimo progettare un nuovo linguaggio con immutabilità in mente, come sarebbe questo?