Статьи

Золотые правила кодовой документации

Вот еще одна тема, которая очень субъективна, которая ведет к жарким дискуссиям, к религиозным войнам, и, тем не менее, нет объективных правдивых или неправильных.

Предыдущий пост на моем блоге  был реблог моих блог партнеров JavaCodeGeeks . Количество поляризованных разглагольствований, спровоцированных этим блогом на JCG, просто смешно. В частности, мне нравится тот факт, что люди склонны утверждать,  догматические вещи,  как:

Если вам нужны комментарии для пояснения кода, лучше подумайте, как писать код по-другому, чтобы он был более понятным. Вам не нужен еще один язык (комментарии), чтобы связываться с основным языком (кодом).

Совершенно очевидно, что этот человек написал 1-2 приложения «Hello world», где это, очевидно, справедливо. Мой ответ на это  был:

Как бы вы записали эту бизнес-логику в код, чтобы вы могли жить без комментариев?

Биржевой ордер с кодом выравнивания типа 27 необходимо сгруппировать со всеми другими последующими ордерами с кодом типа 27 (тогда и только тогда, когда они имеют лот округления ниже 0,01), прежде чем фактически выгружать их в течение периода времени не более 35 секунд. (Вымышленный пример в реальном приложении).

Конечно. Код может сообщать «что» он делает. Но только комментарии могут сообщить, «почему» это делает! «Почему» — это более широкая истина, которая просто не может быть выражена в коде. Это включает в себя требования, чувства, опыт и т. Д. И т. Д.

Поэтому пришло время написать еще один поляризационный пост в блоге, который (надеюсь!) Приведет к более жарким дискуссиям! Это о:

Золотые правила кодовой документации

Хорошая документация добавляет  удобочитаемостьпрозрачностьстабильность и надежность  вашему приложению и / или API. Но что такое хорошая документация? Каковы составляющие хорошей документации?

Код это документация

Во-первых, действительно, код — ваша самая важная документация. Код содержит абсолютную правду о вашем программном обеспечении. Все остальные способы описания того, что делает код, являются лишь приблизительными для тех, кто

  • Не знаю код (кто-то еще написал это)
  • Нет времени читать код (это слишком сложно)
  • Не хочу читать код (кто хочет читать  код Hibernate  или  Xerces, чтобы понять, что происходит ??)
  • Нет доступа к коду (хотя они могут  декомпилировать его )

Для всех остальных код  является  документацией. Таким образом, очевидно, что код должен быть написан так, чтобы документировать его назначение. Так что не пишите умный код, пишите элегантный код. Вот хороший пример того, как не задокументировать «цель» (за исключением нескольких носителей языка Perl):

