Java vs. Groovy: How dynamic should we be?

I’ve been working on Java projects now for more than 10 years, have written, read and refactored hundred thousands of lines of code and I can say that I have a quite good feeling about good and not so good code in Java.

Now we’re doing some projects with Grails which takes heavy advantage of the dynamic features of Groovy. Now, after writing some code, we did a short review together, and to be honest there are some things that I really do not understand in this dynamic world:

def v = myService.calculate informationVersion, subjChildren

vs.

BigDecimal v = myService.calculate(informationVersion, subjChildren)

Call me a grey-haired, old-fashioned zombie, but does it really help me to not write the brackets here? And to write a def instead of BigDecimal? I mean, there are so many statistics that the ratio of writing to reading code is about 1:5 or 1:10, so why not investing the few bytes of additional source code in a better readability. And despite of that, the compiler can help me so much more in doing static plausibiltiy checks, if I’m calling methods that exist or not. I also do not type everything with java.lang.Object

What I also do not really understand is the sense of omitting the return statement. Consider the following code snippet:

def getChartData(def informationVersion, def informationStructureElement) {
  if (subjChildren && objChildren) {
    BigDecimal subjValue = myService.getComputedValue(informationVersion, subjChildren)
    BigDecimal objValue = myService.getComputedValue(informationVersion, objChildren)
    [subj: subjValue, obj: objValue] as JSON
  } else {
    null
  }
}

I do understand that the line [subj: subjValue, obj: objValue] as JSON is a return-statement; but if someone writes an additional statement after the else-clause (even if it’s not a return-statement), then this line is not a return statement any longer and therefore the method would be changed. I simply do not see any advantage in omitting the return keyword here.

It somehow reminds me about a very bad habit that I can hear from children from the age of 5 to 12 here in Austria from time to time. They say something like:

Kann ich bitte ein Wasser?

which means something like

Can I please some water

They think that it’s not required to use a verb in that sentence as it’s obvious that they want to have some water and not look at it or something.

Anyways, I can’t say that all of the language features of Groovy or similar other languages are bad; I do see advantages when doing things like that:

SortedSet<Customer> findCurrentContracts(Customer c) {
  Contract.where {
    customer == c
    begin <= new Date()
    end >= new Date()
  }.findAll() as SortedSet<Customer>
}

or

SortedSet<Location> findCurrentLocations(Customer customer) {
  findCurrentContracts(customer)*.location as SortedSet<Location>
}

instead of doing a manual nullpointer-check.

Same for using closures:

def queryClosure = {
  condition {
    contract {
      eq 'customer', customer
      if (location != null) {
        eq 'location', location
      }
    }
  }
  between 'end', dateFrom, dateTo
}
 
return Delivery.createCriteria().list(paginationParams, queryClosure)

But for the things mentioned above – I’m sorry I do not think this is good or makes anything better. When I think of big projects with more than 100 kLoc then it is so important to have code that can be well understood and easily refactored if required. Of course this is also a matter of the used tools (Intellij has much better support for Groovy than Eclipse, i.e.), but in the end there are also many many issues that also Intellij can’t check statically and then you run into issues at runtime.

Features like GORM from Grails are great, and compared to plain Hibernate or JPA-Entities this indeed ensures better readability. But not everything of the possibilities I have with dynamic features ensures more readability or maintainability so I think that one should really be careful with those features.

What do you think?

Vorheriger Beitrag
Langjähriger Mitarbeiter geht in den Ruhestand
Nächster Beitrag
Catalysts ist der beliebteste Arbeitgeber Österreichs

Related Posts

JPF Part 1 – A lightweight alternative to OSGi?

When developing web applications it has always been a challenge how to plug in customer specific extensions and integrations without invading the inner guts of the web application too much. This not only concerns the source code, it is quite easy to keep customer specific sources out of the application’s trunk, the main problems usually arise when thinking about deployment strategies

Weiterlesen

9 Kommentare. Hinterlasse eine Antwort

