The Artima Developer Community
Sponsored Link

Weblogs Forum
Using Groovy Builders to Simplify Complex Object Hierarchy Creation

17 replies on 2 pages. Most recent reply: Jun 26, 2010 8:18 AM by Jeremy Meyer

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 17 replies on 2 pages [ 1 2 | » ]
Jeremy Meyer

Posts: 40
Nickname: jeremy1
Registered: Jan, 2008

Using Groovy Builders to Simplify Complex Object Hierarchy Creation (View in Weblogs)
Posted: Jun 26, 2010 8:18 AM
Reply to this message Reply
Summary
A closer look at how Groovy builders help with creational code in complex API's, using the Java3d API as a fun example.
Advertisement

This is not just a discussion about Java3d, it is a discussion about builders in Groovy and how they can ease our creational code. In my last blog, Java 3D Fun with Groovy, I showed an example of using the Java3d libraries via Groovy. The seamless integration with Java made it easy to use all of the Java3d API classes, but I whined that it was hard to create a 3d scene in code.

Actually, I should have been more specific. It was hard to create 3d scene in readable code, and it was hard to get an idea of the hierarchy of the elements of a 3d scene by looking at other people's code. This is not an unfamiliar problem, and one which Groovy has vastly improved with its builders. I want to illustrate them here.

Structure in Code

Even with a powerful API a lot of our time as software developers is spent just creating stuff. Data structures, domain classes, XML, GUI Layouts, Output streams etc. A recurring theme in the creation of all of these is the creation of an objects which contains objects. These objects might in turn have their own nested objects and so on. The problem with this, is that your typical programming language cannot know anything about the structure of our domain objects, and so our code looks nothing like our hierarchy. Say a customer object has an invoice object in it, or a teacher object has many student objects, when we are initialising our hierarchy, we invariably have to treat all of the objects as if they had the same hierarchical level.

Consider:
   Teacher t = new Teacher("Jones")
   Student s1 = new Student("Bob")
   Student s2 = new Student("Sue")
   t.addStudent(s1)
   t.addStudent(s2)

This looks a bit flat. 5 lines of code, 3 uses of the new keyword (which adds to the amount of text we have to read) and no sense of the hierarchical relationship between teachers and students. This is fine in such a simple case, but in a much more complicated case this code block would be horrible to read.

Wouldn't it be nicer to be able to do something like this?:

   teacher ("Jones") {
      student ("Bob"){}
      student ("Sue"){}
   }

This uses simple-to-read bracket notation, is much less typing and gives a sense of the hierarchy of the data.

This is what Groovy allows us to do with builders. We essentially have the capacity to create a domain specific language around the domain of "building our domain". If this sounds complicated, it isn't. It just means that we can use the minimum amount of syntax to specify the boiler plate tasks of creating object instances, whilst at the same time showing their parent / child relationships.

Groovy builders are an implementation of the GOF Builder pattern, but they are more than that. They make clever use of the powerful syntax and dynamism of the language to give you efficient creational code, cleaner than XML and much cleaner than just using vanilla Java code.

An Example

Another example of the recurring need to create structural data is XML. The Java DOM API lets us build XML documents, but the same problem applies, for example, to create the XML below:
   <?xml version="1.0"?>
   <teacher name = "Jones">
      <student name = "Bob">
      <student name = "Sue">
   </teacher>
We would need something like the following fragment:
   ..
   Element teacher = doc.createElement("teacher");
   teacher.setAttribute("name", "Jones");
   Element student1 = doc.createElement("student");
   Element student2 = doc.createElement("student");
   student1.setAttribute("name", "Bob");
   student2.setAttribute("name", "Sue");
   teacher.appendChild(student1);
   teacher.appendChild(student2);
   ..

Yech! Very noisy and very flat. We don't get a real sense of structure of the data from looking at the code, and we are wallowing in implementation details of the API, with method calls like setAttribute, appendChild and createElement.

Groovy supplies a MarkupBuilder() out of the box. Let's look at how we would generate the same XML as above using Groovy.

def builder = new groovy.xml.MarkupBuilder(writer)
   builder.teacher (name: "Jones") {
      student (name: "Bob") {}	
      student (name: "Sue") {}
   }

Definitely much cleaner and neater.

Looks too simple to work

