Groovy : Closures or Methods

2019-01-16 23:47发布

问题:

I've got into the habit of using Closures everywhere I can in place of regular methods, even when I don't need access to free variables. So, I will use this:

def addNumbers = { left, right -> left + right }

.. instead of this:

def addNumbers (left,right) { left + right }

Is this bad practice? I far prefer the extra power I get when using closures over methods, and I far prefer the syntax.

Thanks!

回答1:

I only use closures where I need them, i.e. I use methods by default. I do this because

  • Methods are simpler than closures. Closures have a delegate, an owner, retain access to variables that were in their local scope when created (what you call "free variables"). By default method calls within a closure are resolved by:

    1. Closure itself
    2. Closure owner
    3. Closure delegate

But this order can be changed at runtime, and a closure's delegate can also be changed to any object.

All of these factors combined can make some code that uses closures very tricky to grok, so if you don't need any of this complexity I prefer to eliminate it by using a method instead

  • A .class file is generated for each closure defined in Groovy. I have exactly zero evidence to support a claim that a regular method is more performant than a closure, but I have suspicions. At the very least, a lot of classes may cause you to run out of PermGen memory space - this used to happen to me frequently until I raised my PermGen space to about 200MB

I have no idea whether the practice I'm advocating (use methods by default and closures only when you need them) is widely considered a "best practice", so I'm curious to hear what others think.



回答2:

While all the things @Don says are true, I don't know that any of them are all that significant. You can override the delegate of a closure which can change execution, but unless you're passing the closure around (which you can't do with a method anyways) you don't really have to worry about any of those things happening. Playing with the delegate is a feature, not a liability.

As for a possible performance hit from extra class files, why are you using Groovy if you're that worried about performance?

My opinion is that it doesn't really matter. If you have a lot of people on your team that are old Java developers, they're probably going to dislike it when you use closures where a method will do. On the other hand, someone fluent in Groovy will get annoyed if you clutter everything up with methods when a closure makes more sense.

tl;dr - There is no hard and fast rule, instead you should exercise good judgement with an eye towards code readability.