Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

I am currently working on a collection implementation in JavaScript. I need a mu

ID: 646956 • Letter: I

Question

I am currently working on a collection implementation in JavaScript. I need a mutable and an immutable version of that. So what I thought of first was something like:

Collection
MutableCollection extends Collection
ImmutableCollection extends Collection.
My main issue with this is that if I want to implement more specific collections like List or Set, they could still inherit from Collection while their Mutable/Immutable implementations could not inherit from MutableCollection / ImmutableCollection.

So this made me think whether having all three, Collection, MutableCollection and ImmutableCollection would actually bring any significant benefit.

An alternative approach which came to me would be to only have Collection and then have a Collection.prototype.makeImmutable or freeze there. I would then also introduce a Collection.requireMutableInstance( collectionInstance ) which can be used in functions explicitly requiring a mutable collection.

Here are my main concerns about putting everything into just Collection:

The prototype definition is getting much bigger compared to defineing a MutableCollection prototype as well which would then hold the code of all the operations for alteration. I guess I could solve this by just defining a second file anyhow which would then just extend the basic Collection definition with those additional operations and the makeImmutable operation.
Documentation of those function signatures that actually care about mutable vs. immutable and not just require the basic collection would look less pretty.
Take:

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

/**
* @param {Collection} collection A collection not yet made immutable.
/*
function messAroundWithSomeCollection( collection ) { /* ... */ }
What would be the more natural way of doing this in JavaScript? Especially without having interfaces I can check against and considering the flatter chains of inheritance if I would also implement a Set and Map collection, the everything-in-one approach seems more intuitive to me.

Explanation / Answer

The "class hierarchy" that you mention depends a lot on what you put in Collection. For an immutable list what you usually need is a way of iterating through values: length, forEach, map, find, etc.

So what has the ImmutableCollection interface that is not already part of Collection? Another possible hierarchy could be:

Iterable: length, forEach
MutableCollection: implements Iterable, but adds mutators add, remove
About how to convert a mutable collection into immutable, use a decorator:

new ImmutableView(mutableCollection)
Where ImmutableView implements Iterable but doesn't expose any mutator. That's the approach used by most collection APIs: Java, Scala, Dart. (Actually Java implementation is broken in the sense that Collection already have mutators, so an Immutable collection is as collection that doesn't follow the substitution principle: add/remove throws exceptions so semantically doesn't implement the interface)

About the Collection.requireMutable. Why do you want to do that? JavaScript is not statically typed, so what you want to do is to emulate some sort of type checking. If that really bothers you, switch to a language like TypeScript or Dart. If not, assume that you receive a mutable collection and don't do any additional check. Everything will be fine as long you:

Do unit tests. TDD is the best companion for big systems based on dynamic languages
Follow the Liskov substitution principle. Even if JavaScript doesn't have static typechecking, is good exercise to think about it. A quick rule of thumb, if your code has some if (x instanceof Y) conditionals.. you are not following the substitution principle. It means that you are not taking advantage of polymorphism.