How do I write an ImmutableMap that follows Liskov's subscription and other SOLID principles without code smell?

I answered the question regaurding a ImmutableMap

. I suggested using the proxy pattern.

The problem is that Map

contains the method put

that I would choose UnsupportedOperationException

. Replacing other copies Map

with ImmutableMap

will break the Liskov Subscharge principle. Moreover, the need to declare put

and putAll

[violates the principle of interface segregation]

There is technically no way to replace an instance Map

with ImmutableMap

, since it Map

is just an interface. So my question is:

Would creation ImmutableMap

using an interface Map

be considered an LSP violation because it Map

contains a method put

and putAll

? Wouldn't the implementation Map

be seen as a code smell "Alternative classes with different interfaces"? How to create a ImmutableMap

running LSP that does not yet contain code smells?

+4


source to share


1 answer


In my opinion, it ImmutableMap

should be implemented Map

. It would be a bad idea not to implement Map

it as there are many methods that take Map

as an argument and only use it in read-only mode. I do not believe that this violates Liskov's subscription principle, because the contract Map

does not make it clear what put

is an optional operation.

It is not ideal that the implementing classes Map

should implement put

, but the alternative would be to have a complex hierarchy of interfaces, each of which would include only a subset of the possible additional methods. If there are optional methods n

, there must be 2^n

interfaces for all combinations . I don't know the meaning n

, but there are some non-obvious optional operations like whether the Iterator

returned map.entrySet().iterator()

operation supports setValue

. If you combine this hierarchy with the hierarchy of interfaces and abstract classes, which are in fact already exist (including AbstractMap

, SortedMap

, NavigableMap

, ConcurrentMap

, ConcurrentNavigableMap

...), you will have a mess.



So there is no perfect answer to this question, but in my opinion the best solution is to create an ImmutableMap

implementation Map

and ensure that every method you write with Map

as an argument explicitly documents whatever properties Map

should have and exceptions that were thrown if the wrong type was passed Map

.

+1


source







All Articles