
Why groovy
Being a Java developer, some time ago I began to look in the direction of other programming languages, and I was thinking about this far from me alone. Some of my acquaintances, who in their time had no small experience in developing for the Java platform, began to move resolutely along the rails (Rails), using Ruby accordingly, someone else is thinking about taming Python with an attachment to it in the form of Django. Enough books are being written on how a Java programmer can migrate to the world of dynamic languages. Can something stop us?
It so happened that not so long ago I had the opportunity to observe the development on Ruby & Rails from a chair next to my partner and even to pee myself, sometimes listening to criticism towards Java - style. As a result, I don’t know for sure yet, unfortunately or fortunately, but I wasn’t drawn out. Still, I didn’t want to leave, perhaps, by some standards, it’s not very big, but still the main thing for me is almost 3 years of experience with Java. At the same time, I can easily give a damn about a considerable part of the time spent studying AS3 / Flex, whose components were integral when writing applications that use streaming video technology. But, fortunately, this practice seems to be over.
This weekend I came across some article about Groovy, I just can not remember how it all began. After that, after seeing a couple of recorded conferences, this time Groovy definitely interested me. The language is designed for the Java platform and is the most popular of the other, dynamic languages ​​used in the JVM. We were pleased, of course, with the fairly simple integration with the components in my usual language, the ability to use familiar frameworks, work in the OSGi environment - all that really stops me from leaving the Java world, while giving the opportunity to write elegant code.
Well, there is enough water, otherwise it has already happened quite a lot, I’ll get down to business and try to explain why Groovy inspired me, the tour of which was one of my main classes for the last weekend.
Javabeans and groovy
After learning a bit of Java and knowing the basics of encapsulation, no matter in what order these two actions are performed, most of us are faced with the need to write JavaBeans - creating class fields and generating “favorite” getters / setters. In the IDE for this, it seems, even HotKey did. Below are JavaBeans in Java and Groovy, respectively.
//Java
import java.util.Date;
public class Employee {
private String firstName;
private String lastName;
private Date dateSince;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Date getDateSince() {
return dateSince;
}
public void setDateSince(Date dateSince) {
this.dateSince = dateSince;
}
}
//Groovy
class Employee {
String firstName
String lastName
Date dateSince
}
It turned out 31 line on Java against 5 on Groovy.
And this is without additional constructors with parameters, the writing of which in Groovy is not required at all:
def e = new Employee(firstName:'Ivan', lastName:'Petrov')
Tell me where is private or what is not always necessary to give the opportunity to change the state of objects (-seeters + constructor)? And this problem is solved with the annotation
@Immutable
import groovy.lang.Immutable;
@Immutable class Employee {
String firstName
String lastName
Date dateSince
}
Exceptions
Regarding this topic, you can argue for a long time ... As you know, in Java exceptions are divided into checked (checked) and unchecked (unchecked). In Groovy, however, all exceptions can be attributed to the unchecked class, that is, no one will force you to catch them when calling methods or indicate that the processing will be somewhere higher. Here you can think that after all we are not children and for this we do not need a warden. But at the same time, no one bothers to specify throws or to wrap code in try / catch blocks.
Delegation
To shorten the code, we often have to redirect method calls from a container class to one or more of its fields, producing some stupid and homogeneous text.
Below is a simple example showing a solution for this problem.
')
import java.text.SimpleDateFormat
class Event {
@Delegate Date when
String title, url
}
def df = new SimpleDateFormat("yyyy/MM/dd")
def gr8conf = new Event(title: "GR8 Conference",
url: "http://www.gr8conf.org",
when: df.parse("2009/05/18"))
def javaOne = new Event(title: "JavaOne",
url: "http://java.sun.com/javaone/",
when: df.parse("2009/06/02"))
assert gr8conf.before(javaOne.when)
Apparently, now it is possible to use methods of the
Date class without problems. The expression
gr8conf.before(javaOne.when)
seems quite logical, while maintaining the purity of the code.
An example, of course, is very primitive, but I think everyone will be able to reproduce in his head those moments in which this could help him.
Closures
There are no closures in Java, and it is impossible to say exactly when they appear, in Java 8, as planned or transferred again. In Groovy, you can use them now. I will not look at closures in great detail here, I think this is a topic for a separate article, but I’ll just give one example of how to reduce the code.
Suppose we have a list of workers (Employee), we need to choose from them a subset that meets a certain selection criterion: it can be a salary, age or department.
List getStaffWithMuchSalaryThan(List staff, double salary);
List getStaffYoungerThan(List staff, int age);
List getStaffByDepartment(List staff, Dept dept);
In each, about the same logic: run through the cycle, checking the satisfaction of the conditions. If it satisfies, add to the result list.
That is, in Java we have three methods of the form:
public List getStaffWithMuchSalaryThan (List staff, double salary) {
List result = new ArrayList ();
for (Employee e: staff) {
if (e.getSalary ()> = salary) {
result.add (e);
}
}
return result;
}
and so for each of the above two more methods. Of course, the problem of code design can be solved with the help of the Strategy pattern, but the number of lines will remain quite large.
Now let's try to write the same thing using closures.
//
def staff = [
new Employee(firstName: 'A', salary:500, age:20, dept:'K'),
new Employee(firstName: 'B', salary:700, age:30, dept:'K'),
new Employee(firstName: 'C', salary:1000, age:25, dept:'A2') ]
//
def getStaffWithCriteria(staff, criteria) {
result = []
for(e in staff) {
if(criteria(e)) result.add(e)
}
result
}
println getStaffWithCriteria(staff, {e -> e.salary > 600}) // 600
println getStaffWithCriteria(staff, {e -> e.age < 27}) //, 27
println getStaffWithCriteria(staff, {e -> e.dept == 'K'}) // K
// UPD: And without one bike, the code is simplified to:
println staff.grep {e -> e.salary> 600}
println staff.grep {e -> e.age <27}
println staff.grep {e -> e.dept == 'K'}
Thank you
theveryResult:
[B, c]
[A, C]
[A, b]Work with collections
Groovy makes it easy to work with lists, from creating them to iterating through them.
It is quite logical:
def list = ['a', 'b', 'c']
instead of Java code:
List list = new ArrayList ();
list.add ("a");
list.add ("b");
list.add ("c");
Suppose we just need to list the elements:
in java:
for(String s: list) {
System.out.println(s);
}
in groovy:
list.each {println it}
A Java loop will not be so attractive if we need access to the index of an item. Then one cannot do without a loop of the form presented below, or by introducing an additional variable, while at the same time performing an increment operation on it within the loop:
for (int i = 0; i < list.size(); i++) {
System.out.println(i + " - " + list.get(i));
}
In Groovy, this task has a simpler solution.
list.eachWithIndex {e, i -> println “${i} - ${e}”}
Also, once everyone had to write code to display a delimited list, with the proviso that after the last element there should be no separator. And so, this is one eye-cutting condition to check whether the element is the last in the cycle.
The groovy code for this purpose is greatly simplified using the join method
list.join(', ')
produces the string:
“a, b, c”Build project
Those who are used to using tools to build projects such as Ant, Maven, instead of the built-in functionality of the development environment, you can advise to try Gradle. Despite my great love for Maven to build Java projects, Gradle for me looks much nicer. Unfortunately, in the framework of this article, everything that can be said good about Gradle does not fit. By the way, yesterday, December 19, the release of version 0.9 took place, including many changes.
Conclusion
Of course, this article does not pretend to be the title of the gurus' sayings or the general guide to use Groovy. More like just to share new experiences. But it would be very nice if further study of this language will allow you to remain committed to the Java platform, while introducing many dynamic features from Groovy. Here only a small part of how Groovy can help make the code simpler and more elegant was considered, but I hope that some readers will not stop at this and try many other goodies offered by this language. In conclusion, you can pay attention to the fact that Groovy is a young language and is currently developing quite actively in its community and partly due to investments from SpringSource. The de facto web framework for the language is Grails.
main sources
groovy.codehaus.orgwww.infoq.com/presentations/Transforming-to-Groovy (you can’t wait for a change of presentation pictures, you can safely press fullscreen on the video)
www.infoq.com/presentations/Industrial-Strength-Groovywww.asert.com.au/pubs/Groovy/Groovy.pdf