`$=`;$_=\%!;($_)=/(.)/;$==++$|;($.,$/,$,,$\,$",$;,$^,$#,$~,$*,$:,@%)=(
$!=~/(.)(.).(.)(.)(.)(.)..(.)(.)(.)..(.)......(.)/,$"),$=++;$.++;$.++;
$_++;$_++;($_,$\,$,)=($~.$"."$;$/$%[$?]$_$\$,$:$%[$?]",$"&$~,$#,);$,++
;$,++;$^|=$";`$_$\$,$/$:$;$~$*$%[$?]$.$~$*${#}$%[$?]$;$\$"$^$~$*.>&$=`

Взято с:
http://fwebde.com/programming/write-unreadable-code/

Видимо, это печатает «Просто еще один Perl-хакер». Я, конечно, не буду выполнять это на моей машине, хотя. Не вините меня за потерю данных ;-)

API это документация

Хотя API все еще является кодом, именно эта часть кода доступна большинству других. Таким образом, должно быть:

  • Очень простой
  • Очень лаконично

Простота — король, конечно. Краткость, однако, не совсем то же самое. Все еще может быть  просто  использовать API, который не является  кратким . Я бы рассмотреть вопрос об использовании в Spring  J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource  простого . Вы настраиваете это, вы вводите это, сделано. Но название вряд ли указывает на лаконичность.

Это касается не только документации, но и дизайна API в целом. Использовать  ваш API должно быть очень просто  , потому что тогда ваш API четко сообщает о своем намерении. И сообщать о своих намерениях — это документация.

Хорошие правила дизайна (и, следовательно, документации) для достижения  краткости  следующие:

  • Не позволяйте методам с более чем 3 аргументами попадать в ваш публичный API.
  • Не позволяйте методам / типам с более чем 3 словами в именах попадать в ваш публичный API.

Лучше всего избегать вышеуказанного. Если вы не можете избежать таких методов, держите вещи в секрете. Эти методы не могут быть использованы повторно, поэтому их не стоит документировать в API.

API должен быть задокументирован словами

Как только код «просачивается» в общедоступный API, он должен быть задокументирован понятными для человека словами. Правда,  java.util.List.add ()  уже довольно  лаконичен . Он четко  сообщает о своих намерениях . Но как это ведет себя и  почему ? Выдержка из Javadoc:

Списки, поддерживающие эту операцию, могут накладывать ограничения на то, какие элементы могут быть добавлены в этот список. В частности, некоторые списки откажутся добавлять нулевые элементы, а другие наложат ограничения на тип элементов, которые могут быть добавлены. Классы списков должны четко указывать в своей документации любые ограничения на то, какие элементы могут быть добавлены.

Итак, есть некоторые хорошо известные списки, которые  «отказываются добавлять нулевые элементы»,  могут быть  «ограничения на то, какие элементы могут быть добавлены» . Это не может быть понято только из сигнатуры метода API — если вы не откажетесь от создания  краткой подписи.

Инструменты отслеживания документации

Инструменты отслеживания — это ваш человеческий интерфейс с заинтересованными сторонами. Они помогают вам  обсуждать  вещи и дают некоторую историческую аргументацию о том,  почему код в конечном итоге написан таким, какой он есть. Держите вещи  сухими , здесь. Распознайте дубликаты и постарайтесь сохранить только один  простой и лаконичный  билет для каждой проблемы.

При внесении изменений в свой код не столь очевидным способом (поскольку у ваших заинтересованных сторон не столь очевидные требования) добавьте короткий комментарий в соответствующий раздел кода со ссылкой на идентификатор отслеживания:

// [#1296] FOR UPDATE is simulated in some dialects
// using ResultSet.CONCUR_UPDATABLE
if (forUpdate && 
    !asList(CUBRID, SQLSERVER).contains(context.getDialect())) {

Да, сам код уже объясняет, что следующий раздел выполняется только в запросах forUpdate и только для диалектов CUBRID и SQLSERVER. Но  почему ? Будущий разработчик с удовольствием прочитает все, что они могут найти о проблеме  № 1296 . Если это актуально, вы должны указать этот идентификатор билета в:

  • Списки рассылки
  • Исходный код
  • API документация
  • Комментарии контроля версий
  • Вопросы переполнения стека
  • Все виды других документов с возможностью поиска
  • и т.п.

Контроль версий это документация

Эта часть документации потрясающая! Это документы  меняются . В больших проектах вы все еще сможете восстановить, почему сотрудник, который давно ушел из компании, сделал странные изменения, которые вы сейчас не понимаете. Таким образом, важно также включить вышеупомянутый идентификатор билета в изменение.

Итак, следуйте этому правилу: Является ли изменение нетривиальным (фиксированное написание, фиксированный отступ, переименованная локальная переменная и т. Д.)? Затем создайте заявку и задокументируйте это изменение с идентификатором заявки в вашем коммите. Создание и ссылка на этот билет стоит вам всего 1 минуту, но это сэкономит будущему сотруднику часы исследования!

Нумерация версий — документация

Простая и краткая  версия система нумерации поможет пользователям понять, какую версию они должны обновить. Хорошим примером того, как сделать это правильно, является  семантическое управление версиями . Золотые правила здесь должны использовать  [X].[Y].[Z] схему управления версиями, которая может быть кратко изложена следующим образом:

  • Если  выпуск патча  содержит исправления ошибок, улучшения производительности и не относящиеся к API новые функции,  [Z] увеличивается на единицу.
  • Если  вспомогательный выпуск  включает обратно совместимые, относящиеся к API новые функции,  [Y] увеличивается на единицу и  [Z] сбрасывается в ноль.
  • Если  крупный релиз  включает в себя обратную несовместимыми API релевантных новых функций,  [X] увеличивается на единицу и  [Y][Z] сбрасываются на ноль.

Строго следуйте этим правилам, чтобы сообщить об  изменениях  между выпущенными версиями.

Где дела идут не так

Теперь вот где это начинает становиться эмоциональным …

Забудьте UML для документации!

Не создавайте вручную большие UML-диаграммы. Ну, сделай их. Они могут помочь вам понять / объяснить вещи другим. Создайте специальные UML-диаграммы для собрания или неформальные UML-диаграммы для высокоуровневого учебника. Генерируйте UML-диаграммы из соответствующих частей вашего кода (или диаграмм сущностей из вашей базы данных), но не рассматривайте их как центральную часть документации вашего кода. Никто никогда не обновит UML-диаграммы вручную с сотнями классов и тысячами отношений в них.

Исключением из этого правила могут быть  архитектуры на основе моделей на основе UML , где UML действительно является частью кода, а не документацией.

Забудьте MS Word или HTML для документации (если вы можете)!

Держите свою документацию близко к коду. Без чрезмерной дисциплины практически невозможно синхронизировать внешнюю документацию с реальным кодом и / или API. Если вы можете, автоматически сгенерируйте внешнюю документацию из той, что в вашем коде, чтобы сохранить вещи  сухими . Но если вы можете избежать этого, не пишите внешнюю документацию. Это вряд ли когда-либо точно.

Конечно, вы не всегда можете избежать внешней документации. Иногда вам нужно написать руководства, учебные пособия, инструкции, лучшие практики и т. Д. Просто помните, что эти документы практически невозможно синхронизировать с «реальной правдой»: вашим кодом.

Забудьте писать документацию рано!

Ваш API  будет  развиваться. Вряд ли кто-то напишет API-интерфейсы, которые будут существовать вечно, как API-интерфейсы Java. Так что не тратьте все это время на размышления о том, как вечно связать класс A с типом B и алгоритмом C. Пишите код, документируйте те части кода, которые просочились в API, ссылайтесь на идентификаторы билетов из вашего кода / коммитов

Забудьте документирование стандартного кода!

Геттеры и сеттеры, например. Они обычно не делают больше, чем получают и устанавливают. Если они этого не делают, не документируйте это, потому что скучная документация становится устаревшей и, следовательно, неправильной. Сколько раз вы рефакторировали свойство (и, следовательно, имя получателя / установщика), но не Javadoc? Точно. Никто не обновляет стандартную документацию API.

/**
 * Returns the id
 *
 * @return The id
 */
public int getId() {
    return id;
}

Ааа, удостоверение личности! Сюрприз Сюрприз.

Забудьте документирование тривиального кода!

Не делай этого:

// Check if we still have work
if (!jobs.isEmpty()) {

    // Get the next job for execution
    Job job = jobs.pollFirst();

    // ... and execute it
    job.execute();
}

Duh. Этот код уже 
прост и лаконичен
, как мы видели раньше. Это не нуждается ни в каких комментариях вообще:

if (!jobs.isEmpty()) {
    Job job = jobs.pollFirst();
    job.execute();
}

TL; DR: все должно быть просто и кратко

Создать хорошую документацию:

  • сохраняя документацию  простой и сжатой .
  • сохраняя документацию  близко к коду  и  API , которые являются  окончательной истиной  вашего приложения.
  • сохраняя вашу документацию  СУХОЙ .
  • делая документацию  доступной для других , через систему  тикетов , контроль версийсемантическое управление версиями .
  • путем  ссылки на идентификаторы билетов на  протяжении всего доступных средств массовой информации.
  • при  забывая о «внешней» документации , до тех пор , как вы можете.

Приложения, API, библиотеки, которые предоставляют вам  хорошую документацию  , помогут вам создавать лучшее программное обеспечение, потому что хорошо документированные приложения, API, библиотеки сами по себе являются лучшим программным обеспечением. Критически проверьте свой стек и постарайтесь избегать тех частей, которые плохо документированы.