Versione mutabile e immutabile delle implementazioni di Collection o entrambe inserite in uno tramite .makeImmutable ()

4

Attualmente sto lavorando a un'implementazione di raccolta in JavaScript. Ho bisogno di una versione mutabile e immutabile di quello. Quindi quello che pensavo prima era qualcosa del tipo:

  • Collection
  • MutableCollection estende Raccolta
  • ImmutableCollection estende Raccolta .

Il mio problema principale è che se voglio implementare raccolte più specifiche come Elenco o Set , potrebbero comunque ereditare da Raccolta mentre le loro implementazioni Mutevoli / Immutabili non possono ereditare da MutableCollection / ImmutableCollection .

Quindi questo mi ha fatto pensare se avere tutti e tre, Raccolta , MutableCollection e ImmutableCollection portasse effettivamente vantaggi significativi.

Un approccio alternativo che mi viene in mente sarebbe di avere solo Raccolta e quindi avere Collection.prototype.makeImmutable o freeze lì. Vorrei quindi introdurre anche un Collection.requireMutableInstance (collectionInstance) che può essere utilizzato in funzioni che richiedono esplicitamente una raccolta mutabile.

Ecco le mie principali preoccupazioni su come mettere tutto solo nella Collezione :

  • La definizione del prototipo sta diventando molto più grande rispetto alla definizione di un prototipo MutableCollection che potrebbe quindi contenere il codice di tutte le operazioni di modifica. Immagino che potrei risolvere questo problema semplicemente definendo un secondo file comunque che estenderebbe la definizione di base Collection con quelle operazioni aggiuntive e l'operazione makeImmutable .
  • La documentazione di quelle firme di funzioni che effettivamente si preoccupano di mutevole e immutabile e non richiede solo che la raccolta di base sia meno carina.

Prendere:

/**
 * @param {MutableCollection} collection
/*
function messAroundWithSomeCollection( collection ) { /* ... */ }

vs.

/**
 * @param {Collection} collection A collection not yet made immutable.
/*
function messAroundWithSomeCollection( collection ) { /* ... */ }

Quale sarebbe il modo più naturale di farlo in JavaScript? Soprattutto senza avere interfacce su cui poter controllare e considerare le catene più piatte di ereditarietà se implementerei anche una collezione Set e Map , l'approccio tutto in uno sembra più intuitivo a me.

    
posta Daniel A. R. Werner 15.07.2013 - 21:02
fonte

1 risposta

1

La "gerarchia di classi" che menzioni dipende molto da ciò che hai inserito nella Collezione . Per un elenco immutabile ciò che di solito ti serve è un modo per iterare attraverso i valori: length , forEach , map , find , ecc.

Quindi cosa contiene l'interfaccia ImmutableCollection che non fa già parte di Collection ? Un'altra possibile gerarchia potrebbe essere:

  • Iterable : length , forEach
  • MutableCollection : implementa Iterable , ma aggiunge mutatori add , remove

Informazioni su come convertire una collezione mutabile in immutabile, usa un decoratore:

    new ImmutableView(mutableCollection)

Dove ImmutableView implementa Iterable ma non espone alcun mutatore. Questo è l'approccio utilizzato dalla maggior parte delle API di raccolta: Java, Scala, Dart. (In realtà l'implementazione di Java è interrotta nel senso che Collection ha già mutatori , quindi una collezione Immutable è una collezione che non segue il principio di sostituzione: add / remove genera eccezioni, quindi semanticamente non implementa l'interfaccia)

Informazioni su Collection.requireMutable . Perché vuoi farlo? JavaScript non è tipizzato staticamente, quindi quello che vuoi fare è emulare un controllo di tipo. Se ciò ti infastidisce, passa a un linguaggio come TypeScript o dardo . In caso contrario, si supponga di ricevere una raccolta mutabile e di non effettuare alcun controllo aggiuntivo. Tutto andrà bene finché tu:

  • Esegui i test unitari. TDD è il miglior compagno per i grandi sistemi basati su linguaggi dinamici
  • Seguire il principio di sostituzione di Liskov. Anche se JavaScript non ha un controllo ortografico statico, è un buon esercizio per pensarci. Una regola empirica, se il tuo codice ha alcune condizioni condizionali if (x instanceof Y) , non stai seguendo il principio di sostituzione. Significa che non stai sfruttando il polimorfismo.
risposta data 14.09.2013 - 17:44
fonte

Leggi altre domande sui tag