можно ли автоматически сформировать документацию на основе комментариев к программному коду
Автоматическая генерация технической документации
Продолжая тему использования Asciidoc (и других аналогичных форматов) для организации процессов непрерывного документирования, хочу рассмотреть тему автоматический генерации технической документации.
Автоматическая генерация документации — распространенный, но очень расплывчатый термин. Я понимаю под этим термином извлечение для представления в удобном виде информации, содержащейся в исходном коде и настройках документируемой программы (информационной системы).
Общая схема автоматической генерации документации
Если рассматривать процесс автоматической генерации как чёрный ящик, то на входе имеем исходный код, а на выходе — документацию или её фрагмент. Однако в реальности при автоматической генерации документации целесообразны еще два промежуточных звена.
За исключением самых простых случаев, документация готовится в различных выходных форматах (html, docx, odt, pdf и т.п.) и собирается из разных источников (в том числе не автоматически генерируемых) поэтому целесообразно использовать специальные форматы для подготовки документации. Предположим, необходимо подготовить документацию по стандартам ЕСКД? Эта проблема, описана в предыдущей статье. При решении проблем автоматической генерации хватает проблем и без требований ГОСТ.
Общая схема генерации документации выглядит следующим образом:
Рассмотрим практические приёмы, которые можно использовать при реализации ИТ-проектов. Для примеров будем использовать Asciidoc, однако приёмы применимы к любым языкам разметки текста(reStructuredText, Markdown), и текстовым маркапам для построения диаграмм (рекомендую проект kroki, который позволяет быстро ознакомиться и внедрить наиболее популярные средства построения диаграмм).
Преобразование исходного кода в структурированный формат
Единых подходов к превращению исходного кода в структурированный формат не существует. Рассмотрим наиболее частые варианты.
Информация для документации извлекается из структуры исходного кода
Как правило, используются дополнительные средства языка, обычно комментарии в специальном формате (комментарии Javadoc, ReST и т.п.) и аннотации.
Средств, обеспечивающих преобразование исходного кода в документацию, причём очень зрелых, много. Можно смело брать и использовать подходящие для конкретного проекта. Разработка собственных средств затратна. Мы пошли указанным путём только раз, разрабатывая проект для миграции структуры базы данных. Целесообразность определялась использованием средства во всех наших проектах и желанием попробовать свои силы.
Следующие подходы более гибки с точки зрения настройки автоматической генерации документации в реализуемых проектах.
Структурированный формат получается как один из результатов исполнения исходного кода
При данном подходе считывается и сохраняется в структурированный формат состояния объектов (например, структуры базы данных, конфигурации развернутой среды информационной системы и т.п.), создаваемых в результате работы приложения.
Отдельно отметим использование для документирвоания логов. Типовой пример — тесты. Например, большинство инструментов для тестирования выдают результаты в формате Junit xml report. Это, позволяет сделать универсальные инструменты генерации отчётности по тестам, самый известный, наверное — Allure Framework.
В этой статье показано, как используют JSON-файлы, которые генерирует при работе Cucumber, как документация строится на основе логов, создаваемых в результате работы тестов.
Типовой пример создания документации на основе считывания состояния объектов, создаваемых в результате работы приложения, — документирование структуры БД. В конце раздела приведен пример, иллюстрирующий данный подход.
Исходный код сразу представляет собой структурированный формат
Многие языки уже реализованы в структурированном формате (например, xsd-схемы, OpenAPI, различные DSL для описания предметной области, файлы настроек).
Иногда проводят предварительную обработку этих форматов, например, объединение спецификации в единую иерархическую структуру (так называемая операция «flatten»).
Частным (и частым) случаем является ситуация, когда настройки содержатся в базе данных.
Пример — генерация документации по структуре базы данных
Пример иллюстрирует достаточно частую ситуацию, когда информация для документации хранится в таблицах СУБД.
Создаём скрипт, описывающий структуру БД. Этот скрипт не выглядит как исходник для поддержания структуры БД, однако, как это не парадоксально, таковым является, подробности в документации к уже упомянутому проекту. Это также может быть миграционный скрипт в любой системе контроля версии базы данных.
Применим скрипт к базе данных и воспользуемся двумя инструментами СУБД (пример приведён для PostgreSQL): динамическими представлениями для извлечения сведений о структуре и возможностью создавать JSON-файлы на основе результатов сохранения запросов.
В результате получим JSON-файл:
В следующем разделе будет показано, как этот файл превратить в документ.
Использование шаблонизаторов
Для превращения структурированного файла в документ используют специальный тип языков,
шаблонизаторы. Шаблонизатор позволяет задать правила обхода иерархической структуры данных и правила, по которым элементы иерархии исходного документа преобразуют в выходной документ.
Формат этих правил достаточно простой, они безопасны с точки зрения исполнения, поэтому часто шаблонизаторы используются для настройки различных аспектов работы приложений непосредственно пользователями.
Самым известным языком обработки шаблонов (но далеко не самым простым) является XSLT. Самым минималистичным — Mustache.
Свой язык написания шаблонов и шаблонизатор также создать довольно просто. Например, для создания системы генерации отчётов в форматах Excel и ods мы пошли этим путём.
Можно вообще обойтись без шаблонизатора, просто структурировать код определенным образом, в этой старой статье 2003 года Мартин Фаулер признается в нелюбви к XSLT и заодно объясняет, как его заменить кодом, написанным на языке Ruby. За 18 лет оказалось, что и статические языки также можно прекрасно использовать для этих целей, и XSLT прекрасно себя чувствует, и предложенный в статье подход оказался очень хорош.
В примерах будет использоваться Liquid для работы с JSON и XSLT для работы с XML. В обоих случаях будет использоваться реализация в Ruby, потому что (1) Наиболее распространенный в настоящий момент процессор Asciidoc — Asciidoctor — написан на Ruby (2) Ruby-скрипты отлично работают в java и javascript, что часто позволяет не плодить цирк технологий.
Пример генерации документа из JSON-файла
Рассмотрим простой пример по генерации документа на основе полученного выше JSON-файла.
Генерация диаграммы в формате PlantUML:
На выходе получаем следующий текст диаграммы:
Аналогично сгенерируем документ в формате Asciidoc:
Для объединения обоих кусков в один документ воспользуемся директивой include:
Синтаксис Asciidoc рассмотрен в статье Asciidoc для ЕСКД. Подробнее структурирование документации в Asciidoc планирую описать в отдельной статье. Здесь лишь хотелось бы отметить, что при вставке диаграммы мы указываем параметры её отображения. В разных документах одну и ту же диаграмму мы можем отобразить по-разному (в разных цветах, с разным разрешением, в разной ориентации и т.п.).
Результаты превращаем в файл в формате Microsoft Word с помощью проекта, о котором рассказано в предыдущей статье.
Ключевые техники, используемые при генерации документации
Для рассмотрения ключевых техник приведём пример с преобразованием XML-файла.
Для примера возьмем выписку из ЕГРЮЛ от Федеральной налоговой службы. Не совсем документация, но удобно для демонстрации основных приёмов преобразования структурированных данных в документацию.
Исходные данные (схема xsd и пример сообщения) взяты на сайте СМЭВ 3 — https://smev3.gosuslugi.ru/portal/inquirytype_one.jsp?id=41108&zone=fed. Для примера приведём небольшую часть выписки из ЕГРЮЛ:
Как видно, названия тэгов и атрибутов вполне говорящие, но мы возьмем полные названия параметров из схемы xsd.
Преобразование выписки из ЕГРЮЛ в формат Asciidoc выглядит следующим образом:
Наименования тэгов и атрибутов XML-документа обёрнуты в фигурные скобки — специальный синтаксис для отображения значений атрибутов Asciidoc. Значения атрибутов легко извлекаем из xsd-схемы с помощью следующего преобразования:
Объединим полученные значения атрибутов Asciidoc (два файла, т.к. описание сервиса по выдаче ЕГРЮЛ состоит из двух схем xsd) и файл с содержанием выписки:
На выходе Microsoft Word даёт следующую картинку:
Борьба с пробельными символами
Поскольку конечным форматом преобразования является текстовая разметка, вопрос пробелов крайне важен: текст, смещенный на несколько пробелов, может быть воспринят как блок с моноширинным текстом.
Пробелы могут влиять на эстетику, читаемость и обрабатываемость выходного документа. Например, после каждого абзаца в Asciidoc должно быть два переноса строки. Их может быть и три, но читается файл хуже. Во многих автоматически сгенерированных документах количество переносов строк абсолютно не предсказуемо. Особенно это неудобно при сравнении версий файла. При наличии на выходе файла в формате XML или JSON можно было бы применить утилиты, создающие красивый выходной файл. Для текстовых маркапов, насколько я знаю, таких утилит не существует.
С другой стороны, крайне важно, чтобы сам шаблон был красивым и удобным для чтения и редактирования, чтобы, как минимум, были отступы в циклах и условных операторах.
Поработав со многими шаблонизаторами, пришёл к выводу, что единственный практически универсальный вариант — указать шаблонизатору, чтобы он вырезал все пробелы и переносы, а переносы указывать вручную в шаблоне. В приведенном примере есть опция и после каждой выводимой строчки помещена команда
. Некоторые шаблонизаторы воспринимают \n как символ переноса. Если нет, необходимо провести пост-обработку выходного файла и самостоятельно заменять данную комбинацию на перенос строки.
Рекурсия
Рекурсия обеспечивает наглядный способ обхода узлов структурированного документа с большим количеством единообразных уровней иерархии, как в приведённой выписке из ЕГРЮЛ.
Экранирование и другие операции со вставляемыми данными
Данные для вставки в Asciidoc файл могут вступить в конфликт с разметкой Asciidoc. Например, вы хотите взять текст из Open API спецификации и добавить символ « ; ». Однако разработчик мог при описании сам поставить тот же символ. В результате в выходной файл попадёт два символа « ;; » и Asciidoc будет воспринимать текст как терминологический список, и хорошо ещё, если мы быстро поймём, почему на выходе текст отформатирован странно.
Для полного отключения синтаксиса Asciidoc во вставляемых значениях, достаточно их просто экранировать.
Выводы
И анонс: следующая статья будет посвящена вопросам обеспечения качества документации в формате Asciidoc.
Автоматическое создание документации к программам на MQL5
1. Введение
Большинство Java программистов знакомы с автоматическим созданием документации, которая может быть создана при помощи программы JavaDocs. Идея заключается в структурированном комментировании кода и создании удобного файла справки.
В мире C++ также есть несколько автоматических генераторов документации, одними из лидеров являются программы Microsoft’s SandCastle и Doxygen.
2. Программа Doxygen
Программа Doxygen является системой автоматического создания документации c открытым исходным кодом в соответствии с GNU General Public License. Это означает, что ее разработка была похожа на другие проекты с открытым кодом, такие как Linux и Mozilla. Ее можно бесплатно скачать и использовать, исходный код Doxygen открыт для всех. Программа была разработана и совершенствуется несколькими разработчиками.
2.1 Загружаем Doxygen
Рис 1. Загрузка Doxygen
2.2 Настраиваем и запускаем Doxygen
Теперь все готово. Имейте в виду, что Doxgyen сохранит данные настройки в конфигурационном файле. Подготовленный файл с настройками приложен к статье.
Рис 7. Запуск Doxygen
2.3 Использование Doxygen
В качестве примера рассмотрим функцию CiMACD::Create() в файле MQL5/Include/Oscilators.mqh. Имейте ввиду, что файлы с описанием индикаторов отсутствуют в самой первой поставке MetaTrader 5. Для их получения, возможно, понадобится скачать последнюю версию MetaTrader 5.
Некоторые простые изменения ключевых слов позволят программе Doxygen правильно интрепретировать комментарии.
Для этого комментарии должны быть вида «///» (вместо «//»), в описании входных параметров «INPUT:» нужно заменить на «\param«, а «OUTPUT:» на «\return«.
После обработки программой Doxygen, файл справки будет выглядеть, как показано на рис. 8:
Рис 8. Описание функции CiMACD::Create(), созданное Doxygen
2.4 Используем Doxygen для документирования всего кода, поставляемого с MQL5
Я написал утилиту в виде скрипта MetaquotesCommentsToDoxygen.mq5 (прилагается к статье), который производит автоматическую конвертацию комментариев разработчиков компании MetaQuotes, таким образом, чтобы Doxygen смог их интерпретировать. Этот шаг не является необходимым для создания файла справки, однако он позволяет продемонстрировать полезные дополнительные возможности документирования, реализованные в программе Doxygen.
Для создания справки по всему коду MQL5, поставляемому с MetaTrader, нужно сделать следующее:
Если нужно включить в документацию обработку комментариев, их нужно предварительно структурировать:
Рис 9. Список классов, созданный Doxygen
Рис 10. Диаграмма потомков класса CArrayObj, созданная Doxygen
Рис. 11. Список функций класса CArrayObj, созданный Doxygen
Рис 12. Список определений (defines), созданные Doxygen
3. Программа Microsoft HTML Help Workshop
Остался всего один шаг для того, чтобы сделать еще более удобной документацию, созданную при помощи Doxygen. Программа Doxygen создает файл index.html, который содержит ссылки на множество других html-файлов и картинок. Это похоже на небольшой web-сайт, такая громоздкость делает документацию неудобной для распространения.
Давным-давно Microsoft осознала, что файлы справки для Windows-приложений лучше делать в HTML, для этой цели они разработали программу HTML Help Workshop. Эта программа берет файлы, созданные при помощи Doxygen, и компилирует их в один файл справки CHM. Файлы справки MetaTrader 5/MQL5 имеют тот же формат.
3.1 Загружаем HTML Help Workshop
Вы можете скачать и установить htmlhelp.exe с сайта Microsoft.
Рис 13. Загрузка HTML Help Workshop
3.2 Создаем скомпилированный файл справки HTML
Результаты работы Doxygen могут быть легко сконвертированы в файл справки CHM при помощи программы HTML Help Workshop. Используя наши настройки, Doxygen создает файл index.hhp, готовый для использования в программе HTML Help Workshop, как показано на рис. 14.
Рис 14. Местонахождение файлов index.htm и index.hhp, созданных Doxygen
Рис 15. Компиляция файлов в CHM при помощи HTML Help Workshop
. когда она завершена, можно скопировать и переменовать созданный файл index.chm в папку MetaTrader 5/Help, как показано ниже на рис. 16 и 17.
Рис 16. Местонахождение созданного файла справки index.chm
Рис 17. Копируем index.chm в каталог справки MQL и переименовываем его в MQL5 codeset help.chm
4. Итоги
Результаты данной работы убедили меня использовать Doxygen (или похожие программы) в будущем для создания документации к любому моему коду на MQL5, это значительно облегчает его понимание и использование. Надеюсь, что другие авторы также найдут Doxygen полезным.
11 августа 2015 г. Комментирование кода и генерация документации в PHP
Зачем нужны комментарии к программному коду? В каком виде их писать? Где они нужны, а где нет? Как правильно комментировать код? Как придерживаться одинакового стиля документирования всем участникам команды? Какие есть инструменты для генерации документации? В этой статье я постараюсь дать ответы на эти и другие вопросы, а также поделюсь своими мыслями по этому поводу. И поможет мне в этом кролик…
Итак, документация для программы бывает двух видов. Первая — это в самом коде программы в виде комментариев. Второй вариант — используется сторонний инструмент или отдельное место для хранения, например WIKI-движок, в котором описываются концепции работы приложения, примеры использования, взаимодействия между модулями, приводятся разные блок-схемы и диаграммы, в общем, всё то, что нельзя засунуть в код.
Варианты размещения документации
Давайте для начала рассмотрим документацию за пределами кода программы. Хотя это не есть целью данной статьи. В open source проектах нередко встречается практика, когда статьи по документации хранятся в том же репозитории, что и основной код. Например, в библиотеке для генерации фейковых фикстур для PHP документация помещена в README файл; чтоб дочитать до конца, нужно немного поскролить. Популярный HTTP-клиент для PHP Guzzle хранит инструкции по применению в разных файлах в отдельной папке docs. Хранить документацию возле кода — это, конечно, хорошо и удобно. Один раз скачав пакет вендора, у вас есть и код, и документация. Если ваша библиотека небольшая, если она стабильная и не предполагает в будущем постоянных изменений API, которые повлекут за собой постоянное переписывание документации, тогда можете смело размещать документацию в репозитории вашего проекта.
Но всё же всему есть разумный предел. Например, если вы затеяли создание собственного фреймворка, который пишется командой разработчиков, и планируете постоянные релизы, он должен быть полностью задокументирован, более того, документация должна быть переведена на несколько языков, и тогда помещать документацию в репозиторий проекта — не вариант. Потому что для документации характерны постоянные правки, доработки, переводы, исправление опечаток. Это все выливается в большое количество коммитов-фиксов, которые засоряют историю проекта. Навигация по истории коммитов, где изменения кода теряются между изменениями документации, сложна и неудобна. В таком случае лучше создать отдельный репозиторий для документации, например, как это сделали для Symfony. GitHub, GitLab, Bitbucket также предоставляют встроенный инструмент WIKI, его фишкой является то, что он прикреплен к проекту, т.е. не является самостоятельным репозиторием. Но к нему также можно обращаться через Git, т.е. стянуть себе документацию, редактировать её в удобном для себе редакторе, группировать изменения в коммиты и отправлять на сервер, так же и получать свежие правки. Вот пример хорошо оформленной WIKI для библиотеки визуализации D3.js. Конечно, же можно создать сайт для своего продукта и разместить документацию на нем. Но если вы используете какой-либо способ из перечисленных выше, то вы сможете сгенерировать веб-страницы документации из вашего Git или WIKI репозитория, инструменты для этого есть. Если вы любитель комплексных решений, обратите внимание на Confluence от Atlassian. Возможности Confluence вышли далеко за пределы обычного WIKI-движка.
Комментирование кода в коде
Опустим реализацию этого интерфейса, просто создадим новый объект от класса Rabbit :
Код читается естественно. Метод run заставляет кролика бежать, метод stop также интуитивно понятен, он останавливает текущее действие, и кролик замирает на месте. Теперь давайте немного надрессируем животное и научим его бежать на определенное расстояние, которое будем передавать как параметр в метод run.
И кролик побежал. только по коду непонятно, что означает число 100. Это минуты или метры, или сантиметры, или футы? Ситуацию исправил бы комментарий
Если кролик начинает «бегать» в вашем коде в нескольких местах, то каждое такое место будет нуждаться в дополнительных комментариях. Комментарии будут дублироваться и их нужно будет поддерживать в нескольких местах одновременно. Первое, что можно сделать, чтоб убрать комментарий — это заменить число на переменную.
В таком случае комментарий уже не нужен, так как читабельность чуть-чуть улучшилась, можно увидеть по коду, что кролик пробежит 100 метров. Лучшим же вариантом будет добавить контекст в название метода.
Rabbit — имя существительное, run — глагол, in metres — контекст, который мы добавляем методу, чтобы он передавал суть. Пользуясь такой схемой, можно написать методы
Они будут передавать суть метода, без дополнительных комментариев. Просто грамотно давайте имена переменным и методам, таким способом вы уменьшите количество необязательных комментариев в вашем коде. Роберт Мартин на этот счет дает совет:
Не тратьте время на написание комментариев, объясняющих созданную вами путаницу, — лучше потратьте его на исправление.
Что делать, если комментарий очень большой? Как его превратить в название метода? На самом деле, не стоит бояться длинных названий методов. Длинна метода должна быть приемлемой, чтоб одновременно передавать суть и не превращать метод в нечитабельный текст. Так будет ОК:
Но вот это уже перебор:
Такой метод тяжело читать, архитектура была выбрана неправильно. Его можно зарефакторить, например, как-то так:
Есть, правда, и исключения в длине названия методов. Например, когда вы пишете спеки на phpSpec, то можете не ограничивать себя в длине метода, главное, чтоб он передавал всю суть. Вот пример кода, взятого из документации phpSpec:
В спеках для названий методов используется запись underscore, поэтому глазу легче зацепиться за границы слов и прочитать длинное предложение. Это не по стандарту PSR, где используется camelCase, но для удобочитаемость тестов такой вариант подойдет.
Чувство меры в названиях методов приходит со временем, с опытом. Можно подсмотреть, как это делают в популярных фреймворках и библиотеках.
Характеристики комментариев
Для комментариев свойственные также следующие характеристики.
Неактуальность
Очень часто, меняя код, забывают поменять комментарий. Это особенно актуально, когда над одним участком кода трудятся несколько программистов. Комментарии есть, но они написаны одним из программистов, остальные не решаются изменить чужие комментарии либо ленятся, либо просто не обращают внимание. В результате, старый неактуальный комментарий только запутает нового человека в команде. Решение проблемы простое. Либо всегда следить за актуальностью комментариев, что потребует значительного внимания и стараний. Либо удалить неактуальный комментарий. Отсутствие комментария лучше, чем устарелый, неактуальный комментарий.
Избыточность
Это когда комментарий написан там, где он не нужен, где все понятно и без комментария. Вот пример кода, отягощенного избыточными комментариями.
Код останется абсолютно понятным, если комментарии уберем, так как код читабельный.
Неполнота
Во время написания программы вы можете быстро зафиксировать свою мысль в виде комментария сразу в коде. Позже вы вернётесь к этому месту, комментарий напомнит вашу мысль, и вы сможете ее продолжить. После того, как мысль превратилась в код, неполный комментарий нужно убрать, либо превратить его в что-то более осмысленное. Другими словами, не заставляйте читателей догадываться что вы имели в виду. Например, рассмотрим процесс приема пищи кроликом:
Что означает комментарий, что «кролик умрет»? В жизни этот процесс понятен. А в программе? Что автор хотел сделать после этого? Освободить память занимаемую кроликом? Кинуть исключение и обработать его в другом месте? В данном коде с кроликом ничего не случится, он просто не получит новых калорий от поедания чего-либо, кроме морковки и капусты. Но для нового человека, который будет дописывать код, замысел автора непонятен. Скорее всего новичок удалит комментарий и сделает по-своему.
Недостоверность
Людям свойственно делать ошибки. Программисты их делают не только в коде, но и в комментариях. Либо из-за невнимательности, либо из-за усталости, либо из-за незнания иностранного языка в комментарий вносится путаница и дезинформация. К сожалению, от этого никто не застрахован. Единственное, что можно посоветовать в таком случае — это ответственно относиться к комментариям. Если вы уже решились что-то написать, то пишите грамотно. Перфекционизм в комментариях не помешает 🙂
Неочевидность
Это когда в конкретном месте кода используются неизвестные или не очевидные термины.
Тут указывается, что рост кролика определяется каким-то коэффициентом (сам придумал :)), который зависит от каких-то факторов. В данном месте непонятно, что означает коэффициент роста кролика и как он считается. Чтоб разобраться, как работает эта функция, все равно придется переходить в ее описание и изучать код. Лучше комментарий отсюда убрать, а разместить более детальный комментарий в описании самой функции.
Так что, комментарии вообще не писать?
Писать, но нужно брать за них ответственность. Вот моменты, когда они необходимы.
Информативность
В некоторых местах без комментариев не обойтись. Когда нужно объяснить алгоритм или когда группа программистов была вынуждена временно применить какой-то «костыль» в коде, желательно оставить комментарий об этом. Написать, зачем оно было сделано, что оно затрагивает и когда должно быть исправлено. Но все же старайтесь правильно подбирать названия вашим переменным и методам.
Регулярные выражения всегда меня вводят в ступор и приходится тратить достаточно времени, чтоб их расшифровать. В таком случае информативный комментарий не помешает:
Намерения
Одну и ту же задачу на языке программирования можно решить многими способами. Программист имеет собственный стиль программирования и, знакомясь с кодом другого программиста, с другим стилем, ему может быть тяжело прочитать код «по диагонали». Если вы обладаете каким-то особым стилем программирования, либо по опыту знаете, что алгоритмы, которые вы используете, тяжело читаются другими, то оставляйте в коде подсказки непосредственно перед началом сложного участка кода.
Предупреждения
Бывают случаи, когда пока каким-то причинам нельзя использовать ту или иную функцию (например, не установили еще необходимое расширение на продакшене, либо не обновил вендор), либо какая-то функция выполняется очень долго и без необходимости ее лучше не запускать, либо из-за большой потребности в ресурсах цикл нельзя выполнять более Х раз. В таких случаях комментарии будут очень полезными.
Усиление
Когда одна строка кода является настолько важной, что необходимо обратить на нее внимание. Например, однажды со мной случился случай, когда на стейджинге не была задана кодировка для мультибайтных функций, я очень долго искал проблему и когда нашел, то добавил в свой код ручную установку параметра с пояснительным комментарием для чего это нужно:
И еще один совет от Роберта Мартина:
Не документируйте плохой код — перепишите его.
Если вам довелось встретиться с жутко непонятным кодом, вы потратили много времени на его разбор, а после решили добавить от себя пару комментариев для будущих разработчиков, то код от этого лучше не станет. В этой ситуации, раз вы уже достаточно разобрались с кодом, попробуйте зарефакторить его до более читабельного состояния. Правило бойскаута гласит: «оставьте место (код) чище, чем было до вашего прихода».
Документируем с помощью докблоков
Есть отдельный вид комментариев в PHP, который имеет свой устоявшийся стандарт — это докблоки (DocBlock). Для обработки докблоков существует инструмент phpDocumentor (ранее известен как phpDoc). Он умеет читать докблоки из кода и строить на их основе документацию. DocBlock — это комбинация DocComment и помещенных в него описаний по стандарту PHPDoc. В PHP есть поддержка C-подобных многострочных комментариев (DocComment):
Докблок отличается дополнительной звездочкой /** в начале комментария:
В данном примере @param, @return, @throws являются тегами PHPDoc и будут распрарсены с помощью phpDocrumentor’а. @Rest\Post(«/login») — это аннотация FOSRestBundle. Отличие аннотаций от тегов в том, что теги просто документируют код, а аннотации меняют или добавляют поведение для кода. Отличительная черта аннотаций PHP от аннотаций Java, в том, что в Java аннотации являются частью языка, а в PHP — всего лишь комментариями, и чтоб к ним достучаться приходиться использовать рефлексию. Возможно в будущем аннотации также станут частью PHP, а пока для их считывания используется вот этот парсер https://github.com/phpDocumentor/ReflectionDocBlock. Так же стоит заметить, что если мы изменим начало докблока с /** на /* это уже не будет считаться докблоком, даже если там есть теги или аннотации, соответственно парсер проигнорирует это место.
Докблоки настолько прижились в коммюнити PHP-программистов, что на их основе готовится PSR-5 (PHP Standard Recommendation). На момент написания статьи он еще находился в черновом варианте.
В PHP с помощью докблоков можно документировать такие элементы:
Важно также, что один докблок может быть применён только к одному структурному элементу. Т.е. на каждую функцию — свой докблок, на переменную внутри функции — свой, для класса — свой.
В PHPDoc существует много тегов, но не каждый тег применим ко всем структурным элементам. Ниже предоставлен список существующих тегов, область их использования и объяснение.
Устаревшие теги, которые, скорее всего, в будущем не будут поддерживаться:
Удобство использования докблоков в IDE
Если вы разрабатываете open source проект, то конечно документирование публичного API с помощью докблоков необходимо. Это не только позволит вам сгенерировать готовую документацию, но также позволит использовать ваш код удобно другим разработчикам в своих IDE. Что касается вашего приватного кода для аутсорс проекта, то использование докблоков может показаться не очень уместным, тем не менее советую их использовать, это значительно ускорит вашу разработку.
Для примера возьмем самую популярную IDE для PHP — PhpStorm. Рассмотрим предыдущий пример поиска кроликов:
Или добавить тег @return в метод findRabbitsInLocations :
Таким образом, не отрываясь от клавиатуры, вы можете использовать классы с публичными методами, которые написали ваши коллеги. PhpStorm будет выдавать вам подсказки, и если метод назван понятно, вы сможете использовать его даже без чтения его исходного кода и документации.
Еще одна полезная фича докблоков в паре с PhpStorm — это предупреждения о неправильных входных параметрах. Допишем докблок для одного из методов класса Rabbit :
Тут мы указываем, что на вход должно приходить целое число (опять же, в PHP7 это возможно будет задать на уровне синтаксиса самого языка). Что будет, если мы передадим в этот метод массив?
Как соблюдать стили комментирования
Это хорошо, если все участники команды соблюдают правила документации для PHPDoc. Но все же на практике все намного печальнее. Полностью соблюдать стандарт получается только у перфекционистов, либо у тех, кто долго пользуется докблоками и это у них автоматизировано. Есть категория программистов-новичков, которые хотят использовать докблоки, но забывают их иногда использовать, либо еще не полностью разобрались с тем или иным тегом. Ну конечно же, есть упертые люди, которые не делают это, даже если предварительно команда согласилась делать.
Чтоб минимизировать дискомфорт, нужно заставить каждого участника команды включить в PhpStorm инспекцию докблоков Settings > Editor > Inspections > PHPDoc и отметить там все галочки:
Так же следует использовать PHP CodeSniffer (phpcs) с подходящим вам код стайлом. Не уверен, как насчет всех код стайлов, но для Symfony докблоки являются обязательными. Поэтому phpcs в Шторме будет выдавать вам предупреждения на лету. Настройки делаются в том же месте, а вот еще есть дополнительная инструкция.
Конечно это не заставит всех на 100% придерживаться правил. Но особенных ленивцев можно нагрузить еще одной цитатой из книги «Чистый код», правда, это больше относиться к форматированию кода, но смысл тот же:
«Правила должны соблюдаться всеми участниками группы. Это означает, что каждый участник группы должен быть достаточно разумным, чтобы понимать: неважно, как именно размещаются фигурные скобки, если только все согласились размещать их одинаковым образом.»
Генерация документации с помощью phpDocumentor
Теперь, когда все придерживаются правил, и ваш код покрыт докблоками, можно сгенерировать документацию. Приводить всю документацию по phpDocumentor не буду, всего лишь минимум команд, остальное на официальном сайте.
Итак, нужно установить phpDocumentor. Его можно поставить глобально вот так:
Либо добавить как зависимость в composer.json вашего проекта.
А теперь, находясь в директории проекта, который вы покрыли докблоками, просто запустите из консоли:
Генерация документации с помощью Sami
Еще один инструмент для генерации php-документации на основе докблоков — утилита Sami. Возможно, она не такая известная, но я решил ее упомянуть, так как с помощью Sami генерируется документация нашей любимой Symfony. А написал эту утилиту сам Fabien Potencier, и писал об этом когда-то в своем блоге.
Заключение
Это всего лишь небольшой обзор проблемы комментирования кода и способов ее решения в PHP. Данная статья затрагивает всего понемногу, чтоб побудить желание исследовать тему документации кода самостоятельно. Если вы новичок в PHP, то советую почитать подробную документацию о phpDocumentor. Если у вас богатый опыт разработки проектов с хорошей документации, то можете поделиться им в комментариях. ^_^