It all looks a bit too simple to work, but in fact, if you look at my blog, Creating a Domain Specific Language with Groovy , you will see how you can use method interception and closure passing to create "pretend" methods and query their parameters, thus giving you the power to dynamically tailor behaviour. In this case, the methods "teacher" and "student" don't actually exist, but Groovy uses the calling mechanism to create the XML on the fly, as your code tries to call the methods. In the example above, it writes the resulting XML to the writer passed as a constructor parameter to the builder. This gives us an elegant way of constructing a structured XML document.

So what Else Can Builders Do?

I started this blog by saying that I would demonstrate how I could make simple Java3d scenes easier to render. Let me wrap this effort in a disclaimer from the start, by saying that the Java3d library is very complex, and I will demonstrate a simple builder that can create scenes using a subset of the API. The idea here is not so much to build a complete layer on top of Java3d, as it is to illustrate that with certain, complex API's, we can gain enormous power from creating thoughtful builders in Groovy. [As an aside, though, creating a library of builders around the Java3d API seems like a really exciting and fun project, so if anyone has knowledge of Java3d and is interested in a challenge, let me know!]

The Java3d 'Problem'?

To create a 'Simple Universe' scene in Java 3d, we need to build a fairly rich object scene graph. The Java3d library provides us with a rather nice "ColorCube" which is easy to work with and view, so the minimal code we need to create a simple universe, with a visible object in it, is this:
..
def universe = new SimpleUniverse()
def group = new BranchGroup()
group.addChild(new ColorCube(0.1))
universe.getViewingPlatform().setNominalViewingTransform()
universe.addBranchGraph(group) 
..

But this presents the same problem as the other examples. There is a hierarchy here, but we certainly can't see it in the code, and we are adding children and branch graphs to groups and universes, which looks very complicated. By default, we get this:

Which is a little boring so we should at least rotate it, so we can see it is a cube. This means doing the following:
   def cube = new ColorCube(0.3)
   def universe = new SimpleUniverse()
   def bGroup = new BranchGroup()
   def rot = new Transform3D()
   def trans = new Transform3D()
   rot.rotX 0.77 
   trans.mul rot
   rot.rotY 0.77
   trans.mul rot
   def tGroup = new TransformGroup(trans)
   bGroup.addChild(tGroup)
   tGroup.addChild(cube)
   universe.getViewingPlatform().setNominalViewingTransform()
   universe.addBranchGraph(bGroup)
This is not a Java3d tutorial, but you can see there is suddenly extra complexity here. It comes from the fact that to rotate something in a 3d scene, we have to insert a new object into the hierarchy, a TransformGroup. This transform group is given yet another object, a Transform, which can specify its rotation, scale and translation. It yields the slightly more interesting image:

A Solution

Let's look at the builder code that I can use to achieve the identical 3D scene hierarchy before I explain how I have implemented the builder:

   new Java3DBuilder().BranchGroup {
      TransformGroup (scale: 0.3, rotX:0.77, rotY:0.77) {
         ColorCube {}
      }
   }

That's it!! 14 lines down to 3! And look how intuitive it is by comparison. The BranchGroup clearly contains a Transform Group which has some parameters, and that in turn contains a ColourCube. Ok, this isn't magic, there is obviously some code needed to do this, but it is roughly 100 lines and it takes the form of extending an abstract class. The parsing logic is already there and so it really is easy to create a DSL which is intuitive to use, clean and simple. I also obtained a lot of leverage from the dynamicism of Groovy (features like dynamcic property setting, and constructor calling) and was able to implement some powerful default behaviour which covers a lot of the Java 3d classes that I haven't specifically considered.

Implementing a Builder

As I mentioned earlier, implementing a builder is just a question of extending an abstract Java / Groovy class. The full source is available here, and the full specification of groovy.util.BuilderSupport can be found in the Groovy documentation . The methods I was interested in are below:

public abstract class BuilderSupport extends GroovyObjectSupport {
   .. 
   protected abstract void setParent(Object parent, Object child);
   protected abstract Object createNode(Object name);
   protected abstract Object createNode(Object name, Object value);
   protected abstract Object createNode(Object name, Map attributes);
   protected abstract Object createNode(Object name, Map attributes, Object value);
   ..
} 

