On 13/01/10 13:03, Francois wrote:
Le 13/01/2010 12:24, Matthew Swift a écrit :
Hi Emmanuel,
I'm just giveng my point of view about the following, I don't think I
can be relevant elsewhere:
Also, I strongly believe that DNs and RDNs and AVAs should be immutable
objects (as well as any other low level API type). What do you think?
I will go further : DN, RDN and AVA should be immutable, but Attribute
should be immutable too, and Entry should have at least an immutable
DN (and facilities to copy an entry with a new DN or ParentDN at
factory level).
For attribute, the rationnal is that one replace attribute by a new
one most of the time, and it's much easier to deal with immutable
attribute - that's one of the aspect of UnboundId SDK that I prefer.
I understand very well why you think Attribute could be immutable. In
fact, I went to great lengths to convert our Attribute API in OpenDS
server so that it was immutable in order to be able to optimize for the
common case (single valued attributes) and to avoid defensive copies.
The result was a 4x performance improvement in the server (!). However,
this did introduce some pain - any code in the server which tried to
modify an attribute became more complex. For example, I had to implement
an AttributeBuilder class to facilitate incremental construction of
Attributes.
In fact, ironically, I heard on the grape vine that Neil Wilson was
pretty impressed with the improvements that we got and this is why
UnboundID's Attribute class is immutable (except that Neil, being
notoriously bad at API design, has not made it fully immutable - look at
all those arrays with Javadoc warnings saying that you are not allowed
to modify the content. Very suspect!).
I thought about this long and hard for the OpenDS SDK and decided that a
client API with an immutable Attribute would not be very easy to use.
Many client apps will want to create and modify attributes and we should
make it as easy as possible. In addition, I think that it is very likely
that some users of the SDK (including the server itself) will need to
have different types of Attribute - in other words, they'll need to
sub-class Attribute (e.g. in order to create lazy decoded Attributes,
virtual Attributes, copy on write, synchronized, etc). By implication
any class which is non-final is not immutable since a sub-class could be
implemented which breaks the contract (I realized that I had made this
mistake in the server since our Attribute class is in fact an interface).
Therefore the approach I took in the OpenDS SDK was to copy the
Collections API approach. Provide a high-level interface providing
read/write operations (side note: an Attribute can be thought of as a
Set of values) and then provide an "unmodifiable" adapter as per
Collections.unmodifiableSet. Then we get the best of all worlds -
including the ability to avoid defensive copies by implementing getters
which return "unmodifiable" Attributes (the OpenDS SDK implementation
also optimizes for the case where an attribute is single valued even
though it is mutable).
For Entry's DN, it's linked to the fact that DN are almost IDs for
entries. So, the semantic of such an operation is much likely in two
cases:
- create a copy of an entry with another DN (change RDN but perhaps
not parentDN)
- move an entry (only the parent DN change).
These two cases (I hope I don't forget other ones) are easily
fulfilled througth factory-like method support.
[Disclaimer: the OpenDS SDK Entry API is not finalized yet in case
you're tempted to look at it. IMO it's way to bloated still and contains
some strange methods]
I agree that Entry DNs should not in general be modified, but I think
preventing clients from doing this is a bit of an artificial constraint.
There's no hard reason I can think of why you would want to prevent
modification.
In addition, if Entry is an interface (as it is in the OpenDS SDK) then,
like Attribute, adapters can by provided which render some Entry
operations unsupported. For example, you could have a Collections-like
unmodifiableEntry method or even a unrenamableEntry in order to address
the requirement above.
Matt