Quando è inappropriato rendere immutabili gli oggetti?

7

Ho una classe che rappresenta un oggetto entità nel nostro sistema (per argomento, un oggetto Cliente)

public class Customer()
{
  private int id;
  private String name;
  ... // 30+ fields

  public Customer()
  {
    // empty constructor!
  }

  // getters and setters
}

Sto cercando di rifattorizzarlo in modo che i campi vengano estratti nei loro oggetti dove sono raggruppati in modo più ragionevole e, allo stesso tempo, creano costruttori parametrizzati, con l'intento di perdere i metodi setter e creare oggetti immutabile (poiché questa è apparentemente una buona cosa).

Tuttavia, questo non ha senso - a volte ho bisogno di aggiornare le informazioni di un cliente! Non è chiaramente immutabile. Dovrei semplicemente non rendere questa classe immutabile - e posso applicare lo stesso argomento a tutte le mie classi di entità?

    
posta Chris Cooper 28.03.2013 - 17:49
fonte

2 risposte

12

Quali sono i vantaggi dell'immutabilità? Questi vantaggi si applicano a un oggetto Cliente?

Generalmente, si usa l'immutabilità per fornire determinismo. Puoi accedere a un oggetto immutabile in sicurezza su più thread? Sì, perché non c'è pericolo che un thread muti l'oggetto mentre un altro thread lo sta elaborando.

Tuttavia, nel caso delle applicazioni Line of Business, un database si occupa in genere di eventuali problemi di concorrenza emettendo blocchi sui record quando le persone li modificano o lasciando vincere l'ultimo salvataggio. Di conseguenza, le classi di dominio in genere non sono progettate in modo immutabile, dal momento che così facendo tenta di risolvere un problema che è già stato risolto.

    
risposta data 28.03.2013 - 18:21
fonte
1

C'è molto campo da coprire tra tipi immutabili ed esponendo tutti gli interni della tua classe attraverso i setter pubblici.

Un tipico costrutto usato per mutare tipi immutabili sta avendo metodi simili a setter che restituiscono una copia dell'oggetto con valori aggiornati di determinati campi - che invece di avere questo:

public void setName (string value) {
   this.name = value;
}

hai qualcosa di simile a questo:

public Customer withName (string value) {
   Customer cust = this.Clone();
   cust.name = value;
   return cust;
}

In questo modo puoi avere un oggetto immutabile che puoi essenzialmente aggiornare. Linguaggi come F # hanno zucchero di sintassi per operazioni simili su record, ma in linguaggi OOP meno funzionali questo sembra innaturale. Ma comunque, probabilmente non è quello che vuoi fare.

Ciò che rende attraente lo stato immutabile è il fatto che rende molte cose più facili da ragionare, dal momento che lo stato non cambierà attraverso un effetto collaterale in un pezzo di codice non correlato - meno posti in cui le cose andranno male. Ma è solo un mezzo per lo stesso fine che i linguaggi OOP incoraggiano a incapsulare.

Invece di affidarti ai setter, mantieni la logica di aggiornamento all'interno della classe. Stesso effetto: meno pulsanti da premere e leve da tirare per mettere il tuo oggetto in uno stato inaspettato e indesiderato. Mantieni un'interfaccia ben definita per gli utenti del tuo oggetto da utilizzare e non ci sarà bisogno di getter e setter generici.

È più lavoro che avere gli oggetti di dominio come semplici oggetti di trasferimento dati e talvolta può non valerne la pena, quindi è un giudizio. Ma se stai facendo qualcosa di remotamente complesso con il tuo oggetto (e visto che stai guardando oltre 30 campi, probabilmente lo sei), potrebbe valerne la pena.

    
risposta data 29.03.2013 - 00:45
fonte