It should be fairly easy to imagine what happens here. Groovy will parse the builder code, calling the createNode method when it sees a new node name, and pass in the value and/or a map of attributes that it finds in the parameter list. In the example above, TransformGroup would be a new node and scale: 0.3, rotX:0.77, rotY:0.77 would be the attributes. When the close curly brace is reached, the setParent method is called with a reference to the parent and the child.

This means that when implementing these abstract methods we can decide on the creational behaviour, and build the hierarchy, which is what makes the model so powerful. Let's look at some of the highlights.

1. Dynamic Class Creation

Using a fairly standard Java classloading technique, I load the class specified in the builder. This means that the builder code need the user to specify the proper classname (e.g. "TransformGroup") but I didn't want to have to specify the full package name. To prevent this I chose the dynamic but slow and slightly repugnant option of appending some expected package names from the API and trying to load each class. This is not a good use of exceptions, and not my preferred option, but for now it keeps the builder code minimal. I have defined a list of packages in the code:
def packages = ['com.sun.j3d.utils.universe',
	'com.sun.j3d.utils.geometry',
	'javax.media.j3d',
	'javax.vecmath'] 

.. and provided the full package isn't specified (which I have allowed, to resolve any conflicting class names), I use the following to create the class:

   for (packageName in packages) {
      try {
         fullName = packageName + '.' + name
         cls = getClass().getClassLoader().loadClass(fullName)
      }
      catch (ClassNotFoundException e) {
         cls = null
      }
      if (cls)
         break
   }

2. Dynamic Property Setting

To obviate the need for huge switch statements, I can use Groovy's dymanic property setting to allow me to set attributes on the object. This means that as long as a valid property X exists (where there is a setX on the object), I can set it with the specified value. Since Groovy will throw an exception if the property doesn't exist, I can do a lot of the work with the code in the default case as below, and for the most part, don't need too much domain knowledge to implement that part of the builder:

def createNode(name, Map attributes) {
   def node
      switch (name.toLowerCase()) { 
         case 'transformgroup':
         node = buildTransformGroup(attributes)
         break
      default:
         node = createNode(name)
         attributes.each {key,val ->
            node.metaClass.setProperty(node,key,val)
         }
         break
      }
   node
}

Note the special case of the TransformGroup. More about that below.

3. Judicious Shortcutting, or Changing of Hierarchy

In general, we obviously want to use domain knowledge to ease our build effort. Here, since a TransformGroup always needs a Transform, I have combined them in my builder so that what looks like setting a property on a TransformGroup is actually setting it on the associated Transform. Under the covers this is creating two nodes with a parent child relationship, so what should be:

