On Aug 15, 2017 8:01 PM, "Gilles" <gil...@harfang.homelinux.org> wrote:

Saying that making record mutable is "breaking" is a bit unfair when we do
> NOT document the mutability of the class in the first place.
>

I'm stating a fact: class is currently immutable, change would make it
mutable; it is functionally breaking.
I didn't say that you are forbidden to do it; just that it would be unwise,
particularly if it would be to save a few bytes.


Exactly.

TL;DR. This is almost always a breaking semantic change; the safest  ways
of implementing it are binary breaking; it's unlikely to have a major
performance impact; it might be better to create a new API module for
enhancements, with current package as legacy or implementation.

If a class previously exposed no mutators, adding one is usually a major
change. This is especially true for final classes, but it still affects use
cases where an instance is owned by another class, which may rely on the
lack of mutability to avoid making defensive copies.
Of course, a final class that has a  package-private getter  to a shared
copy of its backing array could be considered to be sending mixed
messages...

It is possible that a mutable class might have significant performance
advantages over an immutable one beyond saving a few bytes. For example, if
the updates are simple, and depend on the previous value of the cell, then
a mutable version might have better cache behavior. If there's other
sources of cache pressure this might have a higher than expected impact.
The costs of copying the original values might also be relatively
significant.

For an ETL use case these issues are unlikely to be limiting factors; for a
start, there's a non-zero chance that a  CSVRecord was extracted  by
parsing a CSV file. Also a transform will require conversion to some sort
of Number (or String allocation).

The current API doesn't easily support adding alternate implementations of
the relevant types. Implementation classes are final, and important  return
types are concrete.

One solution might be to treat the current code as almost an implementation
module, define a separate API module, and add extra interfaces and
alternate  implementations to support  the target use case (mutable
records, streams, reactivex, transform functions or what have you).

Simon

Reply via email to