La differenza tra mutabile e immutabile consiste nella possibilità di modificare sistemi, infrastrutture o dati dopo la creazione. Le risorse modificabili possono essere modificate internamente, mentre le risorse immutabili non possono essere modificate, poiché qualsiasi modifica crea una nuova istanza.
Mutabile vs immutabile è un principio che guida gli approcci moderni allo sviluppo del software e alla gestione dell'infrastruttura.
Questa distinzione può essere paragonata alla scrittura di un testo su una lavagna. Se è possibile aggiungere parole, cancellare parti o modificare ciò che è scritto, allora si parla di risorsa mutabile. Ma se la lavagna non è più modificabile nel momento in cui si finisce e si deve usare una nuova lavagna per scrivere qualcos'altro, si tratta di una risorsa immutabile.
Sebbene questo concetto si applichi ampiamente all'informatica, si riscontra più comunemente nella programmazione. Nella programmazione, capire quali tipi di dati possono essere modificati direttamente rispetto a quando è necessario crearne una nuova copia è essenziale per le attività comuni. Queste attività includono la scrittura di algoritmi, la creazione di application programming interface (API) e la progettazione di classi in programmazione orientata agli oggetti (OOP).
La scelta di utilizzare oggetti modificabili o non modificabili influisce sul modo in cui i dati vengono gestiti nella memoria, sulla sicurezza con cui possono essere condivisi o modificati e sulla possibilità di sperimentare effetti collaterali indesiderati. Questo è il motivo per cui la distinzione tra mutabile e immutabile è un concetto fondamentale sia per i programmatori principianti che per quelli esperti.
Ad esempio, nel linguaggio di programmazione Python, elenchi e dizionari sono tipi mutabili. Gli elementi possono essere aggiunti, rimossi o modificati all'interno di tali oggetti. Al contrario, oggetti come i booleani (valori veri o falsi) o le tuple, ovvero raccolte ordinate come (1,2,3), sono tipi immutabili. Il loro contenuto non può essere modificato o mutato senza creare un oggetto completamente nuovo.
Newsletter di settore
Resta al passo con le tendenze più importanti e interessanti del settore relative ad AI, automazione, dati e oltre con la newsletter Think. Leggi l' Informativa sulla privacy IBM.
L'abbonamento sarà fornito in lingua inglese. Troverai un link per annullare l'iscrizione in tutte le newsletter. Puoi gestire i tuoi abbonamenti o annullarli qui. Per ulteriori informazioni, consulta l'Informativa sulla privacy IBM.
La scelta tra dati mutabili e immutabili dipende in genere da tre fattori chiave: se i dati necessitano di aggiornamenti frequenti, se sono condivisi tra thread o se richiedono la cronologia delle versioni.
I tipi mutabili in genere funzionano meglio quando i dati richiedono aggiornamenti frequenti e più parti di un programma modificano lo stesso oggetto.
Gli oggetti mutabili modificano i dati internamente, riducendo l'uso della memoria evitando la necessità di creare nuovi oggetti. Questo può ridurre l'uso del processore per la raccolta dei dati inutilizzati (il processo di rimozione dei dati inutilizzati nella memoria libera), perché potrebbe essere necessario creare e raccogliere meno oggetti temporanei.
Ad esempio, i carrelli nelle app usano elenchi modificabili per aggiungere o rimuovere direttamente gli articoli senza creare nuovi oggetti per ogni modifica.
I tipi mutabili offrono prestazioni migliori con dati che cambiano frequentemente, ad esempio elenchi in crescita o contatori in tempo reale, perché aggiornano gli oggetti esistenti anziché crearne di nuovi. Questa efficienza accelera le operazioni nelle strutture di dati che si basano su modifiche rapide.
Ad esempio, la playlist di un'app musicale può utilizzare un elenco mutabile per effettuare aggiornamenti rapidi. Può farlo in microsecondi quando un brano viene aggiunto o eliminato, rispetto alla ricreazione di una playlist di 1.000 brani per ogni modifica.
Gli oggetti mutabili consentono a più parti di un programma di accedere e modificare lo stesso oggetto. Questo processo consente loro di lavorare con uno stato condiviso, cioè con i dati che più componenti leggono e scrivono per coordinare le loro azioni. È utile quando i componenti devono coordinarsi o comunicare tramite dati comuni.
Ad esempio, un'app per la gestione dei progetti utilizza oggetti mutabili per condividere elenchi di attività, calendari e notifiche. Quando un membro del team aggiorna un'attività, tutti vedono immediatamente la modifica.
I tipi non mutabili in genere funzionano meglio quando i dati non devono essere modificati dopo la creazione. Ciò risulta particolarmente importante nelle applicazioni con concorrenza, in cui più parti di un programma accedono agli stessi dati.
Poiché lo stato di un oggetto non modificabile è fisso, non verrà modificato da altro codice. Questa caratteristica rende i programmi più prevedibili e più facili da capire perché elimina i bug legati a mutazioni impreviste.
Ad esempio, le app bancarie spesso memorizzano i record delle transazioni come oggetti immutabili in modo che no-code possa modificarli in seguito. Ciò è critico per garantire la conformità normativa e mantenere traccia dei controlli che dimostrano che le transazioni non sono state manomesse.
Gli oggetti non modificabili sono in genere thread-safe perché il loro stato non può cambiare dopo la creazione. Più thread possono tranquillamente leggerli simultaneamente senza conflitti, anche se gli sviluppatori devono comunque gestire con attenzione i riferimenti nei sistemi concorrenti. Li rende ideali per i programmi multi-thread, in cui più thread devono accedere agli stessi dati senza causare conflitti.
Ad esempio, un' app può eseguire thread simultanei per le condizioni attuali, le previsioni e gli avvisi. Memorizzazione dei dati meteorologici come oggetti immutabili significa che ogni thread può leggere le stesse informazioni senza il rischio che cambino inaspettatamente.
Gli oggetti immutabili possono semplificare il debug perché i valori non cambiano in modo imprevisto durante l'esecuzione del programma. Questa caratteristica può ridurre i bug causati dagli effetti collaterali e aiutare i team a risolvere i problemi più rapidamente.
Ad esempio, nei videogiochi spesso vengono memorizzati i dati sullo stato di salute e le statistiche dei giocatori come oggetti immutabili. Poiché questi valori non possono cambiare in modo imprevisto, gli sviluppatori possono facilmente rintracciare i bug sapendo che il codice non correlato non modificherà le statistiche.
Due degli stili di programmazione più utilizzati, la programmazione orientata agli oggetti (OOP) e la programmazione funzionale affrontano la mutabilità in modo diverso.
L'OOP spesso abbraccia la mutabilità, costruendo programmi attorno a oggetti che contengono sia dati che comportamenti. Questi oggetti possono cambiare nel tempo utilizzando funzioni speciali chiamate setter, che possono aggiornare il valore di una proprietà (ad esempio, modificando l'età di una persona o il prezzo di un prodotto).
Al contrario, la programmazione funzionale tende all'immutabilità. Crea e restituisce nuovi valori ogni volta che qualcosa deve cambiare, rendendo i programmi più prevedibili e più facili da testare.
I linguaggi di programmazione variano anche nell'approccio ai tipi mutabili rispetto a quelli immutabili.
In Python, sono comuni sia i tipi mutabili che quelli immutabili.
Un esempio sono le stringhe, ovvero sequenze di caratteri come nomi o frasi. Le stringhe in Python sono immutabili; l'aggiunta di nuovo testo crea un nuovo oggetto stringa. Al contrario, le liste sono modificabili. Queste raccolte ordinate sono iterabili, ovvero si possono aggiungere, rimuovere o modificare elementi all'interno dell'oggetto elenco.
Invece di usare un compilatore (un programma che converte il codice in linguaggio macchina prima dell'esecuzione) per controllare il codice prima che venga eseguito, Python controlla i tipi in fase di esecuzione. Ciò significa che gli errori vengono rilevati solo mentre il programma è in esecuzione. Gli errori che coinvolgono la mutabilità, ad esempio il tentativo di modificare una stringa immutabile, attivano un TypeError.
Se l'errore non viene gestito, il programma viene arrestato immediatamente, impedendo l'esecuzione di ulteriore codice. Questa procedura consente uno sviluppo più rapido, ma richiede un'attenzione particolare alla gestione dei tipi.
Comprendere la mutabilità in Python aiuta a prevenire errori durante la condivisione di dati tra funzioni o il lavoro all'interno di un modulo condiviso. I tutorial e gli esempi di codice su GitHub forniscono best practice per l'utilizzo dei tipi integrati di Python.
JavaScript utilizza sia tipi mutabili sia tipi immutabili. Come Python, anche le stringhe sono immutabili. Tuttavia, a differenza di Python, tutti gli oggetti sono modificabili per impostazione predefinita.
La sintassi flessibile di JavaScript supporta sia gli stili orientati agli oggetti che quelli funzionali, consentendo agli sviluppatori di gestire la mutabilità in base alle necessità.
Simile a Python, le stringhe Java sono immutabili. Una volta creata, il valore di una stringa non può cambiare. Questa caratteristica può risultare inefficiente per i programmi che creano o modificano frequentemente il testo.
Per risolvere questo problema, Java fornisce StringBuilder, una classe di stringhe modificabili che consente di modificare direttamente il testo senza creare nuovi oggetti. Può migliorare le prestazioni e ridurre l'uso della memoria, bilanciando la sicurezza dell'immutabilità con i benefici della mutabilità.
C++ utilizza la parola chiave const per contrassegnare variabili, funzioni e persino interi oggetti come di sola lettura. Può dare agli sviluppatori un controllo preciso sulla mutabilità, trasformando efficacemente un oggetto mutabile in uno immutabile mediante l'impedimento delle modifiche.
Come Java, le stringhe C++ possono essere mutabili o immutabili, a seconda della loro implementazione.
C++ supporta stili di programmazione sia orientati agli oggetti che funzionali. Nello stile OOP, gli sviluppatori modificano gli oggetti esistenti nel tempo, mentre la programmazione funzionale crea nuovi valori invece di modificare i dati esistenti.
I principi di mutabilità e immutabilità si estendono oltre la programmazione all'infrastruttura e ai sistemi. Gli ingegneri del software moderni applicano questi stessi concetti nella progettazione di architetture cloud e pipeline di implementazione.
L'infrastruttura mutabile si riferisce a server o altre risorse che possono essere modificate dopo la distribuzione. Ad esempio, è possibile accedere a un server e aggiornare manualmente il software, modificare le configurazioni o installare patch. Sebbene questo approccio offra flessibilità, può portare a una deriva della configurazione in cui i server diventano «fiocchi di neve» unici e le modifiche diventano impossibili da tracciare o riprodurre.
Un'infrastruttura immutabile significa che i server o le risorse IT non possono essere cambiati dopo la distribuzione. Invece di aggiornare i sistemi in esecuzione, i team implementano nuove istanze con modifiche integrate, quindi ritirano quelle vecchie. Questo approccio riduce le deviazioni della configurazione, semplifica il rollback e aiuta a garantire implementazioni coerenti.
I principi di mutabilità e immutabilità possono essere applicati anche ad altri ambiti della progettazione di software e sistemi.
Alcuni database utilizzano log di sola aggiunta, ovvero ogni modifica viene registrata in modo permanente e non può essere modificata. Altri sono modificabili e consentono l'aggiornamento o l'eliminazione diretta dei dati, come la modifica di un documento.
Alcuni sistemi di storage cloud possono essere configurati come storage immutabile per conservare le versioni precedenti e impedirle di apportare modifiche. In questo modo è possibile proteggere i dati da modifiche o eliminazioni accidentali. Lo storage modificabile consente di modificare o sostituire i file in qualsiasi momento.
Molti strumenti di controllo delle versioni, come Git, seguono un modello immutabile, in cui ogni commit viene salvato come istantanea separata e immutabile. Aiuta a garantire una cronologia affidabile delle versioni, anche quando vengono aggiunte nuove modifiche.