Potrei avere una visione di livello troppo basso di questo e probabilmente perché sto usando C e C ++ che non rendono esattamente così semplice rendere tutto immutabile, ma vedo i tipi di dati immutabili come un dettaglio di ottimizzazione per scrivere di più funzioni efficienti prive di effetti collaterali e in grado di fornire facilmente funzioni come i sistemi di annullamento e l'editing non distruttivo.
Ad esempio, questo potrebbe essere enormemente costoso:
/// @return A new mesh whose vertices have been transformed
/// by the specified transformation matrix.
Mesh transform(Mesh mesh, Matrix4f matrix);
... Se Mesh
non è progettato per essere una struttura di dati persistente ed era, invece, un tipo di dati che richiedeva la copia completa (che poteva estendersi su gigabyte in alcuni scenari) anche se tutto ciò che faremo è cambiare un parte di esso (come nello scenario sopra in cui modificiamo solo le posizioni dei vertici).
Quindi è quando raggiungo l'immutabilità e progetto la struttura dei dati per consentire che parti non modificate di esso vengano copiate in modo superficiale e contate come riferimento, per consentire alla funzione di cui sopra di essere ragionevolmente efficiente senza dover copiare in profondità intere mesh mentre è ancora in grado di scrivere il essere privo di effetti collaterali che semplifica notevolmente la sicurezza dei thread, la sicurezza delle eccezioni, la possibilità di annullare l'operazione, applicarla in modo non distruttivo, ecc.
Nel mio caso è troppo costoso (almeno dal punto di vista della produttività) per rendere tutto immutabile, quindi lo conservo per le classi che sono troppo costose per essere copiate per intero. Quelle classi sono generalmente strutture di dati pesanti come mesh e immagini e generalmente utilizzo un'interfaccia mutabile per esprimere le modifiche ad esse attraverso un oggetto "builder" per ottenere una nuova copia immutabile. E non lo sto facendo così tanto per cercare di ottenere garanzie immutabili a livello centrale della classe, tanto quanto aiutarmi a usare la classe in funzioni che possono essere prive di effetti collaterali. Il mio desiderio di rendere Mesh
immutabile sopra non è direttamente quello di rendere immutabili le mesh, ma di consentire di scrivere facilmente funzioni prive di effetti collaterali che introducono una mesh e ne producono una nuova senza pagare una memoria enorme e costi di calcolo in cambio.
Di conseguenza ho solo 4 tipi di dati immutabili in tutta la mia base di codice, e sono tutte strutture di dati pesanti, ma li uso pesantemente per aiutarmi a scrivere funzioni prive di effetti collaterali. Questa risposta potrebbe essere applicabile se, come me, stai lavorando in una lingua che non rende così facile rendere tutto immutabile. In tal caso, puoi spostare la tua attenzione verso il fatto che la maggior parte delle tue funzioni eviti gli effetti collaterali, a quel punto potresti voler rendere immutabili strutture di dati selezionate, tipi di PDS, come dettaglio di ottimizzazione per evitare le costose copie complete. Nel frattempo quando ho una funzione come questa:
/// @return The v1 * v2.
Vector3f vec_mul(Vector3f v1, Vector3f v2);
... quindi non ho la tentazione di rendere immutabili i vettori poiché sono abbastanza economici da copiarli per intero. Non è possibile ottenere vantaggi in termini di prestazioni trasformando i vettori in strutture immutabili in grado di copiare superficialmente parti non modificate. Tali costi supererebbero il costo della sola copia dell'intero vettore.