Я уже некоторое время преподаю Grails не-Java программистам. Это также означало научить их некоторым способам работы, которые мне очень дороги, таким как парное программирование и анализ кода .
Конечно, в начале работы с новой командой я делаю много рецензий, но со временем мне нужно, чтобы все поняли, почему они важны и на что обращать внимание в коде как на рецензента . У каждой команды должны быть согласованные руководящие принципы проверки кода, поэтому мы записали некоторые соглашения и правила и согласились следовать им.
Здесь я опишу некоторые руководящие принципы и передовые практики для проведения коллегиального обзора кода (работы). Это не исчерпывающий список, и некоторые из них довольно просты для опытных разработчиков, но он помог мне охватить некоторые основы для не-Java младших команд, начиная с Java, Groovy и Grails.
Генеральная
- Соответствует ли код спецификациям или критериям приемлемости, написанным в пользовательской истории, или есть серая область?
- Вы понимаете, что запрограммировано? Сможете ли вы внести изменения в него позже?
- Были ли использованы правильные конструкции Grails и Groovy для реализации правильных вещей?
- Является ли код читабельным и соответствует ли он нашим правилам стиля кода и наименования вещей? Смотрите следующие разделы.
Именование
Используйте правильные структуры и имена. Используйте правильные имена артефактов Grails, таких как классы доменов, контроллеры, сервисы, метки TagLib, а также методы и переменные.
- Пакеты должны начинаться с
nl.<company>
nl.first8.myapp
nl.<company>
за которым следует имя приложения, напримерnl.first8.myapp
- Классы начинаются с CAPITALS, например
Animal
, методы и переменные записываются в camelCase , напримерdisplaySummary()
илиanimalInstanceList
- Старайтесь избегать сокращений. Предпочитаю
domainCode
dmnCd
- Имя действительно покрывает предмет?
читабельность
Общие рекомендации по удобочитаемости и форматированию, позволяющие легко читать код и составлять его единообразно. Часть может быть выполнена автоматически с помощью встроенного средства форматирования в IDE, например, Ctrl-Shift-F
в Eclipse или GGTS, но не все.
Не все однострочники
В приведенном ниже примере разделите, например, инициализацию переменных, чтобы их использование стало более понятным.
1
|
out << body() << ( (attrs. int ( 'offset' )) + "-" + ( Math.min(attrs. int ( 'count' ), attrs. int ( 'offset' ) + attrs. int ( 'max' ) ) ) + " " + title + " " + attrs. int ( 'count' ) ) |
мог стать
1
2
3
4
5
|
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 |
Спок тесты и этикетки
Можно много сказать о «правильном» написании тестов Спока , но это выходит за рамки этого поста.
Используйте правильные метки в тестах Спока для удобства чтения. Используйте and:
для разделения нескольких меток — с дополнительным «текстовым описанием» после них — чтобы они выделялись. Напишите
1
2
3
4
5
6
|
when: "searching for existing animal" ... then: "we have results" model.animalSearchResults.animalsCount == 1 flash.successMessage == "animal.all.found.message" session.selected.size() == 1 |
в виде
01
02
03
04
05
06
07
08
09
10
11
|
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 |
Бело-пространство
Используйте пробелы для разделения комбинированных операторов. Напишите
1
|
Integer.valueOf(params.offset?:attrs.offset) |
в виде
1
|
Integer.valueOf(params.offset ?: attrs.offset) |
Пробел и скобки
В общем, до и после скобок вам НЕ обязательно использовать пробелы. Напишите
1
2
3
|
if ( params ) if ( total > 0 ) if ( end < begin ) |
в виде
1
2
3
|
if (params) if (total > 0 ) if (end < begin) |
Фигурные скобки
Используйте фигурные скобки для однострочников. Напишите
1
2
|
if ( end < begin ) end = begin |
в виде
1
2
3
|
if (end < begin) { end = begin } |
Несмотря на то, что вы можете написать оператор if в одной строке или только в строке ниже без фигурных скобок, особенно если есть несколько операторов друг за другом, это улучшит читабельность и более четко покажет намерение.
сравнить
1
2
3
|
if (end < begin) end = begin end = end + 1 |
с участием
1
2
3
4
|
if (end < begin) { end = begin } end = end + 1 |
Комментарии
Используйте комментарии, чтобы указать назначение классов и методов, прояснить сложные фрагменты кода и документировать принятые решения («почему?»). Для Java en Groovy-кода мы можем использовать Javadoc для генерации документации API в формате HTML в исходном коде.
Ага на занятиях
Используйте комментарии Javadoc вверху класса для описания общего назначения, такого как
1
2
3
4
|
/** * General convenience tags for layout - header, body and footer - purposes. */ class LayoutTagLib { |
Ага по методам
Используйте Javadoc для открытых методов, чтобы описать цель и ее параметры. Вы можете использовать @param
для параметров, @return
для того, что он возвращает, когда или если исключения @thrown
с @thrown
и т. Д.
1
2
3
4
5
6
7
8
|
/** * 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" ) |
Убирать
Удалите устаревшие комментарии, например, которые остались позади, или которые просто неверны, или исправьте их!
Simplicitly
Является ли код простым и выполняет ли он свою работу самым простым способом … но не проще
Интуитивно понятный API
Используйте интуитивно понятный API. Используйте похожие структуры или названия. Требуется ли только фактический требуемый вход и используются ли другие разумные значения по умолчанию? Если вы создаете тег betterPaginate
, не слишком обременяйте пользователя всеми видами ввода. У него вместо
1
|
< g:betterPaginate offset = "${params.offset?:0}“ count=" ${results.animalsCount?:0}" max = "${params.max?:0}" /> |
разрешить использовать ваш тег как
1
|
< g:betterPaginate count = "${results.animalsCount}" /> |
где вы позаботитесь о значениях по умолчанию, а также чтение из params
Простое написание
Чем сложнее используемые строки, тем сложнее понять, что происходит и куда должны идти изменения. Оказывается, что следующие 10 строк созданы сотрудником
01
02
03
04
05
06
07
08
09
10
11
12
|
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 строки с таким же поведением:
1
2
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 ) |
Если у вас есть хороший тест, вы можете более свободно реорганизовать подобные конструкции и при этом быть достаточно уверенным, что вы ничего не изменили неожиданно.
Ох и:
Кредиты изображений:
- Что такое Code Review? — http://smartbear.com/all-resources/articles/what-is-code-review/
- Как облегчить дружественные обзоры кода — http://www.syncano.com/friendly-code-review/
Ссылка: | Основные рекомендации по проверке кода Groovy и Grails от нашего партнера по JCG Теда Винке в блоге Теда Винке . |