Опирается на правила: JS-7.1JS-7.5 и JS-7.X1JS-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:

  • «Перебираем массив» (видно по for loop).
  • «Создаём объект» (видно по 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 + implements UseCaseCommand уже = 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) { ... }

Причины:

Гниёт быстрее кода

Сигнатура переименована (getUserfindUser) — 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.

Что запрещено

АнтипаттернПравилоЧто взамен
Комментарий дублирует имя methodJS-7.1имя/структура — первичны
Комментарий с кодом правила (// BR-C5: ...)JS-7.3гайд + commit message
// removed because ..., // added for ...JS-7.4git blame
/** ... */ с @param, @returnJS-7.X1без Javadoc
javadoc-task в build.gradleJS-7.X2не запускаем
*-javadoc.jar в Maven CentralJS-7.X2не публикуем
// TODO until 2024 без actionableJS-7.4ticket в issue tracker
Комментарий описывает WHAT (loop, assignment)JS-7.2WHY only
Комментарий на каждый method (boilerplate)JS-7.1по умолчанию никаких

Куда дальше

  • Java → раздел 7. Комментарии — нормативные формулировки.
  • Именование — хорошее имя устраняет необходимость в комментарии.
  • Выражения — guard expression вместо комментарием объясняемой логики.
  • Lombok — @RequiredArgsConstructor устраняет boilerplate.
  • Современные фичи Java — sealed + switch exhaustiveness вместо инлайн-комментариев.
  • Checkstyle — не enforce Javadoc, только формальные правила.