tags:

views:

154

answers:

4

[Later: Still can't figure out if Groovy has static typing (seems that it does not) or if the bytecode generated using explicit typing is different (seems that it is). Anyway, on to the question]

One of the main differences between Groovy and other dynamic languages -- or at least Ruby -- is that you can statically explicitly type variables when you want to.

That said, when should you use static typing in Groovy? Here are some possible answers I can think of:

  1. Only when there's a performance problem. Statically typed variables are faster in Groovy. (or are they? some questions about this link)
  2. On public interfaces (methods, fields) for classes, so you get autocomplete. Is this possible/true/totally wrong?
  3. Never, it just clutters up code and defeats the purpose of using Groovy.
  4. Yes when your classes will be inherited or used

I'm not just interested in what YOU do but more importantly what you've seen around in projects coded in Groovy. What's the norm?

Note: If this question is somehow wrong or misses some categories of static-dynamic, let me know and I'll fix it.

A: 

Groovy does not support static typing. See it for yourself:

public Foo func(Bar bar) {
  return bar
}
println("no static typing")

Save and compile that file and run it.

Pablo Fernandez
The file will run, but if you try to pass a non-Bar to the function, it will give a `groovy.lang.MissingMethodException: No signature of method:`
Yar
that is at __runtime__ i believe
Pablo Fernandez
Not sure, Pablo: my understanding is that the bytecode produced by Groovy is different if you use the types or if you don't.
Yar
Yes, it statically assigns types to the method parameters.But it doesn't check the types on method calls until runtime.
slim
+1  A: 

I have seen type information used primarily in service classes for public methods. Depending on how complex the parameter list is, even here I usually see just the return type typed. For example:

class WorkflowService {
    ....
    WorkItem getWorkItem(processNbr) throws WorkflowException {
        ...
        ...
    }
}

I think this is useful because it explicitly tells the user of the service what type they will be dealing with and does help with code assist in IDE's.

John Wagenleitner
Thanks for that, that's kind of my thought too
Yar
+5  A: 

In my experience, there is no norm. Some use types a lot, some never use them. Personally, I always try to use types in my method signatures (for params and return values). For example I always write a method like this

Boolean doLogin(User user) {
// implementation omitted
}

Even though I could write it like this

def doLogin(user) {
// implementation omitted
}

I do this for these reasons:

  1. Documentation: other developers (and myself) know what types will be provided and returned by the method without reading the implementation
  2. Type Safety: although there is no compile-time checking in Groovy, if I call the statically typed version of doLogin with a non-User parameter it will fail immediately, so the problem is likely to be easy to fix. If I call the dynamically typed version, it will fail some time after the method is invoked, and the cause of the failure may not be immediately obvious.
  3. Code Completion: this is particularly useful when using a good IDE (i.e. IntelliJ) as it can even provide completion for dynamically added methods such as domain class' dynamic finders

I also use types quite a bit within the implementation of my methods for the same reasons. In fact the only times I don't use types are:

  1. I really want to support a wide range of types. For example, a method that converts a string to a number could also covert a collection or array of strings to numbers
  2. Laziness! If the scope of a variable is very short, I already know which methods I want to call, and I don't already have the class imported, then declaring the type seems like more trouble than it's worth.

BTW, I wouldn't put too much faith in that blog post you've linked to claiming that typed Groovy is much faster than untyped Groovy. I've never heard that before, and I didn't find the evidence very convincing.

Don
Great answer, thanks Don. I don't know about that blog post, but if I get some time to do some benchmarks, I'll post back here. It seems reasonable to me, and I think the bytecode is different depending on how you spec the variables.
Yar
+1  A: 

I worked on a several Groovy projects and we stuck to such conventions:

  • All types in public methods must be specified.

    public int getAgeOfUser(String userName){ ... }

  • All private variables are declared using the def keyword.

These conventions allow you to achieve many things.

First of all, if you use joint compilation your java code will be able to interact with your groovy code easily. Secondly, such explicit declarations make code in large projects more readable and sustainable. And of-course auto-completion is an important benefit too.

On the other hand, the scope of a method is usually quite small that you don't need to declare types explicitly. By the way, modern IDEs can auto-complete your local variables even if you use defs.

Victor Savkin
Very interesting. What's the advantage of using def for private vars instead of just declaring the type? You know it anyway and Groovy won't force you to cast.
Yar
If you have a local scope you knows the type of your variable and it looks better. For example: `def factory = PersonContactFactory.newInstance()`looks a bit clearer than: `PersonContactFactory contact = PersonContactFactory.newInstance()`This is the only reason why I prefer to use defs in a local scope. Anyway, your IDE knows the type of your variable and you don't have any static checking.
Victor Savkin