Best Practices to be followed while developing Gra

2019-03-08 02:17发布

问题:

While developing a Grails application, what do you consider to be "best practices" and why? I'm not interested in a debate on best practices, but one or more statements backed up with a justification and/or a description of when the best practice applies and when it does not. I don't believe that there is one best way to develop Grails applications but that there are a number of guidelines that will lead to more maintainable applications with fewer bugs lurking in them.

My experience of Grails is that it offers so many capabilities that there is a temptation to use them all in a single application, which results in some of the worst spaghetti code that I have seen since I debugged a Fortran program with GOTO statements into and out of part of a DO loop.

We all know how Grails creates a place for domain classes, services, views, controllers, etc. What kind of functions belong in these places? What rules of thumb help you to do the right thing? What are Grails code smells?

回答1:

  1. Understand the Grails conventions. Grails is convention driven; and the conventions are how Grails can do a lot of its magic for you. Views should just be views. Controllers should just be controllers. Services and Model objects should contain all of the logic of your application. This means the when you click a link, or invoke an endpoint, you call into a Controller. The controller will invoke a service (which might in turn invoke other services) and give a concise response. The service will return model objects or data to the controller, which will simply render an appropriate response. Services are transactional, so anything that hits the database should go in a service.

  2. Test. Test. Test some more. Having tests is the best way to ensure you can add functionality without breaking new functionality, i.e. that your project is maintainable.

  3. Dependency Injection. You need to put your components in the appropriate grails-app/folder. Services go into the services folder. Controllers go into the controllers folder. If you have a Thing model object, and you need a controller and service for it, then your controller and service should be named ThingController and ThingService. To get the ThingService into your ThingController, put def thingService in your controller, and grails will autowire it up for you. If you fail to follow naming conventions and the rules for where to put the various components, the autowiring might fail.

  4. Understand the underlying technologies, namely Spring and Hibernate. You are going to run into issues modeling your domain objects and getting them to work together. Grails really is a high productivity framework, but if you don't understand how Hibernate works, you are going to get lost easily when trying to get your persistence to behave the way you want it.

  5. Groovy is not Java. A lot of Java knowledge will serve you well. But Groovy is a dynamic language and Grails has its own set of gotchas that stem from Groovy. You will run into runtime issues around typing in Grails that you largely avoid with Java. Testing helps with this.

These things seem obvious, but many questions arise around these issues.



回答2:

  1. Avoid the temptation to put lots of logic in the web layer. For views, strive make them as simple as possible. Put as much boilerplate in your layouts. Avoid conditional logic like the plague. Split out shared content into templates and g:render them. Build your own taglib for common UI elements.

  2. Similarly, keep your controllers as simple as possible. Inexperienced developers seem to have a habit of throwing everything in the controller, because it seems most obvious. Some hints: queries and object retrieval logic can go in domain objects. If you see withTransaction() and need transactional behaviour, it's a good candidate for a service. If you've got complex data binding, split it out into a command object.

  3. For domain objects, take advantage of the ability to override setters and getters to make properties easier to work with. Creating short named queries and chaining them together is an excellent way to decompose complex query logic. Anything that applies to a single object of that type with few dependencies should go in the domain object class. Keep the logic specific to that object, though. More complex business logic that deals with groups of objects belongs in services.

  4. If in doubt, it can go in a service. Services should be stateless. If you find you need to store state, you probably need a new domain object.



回答3:

What I can think of...

  1. Test as much as you can with unit tests, not integration tests. Unit tests are ways faster to run/debug and enforce low coupling better. Use mockDomain(), mockLogging() etc.
  2. Use grails console to test and explore your code in the wild. Embed a Groovy console into your web UI - it's an invaluable tool to examine insides of a running application.
  3. Do use domain objects to model domain logic. Moving domain logic to Services is a hangover of inconvenient persistence layers.
  4. Keep Controllers brief. If a logic can be expressed in a terms of a specific class, move the logic there or create a new class. Test it afterwards.
  5. Separate layers. Keep domain logic to domain classes. Keep presentation logic in controllers/views.
  6. transactional Service is not the only way to make a transaction. Invoking DomainClass.withTransaction{ ...a couple of lines here... } from Controller is pretty fine, as long as they obey to #4.
  7. Strive for perfection - unlike in Java, it's achievable :D Do know the technology. Use Builders, proper plugins, Commands, metaprogramming, whatever, to make your code shorter, more readable, groovier.


回答4:

  1. Develop re-usable parts of your application as Grails plugins. These plugins can be tested individually and will remove complexity from your main application(s). Consider publishing the plugins in the public plugin repository if you think others can benefit from them.

  2. Use the release (previously known as maven-publisher) plugin to deploy in-house plugins to your Maven repository.

  3. Make yourself familiar with the resources plugin for handling of static resources. This plugin is going to be a part of Grails 1.4 and will be used by many popular plugins.

  4. Don't be afraid to look into the source code of the third party plugins you're using or Grails itself for that matter (this has saved me so many times!). Grails and many of the most popular plugins host their source code on GitHub making it very convenient to browse the code, fork projects and contribute patches.