TransformGroup () {
   Transform3D (scale: 0.6, rotX:0.77, rotY:0.77) {
      ColorCube {}
}

Is actually more simply declared:


TransformGroup (scale: 0.6, rotX:0.77, rotY:0.77) {
      ColorCube {}
}

In the same vain, I have simplified the use of rotation of transforms. In Java3d, these need some vector calculation to combine them, but it is a distracting nuisance to create (and throw away) these vector classes during initialisation. In the special case of the TransformGroup, I used the powerful case statement in Groovy to simplify the use of rotx, roty or rotz. By default, though, I just delegate the setting of any TransformGroup property to its child Transform:
attributes.each {key,val ->
   switch (key.toLowerCase()) {
   case ['rotx', 'roty', 'rotz']:
      // invoke the method on the temp. transfrm and multiply together 
      temp.metaClass.invokeMethod(temp,key,val)
      transform.mul(temp)
      break
   default:
      transform.metaClass.setProperty(transform,key,val)
   break
   }
}

Experimenting With the Results

So, in about 100 lines of code, we have a builder which makes it very easy to play with the basic 3d universe. Because a lot of the build code is dynamic and generic, I can make use of many of the classes in java3d that I don't know anything about yet, so it really is a successful domain specific language. I can now experiment with the library using much simpler code.

For example, using a Cone is more complicated than the ColorCube because you need to specify a material for it. Also, putting two objects into our universe can be done in such a way that they can be rotated and moved independently of each other. So if I want to create a cube impaled on a cone, I can experiment with a small body of code that actually gives me a clue what it represents. Note that although this is a DSL, and looks somewhat declarative, it is in fact ordinary Groovy code, and so any valid Groovy statements can appear in between the node declarations.

..
builder.BranchGroup {
   TransformGroup (scale: 0.4, rotX:0.67, rotY:0.53) {
      ColorCube {}
   }
   TransformGroup (scale: 0.65, rotZ:0.22, translation: new Vector3f(0.1f,0.1f,0.1f)) {
      def appearance = new Appearance()
      appearance.setMaterial(new Material(green,green,green,green, 0.1f))
      Cone(appearance: appearance) {}
   }
}
..

Where to From Here?

There is a lot missing from this builder, but it wouldn't be very hard to add. As I said earlier, if you are interested, let me know. In general, there is nothing to stop you creating different builders to be used together, or nesting builders to create more complicated hierarchies. I hope I have convinced you that builders are a very important part of any API to provide, and failing that, a very good approach to creating a layer of abstraction that simplifies the use of existing API's.

References:

Download the code here.
GOF Builder Pattern
Groovy Builder Documentation


Chris Dams

Posts: 14
Nickname: chrisd
Registered: Sep, 2009

Re: Using Groovy Builders to Simplify Complex Object Hierarchy Creation Posted: Jun 29, 2010 3:28 AM
Reply to this message Reply
Actually, one does not need this at all for readable code. E.g., in C++ one would do

(new teacher("Jones"))
-> AddStudent("Bob")
-> AddStudent("Sue");

But apart from not being very useful, it can easily become harmful too. It suffers from the "use brain damaged toy langauge for things that could have been done in the programming language" anti-pattern. It shares this anti-pattern with the common practices of using a GUI GUI-builder and with the building of web pages from templates.

The problem occurs when it turns out that things were a bit more dynamic then initially forseen (i.e., always) and the use of the toy language develops into using "interesting" features and/or extending it by oneself with "interesting" extensions and/or massive amounts of code-duplication and/or duplication of long sequences of mouse clicks.

Jeremy Meyer

Posts: 40
Nickname: jeremy1
Registered: Jan, 2008

Re: Using Groovy Builders to Simplify Complex Object Hierarchy Creation Posted: Jun 29, 2010 4:26 AM
Reply to this message Reply
> Actually, one does not need this at all for readable code.
> E.g., in C++ one would do
>
> (new teacher("Jones"))
> -> AddStudent("Bob")
> -> AddStudent("Sue");

I am not sure what you mean by "in C++ one would do". By your code fragment above, I can see that a) there is no structure (i.e. no open close brackets to show the scope of Teacher), b) your AddStudent method takes a String, rather than an object (so you must have knowledge in your Teacher class about how to create Students) and c) your AddStudent method returns the instance of the Teacher on which it is called. I am not surprised you think this is an anti-pattern.

> It suffers from the "use brain damaged toy
> langauge for things that could have been done in the
> programming language" anti-pattern.

I am open to balanced arguments, but if you are going to be vitriolic, you need to at least present a sensible counter example. Your example above makes all sorts of assumptions.

> The problem occurs when it turns out that things were a
> bit more dynamic then initially forseen (i.e., always) and
> the use of the toy language develops into using

Forgive me, but this is something of a rant and one not really backed up by facts. I hate censorship and I don't like removing posts, so if you are prepared to present a decent argument for why you don't like builders and/or dynamic languages, I look forward to a healthy debate based on your experience and study.

James Watson

Posts: 2024
Nickname: watson
Registered: Sep, 2005

Re: Using Groovy Builders to Simplify Complex Object Hierarchy Creation Posted: Jun 29, 2010 6:57 AM
Reply to this message Reply
What's the advantage over this?
new Teacher("Jones")
  .addStudent("Bob")
  .addStudent("Sue")

Jeremy Meyer

Posts: 40
Nickname: jeremy1
Registered: Jan, 2008

Re: Using Groovy Builders to Simplify Complex Object Hierarchy Creation Posted: Jun 29, 2010 7:31 AM
Reply to this message Reply
> What's the advantage over this?
>
> new Teacher("Jones")
>   .addStudent("Bob")
>   .addStudent("Sue")
> 


Hi James,
please see my response above. Have a look at the more complex example lower down in the blog. Without a standard way to scale complexity, you would end up creating a lot of "build" logic into your hierarchy, which is exactly what we want to avoid, and exactly what the builder pattern is all about, (see the GOF link). With the builder, we could also change the way in which we build the hierarchy according to other criteria. So, your example above could be a "classroom" builder. How about an "examiner builder" for example, where the relationship with students happens in a slightly different way?