We chose to introduce programming conventions in our Grails projects as especially junior devs were a bit too “enthusiastic” about Groovy’s dynamic language features 😉 This included explicit type declarations (instead of “def”), using the return statement, meta-programming code only when absolutely necessary (e.g. dynamically adding methods to certain classes), etc.

But there are times when those dynamic language features – including dynamic typing and duck typing – come in very handy. For example, GPath is independent of the underlying data format which could be JSON, XML etc. or creating a project-specific DSL can be worth the effort too and is easily done in Groovy.

I guess the more powerful a language is the more the project team needs to introduce mechanisms to ensure a certain degree of code quality.

Antworten

I understand why you are feeling that way Klaus and I guess some is because you are grey-haired 😉

As Andre pointed out I think that every team has to create some rules for Groovy projects and stick to them. These rules have to be more specific and strict than code style rules for Java applications. I am not a big fan of leaving out all the brackets too.

Still Groovy allows a lot of nice ways to write less code that is better to read than the Java equivalent.

I can only agree with the last sentence of Andre and as Uncle Ben in Spiderman said: With great power, comes great responsibility 😉

Antworten

Groovy gives you new options.

Writing
def x = …
tells the reader that he doesn’t need to care about the type of x.

Writing
MySpecialType x = …
tells the reader that he should be concerned about the type.

For understanding code, it actually helps much to know where the type is essential and where it is not.
In Java, it always looks as if the type was essential, even when it isn’t.
This puts more burden on the reader.

It is a beginner’s error to omit type declarations where they are essential.
It is frustrating to read through lengthy type declarations (esp. with Generics) only to find that they are not essential.

Antworten

@ Dierk König

ACK – in the application domain model (I am not talking about the Grails domain class ;)) I would consider explicit typing as a must, whereas “clue code” in Grails controller method implementations might profit from a more dynamic kind of code (e.g. when mapping between request parameters and the model) in terms of readability and reusability.

That guideline worked great for us in our projects, but as you’ve said – the point is that Groovy does not force the one or the other direction.

Antworten

Very informative!

And i agree with you Klaus. I think that’s one of the reasons why C# is so awesome, because you can use all those awesome features if you want to.

Antworten

@ Christian Bartsch be careful mentioning that thing in a Java discussion 😉

Antworten

Klaus, the examples you’re discussing have little to do with static vs. dynamic but are about syntax.
You can have closures, type inference for variables, etc in statically typed languages (such as in Scala or C#)

IMO the relaxed syntax and the dynamic typing are two separate things.

Groovy takes away many of the syntactic restrictions you have in Java, so concerning coding style, you’re left more on your own when you’re using Groovy, just as Andre and Tom pointed out.

Dynamic languages are about the compiler not enforcing the types, so it’s also less strict. Which again leaves you with more freedom/power, and again more responsibility :). What the compiler checks for you in Java, you have to ensure with tests (or other tools) in Groovy.

The larger your projects, the more rules you’ll want to enforce for uniform code, so you’re probalby better off with Java for these (but there are certainly use cases for groovy there as well … e.g. gradle, other tooling, perhapt unit tests).

I think both Groovy and Java have their place … on my part, I’ll use Groovy for the upcoming CCC 😉

Antworten

@ Thomas Einwaller haha yes but i can’t be the only one who loves lambda expressions and LINQ and all those other awesome stuff and wishes too see them one day in the release notes of a Java version (one can dream 😉 )

Antworten

Christoph, you are right of course, most of the things have nothing to do with dynamic and static binding, and actually I first wrote the blog entry itself and was then searching for a fancy title… well that was the optimum that came out to me 😉

Antworten

Schreibe einen Kommentar zu Christian Bartsch Antworten abbrechen

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.

Bitte füllen Sie dieses Feld aus
Bitte füllen Sie dieses Feld aus
Bitte gib eine gültige E-Mail-Adresse ein.
Sie müssen den Bedingungen zustimmen, um fortzufahren

Menü