Mutable objects have their issues, and yet this is a common and popular paradigm in DSL design. I guess however the point with a DSL is that it is so simple and limited that it compensates for the potential risks. Similar to the dynamic versus static language argument.
Now there are ways to reduce the risk. If I remember correctly, one pattern commonly used in the DSL book was to remain strict with model objects, but slack on model builder objects. In this case the Node and Person objects are model objects, and we would put the fancy DSL stuff into a separate class, not as a static method of the Person class. This can help conceptually separate the solid and reliable model from the convenient DSL. On a separate note, perhaps I'm just being slow, but I don't see the aspects of the code below that would be disabled by a mutable builder? Is it the final on 'friends'? That keyword should not stop modifying the contents of friends. ANd you code below does not expose the friends instance to outside influences, so no-one can modify it anyway. What am I missing. On Wed, Jun 23, 2010 at 8:15 PM, Tobias Ivarsson < tobias.ivars...@neotechnology.com> wrote: > Because mutable objects are evil. It would for example make it impossible > to > write classes like this: > > class Person { > private final Expansion<Node> friends; > Person(Node node) { > this.friends = node.expand( FRIEND ).nodes(); > } > Iterable<Person> getFriends() { > return persons( friends ); > } > Iterable<Person> getFriends( final int minimumAge ) { > return persons( friends.filterNodes( new Predicate<Node>() { > public boolean accept(Node friend) { > return minimumAge >= (Integer)friend.getProperty("age"); > } > }) ); > } > static Iterable<Person> persons( Iterable<Node> persons ) { > return IterableWrapper<Person, Node>( persons ) { > protected Person underlyingObjectToObject( Node person ) { > return new Person( person ); > } > } > } > } > > This might be an acceptable loss though. This could be a case where it is > ok > to reuse the same object and mutate the internal state. It's something to > think about... > > -tobias > > On Wed, Jun 23, 2010 at 7:10 PM, Craig Taverner <cr...@amanzi.com> wrote: > > > Why not have includes() return the same instance with internal state > > changed, then the various call options are equivalent. > > > > On Jun 23, 2010 6:41 PM, "Tobias Ivarsson" < > > tobias.ivars...@neotechnology.com> wrote: > > > > On Wed, Jun 23, 2010 at 6:10 PM, Craig Taverner <cr...@amanzi.com> > wrote: > > > > > > (I also noticed that r... > > I get that feeling as well. Another feeling I get with includes() is that > > it > > might be possible to do the following: > > > > > > Expansion<Relationship> expansion = startNode.expand( KNOWS ); > > expansion.includes( LIKES ); > > expansion.includes( LOVES ); > > for (Node node : expansion.nodes()) { > > ... > > } > > > > With includes() one gets the feeling that the above would expand LOVES, > > LIKES and KNOWS relationships, but it will in fact only expand KNOWS > > relationships. With and() I don't think that mistake would be as common. > > > > Cheers, > > -- > > > > Tobias Ivarsson <tobias.ivars...@neotechnology.com> > > Hacker, Neo Technology > > www.neotechnology.com > > Cel... > > _______________________________________________ > > Neo4j mailing list > > User@lists.neo4j.org > > https://lists.neo4j.org/mailman/listinfo/user > > > > > > -- > Tobias Ivarsson <tobias.ivars...@neotechnology.com> > Hacker, Neo Technology > www.neotechnology.com > Cellphone: +46 706 534857 > _______________________________________________ > Neo4j mailing list > User@lists.neo4j.org > https://lists.neo4j.org/mailman/listinfo/user > _______________________________________________ Neo4j mailing list User@lists.neo4j.org https://lists.neo4j.org/mailman/listinfo/user