Nitin Kumar works as a Software Architect , predominately focus on Agile, TDD, Service Oriented Architecture, Grails and JEE. Besides working in software development, He writes technical articles and watch and study new technologies. He has been in IT for over 13 years and advocating on Craftsmanship, Domain driven development, TDD, Refactoring , Pair-Programming and lean development. He has expertise in high performance Java system and contributed to various open source projects. Nitin is a DZone MVB and is not an employee of DZone and has posted 13 posts at DZone. You can read more from them at their website. View Full User Profile

Grails Best Practices

04.04.2013
| 18629 views |
  • submit to reddit

Grails is designed to be an interactive agile based rapid development framework which advocates convention not configuration.

This article explained the usage and best practices around the Grails.

Domain-driven design

Always use domain-driven design: First create your basic domain model classes, and then use scaffolding to get them online. This will help you stay motivated and understand your domain better.

Use Test Driven Approach: Domain model test cases provide a great way of experimenting testing out your validations.

Validate: Use validators to keep your domain objects in order. Custom validators aren’t hard to implement, so don’t be afraid to roll your own if the situation demands. It’s better to encapsulate the validation logic in your domain class than to use dodgy controller hacks

Follow the Grails Convention

Follow Grails conventions: Grails is convention driven development which need to follow as per convention means Views should just be views. Controllers should just be controllers.

Service as Transactional: Keep the transactional part in service

Functional Logics: Functional logics will be implemented as part of Services and Model objects. This means pass the request to Controller and Controller in turn will invoke the service.

Dependency Injection

Grail is based on dependency injection on convention so we need focus on folder convention to put component on appropriate grails-app/folder and proper naming convention

Location Convention: Services go into the services folder. Controllers go into the controller’s folder.

Naming Convention: If you have a Xxx model object, and you need a controller and service for it, then your controller and service should be named XxxController and XxxService. Grail will auto wire based naming convention

Presentation/View

Use pagination: Paginating large datasets creates a much better user experience and improves overall presentation performance.

Use custom tags: Develop reusable custom tag for your UI. It will improve overall development productivity and enhance maintenance.

Use Layout smarter. Handle basic flash message display in your layout rather than repeating it for each view.

Pick a right JavaScript library. Choose an Ajax library that makes sense for the rest of your app. It takes time to download libraries, so minimize the number of libraries in play.

Use convention-based layout: Favor convention-based layouts over explicit Meta tags. Often a specific layout for one particular action can make things much more maintainable than doing meta-magic branching. Take advantage of Meta tag styles when you need to style a subset of pages for a controller, but use convention layouts for the rest.

Externalize config file: Always include an externalized config file, so that any configuration that needs to be overridden on production can be done without even generating a new war file

Prefer dynamic scaffolding: Always prefer dynamic scaffolding over static scaffolding.

Use Datasorce config: Use DataSource.groovy property file to configure datasorce

Re-use custom validators: All custom validators place in a shared validator’s file, to support re-usability of these constraints amongst other domains.

Avoid logic in web layer: We should avoid putting lots of logic in the web layer to make a clear separation between presentation layer and business layer.

Use BuildConfig.groovy: To install any plugin in your application, declare it in BuildConfig.groovy rather than using the install-plugin command.

Keep simple view: Make view as simple as possible and use service layer for business logics

Re use template and custom taglib: Split out shared content into templates and g:render and build custom taglib for common UI elements

Use layouts: Use layout for consistent look across the UI.

DRY: Keep your views DRY ("Don't repeat yourself"). Split the repeated content into templates.

Controller

Keep Controller thin: Don’t perform business logic, web services, DB operation or transaction within controllers. Keep the controller as thin as possible. The purpose of a controller is to accept incoming request, invoke domain or a service for a result, give the result back to the requester.

Use command object: Take advantage of command objects for form submissions. Don’t just use them for validation—they can also be handy for encapsulating tricky business logic. Understand data binding. Data-binding options in Grails are plentiful and subtle.