Jiri Goddard

Posts: 54
Nickname: goddard
Registered: May, 2007

Re: Using Groovy Builders to Simplify Complex Object Hierarchy Creation Posted: Jun 29, 2010 8:16 AM
Reply to this message Reply
Neat :) The only concern I have is that you have to understand the API anyway in order to write a decent builder, don't you? Looking at Groovy code brings up a question how Scala would fit this task...

Chris Dams

Posts: 14
Nickname: chrisd
Registered: Sep, 2009

Re: Using Groovy Builders to Simplify Complex Object Hierarchy Creation Posted: Jun 29, 2010 8:44 AM
Reply to this message Reply
> a) there is no structure (i.e. no open close brackets to
> show the scope of Teacher),

I attempted to show the structure by using indentation, but sadly the forum removed the spaces that I put in front of the lines that start with a "->". The indentation would show the structure.

> b) your AddStudent method takes a String, rather
> than an object (so you must have knowledge in your Teacher
> class about how to create Students)

This is a simple example (the more or less literal adaptation of what you showed). Sure, it can and probably should be extended in various ways. For instance, it could take a pointer to a Student instead. In more complicated cases one would apply various creational design patterns. These various creational design patterns have been known for a long time and I do not really understand why we would want to do away with them. Also, one would apply refactoring of similar code fragments to obtain clean and non-duplicated code.

> c) your AddStudent
> method returns the instance of the Teacher on which it is
> called.

This is an example of the technique of method chaining. Method chaining is useful if the same method is going to be called many times on the same instance. It is also used when writing text to files in C++. E.g., one writes.

cout << "Number of students: "
<< Teacher.GetNumberOfStudents() << endl;

> Forgive me, but this is something of a rant and one not
> really backed up by facts. I hate censorship and I don't
> like removing posts, so if you are prepared to present a
> decent argument for why you don't like builders and/or
> dynamic languages, I look forward to a healthy debate
> based on your experience and study.

Actually, the problems with the kind of design that you present were mentioned by me. One is essentially writing part of the application in another less powerful langauge. This can possibly contain syntactic sugar to write things faster and/or more beautifully but one gets into problems when one runs into the limitation of the less powerful language.

I never used the builder that you describe, but already mentioned that I expect exactly the same problems that one faces with HTML templates for webpages. I had to extend a web application for the creation of quotations based on choices that the user would make. There were quite a lot of HTML template pages for all the choices. Then there was the possibility of extending an existing product. In that case input boxes would be replaced by two input boxes where the first showed the current value for some choice and the second was editable and to be used to enter a new value. Because of this every template was duplicated and the part of the template that created the input box, was replaced by code to show two input boxes. Could this have been prevented by putting this logic in the code that handles the templates? Not really, there would sometimes be more differences between the two versions. I will spare you the details of how this design ended up with the triplication of all the template pages but such was the mess that I found. And that was not even the only problem with it. Yes, every template looked very nice and clear and syntactically sugered to the max. But almost all of them were code triplicated and adding a new page with choices in triple would be the most common extension to the application. Including adding some code for handling the results that would also be code triplicated.

I solved this problem for the most part by pulling the HTML template code back into the application and let the C++ code do the work of the creation of pages instead of the templates. The root of the problem is that the ad-hoc template language is not as powerful as the programming language and one pays a price for that and that that will get exponentially higher as the application becomes more complicated.

Chris Dams

Posts: 14
Nickname: chrisd
Registered: Sep, 2009

Re: Using Groovy Builders to Simplify Complex Object Hierarchy Creation Posted: Jun 29, 2010 8:48 AM
Reply to this message Reply
> What's the advantage over this?
>
> new Teacher("Jones")
>   .addStudent("Bob")
>   .addStudent("Sue")
> 


I was showing C++ code because that is the language that I speak best by far. The disadvantage of this code is that it would not compile in C++.

Jeremy Meyer

Posts: 40
Nickname: jeremy1
Registered: Jan, 2008

Re: Using Groovy Builders to Simplify Complex Object Hierarchy Creation Posted: Jun 29, 2010 1:01 PM
Reply to this message Reply
> Neat :) The only concern I have is that you have to
> understand the API anyway in order to write a decent
> builder, don't you? Looking at Groovy code brings up a
> question how Scala would fit this task...

