Monday, April 28, 2008

Groovy Ignores Scope

Let me start out with.. I like Groovy. I haven't used it extensively yet on any of my projects, but I have done odd jobs with it.

With that said, there seems to be an important issue with Groovy in my opinion and I don't understand why there aren't many posts about it, or why it's not mentioned in the documentation, or why it still exists... Groovy does not currently enforce scoping constraints.

Take the following for example:
class PrivateMethodClass {

private static String privateMessage = 'foo'
private static String getPrivateMessage() { 'boo' }

private String privateInstanceMessage = 'instanceFoo'
private String getPrivateInstanceMessage() { 'instanceBoo' }

private static void sayHelloStatic() { println('hello static') }
private void sayHelloInstance() { println('hello instance') }
}


If you were to attempt to call any of these private variables/methods in Java, outside of the PrivateMethodClass, you would get an error when attempting to compile. In groovy on the other hand, this is totally acceptable to do.

So in Groovy this:
class PrivateMethodClassTest {

public static void main(String[] args) {
println 'attempt to call static.'

PrivateMethodClass.sayHelloStatic()

new PrivateMethodClass().sayHelloInstance()

println PrivateMethodClass.privateMessage

println PrivateMethodClass.getPrivateMessage()

println new PrivateMethodClass().privateInstanceMessage

println new PrivateMethodClass().getPrivateInstanceMessage()
}
}

Yields:
C:\projects\grovvyScopingFlaw>groovy PrivateMethodClassTest.groovy
attempt to call static.
hello static
hello instance
foo
boo
instanceBoo
instanceBoo


There is a Jira issue for this at http://jira.codehaus.org/browse/GROOVY-1875 and it is supposed to be fixed in 2.0 if I'm reading the issue ticket correctly.

I debated about whether I should post about this or not as I thought this might be old news, but as I mentioned this to people around me who are very interested in Groovy, I got a lot of surprised responses. So there it is.

3 comments:

Gayle said...

Good thing to point out, Eric. I will rehash a point that Neal Ford made when he gave a talk on Groovy at the last Central Ohio Java User Group meeting... It may seem weird that Groovy ignores scope, but even in Java, through the use of Reflection, you can call those private methods and access those private data members if you really want to. You just have to work harder. So for that reason, you could think of private as a kind of documentation, in that it makes you have to work harder to get to it. So think of Groovy's private as a more loosely-enforced form of documentation.

Eric said...

This is true. Thanks for the comment. I guess I find that to be easier to rationalize in Java... You can BUT, you must go out of your way. You must go out of your way enough to where you're most likely not going to do it unless you really need to, and just widening the scope isn't something you want to do. In Groovy, on the other hand, disregarding the scope up front, seems to make the scoping modifiers meaningless.

Josh Brown said...

I agree, Eric. You have to know Reflection exists to use it, and I'd venture to say a lot of people don't even know about it. It's one of those "security by obscurity" cases - since some people don't know about it, making members/methods private is relatively secure. And hopefully the people who do know about Reflection are responsible enough to use it properly.

I do agree, Gayle, that Groovy is "a more loosely-enforced form of documentation," but I think it should be more strongly enforced. I guess we'll just have to wait until 2.0.

Thanks, Eric, for doing the research and pointing this out.