среда, 16 марта 2011 г.

Sandcastle, MAML, и документирование ПО

Как известно, Visual Studio позволяет писать комментарии в коде в xml-формате, если они предваряются тройным слешем ("///"). Большинство при этом используют лишь пару простых тегов, как например <summary> и <param>.

На самом деле, тегов там можно использовать довольно много. Наиболее полезные, на которые я б сразу посоветовал обратить внимание - это <see cref="">, <example>, <para>, и <remarks>. Также, иногда очень полезен будет тег <list>. Более подробно обо всем этом ниже.

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


Мне пришлось разобраться со всем этим, когда разрабатывал описание API для одного из наших клиентов. И настолько мне понравился результат, что по собственной инициативе задокументировал некоторые неймспейсы основного нашего проекта, и сгенерировал по ним chm-файлик (он как раз представлен на скриншоте выше). Коллегам эта затея пришлась по душе, так что надеюсь в дальнейшем общими усилиями нам удастся эту линию продолжить, и создать документацию для большей части общих сборок.

В общем, в этом сообщении я расскажу немного про язык MAML, про инструменты для генерации документации (особенно про SandCastle), ну и вообще про то, как это все настраивать и как с этим всем работать.

XML-комментарии в Visual Studio

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

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

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

Для документирования удобнее всего использовать вышеупомянутые XML-комментарии. Это логично - все действия производятся в студии, и никаких ухищрений при этом не требуется.

Пока разбирался с генерацией документации, открыл для себя несколько моментов, касающихся XML-комментариев в студии. Спешу поделиться:
  1. Многие наверное замечали, что перенос строк в теге <summary> не работает. И складывали ласты, считая это багом. А вот и нет! Оказывается, если использовать тег <para> (параграф, аналог HTML-ного <p>), то строки замечательно переносятся даже в интеллисенсе.
     
  2. Тег <example> - очень важный и полезный тег. Всем советую его заполнять, если вы пишете reusable-код в общих сборках. Вспомните сами, насколько лучше читаются топики на MSDN, в которых есть примеры использования класса.
    Тег <example> при этом можно использовать в сочетании с тегом <code>, чтобы размещать примеры кода. При формировании документации, тег <code> автоматически обеспечивает подсветку синтаксиса, если ему заполнить атрибут language (самые частые значения: cs, vb, cpp, js, vbs, xml, html).
    Более того, <code> имеет ряд довольно полезных атрибутов, которые, например, позволят вынести код в отдельные файлы (или даже в отдельный, компилирующийся, проект!) и вставлять этот код по ссылкам.

    Пример использования тэга example в коде:
    /// <summary>
    /// Временно выставляет нужную культуру текущему потоку.
    /// Требуется для локализации
    /// </summary>
    /// <param name="code">Код, который выполняется в контексте заданной культуры.</param>
    /// <param name="lcid">Код культуры.</param>
    /// <example>
    /// Приведенный фрагмент выводит в консоль значение TestResource из TestResourceFile.resx для
    /// локали, соответствующей той, с которой был создан текущий SPWeb.
    /// <code language="cs">
    /// RunWithCulture(SPContext.Current.Web.Locale.LCID, () =>
    /// {
    ///     Console.WriteLine(LocalizationHelper.Localize("TestResource", "TestResourceFile"));
    /// });
    /// </code>
    /// </example>
    public static void RunWithCulture(int lcid, Action code)
    {
        int oldLcid = Thread.CurrentThread.CurrentUICulture.LCID;
        Thread.CurrentThread.CurrentUICulture = new CultureInfo(lcid);
        code();
        Thread.CurrentThread.CurrentUICulture = new CultureInfo(oldLcid);
    }

    После сборки в SandCastle Help File Builder увидим следующее:


  3. Если у класса или метода много особенностей, довольно часто они выносятся из <summary>, все равно слишком много текста через интеллисенс читать никто не будет. Выносятся в обычные комментарии. Однако, именно для этого существует, оказывается, тэг <remarks>, который создан для хранения всяких заметок и особенностей, а в документации появляется в виде отдельной секции в файле, под названием "Замечания".
     
  4. Когда мы пишем "для этого можно использовать метод X", или "этот функционал реализован классом Y", крайне полезно название метода или класса заключить в тег <see cref="(здесь имя класса или метода)">. В этом случае в сгенерированной документации будут проставлены ссылки на соответствующие страницы.
     
  5. Документация по другим тэгам: http://msdn.microsoft.com/en-us/library/5ast78ax(VS.71).aspx.

Генерация документации

Я успел попробовать несколько утилит для создания документации, но для Visual Studio 2010, как выяснилось, лучше всего подходит пакет SandCastle Help File Builder. Он предоставляет визуальную среду, немного даже похожую на саму Visual Studio, благодаря чему создания проекта документации не вызывает затруднений.

Обычно все что нужно - это добавить ваши csproj-проекты в Documentation Sources проекта SandCastle Help File Builder, и нажать кнопку Build.