Well, yes, you do, to do a proper job. But because of the dynamism of Groovy, it was pretty easy to do stuff like (propertyName: value) without knowing the API at all, with the knowledge that if I looked in the documentation, and found that a class had a particular property, (of if it had a particular child node of a different class) I could just experiment with them, but using the nicer syntax. I would love to hear how Scala would handle this. Bill!?

Jeremy Meyer

Posts: 40
Nickname: jeremy1
Registered: Jan, 2008

Re: Using Groovy Builders to Simplify Complex Object Hierarchy Creation Posted: Jun 29, 2010 1:18 PM
Reply to this message Reply
> I attempted to show the structure by using indentation,
> but sadly the forum removed the spaces that I put in front
> of the lines that start with a "->". The indentation would
> show the structure.
Yes, that can be very annoying. Try using the HTML tags. However, "showing" the indentation is not what I am talking about. {Teacher {student1} {student2}} shows structure, and there is no indentation. The difference is crucial. Python (and Make) use whitespace in the form of tabs to create structure, which works well if controlled, expected and used with a decent editor..

> This is a simple example (the more or less literal
> adaptation of what you showed). Sure, it can and probably
> should be extended in various ways.
I think you misunderstood. I don't think it should be extended. You are bringing build logic into your domain abstraction. This creates tight coupling and makes for very poor design.

> These various creational design patterns have been known
> for a long time and I do not really understand why we
> would want to do away with them.

Nobody wants to do that, hence the Builder, which is a GOF builder pattern. The point is that there is support built into the language, and you don't need to implement it yourself.

> This is an example of the technique of method chaining.

Again, I think you misunderstood. I know what method chaining is, I just don't think you want an AddStudent method returning a Teacher. This is weak cohesion and what I would call "poor affordance". Highly unintuitive, and limits what you can do with an AddStudent method.


> One is essentially writing
> part of the application in another less powerful langauge.

I am not sure what you mean by a less powerful language. What are your criteria for power in a language? Speed? This is not a useful measure. Languages should present powerful abstractions to aid with problem solving. If speed were the most important issue, lanuages like Java would never have lasted until CPU's caught up, and made them worthwhile, but they did.

Groovy is a more powerful language than Java or C++, but obviously much slower than either.

> but one gets into problems
> when one runs into the limitation of the less powerful
> language.
.. and for example these limitations would be? Groovy is a superset of Java for all intents and purposes..

> I will spare
> you the details of ..

too late, I fear :) No offense, but your argument is a religious one, and it sounds like you have already made up your mind, or perhaps you have heard bad things about dynamic languages, or Groovy. You should try them with an open mind.

James Watson

Posts: 2024
Nickname: watson
Registered: Sep, 2005

Re: Using Groovy Builders to Simplify Complex Object Hierarchy Creation Posted: Jun 29, 2010 2:17 PM
Reply to this message Reply
> > I attempted to show the structure by using indentation,
> > but sadly the forum removed the spaces
> ...
> Yes, that can be very annoying. Try using the HTML tags.

FYI If you use 'java' tags, Artima retains your whitespace. I've never understood why the 'code' tags do not.

John Zabroski

Posts: 272
Nickname: zbo
Registered: Jan, 2007

Re: Using Groovy Builders to Simplify Complex Object Hierarchy Creation Posted: Jun 29, 2010 3:51 PM
Reply to this message Reply
> Neat :) The only concern I have is that you have to
> understand the API anyway in order to write a decent
> builder, don't you? Looking at Groovy code brings up a
> question how Scala would fit this task...

In Scala, you would probably have a syntax transformation compiler plug-in that is injected after the parsing stage and before the naming stage. In this way, it does not matter what the syntactic representation of the Builder is. It could be a custom XML dialect like XAML, or JSON, simply whatever.

I thought about posting some code to demonstrate this, but did not want to (a) showboat (b) re-install Scala after not having touched it since shortly after 2.7.5 (when the plug-in architecture stabilized, IIRC).

Fred Finkelstein

Posts: 48
Nickname: marsilya
Registered: Jun, 2008

Re: Using Groovy Builders to Simplify Complex Object Hierarchy Creation Posted: Jun 30, 2010 1:49 AM
Reply to this message Reply
>> Again, I think you misunderstood. I know what method
>> chaining is, I just don't think you want an AddStudent
>> method returning a Teacher. This is weak cohesion and
>> what I would call "poor affordance". Highly unintuitive,
>> and limits what you can do with an AddStudent method.

