Ты не видел тут американскую подлодку? Видел. Куда она поплыла? Курс Зюйд-Зюйд-Вест. Ты не умничай, пальцем покажи.(С) бородатый анекдот За работу Уатт потребовал 1000 фунтов, и когда у него попросили счет, он написал: «Удар кувалдой — 1 фунт, знания, куда ударить, — 999 фунтов»(С) исторический анекдот За время карьеры, чаще всего сталкивался с ситуацией — когда получаешь проект в котором непонятно, где «вход», где «выход» и один только вопрос — «куда ткнуть?!». Товарищи, давшие проект, говорят — «это делал Вася, но он уже уволился, а на звонки не отвечает и никто не знает что к чему». Знакомая ситуация? Так же, после перебросок между многочисленными проектами бывало — когда смотришь непонимающе на код, а в коммитах автором видишь своё имя, но уже не помнишь вообще что к чему и как писал. Знакомо? В какой‑то момент меня стала доставать такая ситуация и я сделал себе небольшую автоматизацию, что бы снизить количество проблем и ненужных нагрузок на мозг, это — карта проекта. В 2015м году, устав от постоянного отсутствия документации по проектам, я сделал себе специальный плагин и редактор позволяющие мне хранить описание проектов и неформализованные знания в виде интеллект‑карт (mind maps). Они оформляются текстовыми MMD файлами (сходными по формату с Markdown) и хранятся прямо среди исходных текстов проектов, попадая и в системы контроля версий. Об этом я уже писал статью на хабре и желающие могут ознакомиться по ссылке. Мой плагин для работы с интеллект‑картами позволяет их формировать и редактировать вручную, но бывало «протухали» ссылки после рефакторинга и переименования исходных текстов. Была идея подключиться к подсистемам IDE и отслеживать редактирование исходников, внося изменения динамически в карты, но это и непросто и к тому же не универсально. Мне захотелось генерировать карту приложения автоматически, на базе проставленных меток и не быть привязанным ни к средам разработки, ни к билд‑системам. В Java для этого идеально подходит аннотирование исходных текстов в нужных местах и как универсальное средство обработки — процессоры аннотаций, которые можно подключить прямо к Java компилятору. Так что напросился логичный вывод — сделать набор аннотаций для пометки нужных и важных мест в исходниках проекта и к нему сделать обработчик, который, в процессе компиляции, строит карту опираясь на помеченные места. Это позволило отвязаться от IDE в процессе и дать возможность в билд‑системах просто генерировать документацию по запросу, например через активацию профиля в том же Maven. Я хотел бы кратко показать как это работает, на примере известного очень многим проекта Spring Pet Clinic. Добавим специальный профиль в Maven проект и будем получать (по запросу) карту размеченных «точек интереса» этого проекта. Начнем с клонирования проекта из GitHub Проект поддерживает одновременнно и Gradle и Maven билд-системы, но я буду показывать только на примере Maven, так как пользуюсь в основном им (для Gradle тоже есть вариант на wiki-странице проекта). Сбилдим проект для уверенности, что проект не содержит ошибок. В Maven это производится вводом команды mvn package (активной должна быть директория содержащая pom.xml проекта). Первым делом добавляем зависимость с аннотациями в проектный файл pom.xml (это дескриптор проекта для Maven). Добавленный пакет содержит весь требуемый набор аннотаций помеченных как "уровня исходных текстов", то есть компилятор не поместит их в итоговые скомпилированные файлы. Следующий шаг — добавить профиль, подключающий процессор аннотаций к процессу компиляции. Процессор будет извлекать информацию из аннотаций и формировать нужные нам документы при активации этого профиля. Профиль нужен, что бы получать документы по запросу, а не включать их генерацию в каждое построение проекта, хотя и такое тоже можно. Мы получили в проекте дополнительный Maven-профиль mmddoc который можем активизировать, добавив в список активных профилей при построении проекта. При выполнении проект строится, но никаких изменений в процессе и результатах мы пока не видим. «Что бы получить что то нужное, надо добавить что то нужное» — нам надо добавить аннотации‑метки. Первая важная аннотация, которая запускает процесс, это аннотация com.igormaznitsa.mindmap.annotations.MmdFile. Именно она говорит процессору, что следует создать MMD файл. Добавим её в главный класс, запускающий приложение PetClinicApplication. Но нам мало просто добавить эту аннотацию, мы должны прописать имя файла и указать корневой элемент карты, описывающий приложение, так что выглядит это в коде вот так. Мы задали целевое имя файла PetClinic, задали ему уникальный идентификатор MAIN_APP который может использоваться в других аннотациях если потребуется и добавили корневой элемент содержащий текст Pet clinic application. Вроде всё работает и в исходных текстах при вызове генерируется MMD файл содержащий карту, которую может отрисовать плагин для NetBeans или Intellij IDEA. Но при щелчке по иконке файла в карте мы никуда не переходим и видим сообщение об ошибке «файл не найден». Это потому, что нам надо настроить пути для генерации. Плагин ждет, что ссылки будут относительными путями от корневой директории проекта. Добавляем к нашему процессору параметр, описывающий путь к корню проекта. Проект одномодульный, поэтому путь тривиальный и просто берется из project.basedir предоставляемой Maven. Опять перестраиваем проект с профилем mmddoc и получаем файл с корректно работающей ссылкой, которая открывается при кликом мыши и позиционирует нас на ту самую строку, где расположили нашу аннотацию. Теперь наша карта не даст нам никогда забыть — «где же у нас находится точка запуска приложения?», но этого маловато. Пора добавить на карту более ценную информацию — например информацию об HTTP контроллерах и их опубликованных методах. Начнем пожалуй с контроллера «ветеринара» в классе VetController. Идем в этот класс и добавляем к его заголовку «хитрые аннотации». Что же они значат? Первая аннотация MmdFileRef. Она говорит процессору, что для всех MMD узлов, найденных в классе, следует использовать файл документации с идентификатором MAIN_APP. Если еще помните, это тот самый идентификатор который мы присвоили файлу карты в PetClinicApplication. Следующая аннотация MmdTopic. Она создает на карте узел с текстом Vet и ссылкой на строку в файле где расположена. Но что бы выделить, что это «контроллер» и поместить его в раздел Controllers, мы задаем путь где указываем, что данный узел на карте должен располагаться как дочерний у узла с текстом Controllers (процессор сам автоматически создаст такой узел если не найдет). Результат нового построения MMD документа дает нам следующее изменение карты Наша карта уже начала нести смысл и теперь любой может, открыв её, сразу понять где главный элемент приложения, а где находится контроллер для Vet. Всего парой кликов на карте перейдя в нужную точку кода. Но давайте добавим больше информации по контроллеру. Там имеются методы обрабатывающие HTTP запросы, их стоит нанести на нашу карту. Для этого, к найденным HTTP методам, добавим аннотации MmdTopic  После повторного построения проекта, наш документ изменился. Теперь карта несет полезную информацию и нанятый джун Петя, при требовании подправить «что‑то там с показом списка ветеринаров», не будет рыдать и клясть судьбу, пытаясь выяснить — «дяденьки! Какой класс отвечает за показ ветеринаров в нашем проекте?! В каком месте?!». Он просто откроет карту и ткнет мышью, попав в нужное место проекта. Обратите внимание, что у добавленных узлов еще и появились какие‑то записи рядом с файловыми ссылками. При щелчке на них, Петя увидит тип HTTP метода и его путь запроса, т. е. ту информацию которую мы указали в аннотации в поле note. Давайте добавим еще один контроллер, на этот раз — контроллер владельца животного. Он расположен в классе OwnerController. Сначала опять добавим ссылку на главный файл документа, что бы указать где хранить узлы определенные в классе. Затем определим базовый узел класса с указанием, что он должен так же лежать в пути с узлом Controllers  На карте приложения добавился еще один узел, описывающий "Владельца" Добавим метки ко всем его HTTP методам. Итоговая карта стала гораздо насыщенней Давайте рассмотрим - что же мы такого сделали на примере метода showOwner Обратите внимание, что MmdTopic аннотация была добавлена и к аргументу метода описывающему переменную HTTP пути и мы на полученной карте видим эту отметку (а кликнув на её файловой ссылке, можем сразу перейти на точку определения параметра). Всё вроде хорошо, но нас не очень устраивает, что полученный документ расположен в папке с исходными текстами, давайте вынесем его в какую то более подходящую папку. Для этого мы добавляем в параметры процессора аннотаций пару дополнительных параметров. Первый говорит процессору где хранить сгенерированные документы, а второй разрешает его автоматически создавать. Я выбрал .projectKnowledge, потому что плагины для IDE исторически автоматически распознают эту папку и её содержимое можно найти через специальную форму в той же Intellij IDEA. Вот в принципе и всё нужное для минимального использования инструмента. Можно менять цвета, расположения, добавлять URL в узлы и «эмотиконы», но это уже «сахар» и с этим можно играться самостоятельно. Главное, что теперь у нас есть минимальная карта приложения, которая всегда может быть сгенерирована по запросу или обновлена при построении проекта и заинтересованное лицо сразу увидит наличие контроллеров и их HTTP методы. Любые изменения в позиционировании или именах файлов, любой рефакторинг, всё это после перестройки карты будет отображено и не надо будет лазать по текстам и клясть «устаревшую документацию». PetClinic это одномодульный проект с простой иерархией. Не так часто в энтерпрайз мире мы имеем дело с простыми проектами, как правило мы имеем дело с многомодульными иерархиями проектов. Плагин IDE, отображающий карту, рассчитывают путь файловых ссылок от корня самого верхнеуровневого проекта, что неочень совместимо с использованием maven параметром project.basedir, который содержит путь к директории текущего обрабатываемого проекта. Для таких таких случаев я использую специальный плагин, позволяющий мне получить путь к корневому родительскому модулю и сохранить его в выбранном свойстве. Выглядит полный maven профиль так:  Плагин  directory-maven-plugin ищет самую верхнеуровневую директорию проекта и помещает её путь в свойство mmd.basedir, которое я потом использую как базовый путь для  генерации ссылок. Помимо всего прочего, иногда полезно включить очистку папки с документами в фазу инициализации построения проекта. Это можно сделать, добавив следующий вызов maven-clean-plugin  Разработчик разнопрофильного ПО