Non restituisce una raccolta come non modificabile / immutabile, senza necessità di interrompere l'ambito del metodo?

6

Diciamo che creo un Collection in un metodo di istanza. Non assegno quel riferimento a nessuna variabile di istanza. Piuttosto, lo restituisco al invocatore. Quindi esco.

Ora, l'unica cosa con un riferimento a quel Collection è l'invocatore.

Quindi, come lo scrittore del metodo, perché mi interessa cosa fa l'invoker con il Collection restituito? Se l'invocatore vuole trattarlo come Non modificabile / Immutabile non è affar mio. In effetti, avrei infranto il mio metodo di manovra a mano ammanettando l'invocatore in quel modo.

In questo momento sto scrivendo un metodo che converte un String usando espressioni regolari. Ero pronto ad andare con la restituzione di un ImmutableList . Ma, sto per cambiare idea.:

public interface someInterface {
    List<String> tokenize(String text);
    com.google.common.collect.ImmutableList<String> tokenizeImmutable(String text);
}

Una volta che esco e muoio, se l'invoker muta il mio Collection , quello che ho creato, non è nulla su cui dovrei avere alcuna influenza. Voglio dire, I potrebbe bloccarlo, e concettualmente la tokenizzazione dovrebbe essere bloccata, ma questo è fuori dal mio ambito.

    
posta konishiki 12.02.2016 - 04:05
fonte

3 risposte

1

Risposta breve (ma inutile) alla tua domanda: No, in generale non rompe lo "scope".

Come per tutto il resto, ci sono casi in cui forzare l'immutabilità è buona e casi in cui non lo è.

Alcuni casi sono più neri o più bianchi di altri, naturalmente. Il tuo esempio è un candidato per quando potresti non voler forzare questo sull'invocatore. Tuttavia, potresti restituire una raccolta e, sebbene solo creata localmente, potresti avere un caso in cui questa raccolta è una bestia costruita a mano per scopi speciali. E quella bestia sembra avere prestazioni pessime quando la modifichi, quindi potresti voler proteggere i tuoi utenti dal dover conoscere questo fatto semplicemente proibendo le modifiche.

Come sottolineato da @Bwmat, un altro scenario tipico sta fornendo l'accesso a una collezione di attributi membro. Normalmente, non vuoi che cambi al di fuori della tua classe, quindi ti inclini all'immutabilità. Ma neanche questo è un proiettile d'argento. A volte i chiamanti eseguono un thread diverso e semplicemente iterando su quella raccolta può causare una ConcurrentModificationException, quindi si decide di restituire una copia. In casi ancora più rari potresti persino sentirti obbligato a restituire la collezione vera e propria (anche se ora è un'area maledettamente buia).

Come puoi vedere da questi esempi, la discussione include spesso i comportamenti di entrambi i lati - il lato del dichiaratore del metodo e il lato del cliente. Il termine ambito del metodo usato nella tua domanda è ambiguo e potrebbe essere alla radice del problema qui.

Abbiamo l'ambito del metodo rigorosamente lessicale utilizzato nel dominio del compilatore. È la parte del tuo codice in cui gli argomenti e le variabili locali del metodo sono accessibili. Ovviamente, questo ambito non è inteso qui, dal momento che guardare il metodo chiamante è chiaramente al di fuori di esso.

L'ambito del metodo di un metodo di interfaccia si estende ben oltre a tutti i punti in cui il programma di caricamento classi può potenzialmente accedere all'interfaccia. In altre parole, fa parte di tale ambito considerare gli usi di invoker del tuo metodo e i suoi valori di ritorno.

Infine, puoi definire un ambito completamente diverso per il tuo metodo nell'area del tuo dominio problematico (come nel "scope tokenization scope") e potresti venire a un'altra soluzione su quale dovrebbe essere il miglior tipo di ritorno.

In sintesi, tieni presente che lo ambito del tuo metodo in realtà significa per te e il tuo team e, come al solito, soppesare i pro e i contro di ciascun approccio all'interno di tale ambito.

    
risposta data 12.02.2016 - 09:28
fonte
4

Il ritorno di dati immutabili è un esempio di "il pozzo del successo" . Affinché un'altra parte del sistema possa modificarlo, è necessario convertirlo esplicitamente in un set di dati mutabile e modificarlo. Questo riduce le possibilità di una modifica accidentale che porta a un bug. Quindi la fase: rendi più facile scrivere codice affidabile utilizzando tipi di dati immutabili per impostazione predefinita, rendi più facile cadere nella "fossa del successo".

L'unica ragione per non restituire un insieme di dati immutabile è per motivi di prestazioni. Anche qui, c'è il rischio di micro-ottimizzare il codice. Se le prestazioni del metodo diventano un problema, prendi in considerazione la possibilità di cambiarlo; non prima.

    
risposta data 12.02.2016 - 16:59
fonte
1

In primo luogo, restituire una lista immutabile non preclude che l'invocatore crei immediatamente una lista mutabile, quindi, a parte alcuni problemi di rendimento, non stai limitando ciò che è possibile per l'invocatore. Tuttavia, hai toccato perché è ancora desiderabile restituire una collezione immutabile nella tua domanda.

I do not assign that reference to any instance variables. Rather, I just return it to the invoker.

Come lo sa questo invocatore? Se sto accedendo al tuo tokenizzatore tramite someInterface come applicherai questo in ogni classe che implementa quell'interfaccia? Un commento? Se stavi programmando in Rust questo sarebbe applicabile, ma poche altre lingue ti consentono di esprimere il trasferimento della proprietà.

Restituendo una collezione immutabile, l'invocatore immediatamente sa che non devono preoccuparsi di qualcuno da qualche parte con un riferimento alla stessa lista; sanno immediatamente che due chiamate al tokenizer restituiscono oggetti non interagenti.

Se il costo delle prestazioni di restituire una collezione immutabile era troppo grande, si potrebbe considerare l'utilizzo di tecniche come Rust e C ++ per restituire un oggetto che rappresenta la proprietà esclusiva di un valore. Questo ti permetterebbe di comunicare (anche se non abbastanza far rispettare) la garanzia. Certo, senza la garanzia probabilmente non vale la pena.

    
risposta data 12.02.2016 - 09:14
fonte

Leggi altre domande sui tag