I understand your viewpoint but what do you think about the fluent interface technique?

http://en.wikipedia.org/wiki/Fluent_interface

(even Martin Fowler seems to be curious about it)

I don't think that it limits what you can do with the addStudent method. What else could the addStudent-method return? There cannot be any failure during this operation, that's clear. So you can return what you want.

Besides I think the groovy features you introduced are pretty cool and worth experimenting with. It feels like a way of 'tightening' the language towards a specific context.

Jeremy Meyer

Posts: 40
Nickname: jeremy1
Registered: Jan, 2008

Re: Using Groovy Builders to Simplify Complex Object Hierarchy Creation Posted: Jun 30, 2010 4:47 AM
Reply to this message Reply
> I understand your viewpoint but what do you think about
> the fluent interface technique?

I like it. I am not sure it is a technique as much as a philosophy, though. If you are talking about method chaining.. see below.

> http://en.wikipedia.org/wiki/Fluent_interface
>
> (even Martin Fowler seems to be curious about it)

Well Martin has done more research into DSL's than anyone, in fact he popularised the term, so I would say that something like a builder DSL would be a preferable implementation of a fluent interface. He also might consider a fluent interface consisting of multiple chained methods to be a primitive type of internal DSL, but we would have to ask him.

> I don't think that it limits what you can do with the
> addStudent method.
..
> There cannot be any failure during this operation,
> that's clear. So you can return what you want.

This would certainly be true if objects were being passed in, but this is not a simple setXXX method. In the example provided it was primitive data (not objects) being passed in to the addXXX code, this would suggest that some creational knowledge about how to create a Student exists on the Teacher, which is poor cohesion. Builders remove that coupling. Also, traditionally we would return a reference or pointer to the object just created. I prefer: teacher.addName("Name").addStudent(StudentData d).addGrade(int i)
(i.e. addStudent builds and returns a student) to the less intuitive:
teacher.addName(n).addStudent(x).addStudent(y)

Of course if the x and y are object references, then you don't need to return students, and perhaps returning the teacher might work. Where does this lead though? Should and object return a reference to itself as the return value of all of its setters, then? That might be an interesting default implementation for a language, actually, but I worry that it would ultimately lead to misuse and equally hard to read code.

> Besides I think the groovy features you introduced are
> pretty cool and worth experimenting with. It feels like a
> way of 'tightening' the language towards a specific
> context.

Yes, that is a good way of putting it. I think there is an important distinction between having curly braces that show structure, and just indents (particularly ones which are checked by the standard language parser), and I really like the power of Groovy's property constructors (name: "George", age: "35"). That data is being passed straight through to the standard object construction mechanism, and doesn't need any domain knowledge in the owner object or parent. I honestly think it is a lot more than syntactic sugar, it is genuine power. But "tightening" is definitely a good way of thinking about the relationship between a language and an internal DSL that it implements. It suggests narrowing choices, and reducing scope of error.. all good.

I think DSL's tend to scare people, but people don't seem to realise that they have been using them for years. Tcl/Tk was one, RegEx is another.. the list is very long. They really just are more, cunning abstractions for known problems..

Jeremy Meyer

Posts: 40
Nickname: jeremy1
Registered: Jan, 2008

Re: Using Groovy Builders to Simplify Complex Object Hierarchy Creation Posted: Jun 30, 2010 4:55 AM
Reply to this message Reply
> In Scala, you would probably have a syntax transformation
> compiler plug-in that is injected after the parsing stage
> and before the naming stage.
cool!

>It could be a custom XML dialect like XAML, or JSON,
> simply whatever.

Ok, well it would be a dreadful pity to bring XML back into the fray..but how much work would it be, to create a parser which would handle something similar to the Groovy builder example above. Bearing in mind that I just implemented an interface (more or less)?

> did not want to (a) showboat

Please feel free to showboat!

> (b) re-install Scala after
> not having touched it since shortly after 2.7.5 (when the

Well I can only encourage you to dive in..!

Flat View: This topic has 17 replies on 2 pages [ 1  2 | » ]
Topic: plac, the easiest command line arguments parser in the Python world Previous Topic   Next Topic Topic: Do Career Plans for Developers Actually Damage an Organisation?

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use