Опирается на правила:
JS-7.1…JS-7.5иJS-7.X1…JS-7.X2из Java Style Guide → раздел 7. Комментарии.
Важно знать
- По умолчанию — не пишем комментарии. Имена + структура говорят сами.
- Комментарий уместен только когда WHY неочевиден.
- Не цитируем коды правил в исходниках (BR-C5, AUTH-15, R-LAY-3).
- Не пишем «что было», «убрано для X», «TODO до spring 4» — git blame.
- Javadoc НЕ используем нигде, включая публичный API библиотек.
@param,@return,@throwsтеги — запрещены.- Не публикуем
*-javadoc.jar— один источник правды (код + спека).
Комментарии — последняя линия документации, когда имя и структура не справляются. UCP занимает жёсткую позицию: меньше комментариев, никаких Javadoc, никаких кодов правил в коде. Каждое из этих ограничений уменьшает «гниение» документации со временем.
По умолчанию — не пишем
JS-7.1: имена и структура — первичны.
// ✗ — комментарий дублирует имя
// проверяем владельца
if (!owner.equals(requester)) { ... }
// ✓ — имя method-а самодокументирует
private boolean isOwner(User requester, Order order) {
return order.customerId().equals(requester.id());
}
if (!isOwner(requester, order)) { ... }
isOwner уже всё сказало. Комментарий «проверяем владельца» — шум.
Когда метод/имя не справляются — не комментируем, а переименовываем или рефакторим.
Уместен только когда WHY неочевиден
JS-7.2: hidden constraints.
// ✓ — WHY: статус-код выбран осознанно
// 404, не 403 — не подтверждаем существование чужого продукта
throw new OwnProductRequiredException(productId);
// ✓ — WHY: workaround
// Postgres до 14 не поддерживает FOR UPDATE SKIP LOCKED с CTE.
// При 12.x придётся откатиться к prepared statement.
var locked = dsl.fetchSomeWithLock(...);
// ✗ — WHAT, не WHY (имя method уже говорит)
// загружаем заказ
var order = orderRepository.findById(orderId).orElseThrow();
Что считается WHY:
- Workaround для известного бага (
// Workaround for Spring Boot #12345). - Compliance/security рассуждение (
// 401 vs 403: client должен делать refresh, не relogin). - Performance trade-off (
// linear scan быстрее HashMap для < 5 элементов). - Hidden constraint (
// threadsafe только если caller держит lock).
Что не считается WHY:
- «Перебираем массив» (видно по
forloop). - «Создаём объект» (видно по
new). - «Возвращаем результат» (видно по
return).
Не цитируем коды правил
JS-7.3: коды живут в гайде, не в коде.
// ✗ — все запрещены
// BR-C5: Publish — только из DRAFT|HIDDEN.
// AUTH-15: фасад над audit log.
// R-LAY-3: маппинг через MapStruct.
// TS-9..TS-11: fluent preparer.
Причины:
Дублирует source-of-truth
Правило живёт в style-guide.md или docs/spec/. Если код противоречит — правило source. Комментарий с кодом — дублирующая запись, которая может устареть.
Хрупко
При следующей ревизии гайда нумерация уезжает (R-LAY-3 стало R-LAY-5). Комментарии в коде молча становятся ложью. Тысячи мест надо обновлять при каждой ревизии — никто не делает.
Шум для читателя
Соответствие правилу выражается именами и структурой:
record+ implementsUseCaseCommandуже =R-UC-1..3.@RequiredArgsConstructorуже =JS-6.1.@Mapper(componentModel = "spring")уже =R-LAY-3.
Не нужно явно пометить «соответствует правилу X» — это и так видно.
Где живут коды
- Commit messages:
JS-6.5: replace @Data with @Getter @Setter. - PR description: «Этот PR соответствует R-DIST-IDEM-* — добавляет processed_event».
- Гайд / спека:
style-guide.mdссылается на свой собственный код. - Liquibase remarks: human-readable, не код правила.
Не «что тут было», «убрано для X»
JS-7.4: git blame.
// ✗ — все запрещены
// removed because we don't need this anymore
// added for the customer flow
// TODO: remove after Spring 4 migration
// changed from List to Set for performance (2024-03-15)
// previously this was inside the loop
Что плохо:
- git blame показывает кто, когда, в каком commit изменил.
- Commit message — авторитет, не комментарий.
- Эти комментарии гниют: «TODO до Spring 4» осталось через 5 лет.
- Засоряют diff — каждый PR имеет добавления-удаления таких комментариев.
Если действительно нужно — пишем в commit message, не в коде.
Javadoc — не используем
JS-7.5: critical правило без исключений.
// ✗ — Javadoc любого вида
/**
* Returns the user by id.
*
* @param userId the user id
* @return the user
* @throws NotFoundException if user not found
* @see UserRepository
*/
public User getUser(Long userId) { ... }
// ✓ — без Javadoc
public User getUser(Long userId) { ... }
Причины:
Гниёт быстрее кода
Сигнатура переименована (getUser → findUser) — Javadoc остался про старое имя. Изменено поведение (@throws NotFoundException → теперь возвращает Optional) — Javadoc устарел.
Через год Javadoc хуже отсутствия документации — он вводит в заблуждение.
Сам код — документация
public Optional<User> findUser(Long userId) {
return userRepository.findById(userId);
}
Имя + типы + типы возврата + реализация говорят больше, чем 5-строчный Javadoc «Returns the user by id».
Consumer OSS читает источники
UCP-команда поддерживает OSS-библиотеки (ddd-building-blocks, usecase-pattern). Consumer не открывает Javadoc на сайте — он:
- Кликает
Cmd-Clickв IDE → видит реализацию. - Открывает GitHub → читает короткий код (
AggregateRoot.java≈ 80 строк). - Запускает тесты → видит fully behavior.
Javadoc-сайт хуже: нет контекста, нет ссылающихся мест, нельзя запустить тесты.
Сложный контракт — спека
docs/spec/order-service/aggregates/order.md
Подробный контракт (state machine, инварианты, business rules) — в спеке, версионируется отдельно, обсуждается командой. Javadoc — инициатива одного автора, не проходит через коллектив.
Что писать вместо Javadoc
- Имена (см. Именование).
- Не-очевидные инварианты (threadsafety, lifecycle) — короткий
//или/* ... */комментарий без@param/@return. - Доменный контракт — спека в
docs/spec/.
Запреты конкретно
JS-7.X1: любой /** ... */ блок с тегами @param, @return, @throws, @see — это Javadoc-блок, нарушение JS-7.5.
JS-7.X2: конфигурация javadoc-task в build.gradle / pom.xml для production-сервиса. Не запускаем ./gradlew javadoc, не публикуем *-javadoc.jar.
Что запрещено
| Антипаттерн | Правило | Что взамен |
|---|---|---|
| Комментарий дублирует имя method | JS-7.1 | имя/структура — первичны |
Комментарий с кодом правила (// BR-C5: ...) | JS-7.3 | гайд + commit message |
// removed because ..., // added for ... | JS-7.4 | git blame |
/** ... */ с @param, @return | JS-7.X1 | без Javadoc |
javadoc-task в build.gradle | JS-7.X2 | не запускаем |
*-javadoc.jar в Maven Central | JS-7.X2 | не публикуем |
// TODO until 2024 без actionable | JS-7.4 | ticket в issue tracker |
| Комментарий описывает WHAT (loop, assignment) | JS-7.2 | WHY only |
| Комментарий на каждый method (boilerplate) | JS-7.1 | по умолчанию никаких |
Куда дальше
- Java → раздел 7. Комментарии — нормативные формулировки.
- Именование — хорошее имя устраняет необходимость в комментарии.
- Выражения — guard expression вместо комментарием объясняемой логики.
- Lombok —
@RequiredArgsConstructorустраняет boilerplate. - Современные фичи Java — sealed + switch exhaustiveness вместо инлайн-комментариев.
- Checkstyle — не enforce Javadoc, только формальные правила.