我曾经(现在仍然)在一段时间内向非Java程序员教授Grails。 这也意味着指导他们进行一些我非常喜欢的工作方式,例如结对编程和进行代码审查 。
当然,在新团队成立之初,我会做很多审查,但是随着时间的流逝, 我需要每个人都去理解它们为什么重要以及作为审查者自己应该在代码中寻找什么 。 每个团队都应该有一套他们同意的代码审查指南,因此我们写下了一些约定和规则并同意遵循它们。
在这里,我描述了一些对同事(工作) 进行对等代码审查的准则和良好实践 。 这不是一个详尽的清单,对于经验丰富的开发人员来说,有些清单很简单,但是它很好地覆盖了从Java,Groovy和Grails开始的非Java初级团队的一些基础知识。
一般
- 该代码是否满足用户故事中编写的规范或接受标准 ,或者是否存在灰色区域?
- 您了解编程的内容吗? 以后您可以对其进行修改吗?
- 是否已使用适当的Grails和Groovy构造来实现适当的东西?
- 代码可读性强 ,并且符合我们的代码风格和事物命名准则吗? 请参阅以下各节。
命名
使用正确的结构和名称。 使用Grails工件的正确名称,例如域类,控制器,服务,TagLib以及方法和变量。
- 软件包应以
nl.<company>
开头,后跟应用程序名称,例如nl.first8.myapp
- 类以CAPITALS开头,例如
Animal
,方法和变量以camelCase编写,例如displaySummary()
或animalInstanceList
- 尽量避免缩写。 在
domainCode
上dmnCd
- 名称实际上涵盖了主题吗?
可读性
通用的可读性和格式指南可轻松阅读代码并以一致的方式编写代码。 可以使用IDE中的内置Formatter自动完成部分操作,例如Eclipse或GGTS中的Ctrl-Shift-F
,但不是全部。
并非所有单线
在下面的示例中,拆分例如变量的初始化,以使其使用变得更加清晰。
out << body() << ( (attrs.int('offset')) + "-" + ( Math.min(attrs.int('count'), attrs.int('offset') + attrs.int('max') ) ) + " " + title + " " + attrs.int('count') )
可能成为
int start = attrs.int('offset')
int total = attrs.int('count') )
int end = Math.min(total, start + attrs.int('max') )
out << body() << start + "-" + end + " " + title + " " + total
Spock测试和标签
关于“适当”编写Spock测试 ,有很多话要说,但这超出了本文的范围。
在Spock测试中使用适当的标签以提高可读性。 使用and:
分隔多个标签-在其后加上其他“文字描述”-使它们脱颖而出。 写
when: "searching for existing animal"
...
then: "we have results"
model.animalSearchResults.animalsCount == 1
flash.successMessage == "animal.all.found.message"
session.selected.size() == 1
如
when: "searching for existing animal"
...
then: "one found animal is returned"
model.animalSearchResults.animalsCount == 1
and: "all found message is displayed"
flash.successMessage == "animal.all.found.message"
and: "animal has been auto-selected"
session.selected.size() == 1
空格
使用空格分隔组合的语句。 写
Integer.valueOf(params.offset?:attrs.offset)
如
Integer.valueOf(params.offset ?: attrs.offset)
空格和方括号
通常,在括号之前和之后,您不必使用空格。 写
if ( params )
if ( total > 0 )
if ( end < begin )
如
if (params)
if (total > 0)
if (end < begin)
大括号
将大括号用于单线。 写
if ( end < begin )
end = begin
如
if (end < begin) {
end = begin
}
尽管您可以在一行或仅下面的行上编写if语句,而不会产生任何错误,尤其是当彼此后接多条语句时,这将提高可读性并更清晰地显示意图。
相比
if (end < begin)
end = begin
end = end + 1
与
if (end < begin) {
end = begin
}
end = end + 1
注释
使用注释陈述类和方法的目的,阐明困难的代码段并记录所做的决定(“为什么?”)。 对于Java en Groovy代码,我们可以使用Javadoc在源代码中生成HTML格式的API文档。
关于类的Javadoc
在类顶部使用Javadoc注释来描述一般用途,例如
/**
* General convenience tags for layout - header, body and footer - purposes.
*/
class LayoutTagLib {
方法的Javadoc
在公共方法上使用Javadoc描述目的及其参数。 您可以将@param
用作参数,将@return
用作返回值,何时或是否使用@thrown
引发异常等。
/**
* Gets the user for specified code and role.
*
* @param code The code, either username or email address
* @param role The role identification e.g. A, B or C. Default is A.
* @return the user or null if not found
*/
User findUser(String code, String role = "A")
清理
删除过时的注释,例如遗留的注释或明显错误的注释,或进行更正!
简单地
代码是否简单,是否以最简单的方式完成工作? 但不简单
直观的API
使用直观的API。 使用类似的结构或命名。 是否仅需要实际所需的输入,并且是否正在使用其他合理的默认值? 如果您要创建一个betterPaginate
标签,则不betterPaginate
用户带来太多输入负担。 让他代替
<g:betterPaginate offset="${params.offset?:0}“ count="${results.animalsCount?:0}" max="${params.max?:0}"/>
允许将您的标签用作
<g:betterPaginate count="${results.animalsCount}" />
您将在其中处理默认设置,以及从params
读取内容等。
简单的写作
使用的行越复杂,就越难理解发生了什么以及应该在哪里进行更改。 事实证明,同事创建的以下10行
int offset = 0
int total = 0
int max = 0
if (params) {
offset = Integer.valueOf(params.offset ?: attrs.offset ?: 0)
max = Integer.valueOf(params.max ?: attrs.max ?: 0)
} else if (attrs) {
offset = Integer.valueOf(attrs.offset ?: 0)
max = Integer.valueOf(attrs.max ?: 0)
}
total = Integer.valueOf(attrs.total ?: 0)
可以在3行中用相同的行为重写:
int offset = Integer.valueOf(params.offset ?: attrs.offset ?: 0)
int max = Integer.valueOf(params.max ?: attrs.max ?: 0)
int total = Integer.valueOf(attrs.total ?: 0)
如果您具有良好的测试,则可以更加自由地重构这些类型的结构,并且仍然可以确信自己没有意外更改。
哦,还有:
图片学分:
- 什么是代码审查? – http://smartbear.com/all-resources/articles/what-is-code-review/
- 如何促进更友好的代码审查– http://www.syncano.com/friendly-code-review/
翻译自: https://www.javacodegeeks.com/2015/03/basic-groovy-and-grails-code-review-guidelines.html