Grails 最佳实践

阅读数:5364 2012 年 5 月 11 日 00:00

我在 IntelliGrape 工作,这是一家专门使用 Groovy & Grails 进行开发的公司。本文是我们 Grails 项目遵循的最佳实践的基本清单,收集自邮件列表、Stack Overflow、博文,播客 IntelliGrape 的内部讨论。它们分为控制器、服务、Domain、视图、TagLib、测试和其他。

这里的建议是专门针对 Grails 2.0 的,尽管其中的大多数是多个版本都适用的。

控制器

  1. 不允许控制器充当其他角色。控制器的角色就是接受传入的请求、检查权限等、问 Domain 或 Service 要结果、将结果用所需的格式(如 HTML、JSON 或 XML)返回给请求者。要让控制器保持苗条。别让它执行业务逻辑、查询或更新。
  2. 如果一个控制器代表了一个单一的 Domain Class,使用标准的命名公式“<DomainClass>Controller”为控制器命名。
  3. 避免代码重复 - 通用的操作应该提取成闭包或者方法。更多信息参见这篇博文
  4. 将复杂的数据绑定划分为一个 Command 对象。可以让 Command 对象丰富些(就像富 Domain Class)。创建一个有层次的 Comand 对象在某些情况下也是有用的。

服务

  1. 服务是复杂业务逻辑或粗粒度代码的最佳候选。如果有必要,服务 API 可以很容易的暴露成一个 RESTful/SOAP Web 服务。
  2. 服务缺省为事务性的,但是如果服务的方法没有更新持久化存储,可以设置为非事务性的。

视图

  1. 尽量保持视图的简单 - 在这一层,抵制放置业务或数据库逻辑的诱惑。
  2. 使用布局(Layout)保证应用的所有页面或者页面子集有一个统一的外观。
  3. 让你的视图保持 DRY(别重复你自己)。将重复内容放在模板中。
  4. 对通用的 UI 元素,使用自定义的 TagLib。

Domain

  1. 最好将模型 Domain 特定的逻辑放在自己的 Domain 中。符合“单个 Domain 加少数依赖”的任何代码都应该被放到自己的 Domain Class 里。但仅限于那个 Domain 相关的逻辑,处理多个 Domain 的更复杂业务逻辑属于服务。
  2. 为了重用公共局部查询或者分解复杂逻辑,使用命名查询,并根据需要把它们组合起来,就像常见的 jQuery 函数链式调用一般。
  3. 别在 Domain 文件夹下混入其他的通用工具类或数值对象,它们应该呆在 src/groovy 目录下。如果这些类需要支持验证,可以用 @Validateable 对其进行注解。
  4. 使用有意义的构造函数实例化 Domain 对象,避免任何不必要的状态并只构造有效的对象。

TagLib

  1. 保持各标签的精简。一个标签可以调用其他标签,如果需要,一个标签可以分解成可重用的子标签。
  2. TagLib 可以被认为是 MVC 架构中视图层的一部分,但深入 Domain 内部组装或者格式化数据显示也是可以接受的。依旧遵循(即不是完全禁止)最小化与 Domain 直接交互的原则。
  3. 它应该包含更多的逻辑,而非渲染;虽然有少许渲染还是不错滴。
  4. 为了更好的组织结构,可以使用多个自定义的 TagLib。

测试

  1. 较之集成测试,更偏爱单元测试。不仅因为它们运行 / 调试更快,而且能更好地强制松耦合。服务的测试比较特殊,使用集成测试会更好些。
  2. 在单元测试中,使用 save(validate:false) 保存没有完全装入的对象。

Config.groovy

  1. 将所有环境特定的配置放在 Config.groovy,如 serverURL、每个环境下各异的常量等等。
  2. 将个人配置内容(比如本地数据库用户名或密码等等)放在 <Local>Config.groovy 文件中,并加入到版本控制系统的忽略列表中,以便每个团队成员能够根据自己的特定需求覆盖配置。
  3. 虽有些争议,但我们建议设置 grails.gorm.failOnError = true,这样只要保存对象时 Domain 校验失败就会抛出一个异常。由此,你就不再需要检查是否保存成功。
  4. 在 Grails 2.0 中,缺省“grails.hibernate.cache.queries = true”,毋须添加 cache:true 就会自动缓存查询。把它设为 false,只在真正有助于提高性能时才缓存。

杂项

  1. 理解并坚持 Grails 的惯例,因为 Grails 就是惯例驱动的。使用这些惯例会让你的开发者生活更轻松。
  2. 在不同的包中组织 Grails 的制品,别用com.businessname.appname.domaincom.businessname.appname.controller。否则在 FooController 中,我们将最终需要导入 Foo 类。 既然 Grails 已经将这些制品放在了不同目录下,它们就不需要再被分离了。可以参考这篇博文
  3. fixtures 插件可以在开发时用来初始化数据。
  4. 将你应用的可重用部分开发成 Grails 插件。这些插件可以独立测试,还可以消除你的应用的复杂性。如果你认为其他人会需要这些插件,你还可以把插件发布到公共的插件库中。
  5. 更新脚手架模板以生成你的项目特定的视图和控制器。
  6. 青睐动态脚手架,而不使用静态脚手架,除非前者不满足你的需求。例如,如果仅需要修改“save” action,你可以仅重载“save” action,在运行时动态生成其他脚手架代码。
  7. 总在 DataSource.groovy 中设置数据库的重连属性是很好的习惯。
  8. 总保证自己应用中含有一个外部的配置文件(那怕是一个空文件),这样,在产品环境中需要覆盖任何配置时都无需重新生成一个新的 WAR 文件。
  9. 如果你想对你所使用的插件进行小的改动,例如改变 quartz 监控插件的 list.gsp 以符合应用主题,那么不要因为这点小改动而把插件源代码包含到项目里,你可以遵循相同的目录结构或包重载这些文件。原因是应用的优先级比插件高。
  10. Domain 中所有自定义的校验可以放在一个共享的校验文件中,以便其他 Domain 重用这些约束。参见这里的示例
  11. 在应用中安装任何的插件,最好在 BuildConfig.groovy 文件中声明,而不是使用 install-plugin 命令。请看这个线索了解详情。

我还漏了什么吗?你们的项目或组织中遵循哪些 Grails 开发的最佳实践?可以通过评论分享出来,以便将来丰富本文的内容。

关于作者

Grails最佳实践Amit Jain是一位软件工程师,具有 4 年多的 Java 和 Grails 开发经验。他是一位敏捷的爱好者和认证的 Scrum Master。在最近 3 年中,他就职于 IntelliGrape,这是一家专门使用 Groovy & Grails 进行开发、 敏捷外包及项目的公司。参见 IntelliGrape 网站

查看英文原文: Grails Best Practices  


感谢胡键对本文的审校。

给 InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家通过新浪微博( @InfoQ )或者腾讯微博( @InfoQ )关注我们,并与我们的编辑和其他读者朋友交流。

收藏

评论

微博

用户头像
发表评论

注册/登录 InfoQ 发表评论