К этому есть только одно важное замечание. В проекте должна быть включена генерация файла XML-документации. Делается это через свойства проектов, достаточно проставить одну галочку (название файла значения не имеет, SandCastle будет сканировать все XML-файлы в папке проекта):


Сборка идет довольно долго, поэтому я обычно выключаю документирование унаследованных свойств и методов (в свойствах проекта, DocumentInheritedMembers проставить в False). Кроме того, SandCastle Help File Builder позволяет выключать из проекта полностью или частично некоторые классы и неймспейсы, путем задания свойства ApiFilter. Тоже частно пригождается.

После того, как вы добились генерирования документации по коду, часто возникает необходимость добавления каких-то дополнительных файлов или статей. Это может быть FAQ, база знаний, статьи разработчиков, списки полезных ссылок, и т.д. Это тоже можно сделать, причем довольно легко - нужно добавить в проект элемент типа ContentLayout (на проекте правой кнопкой, Add -> New Item -> Content Layout). Лэйауты редактируются через довольно удобный UI, который позволяет легко создавать новые топики.


Создав новый топик на основе одного из предложенных шаблонов, вы можете удивиться, обнаружив какой-то совершенно незнакомый XML-язык вместо привычного HTML. Поразбиравшись еще немного, сразу вспоминается XML-язык для комментариев в Visual Studio. Да, действительно, некоторая общность в этих языках присутствует, но все же они разные.

А язык, на котором пишутся топики в SandCastle Help File Builder, называется Microsoft Assistance Markup Language, или просто MAML.

Язык MAML

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

В качестве примера можно привести тэг <troubleshooting>, который имеет следующую структуру:
<troubleshooting>
    <problem>
        <symptom />
        <cause />
        <solution>
            <para />
            ...
        </solution>
    </problem>
    ...
</troubleshooting>

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

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

Основной недостаток именно SandCastle Help File Builder'а - это отсутствие интеллисенса. Также, те кто пишут документацию на русском языке, могут обнаружить презабавнейшие "фичи": вне зависимости от раскладки, нажимая на русскую букву "х", вы получите "[]". То же самое - с фигурными скобками (shift+х), и кавычками (shift+э).

В целом, конечно среда для MAML'а далеко неидеальная. Для написания пары-тройки небольших статей подойдет и она, в остальных же случаях рекомендую добавлять в проект html-файлы, это тоже делается довольно легко.

Напоследок, как и про XML-комментарии в Visual Studio, дам несколько подсказок по MAML-у:
  1. Картинки вставляются следующим образом:
    • Копируем картинку в папку проекта или в какую-нибудь вложенную папку, например images.
    • Добавляем в проект существующий файл (Add -> Existing item...). В диалоговом окне открытия файла нужно не забыть перещелкнуть тип файлов на "Картинки".
    • Щелкаем по вновь добавленному файлу и в свойствах меняем его тип с Content на Image. Также, можно прописать Image Id, если не хочется использовать имя файла.
    • В MAML-файле пишем:
      <mediaLink>
          <image xlink:href="{imageId}"/>
      </mediaLink>
      

  2. Если вам понравился MAML, но хочется редактировать MAML-файлы в более удобном виде, вы можете скачать xsd-схемы и подключить их в Visual Studio.
    Схемы можно найти в исходниках DocProject, в каталоге Main/Source/DocToMaml Help/Help/Schemas.
    Прямая ссылка на последнюю (на момент написания статьи) версию файлов: http://docproject.codeplex.com/SourceControl/changeset/view/34004#454905 (тянуть нужно все xsd в этой папке).
     
  3. Наиболее вменяемая статья по синтаксису MAML: http://www.help-info.de/en/Help_Info_AP_Help/longhorn_maml_example.htm
     

2 комментария:

  1. Андрей, привет.

    А каким образом вытаскивать это все в веб потом? - я видел для SPRibbon юзается все то, о чем ты тут пишешь и доступено через твой веб-сайт онлайн. Каким образом это делается? - пни что и куда гуглить.

    Второй момент - это doc/pdf. Был ли опыт перегонки каких то статей из sandcastle в pdf?

    Ну и последнее, если мы говорим о user manuals или articles, how-tos, почему бы не пойти с wiki? Мы обнаружили, что это не так и просто, ибо нет нромальный авторинг-тулз или десктоп клиентов для работы с wiki - основной затык это картинки. Как в случае с sabdcastle можно это решить? - какой experience будет по работе с картинками?

    ОтветитьУдалить
    Ответы
    1. 1. В веб-сайт можно компилить, для этого есть настройка в проекте.

      2. В PDF - Google, "chm to pdf" - конвертеров куча, но качество наверняка пострадает, надо смотреть. В любом случае, другого варианта я не знаю - задачи такой не возникало.

      3. Про то, как вставляются картинки, написано в конце поста.

      Удалить

Внимание! Реклама и прочий спам будут беспощадно удаляться.

Примечание. Отправлять комментарии могут только участники этого блога.