В этой статье пойдет речь о том, как я подошел к документированию баз данных продуктов Veeam на MediaWiki движке. Сразу оговорюсь, что документация эта служит исключительно для внутреннего пользования, поэтому я много где позволял себе определенные вольности.  Хоть главной причиной выбора платформы MediaWiki и было нежелание плодить без необходимости сайты документации, это решение также позволило воспользоваться многими преимуществами MediaWiki: понятный и привычный интерфейс, удобство поиска, полуавтоматическое создание документации и многое-многое другое. Ahoj! Меня зовут Коля, я QA тимлидер. QA в Veeam включает в себя не только/не столько тестирование, сколько обеспечение качества в широком смысле. И среди прочих значений этого самого широкого смысла затесалась такая штука, как управление знаниями. По этой теме довольно много абстрактных статей и книг, повествующих о принципах Knowledge management, но на удивление мало конкретных рекомендаций и практически применимых идей, во всяком случае сколько-нибудь свежих. Это заставляет меня думать, что или все пользуются тем, что дают известные компании и радуются, или не пользуются ничем и страдают, или пилят свой тайный велосипед, о котором неловко рассказывать в приличной компании. Мне тоже неловко, но я все-таки расскажу. Не томи, зачем конкретно мы тут все собрались? Дано: Продукты с многолетней историей разработки; Полное отсутствие документации БД при наличии большого запроса на нее (особенно в разрезе описания таблиц, столбцов и типов хранимых данных); Вагон страданий QA, Support & Dev; База знаний на движке MediaWiki, к которой RnD привык и с которой все более-менее освоились; Наличие очень небольшого количества времени, которое можно посвятить задаче. Все ж основные рабочие обязанности никуда не исчезли.  Найти: Способ организовать документацию БД на той же MediaWiki, где лежит вся остальная документация. Заставлять коллег пользоваться N+1-ым сайтом для документации чего-то специфичного — бессмысленно и бесчеловечно.  Решение: После множества обсуждений вопроса с техническими писателями в разных публичных чатиках мне стало понятно, что самым адекватным решением будет примерно такой подход: Вытягиваем описания таблиц из кода на TFS Закидываем на MediaWiki информацию о таблицах Силами сотрудников добавляем к этому описания уже на самой вики Звучит просто, но дьявол, как всегда, кроется в деталях. А можно немножко больше контекста перед началом? У нас в компании для работы со внутренней документацией используется большое число разных порталов: и несколько Sharepoint-ов, и пачка Confluence, и файлы на сетевой папке, и, конечно, единственный и неповторимый MediaWiki портал. Он же и самый популярный. На этой вики хранятся описания реестровых ключей, описания различных внутренних и внешних API, статьи по продукту, контакты, описания БД наших продуктов и многое-многое другое. Чуть больше про эту платформу — в моей прошлой статье. Добавление каждого нового типа контента на вики — это целая история со своими взлетами и падениями, героями и злодеями. С базами данных мне довелось провозиться больше всего, так что и рассказ я решил начать с них.  Я не из тех, кто в каждой статье сразу в технические дебри лезет! Мне б сперва с результатами познакомиться...  Страница с описанием таблицы выглядит следующим образом: Здесь есть описание самой таблицы, описание ее столбцов (имя, тип, комментарий), ссылки на типы данных, информация о ссылках между таблицами... И это все?А разговору-то было... Разумеется, это не все! Этот подход предоставляет целый ворох дополнительного функционала, который куда более интересен, чем просто описание таблиц: Механическая работа по добавлению на вики статей о новых таблицах довольно просто автоматизируется, так что все, что будет требоваться от ваших коллег — это добавлять или обновлять комментарии. Чем проще добавлять информацию на вики, тем более охотно этим займутся другие сотрудники.  При помощи того же подхода на вики были добавлены описания enum-ов и прочих типов данных, хранимых в таблицах. Это позволяет, например, не заглядывая в код понять, что такое job_type=14000. Описания типов хранятся в базе примерно так же, как и описания таблиц. В этой статье я не буду рассказывать о том, как организована работа с enum-ами, но если будут заинтересованные, то могу описать в отдельной статье или в комментариях.  Также информацию о таблицах можно добавить на другие страницы. Причем не статический список таблиц, а динамический. Т.е. при добавлении новых таблиц в категорию вам не придется править что-либо в других статьях. Информация автоматически подтянется всюду.  Для удобства навигации и общего понимания связанной с таблицей функциональности таблицу можно добавить в одну или несколько категорий. А сами категории можно вывести в виде дерева при помощи специального расширения.  У категорий есть приятная особенность: они не обязаны формировать дерево, они могут формировать граф. Иными словами, дочерняя категория может быть включена в две и более родительские. Это чертовски упрощает навигацию: вам не приходится гадать, где находится категория "Agent Logging" — в категории "Agent" или в категории "Logging": "Agent logging" находится и там, и там. В поиске по вики можно задать, что вам интересны только таблицы. Более того, можно задать, таблицы какого продукта вам интересны. Кроме этого, семантический поиск позволит искать также по всем полям таблицы. Например, найти все таблицы без описаний или все таблицы, добавленные в версии продукта 1.0.  Для редактирования описаний таблиц можно воспользоваться специально созданными для этого формами. Формы значительно упрощают процесс редактирования. Кроме прочего, информацию о таблицах можно получать через API. Это может быть полезным в самых разных ситуациях: от автоматизации документации до миграции документации на другие порталы (если вдруг вы решите отказаться от MediaWiki, это не станет катастрофой: вы сможете сравнительно безболезненно смигрировать данные).Пример запроса информации по таблице (в нем я запросил только имя и описание) Все свежие правки появляются в новостях, и это решает сразу две проблемы:  Это позволяет информировать заинтересованных пользователей обо всех изменениях схемы;  Появление твоего ника в новостях — маленькое удовольствие, мотивирующее вносить правки. И многое-многое другое. Функционал ограничен только мерой испорченности вашей фантазии и списком расширений MediaWiki.  Выглядит интересно. Как это завести у себя? С чего начать? Для начала создадим пространство имен для того, чтобы отделять логически статьи с описаниями таблиц от обычных статей. Таблицам можно задать свои веса в поисковой выдаче, а также определить другие вспомогательные параметры Когда все готово, мы можем наконец создать шаблоны наших будущих страниц. Окей, погнали!Как будут выглядеть страницы с описаниями? Хочется их как-то унифицировать. Действительно, страницы с описаниями таблиц имеет смысл делать как можно более одинаковыми: это упростит как чтение, так и создание/редактирование. Для этого определим т.н. шаблон MediaWiki — страницу, которая будет определять, как нам выводить информацию. Сама же информация будет храниться в предельно упрощенном формате.  Будет трудно, крепитесь. На самом деле нам потребуется не один шаблон, а два: один для общего описания таблицы и другой для описания столбцов. Что бы мы хотели видеть в описании таблицы? Переведем это в формат Mediaiwki синтаксиса шаблонов. Описание страницы должно выглядеть примерно так: И из этого описания мы будем собирать приятное глазу представление.  Начнем с описания столбца. Можно было бы здесь определить то, в каком виде будет выводиться информация по каждому столбцу, но мы поступим хитрее и воспользуемся Semantic MediaWiki. Это позволит нам в шаблоне TableColumn только сохранить скрытые описания столбцов, а уже в шаблоне Table вывести пачкой все скрытые свойства. Это в разы уменьшит нагрузку на сервер, да и просто приятнее выглядит. А бонусом это позволит нам воспользоваться всеми остальными плюшками Semantic MediaWiki. Впрочем, обо все по порядку.  Semantic Mediaiwiki — расширение для MediaWiki, добавляющее поддержку Linked Data на MediaWiki сайт. С семантическими данными впоследствии можно делать много всего интересного: строить запросы, выводить их в различных форматах и работать с ними по API.  Концепция linked data не новая и пик ее популярности прошел лет 5-10 назад.  Впрочем, отдельные области применения у него остаются. Тот же Google Knowledge Graph аккумулирует информацию из множества источника связанных данных и использует это для улучшения поиска.  Semantic MediaWIki предоставляет множество приятных вещей, из-за которых я продолжаю ее использовать: Нативный API для всех определенных свойств и сущностей Множество встроенных форматов вывода хранимых данных. При этом за счет предыдущего пункта довольно легко писать и свои представления для данных В дополнение к предыдущему пункту семантика весьма быстро строит эти представления. В огромном количестве мест я менял шаблоны mediawiki на представления от semantic mediawiki, тем самым ускоряя загрузку страницы в десятки и сотни раз. Начнем с создания страницы Template:TableColumn Шаблон определяет скрытые из UI свойства. Т.е. если мы создадим страницу Test с таким описанием и сохраним: То сохраненная страница окажется совершенно пустой. Никакой контент не будет выведен, но в базу данных будет записан объект. С такими объектами довольно удобно работать при помощи метода #ask, но до этого мы еще доберемся. Приступим к составлению шаблона самой таблицы. Здесь мы уже будем не только задавать скрытые свойства, но и выводить данные в человеко-читаемом формате.  Создаем страницу Template:Table Это было сложно и непонятно, но все позади. Шаблоны готовы! Итак, мы отделили данные от их представления и унифицировали внешний вид наших страниц.     Работать с шаблонами вручную — это, кхм, развлечение не для каждого.Можно ли добавить немножко графического интерфейса для задания полей по шаблону? Разумеется, и расширение MediaWiki Page Forms сделает за нас большую часть волшебства.  Как в Linux все представлено файлом, так в MediaWiki все представлено страницей. Как и шаблон, форма — это страница в специальном пространстве имен "Form". Создаем страницу "Form:My Product Table" Теперь на другой странице добавим первый шаг создания таблицы: поле, в котором можно будет ввести имя таблицы и нажать кнопку "Создать". После нажатия кнопки будет открыта та самая форма, которую мы только что определили. Итак, можно тестировать Получится что-то такое — на странице создания статьи о таблице БД мы задаем имя таблицы и жмем кнопку: После чего появляется сама форма: А что еще эта ваша семантика умеет? Можно ли в странице о фиче вывести список таблиц, относящихся к этой фиче? У Semantic MediaWiki есть т.н. "ask" запросы со своим языком запросов и пачкой встроенных представлений данных.  К примеру, так можно вывести список таблиц из категории "HPE Lefthand" вместе с их описаниями: После сохранения будет выведена таблица с описаниями: Я прочитал заголовок, и у меня появился вопрос: зачем документации БД нужен API? Ты там таблетки не забыл принять? Во-первых, API можно использовать для автоматизации процесса документирования. Во-вторых, для интеграции с базами знаний других отделов. Например, у нас техподдержка использует отдельный портал на базе xWiki, но им эти знания не менее важны.  В-третьих... Я просто люблю API. ¯\_(ツ)_/¯ На самом деле API для чтения нам достается даром, поскольку ранее мы воспользовались Semantic MediaWiki.  API запросы очень похожи на #ask запросы, которые мы обсуждали выше Что же касается API для редактирования... С этим немножко сложнее, но давайте и об этом поговорим в рамках задачи автоматизации обновления информации о таблицах. Итак, у нас получилось что-то рабочее. Но добавление описания каждой таблицы вручную — это боль. Давай автоматизируем все, что автоматизируется? Попробуем автоматизировать добавление новых таблиц и новых столбцов у старых таблиц. У меня есть: пачка sql скриптов для создания базы продукта в TFS. На их основании мы можем создать описания всех таблиц, имеющихся в разрабатываемой версии продукта. Как именно можно превратить скрипты создания БД в пачку статей на вики? Как будем вытаскивать описания таблиц? Первой мыслью было парсить SQL скрипты самостоятельно (я не очень умный), от чего в итоге пришлось отказаться из-за высокой сложности и несовместимости найденных мной питоновских токенайзеров с Microsoft SQL Server.  Вторая, более здравая мысль — автоматически накатывать на БД скрипты для создания полной БД на отдельном инстансе SQL Server, откуда после тащить информацию через odbc (pyodbc).  В качестве языка с самого начала был выбран Python по той простой причине, что именно на питоне пишется большинство ботов для MediaWiki. Есть даже пара замечательных библиотек: Pywikibot для взаимодействия с вики и mwparserfromhell для удобства работы с шаблонами MediaWiki. Вместе эта сладкая парочка дает что-то похожее на API для редактирования страниц. Скрипт обновления информации на вики выглядит примерно так (приведен не полностью): Для получения таблиц, как я и писал выше, сперва создаем реальную БД на основании исходного кода (накатываем на базу скрипт создания БД), после чего пользуемся магией odbc: Другая интересная часть автоматизации — объединение описаний таблиц, полученных из вики и из pyodbc. Парсинг mediaiwki синтаксиса — самая сложная часть этого процесса, но тут нам на помощь придет mwparserfromhell библиотека: Voila!  Добавляем выполнение питон скрипта в дженкинс, и каждое утро на странице RecentChanges любуемся апдейтами документации: Если же где-то произошла ошибка и нужно откатить прошлую версию страницы, это можно сделать нативными средствами MediaWiki: Для каждой страницы бессрочно хранится история правок, удаления и всего остального. Как просто и удобно звучит! Наверно, это решение очень легко и быстро развернуть, а документация начнет сама себя писать, сиди только да читать успевай? Well... Выше я об этом не обмолвился ни разу, но многие из упомянутых решений из коробки не работают. Или работают, но их нужно донастраивать. Тот же VeForAll каждую версию приходится чинить самостоятельно, из CategoryTree для корректной работы пришлось убрать кеширование, PageForms сыпет багами из неожиданных мест, особенно если вы используете что-то нестандартное. А если у вас приватная вики или вы когда-либо патчили ядро MediaWiki... Лучше запишитесь к психотерапевту заранее. Даже если не трогать вопрос первичной заводки, у самого подхода уйма проблем. Перед тем как внедрять нечто похожее, стоит внимательно прочитать и переварить все нижесказанное.  Во-первых, это самодельный велосипед. Кому-то из вашей компании придется поддерживать его, и этот кто-то — это вы. Во-вторых, у Semantic MediaWiki & Page Forms не очень понятные перспективы. Это, в целом, популярные расширения MediaWiki, но они не используются в Wikimedia Foundation проектах, а значит, не исключено, что они через несколько лет перестанут развиваться совсем. Темпы их развития и сейчас не поражают воображение. Конечно, удобный API для экспорта данных и наличие конвертеров mediawiki разметки в более популярные форматы делают этот риск менее существенным (в случае чего всегда можно переехать), но переезд между платформами — это неприятно и не очень быстро. Какими бы ни были эти платформы. В-третьих, конечно, остается необходимость ручной категоризации и добавления описаний. Сделать это может кто угодно, так что в достаточно ответственном коллективе таблицы не останутся без присмотра. Но это все-таки ручная работа. Роботы не сделают за нас совсем уж все. Ишь, чего напридумывал, охальник!А чего тебе не хватает для полного счастья? На самом деле, основные потребности этот механизм документирования уже покрывает. Хотя есть еще пара нереализованных хотелок: Хочется уметь автоматически строить схему БД по категориям на основе этих данных. Может, у вас есть мысли, как это реализовать проще всего? Раскидать квадратики со стрелочками проще простого, но хочется, чтобы после генерации связи между таблицами были не очень запутанными. Ну и писать свой код не очень хочется для этого. Ссылки на Enum-ы в описаниях столбцов на данный момент добавляются вручную. Хочется в будущем автоматически вытягивать информацию о том, чего стоит ожидать в том или ином поле. Внутренние правила написания кода позволяют легко реализовать это. В перспективе хотелось бы добавить и описания хранимых процедур. Думаю, их добавить будет несложно аналогичным образом. Я читаю эту статью уже десять тысяч лет. Закругляемся? За скобками осталось огромное количество деталей, подробностей и подводных камней. Кажется, статья и так разрослась до неприличных размеров. Полученный способ документирования весьма неортодоксальный, но для конечных пользователей он оказался довольно удобным, если верить отзывам и внутренней статистике правок, поиска и посещений. В общем, оно того стоило. P.s. Спустя несколько недель после публикации я собрал простейшие диаграммы связей таблиц при помощи Mermaid и семантики. Выглядит для больших данных страшненько, но, вообще, читаемо. Подробнее о том, как оно работает, я напишу как-нибудь в следующий раз. Если вы знакомы с синтаксисом Semantic MediaWiki и Mermaid, задача не будет такой уж сложной. QA тимлид