Webinar: I've Seen Grails® Code You Wouldn't Believe
June 15, 2018
"I’ve seen Grails® code you wouldn’t believe …
… or how to properly write maintainable Grails applications"
Over the years, Iván López has built a lot of different Grails applications, and he's learned from his mistakes. As an experienced Grails developer, Iván now possesses a vast amount of knowledge about how to avoid problems and pitfalls in future projects.
For over a year, Iván has been sharing his hard-won expertise with others, so they can benefit from his experience and write more maintainable code that's easy to read and modify.
In this 1-hour webinar, Iván walks you through code examples and demonstrates how to adapt them to best practices. You'll also see code examples that you should never, ever write, along with alternative solutions that will significantly improve your applications.
Iván says, "I promise no developers were harmed in the making of this talk."
The following topics are covered in this webinar:
- Best practices for writing maintainable and testable Grails applications
- How to detect bad code and tips for turning it into good code
- Strategies for avoiding common pitfalls when writing Grails applications
This webinar is an excellent learning opportunity for Grails developers who have had problems adding new features or maintaining their Grails applications and would like to improve their speed, efficiency, and debugging skills.
We had a lot of great questions at the end of this webinar. Here are Iván's responses to the questions we didn't have time to answer.
Q: Can you just define as many UrlMapping files as you wish in your webapp's grails-app/conf, as long as they have different names but end with UrlMapping.groovy?
A: Yes. Take a look at this commit in a sample project I've created for an example.
Q: Any best practices regarding withSession / withNewSession?
A: My best advice is to try not to use them. In most cases, you can create regular services and annotate them with @Transactional. In the other few places in which you need them, I almost always use withNewSession because there is no session available. In any case I try to avoid this as much as I can.
Q: Is it recommended to write business logic always in service layer?
A: Yes it is. Think about this. Imagine that you're creating a regular Grails application that renders GSPs pages, and also you want to create some RESTful or SOAP endpoints. If you write all your business logic in services, the only thing you need to do is call those services from the different endpoints: "regular" controllers, RESTful controllers, and SOAP endpoints.
In these 3 controllers you're dealing with a different transport/communication layer and returning the same thing, but in a different format: HTTP to render HTML, HTTP to return JSON, and HTTP to return SOAP. Once you validate the parameters in these layers (and you can also share the validation logic using command objects), the only thing you need to do is call the same service with the parameters needed.
What I always do when developing new features in a Grails application is start with the services. I don't think about controllers, just services. This way, I can think in terms of my business logic: "I need to receive these parameters, and I need to return this other thing."
Then I use TDD to develop the service, so I make sure that everything works.
After that, I go to the controllers layer, write command objects (with tests), and then write the controllers that call the services I finished in the previous step. As I already developed (and tested) my business logic when I created the services, I know that everything will work, and I just need to pass the appropriate parameters to the services.
Finally, when everything is done, I start up the application to make sure that everything works as expected (and it should because I have tests for everything).
Q: I’ve noticed a lot of auto-generated code when I’m single stepping through code (e.g., transactional wrappers). Any advice on best practice for avoiding this kind of overhead?
A: Most of that code is because of the Spring Framework. Since Grails 3, we rely a lot on AST transformations and traits to generate code during compilation to avoid that overhead.
For example, the Grails @Transactional annotation is applied at compile time vs. Spring @Transactional that relies on runtime proxies. The "problem" is that both Spring and Hibernate use runtime proxies and runtime reflection, so you can't get rid of all those wrappers.
If you want to avoid runtime proxies, I would suggest you take a look at Micronaut. :)