Use the proper naming convention: Use the standard naming convention of “<DomainClass>Controller”.

Use flash scope. Flash scope is ideal for passing messages to the user (when a redirect is involved).

Use errors object: Make use of the errors object on your domain class to display validation messages. Take advantage of resource bundles to make error messages relevant to your application use cases.

Apply filters. Apply filters when you need to selectively fire backend logic based on URLs or controller-actions combos

Services

A service is the right candidate for complex business logic or coarse grained code. If required, the service API can easily be exposed as a RESTful/SOAP web service.

Use for Transactional: Services are transactional by default, but can be made non-transactional if none of their methods update the persistence store.

Avoid code duplication - Common operations should be extracted and reuse across the application

Statelessness: Services should be stateless. Use domain object for state full operation.

Domain

Override setters and getters: Take advantage of the ability to override setters and getters to make properties easier to work with.

Decompose complex query: Assemble named queries by chaining to prepare complex query.

Restrict Specific logic to domain:Keep the logic specific to that object. More complex business logic that deals with groups of objects belongs in services

Use domain objects to model domain logic: Moving domain logic to Services is a hangover of inconvenient persistence layers

Don't mix with domain folder: Don’t mix any other common utility classes or value objects in the domain folder; rather they can go in src/groovy.

Use sensible constructors: Use sensible constructors for instantiating domain objects, to avoid any unwanted state and to construct only valid objects.

TagLib

Simple taglib: Keep a tag simple and break a tag into reusable sub-tags if required.

Should contain logic: Taglib should contain more of logic than rendering

Use multiple custom taglib: Use multiple custom taglib for better organization.

Plug in

Re-usable plugins: Construct re-usable functionality and logic parts of your application as independent re-usable Grails plugins which can be tested individually and will remove complexity from your main application(s).

Public plugin repository: re-usable plugin across the multiple applications could be published in the public plugin repository.

Use fixtures plugin : To bootstrap your data during development

Override plugin for small change: If you need to make a small change to the plugin you are using, then instead of making the plugin inline for this small change, you can override these files by following the same directory structure or package..

Use onChange: Use onChange, if your plugin adds dynamic methods or properties so that those methods and properties are retained after a reload.

Use local plugin repositories: Local plugin repositories serve several purposes such as sharing plugin across the applications

Modularize large or complex applications. Modularize large or complex applications using plugin to bring Separation of Concerns pattern.

Write functional tests for your plugins. For plugins to be reliable, you should write functional tests.

Testing

  Test Driven Development Approach: Grails advocates TDD approach means test first so it make ensure that your functionality covered.

Test Often: Test often so you get quicker feedback when something breaks, which makes it easier to fix. This helps speed up the development cycle.

Use test coverage: Maintain test coverage and avoid gap in test coverage as much as possible

Favor units’ tests over integration tests: As well as being faster to run/debug they enforce loose coupling better. An exception is for service testing, where integration testing is generally more useful.

Use continuous integration (CI). Use a continuous integration (CI) to automate the build and deployment across various environments.

Use grails console to test: Use grails console to test, embed a Groovy console into your web UI - it's an invaluable tool to examine insides of a running application.

Deployment

Use release plugin: Use the release plugin to deploy in-house plugins to your Maven repository.

Use continuous integration (CI). This is almost mandatory for any team bigger than one to catch those bugs that appear when changes from different people are merged together.

Automate the process: Write scripts to automate any repetitive task which reduce errors and improve overall productivity.

Familiar with resource plugin: Make yourself familiar with the resources plugin for handling of static resources

Summary

Grails’s main target is to develop web application quickly and rapidly in agile manner. Grails is based on Convention over configuration and DRY(Don’t Repeat yourself) and not only that we can re-use existing java code in Grails that give power to build robust and stable web application in quickly and rapid manner
Published at DZone with permission of Nitin Kumar, author and DZone MVB.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Tags: