Я уже некоторое время преподаю Grails не-Java программистам. Это также означало научить их некоторым способам работы, которые мне очень дороги, таким как парное программирование и анализ кода .
Конечно, в начале работы с новой командой я делаю много рецензий, но со временем мне нужно, чтобы все поняли, почему они важны и на что обращать внимание в коде как на рецензента . У каждой команды должны быть согласованные руководящие принципы проверки кода, поэтому мы записали некоторые соглашения и правила и согласились следовать им.
Здесь я опишу некоторые руководящие принципы и передовые практики для проведения коллегиального обзора кода (работы). Это не исчерпывающий список, и некоторые из них довольно просты для опытных разработчиков, но он помог мне охватить некоторые основы для не-Java младших команд, начиная с Java, Groovy и Grails.
Генеральная
- Соответствует ли код спецификациям или критериям приемлемости, написанным в пользовательской истории, или есть серая область?
- Вы понимаете, что запрограммировано? Сможете ли вы внести изменения в него позже?
- Были ли использованы правильные конструкции Grails и Groovy для реализации правильных вещей?
- Является ли код читабельным и соответствует ли он нашим правилам стиля кода и наименования вещей? Смотрите следующие разделы.
Именование
Используйте правильные структуры и имена. Используйте правильные имена артефактов Grails, таких как классы доменов, контроллеры, сервисы, метки TagLib, а также методы и переменные.
- Пакеты должны начинаться с
nl.<company>nl.first8.myappnl.<company>за которым следует имя приложения, напримерnl.first8.myapp - Классы начинаются с CAPITALS, например
Animal, методы и переменные записываются в camelCase , напримерdisplaySummary()илиanimalInstanceList - Старайтесь избегать сокращений. Предпочитаю
domainCodedmnCd - Имя действительно покрывает предмет?
читабельность
Общие рекомендации по удобочитаемости и форматированию, позволяющие легко читать код и составлять его единообразно. Часть может быть выполнена автоматически с помощью встроенного средства форматирования в 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 == 1flash.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 = beginend = 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 = 0int total = 0int 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 Теда Винке в блоге Теда Винке . |

