L'oggetto di raccolta è meglio immutabile? [chiuso]

1

Come da questo link , è un consiglio che:

A good object should never change his encapsulated state. Remember, an object is a representative of a real-life entity, and this entity should stay the same through the entire life of the object. In other words, an object should never betray those whom he represents. He should never change owners. :)

Be aware that immutability doesn't mean that all methods always return the same values. Instead, a good immutable object is very dynamic. However, he never changes his internal state.

È meglio reintrodurre le raccolte (in java) come class LinkedList mantenendo l'immutabilità di stato supportando operazioni come add / remove elemento?

Senza overhead delle prestazioni, questa raccolta ( class LinkedList ) può essere introdotta come collezione immutabile?

Perché, qui sotto, ci sono i vantaggi a favore dell'immutabilità:

  • gli oggetti immutabili sono sempre thread-safe
  • aiutano ad evitare l'accoppiamento temporale
  • il loro utilizzo è privo di effetti collaterali
posta overexchange 20.06.2015 - 02:30
fonte

4 risposte

9

As per this link

Visto che la regola n. 1 è orribile, vorrei mettere in guardia dal prendere il resto del post sul blog come legge. Anche se in realtà, nessun post sul blog dovrebbe essere considerato come legge.

E la citazione stessa è piuttosto contraddittoria:

  • A good object should never change his encapsulated state.
  • Be aware that immutability doesn't mean that all methods always return the same values.

Ecco la cosa, se hai uno stato immutabile e i tuoi metodi restituiscono valori diversi, allora almeno una delle due cose è vera:

  1. La tua funzione varia in base ai suoi input.
  2. La tua funzione ha effetti collaterali (funziona con qualcosa che ha ha uno stato mutabile).

(L'esempio nell'articolo colpisce su # 2.)

La seconda di queste condizioni sconfigge lo scopo di avere oggetti immutabili, e fare la distinzione tra "stato incapsulato" e altri stati è nel peggiore dei casi, nel migliore dei casi poco pratico.

E la prima di queste condizioni è buona. Le funzioni dovrebbero variare solo sui loro input ove possibile. Nascondere lo stato immutabile nella classe nuoce un pochino al fronte della chiarezza, ma varia molto in base a ciò che stai effettivamente facendo.

Comunque, alla tua domanda:

Without performance overheads, can such implementations(class LinkedList) be introduced by instantiating as immutable objects?

Dipende dalla tua lingua / implementazione. Le liste collegate si prestano abbastanza bene alla costruzione immutabile perché le parti interne di ciascun "link" non sono realmente mutabili. È relativamente facile creare nuovi collegamenti con nuovi indicatori.

In Java, dubito che potresti fare cose del genere senza un sovraccarico dovuto al colpo al garbage collector. Non si può nemmeno fare il pooling di oggetti poiché non c'è modo di riutilizzare gli oggetti immutabili in modo affidabile. E certamente non potresti farlo mantenendo le interfacce Java esistenti, progettate con la mutabilità (e mantenendo un riferimento alla lista) in mente.

Does a good object never change its state?

Un tale assoluto non è corretto. Sì, l'immutabilità offre numerosi vantaggi. Sì, probabilmente dovresti avere l'impostazione predefinita per rendere i tuoi oggetti immutabili in Java e in molte altre lingue. Ma ci sono molti oggetti perfettamente validi che cambiano il loro stato, e non alcuni oggetti (soprattutto le collezioni) in cui l'oggetto mutevole è di gran lunga migliore (più utilizzabile, più robusto, più performante, più flessibile, più manutenibile) di un design immutabile.

    
risposta data 20.06.2015 - 04:33
fonte
3

tl; dr L'autore sembra pensare che tutti gli oggetti siano value objects , ma questo non è vero.

Gli oggetti valore dovrebbero essere immutabili perché la loro esistenza rappresenta uno valore specifico di qualche spazio valore .

Ad esempio, un oggetto che rappresenta un valore di colore pixel potrebbe essere reso immutabile. La proprietà dell'immutabilità può essere utilizzata per ragionare sul problema più facilmente, riutilizzare oggetti, calcoli della cache e altro ancora.

D'altra parte, un oggetto thread dovrà riflettere lo stato di un thread di esecuzione, consentendo di interrogare lo stato del thread (myThread.isRunning (), ad esempio). Non ci si può aspettare che funzioni se l'oggetto fosse immutabile, a meno che non si possa scambiare il riferimento myThread da sotto di te, ma IMO aggiunge complessità che va contro il problema.

    
risposta data 20.06.2015 - 10:14
fonte
1

Penso che sia più facile ragionare su un oggetto che non cambia stato una volta inizializzato. Ad esempio, gli oggetti valore sono piuttosto facili da ragionare. Assegna un valore e una query per le proprietà.

Questo non è sempre possibile e non penso che sia un grosso problema, ma aggiunge un livello di complessità. I tuoi metodi potrebbero basarsi su uno stato interno coerente che è più facile da violare se il tuo oggetto continua a cambiare.

Se hai bisogno di andare per un oggetto che cambia frequentemente stato, i metodi che modificano lo stato dovrebbero essere limitati e documentati. Limita il tuo utilizzo di setter e preferisci metodi che "si prendono cura di un'azione".

Se la complessità si presentasse potrebbe essere necessaria un'ulteriore estrazione, la tua Factory o qualcos'altro, ma non generalizzerei la regola, valuterei caso per caso se il sovraccarico risolve realmente un problema reale.

Non mi preoccuperei delle prestazioni finché non avrò un problema di prestazioni.

First Rule of Program Optimization: Don’t do it - Michael A. Jackson

    
risposta data 20.06.2015 - 03:17
fonte
1

Without performance overheads, can such implementations(class LinkedList<E>) be introduced by instantiating as immutable objects?

Sì, può. In effetti, una lista collegata è l' primo esempio di una collezione immutabile persistente. (Suppongo che "senza costi generali delle prestazioni" tu stia parlando di persistenza?)

public class LinkedList<E>
    extends AbstractSequentialList<E>
    implements List<E>, Deque<E>, Cloneable, java.io.Serializable {

    private final E value;
    private final LinkedList<E> next;

    static final empty = new Empty();

    LinkedList(E value, LinkedList<E> next) {
        this.value = value;
        this.next = next;
    }

    Optional<E> value() {
        return Optional.of(value);
    }

    Optional<LinkedList<E>> next() {
        return Optional.of(next);
    }

    private class Empty extends LinkedList<Object> {
        private Empty() {}

        Optional<E> value() {
            return Optional.empty();
        }

        Optional<LinkedList<E>> next() {
            return Optional.empty();
        }
    }
}

Non conosco molto bene Java, ma qualcosa del genere dovrebbe farti iniziare.

    
risposta data 20.06.2015 - 09:58
fonte

Leggi altre domande sui tag