Questo è qualcosa che non ho mai capito. Quando ho imparato il C ++, ad esempio, ho avuto molti mal di testa con problemi const, in quanto aggiungeva molta complessità alla programmazione. Perché l'immutabilità è importante? Ed è sempre necessario?
La risposta casuale è che la mutabilità è necessaria, perché il software che non cambia qualsiasi è un po 'inutile. In definitiva, almeno alcuni dei tuoi dati saranno mutabili, anche se si tratta solo dell'input e dell'output del processo.
In realtà, però, stai chiedendo perché sceglieresti di utilizzare dati immutabili anziché mutabili in varie parti del tuo programma, e la risposta è la complessità.
La complessità è la cosa che rende il software difficile. I dati mutabili sono intrinsecamente complessi, perché possono cambiare.
La complessità è ciò che rende il software difficile, perché rende difficile fare qualsiasi cosa con esso. Potrebbe essere la complessità di fare la cosa giusta di fronte a tutto il tuo stato, o la complessità della concorrenza, o la complessità del cambiamento del codice per soddisfare nuovi requisiti.
In definitiva, tuttavia, il software più semplice è più facile continuare a funzionare e migliorare, nel tempo. C'è un sacco di educazione , esperienza e discussione correlata che la maggior parte del costo del software lo sta davvero mantenendo funzionante per tutta la durata del software.
La ragione per cui i dati mutabili rendono il software più complesso è abbastanza semplice, se si contrappone il pensiero che si deve fare sui dati:
Se i dati sono immutabili devi sapere cosa significa, dove è stato assegnato per la prima volta e forse come viene usato qui.
Se i dati sono mutabili è necessario sapere che cosa significa, dove è stato assegnato per la prima volta, dove può essere modificato, quando può essere modificato, se tali modifiche possono accadere contemporaneamente e richiedono blocchi, quali blocchi di sequenza devono essere acquisito in, se il cambiamento dei dati richiede il coordinamento con gli altri, e se è effettivamente cambiato qui.
Ci sono altri vantaggi rispetto ai dati immutabili, come l'efficienza della raccolta dei rifiuti, il funzionamento privo di blocco, la condivisione efficiente della sottostruttura e così via, ma sono scelte tecniche - e mentre stanno diventando più importanti man mano che l'elaborazione multi-core diventa più comune, non sono il cuore del vantaggio.
Infine, alla domanda implicita del perché l'hai trovato così stimolante nel tuo apprendimento della lingua ... Ovviamente, posso solo speculare, ma nella mia esperienza ci sono due cause per questo nelle persone che apprendono la programmazione, i linguaggi di programmazione e paradigmi di programmazione:
Il primo è che la maggior parte dei problemi di insegnamento sono ottimi strumenti per l'apprendimento, ma hanno ben poco a che fare con il "mondo reale" dell'ingegneria del software. Alla scala di un problema di insegnamento, probabilmente conosci l'intero codice base, end to end, ed è abbastanza piccolo da poter contenere un'immagine nella tua testa di come tutto funziona.
Quando lavori con una squadra di cinque, dieci, o cinquanta o cinquecento persone su una base di codice con mezzo milione di righe di codice, dove non hai mai nemmeno visto la maggior parte codice su cosa stai lavorando - beh, allora inizi ad apprezzare i dati immutabili, perché devi sapere molto meno.
Il secondo è che il tuo commento su "ha aggiunto molta complessità" rispecchia quello che molte altre persone mi hanno detto. In generale, hanno ritenuto che aggiungesse molta complessità perché volevano solo scrivere codice finché qualcosa non ha funzionato senza spendere un sacco di tempo a pensare all'immagine più grande del problema.
Ora, non ho idea se questo sia vero o meno per te - non ti ho mai incontrato - ma forse è la stessa cosa.
I dati mutabili sono una soluzione semplice per "Ho bisogno che X cambi in modo da far succedere Y" quando ti trovi in una parte casuale del codice e devi attivare un effetto distante.
Questo aggiunge complessità. Non la complessità locale, certo, perché puoi modificare più facilmente il valore e tutto. Complessità remota. Complessità invisibile.
Espande i dettagli di dove avviene il cambiamento e di dove è definito il comportamento del sistema. Mentre scorri questo percorso e aumenta le dimensioni del sistema, riscopri i problemi che Analisi e progettazione orientata agli oggetti è nato per combattere.
Ancora una volta, non ti conosco, e questo potrebbe non avere nulla a che fare con il motivo per cui tu l'hai trovato "ha aggiunto complessità", ma è il modello più comune nella mia esperienza di persone che dicono che stessa cosa.
L'argomento è che i dati immutabili hanno 2 vantaggi:
Puoi accedervi tranquillamente da 2 thread senza preoccuparti di blocchi o altri problemi di concorrenza.
In molti casi produce codice più facile da ragionare, più facile da testare e più facile da essere sicuro della sua correttezza.
Ad esempio, il risultato di qualche funzione potrebbe essere un oggetto, e forse una delle post-condizioni che vogliamo testare è il valore di alcune proprietà dell'oggetto risultato:
[Test]
public void Result_of_Foo_has_property_X_which_is_based_on_input_Y()
{
var test = BuildObjectForTest();
var result = test.Foo(23);
Assert.AreEqual(15, result.X);
}
Se l'oggetto risultato è mutabile, allora forse la proprietà di test X ha cambiato il valore di X o ha cambiato qualche altra proprietà dell'oggetto. Questo è un effetto collaterale e tentiamo di ridurre gli effetti collaterali perché producono codice complesso. Inoltre, a seconda dello stato interno dell'oggetto test
, forse chiamare nuovamente Foo
con lo stesso argomento potrebbe non produrre lo stesso risultato. I programmatori che utilizzano questo codice devono saperlo.
Se il programmatore che lo usa sa che entrambi sono oggetti immutabili, possono ridurre notevolmente la quantità di pensiero che devono mettere nella comprensione.
Nella mia esperienza, ci sono due tipi di codice: quelli che eseguono un'azione (stampano qualcosa sullo schermo, spostano il robot, aggiornano un record nel database, ecc.) e c'è un codice che risponde a una domanda. Il primo tipo ha ovviamente effetti collaterali perché cambia tipo di cose nel mondo reale (le cose sullo schermo sono sostituite da nuove cose, o il robot si sposta, o i dati del database vengono modificati). Il secondo tipo dovrebbe essere puramente funzionale, che è privo di effetti collaterali. Se ti chiedo di dirmi cosa sia 2 + 2, non dovresti cambiare il valore di 2 per dirmi che la risposta è 4. Pertanto, mi aspetto che i valori 2 e 4 siano immutabili. Allo stesso modo, voglio che i miei valori a
e b
siano immutabili, se ti chiedo il risultato di a + b
.
Leggi altre domande sui tag immutability