I agree with Miroslav's comments that if you choose a good name and
good class hierarchy then many of the problems go away, his example
for file/directory paths is a nice one. Below is an extended example
along the same lines as Miroslav's.

In my own pet project I use the following interface:

public interface ImmutableValueConversions<I, V> {
  I toImmutable() ; // immutable copy or this if already immutable
  V toValue(); // deep copy
}

To give classes the ability to convert, by copying, back and forward
between Immutable and Value (mutable) objects, e.g. an Immutable and a
Value integer pair with a common base interface:

public interface Int {
  int get();
  ... other immutable methods
}

@Immutable public ImmutableInt implements Int,
ImmutableValueConversions<ImmutableInt, ValueInt> {
  private final int value;
  public ImmutableInteger( final int value ) { this.value = value; }
  public int get() { return value; } // written by compiler
  public ImmutableInt toImmutable() { return this; }
  public ValueInt toValue() { return new ValueInt( value ); }
  ... hashCode, equals, toString (written by compiler)
  ... other immutable methods, e.g. add
}

@Value public ImmutableInt implements Int,
ImmutableValueConversions<ImmutableInt, ValueInt> {
  private int value;
  public ImmutableInteger( final int value ) { this.value = value; }
  public int get() { return value; } // written by compiler
  public ImmutableInt toImmutable() { return new
ImmutableInt( value ); }
  public ValueInt toValue() { return new ValueInt( value ); } // deep
copy
  ... hashCode, equals, toString (written by compiler)
  // Mutating methods
  public void set( final int value ) { this.value = value; } //
written by compiler
 ... other mutating methods, e.g. setAdd
}

The interface Int is useful to provide a const-view of either an
ImmutableInt or a MutableInt. EG in Int itself:

  Int max( final Int other ) ;

Which can return either an ImmutableInt or a ValueInt (depending on
which one is the maximum).

This allows me to program primarily using Immutable objects with all
their advantages, but when required switch to mutable.

 -- Howard.

PS Above is a simplification, I am using an extended compiler that
performs more type checking and understands Immutable and Value as
types, not annotations (but the above is useable without an extended
compiler).

On Mar 14, 11:29 am, Miroslav Pokorny <[email protected]>
wrote:
> On Mon, Mar 14, 2011 at 2:44 AM, Fabrizio Giudici <
>
>
>
>
>
>
>
>
>
> [email protected]> wrote:
> > A parallel discussion at the Lombok mailing list revamped some thoughts and
> > doubts about immutability. I'd like have some feedback about it.
>
> > Given that immutability is a "turtles all the way down" thing ("turtleness"
> > in the following), a poster raised doubts about things such as File. File is
> > immutable for what concerns its internal state (the path), but all methods
> > that actually work on the related file don't always return the same values
> > (or do the same thing) because they refer to the actual file which is
> > mutable.
>
> > Such a class is regarded as mutable or immutable? Of course, I'm interested
> > in the practical purposes.
>
> > Curiously, the "anemic object" antipattern is something that would help
> > here. If you defined File only as a wrapper on a path, and FileSystem
> > another class which accepts a File as argument, you would have clearly
> > separated the mutable and immutable portions.
>
> > But I don't like anemic objects. When I can, I just separate the two parts
> > in two different objects, but they stay bound together. Referring to some
> > actual code that I'm not using in production but for some tutorial, I have
> > a:
>
> > FileModel fileModel = new FileModel("/foo/bar");
> > String path = fileModel.getPath();
> > String name = fileModel.getName();
>
> > and the above two methods are the only two specific methods of FileModel.
> > So far, it's anemic and immutable. Going on:
>
> > fileModel.as(Removable).remove();
> > long size = fileModel.as(SizedInBytes).getSize();
> > List<FileModel> children =
> > fileModel.as(Composite).findChildren().results();
>
> > That as() is my way to deal with DCI and Semantic models. In simple words,
> > it just recovers a "role" of FileModel by referring to its interface -
> > as(Removable) is a shortcut for as(Removable.class). All the roles in the
> > example above are simple, stateless objects that work on the real
> > filesystem. Clearly, I've separated behaviours: FileModel on its own
> > encapsulates the really immutable portion, while roles keep the remainder
> > behaviours. But there's no turtleness in FileModel, because there's only a
> > single level of turtles (i.e., fileModel.as() always returns the same thing
> > for each role, but the returned object is not immutable in the strict
> > definition).
>
> > There are variations on the theme. Some roles are de facto hardwired in
> > FileModel; others can be dinamically injected by the context. But once a
> > role has been injected into a FileModel instance, it stays forever.
>
> > How do you comment about immutableness of FileModel? As said, there's no
> > turtleness. It's enough to say that FileModel is not immutable?
>
> > PS Another related question is about equals() and hashCode()... Are two
> > FileModel instances with the same path, but possibly different roles,
> > equals()? I'd say not. But this is another question, and more related of the
> > broken definition of equality in Java.
>
> Firstly im going to say something a little different. Maybe the problem is
> the naming leads one to have problems grasping w/ what is actually
> represented and what state is held by FileModel. This of course means that
> FileModel.setLastUpdated() seems like an oxymoron, how can a File which
> includes a last updated property by immutable and yet the change works when
> the setter is called. For me when i see "Model" i think of a value object
> that holds exactly what it says and its much nicer for alots of the reasons
> we all know that it is immutable (concurrency, no defensive copying etc).
> After all valueObjects are an extension or aggregation of the primitives
> provided by the runtime which themselves are immutable (you cant change an
> int or a long, you can however calculate some new value and replace it).
> Thus continuing in that spirit value objects should always look immutable
> and be immutable.
>
> After all that maybe the answer is to start w/ a better name, something like
> FileSystemPath and still all the actions hanging off it.
>
> FileSystemPath {
>     String name();
>     String path();
>      void setLastUpdated(DateTime ...)
>
> }
>
> FilePath extends FileSystemPath {
>      InputStream read();
>      OutputStream write();
>     etc...
>
> }
>
> DirectoryPath extends FileSystemPath {
>     FilePath createFile( String name);
>    etc...
>
> }
>
> Building on the above, its quite obvious that the object holds the state
> that it is called after and that it really is immutable. It says its a Path
> thats what it holds. By avoiding the need to call it "File" it is more
> evident that it is not a "File" but the path to a File and thus all the
> actions thus hit something else instead of the internal state.

-- 
You received this message because you are subscribed to the Google Groups "The 
Java Posse" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/javaposse?hl=en.

Reply via email to