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?
source to share
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
.
source to share