def showPage() {
// [. . .]
def b = new UiBlockSpecifier().ui {
diagram buildDiagram() (1)
tableFilter t, f (2)
}
taackUiService.show b
}
private UiDiagramSpecifier buildDiagram() {
// Always called (3)
new UiDisagramSpecifier().ui {
// Called only when needed (4)
def data = slowDataRetreiveMethod()
// Draw data Stuffs
}
}
Slow Code
When processing data is slow and the closure is lazy loaded, it is important to put slow code into the closure directly. This way it will only be executed if the closure is effectively displayed.
1 | buildDiagram is always called, even if the target to be drawn is the tableFilter , but the resulting closure is not called all the time |
2 | When sorting or filtering, only the table is drawn, not the diagram |
3 | Part always called |
4 | Called only if needed, slow code should be written here. |
Coding Style Guide for Grails Application Development
Here are some guidelines that should ease application maintenance:
-
Method Modifiers:
-
Use protected, private and final modifiers for methods in a controller that are not actions.
-
-
Coding Style:
-
Prioritize concise code, while maintaining clarity.
-
Employ
@GrailsCompileStatic
or@CompileStatic
annotations throughout the codebase.
-
-
Stateless Actions:
-
Always design actions to be stateless and avoid using sessions.
-
-
Controller Traits:
-
Refrain from using services to implement Controller traits.
-
-
@Transactional Annotation:
-
Reserve the @Transactional annotation solely for controller actions.
-
-
General Rules:
-
Use the final modifier when appropriate.
-
Adhere to the DRY (Don’t Repeat Yourself) principle.
-
Keep the scope of symbols the shortest to enhance code readability.
-
Opt for concise and meaningful local variable names.
-
Clearly specify public method parameters and member names.
-
By following these guidelines, you can maintain a clean and expressive codebase for your Grails application.
i18n
-
Do not centralize i18n, use gradle app module
i18n
folders for each app.
class Book {
String title
}
-
class name localisation "book.label = Libro"
-
class field name localisation "book.title.label = Título del libro"
-
To be efficient
-
do not translate too early
-
when you have a global overview, start translating
-
keep the most important label short, use the
default
namespace for them, specialized label can be long
-
-
Use convention for your i18n:
-
prefix with "default." everything that could be reused
-
do not prefix class name translated
-
In crew app, we use actions and domains specific property files (See Crew i18n folder)
-
Common i18n should be localized into Crew
app module or Server
, properties are not private to an app module.
Configuration
-
Use enum, in code, for configuration
-
Static is king
-
Groovy Enums are readable (more than XML, Json, Yaml …)
-
Security
-
Security-related code should be located near the point of influence
-
We do want to avoid centralization for all concerns
-
Create a new domain per needs, avoid cluttering
User
class -
Abstract concepts should be minimized for security purposes; static checks are crucial
-
-
-
Avoid complex rules that can’t be verified statically during compilation
-
Administrative rules must not rely on permission strings, a boolean value in an object is more explicit when testing in code.
Domain Classes
-
Avoid cyclic dependencies in domain (
User
⇒Cart
ANDCart
⇒User
) if domain classes belong to different app modules -
Domain classes should be barely minimal
-
No helper with external dependencies in domain
We can tell we are efficient if:
-
Small evolutions do not trigger a complete code rewrite
-
Incorporating new features is straightforward
-
Different concerns remain isolated, minimizing mutual influence
-
Things seem simple