Прежде чем изучать, как документировать код, давайте посмотрим на исследования передовых методов документирования кода, так как это может определить наше направление и подход.
Несколько академических статей выделяются как заслуживающие внимания:
- Когда не нужно комментировать: вопросы и компромиссы документации API для проектов на C++
В этой статье рассказывается, как разработчики из Google ищут и пользуются документацией кода. Исследователи обнаружили, что иногда простой код разработчики предпочитают исследовать напрямую. Однако, видя сложный код, разработчики обращаются к документации, часто просматривая формальные объявления классов для получения нужной информации. Бывает, смотрят и на комментарии в коде реализации. Помимо предоставления руководства по наилучшему расположению документации, исследователи также пытаются понять, какие типы ответов и рекомендации разработчики хотят получить в документации.
- Как разработчики используют документацию API: изучение наблюдений
В этой статье исследователи смотрели на то, как разработчики взаимодействуют с документацией API, и обнаружили сочетание как систематического (сначала читайте, изучайте потом), так и оппортунистического (изучайте сначала, читайте потом) стилей обучения. Хотя мы часто пишем систематически, сосредоточение внимания на оппортунистическом поведении может быть более полезным, что побудит нас внимательнее следить за улучшением поиска, навигации, интерактивных компонентов, устранения неполадок, сообщений об ошибках и других функций, ориентированных на действия.
Обе эти статьи взяты из научных журналов. На самом деле редко можно найти исследования о документации API в академических журналах (не знаю почему), чаще они встречаются в инженерных журналах, или журналах по информатике (а не в журналах по техническим коммуникациям).
Когда не нужно комментировать: вопросы и компромиссы документации API для проектов на C++
Во-первых, давайте рассмотрим статью «Когда не нужно комментировать: вопросы и компромиссы в документации API для проектов C++», написанную авторами Эндрю Хэдом, Кейтлин Садовски, Эмерсон Мерфи-Хилл и Андреа Найт. Эта статья была опубликована в 2018 году на 40-й Международной конференции ACM / IEEE по разработке программного обеспечения.
Статью можно почитать на сайте ResearchGate. Можно посмотреть версию .pdf
Эта статья включает труды исследователей, инженеров, юзабилити-специалистов и членов команды Google Engineering Productivity Research. Учитывая, насколько важна документация для понимания кода, исследователи пытаются понять, где лучшее место для документации, а также то, что нужно инженерам от документации. В частности, они сосредоточились на API C++ и спросили, что важнее для получения необходимой информации:
- заголовочные файлы с определениями классов;
- файлы реализации классов.
Следующий скриншот (из их статьи) показывает разницу между двумя видами файлов:
В основном, в C++ заголовочные классы (.h
) содержат классы и основную документацию. Файлы реализации (.cc
) создают и реализуют классы из заголовочных файлов. Короче говоря, файлы заголовков содержат более формальную документацию, которая следует определенным соглашениям аннотаций, в то время как файлы реализации содержат внутреннюю логику того, как класс был реализован. Файлы реализации имеют комментарии, перпендикулярные встраиваемому коду, без формально структурированных аннотаций документов. Главный вопрос, который исследователи хотели узнать, - тяготеют ли пользователи к комментариям встроенного кода в файлах реализации или официальной документации в заголовочных файлах.
Исследователи изучали, когда разработчики переключатся с одного типа файла на другой, и задавали уточняющие вопросы разработчикам. В центральном хранилище кода Google хранится около миллиарда строк кода, которые можно использовать в рамках всей компании, поэтому тысячи разработчиков могут искать код в этом едином репозитории и использовать в своих проектах. Команда, которая использует API, может не знать команду, которая разработала API, и наоборот.
Данное исследование полезно всем, даже тем, кто не документирует С++, потому что оно затрагивает Главный вопрос о жизни, вселенной и вообще:
Следует ли добавлять основную часть документации в формальные описания кода или большая часть вашей документации появляется в контексте кода, заправлено в виде встроенных комментариев?
После сбора информации от более чем 600 участников, исследователи обнаружили, что не весь код одинаков. Сложный код требует более формальной документации, тогда как простой код может вообще не нуждаться в документации.
Тип кода, которому нужна документация
Во-первых, исследователи обнаружили, что большинство разработчиков на самом деле искали в заголовочных файлах документацию:
Интересно заметить, что для более простых API многие разработчики читают код напрямую (а не обращаются к документации), чтобы быстрее понять API. Другими словами, они понимают что происходит, глядя исключительно на код.
Некоторые разработчики придерживаются философских взглядов к точности и актуальности документации и предпочитают рассматривать код в качестве основного источника информации, вместо вторичных или третьих источников информации. Как известно многим разработчикам, которые не доверяют документации, документация может легко устареть, так зачем ей доверять? Зачем вообще читать?
Фактически, такие разработчики считают, что документация для простого кода является помехой и препятствием для разработки. Документ встает на пути разработчика при чтении кода.
Помимо отказа от документации простого кода, исследователи также рекомендуют избегать написания документации для разработки, находящейся в постоянном движении (поскольку она делает документацию постоянно развивающейся целью). Исследователи пришли к выводу, что можно пропустить написание документов, когда не хватает ресурсов для ее обновления. Когда поддержание документации в актуальном состоянии хромает, она «гниет» и становится большой обузой.
Короче говоря, есть веские аргументы против написания документации, особенно для простого кода. Следующая диаграмма показывает, когда документация может не потребоваться с кодом:
Тем не менее, для понимания сложного кода, особенно когда могут быть задействованы несколько файлов и сгенерированный код, разработчики все еще полагались на формальную документацию. Исследователи объясняют следующим:
Короче говоря, когда исходный код не понятен интуитивно, разработчики обращались к более объемной и формальной документации. Такой подход имеет смысл и согласуется с лучшими практиками для документации GUI - всегда следует сосредоточиться на сложных частях системы, а не на очевидных элементах, которые и так понятны каждому.
Конечно, понять разницу между простым кодом и сложным техническому писателю сложнее, чем разработчику, потому что у писателя может быть лишь элементарное представление о сложности кода. Тот факт, что код короткий или длинный, не дает четкого представления о его сложности. Короткий фрагмент вне контекста может сбивать с толку, в то время как более длинный кусок, который содержит полностью функционирующий образец, может быть более понятным.
Приведу аналогию, путешественник посещает город в далекой стране. Посторонний не будет знать, является ли какое-то наблюдаемое событие нормальным или необычным - нужно быть более знакомым с местностью, чтобы оценить, является ли событие странным или обычным. То же самое с кодом.
Можно спросить разработчиков об уровне сложности кода, что предполагает доверие мнению инженеров, которые проектировали и создавали код. Разработчики почти всегда переоценивают уровень интуитивности написанного ими кода, а также и возможности аудитории. Сколько раз вы слышали, как инженеры говорили: «Пользователи поймут код, но если они этого не сделают, им не следует использовать API». Так что рискованнее: отсутствие документации или ее наличие?
Более продвинутые разработчики, вероятно, могут экстраполировать использование API из кода, в то время как начинающим разработчикам может потребоваться больше ручного труда. Как влияют комментарии на удобочитаемость для продвинутых разработчиков, и как они помогают новичкам? Обречены ли мы расстроить одну аудиторию, чтобы помочь другой? В чем риска больше: отсутствие документации или перегрузка ее слишком подробными пояснениями?
Когда документировать код
Отложим пока вопрос о том, документировать или нет, и вместо этого сосредоточимся на сроках написания документов. Исследователи обнаружили, что существует идеальное время для написания и обновления документации:
Другими словами, пишем документы по горячим следам. Если слишком долго ждать после окончания активной разработки, про документацию мало кто вспомнить, так как разработчики займутся другими проектами.
Конечно, сроки не всегда легко спланировать. Доступность тех. писателя может не соответствовать спринтам разработчика. Тех. писатель может работать с проектами со своими сроками, поэтому приходится откладывать документацию на один или более месяцев после разработки. Но к тому времени разработчик может и забыть какие-то детали. Сложность заключается в том, что мы храним множество деталей в наших головах (в нашей кратковременной памяти) пока мы работаем над задачей, но как только мы идем дальше, мозг выбрасывает информацию из краткосрочной памяти, чтобы загрузить оперативную память нашего мозга другим проектом.
В попытках получить от разработчиков четко сформулированные детали, которые больше не находятся в центре их внимания, можно столкнуться с низкой мотивацией и энтузиазмом при проверке документации. Они уже двинулись дальше. Куй железо пока горячо.
Вопросы, решаемые в документации кода
До сих пор мы пытались понять, где должна появиться документация кода и когда она должна быть написана. Теперь посмотрим на документацию кода с другой стороны: какие типы ответов и руководств должны быть в такой документации. На такой сложный и широкий вопрос исследователи отвечают: «Использование API».
Они пишут:
Информацию вывели в диаграмме для удобства чтения:
Ничто особенно не выделяется здесь, за исключением того, что “входные данные” читаются чаще всего. Входные данные являются теми параметрами или аргументами, с которыми разработчики часто обращаются, чтобы понять типы данных, регистры, другие детали. Поэтому лучше документировать параметры очень подробно. Подробное описание мы рассматривали модуле “Документирование конечных тоек” в разделе Шаг 3: Параметры. Сведения о параметрах REST API, которые следует учитывать, могут включать следующее:
- тип параметра конечной точки API: header, query string, path, или request body parameter;
- дефолтные значения;
- минимальные / максимальные значения;
- тип данных (boolean, integer, string и т.д.);
- примеры значений.
Другие сноски о содержании включают вопросы «Как мне…?». Другими словами, вместо справочной информации, разработчикам нужна инструкция, объясняющая, как реализовать справочные темы для достижения бизнес-цели. Как и в случае документации для конечного пользователя (GUI), концентрация внимания на задачах, а не просто определение справочной информации, остается важным элементом документирования кода. Большинство технических писателей уже ориентируют свое мышление на документацию, основанную на задачах, поэтому такой фокус здесь не нуждается в расширении.
Наконец, «Рекомендуемое использование» также является интересным элементом. «Рекомендуемые» пути не так часто встречаются в пользовательской документации, потому что у пользователей обычно есть задача, и есть предпочтительный способ ее достижения. Но в документации для разработчиков часто присутствует десяток способов достижения цели, и то, что код компилируется, не всегда означает, что все хорошо. Код должен масштабироваться, быть эффективным и охватывать множество вариантов использования. Поэтому рекомендации предназначаются для того, чтобы помочь разработчику найти множество потенциальных путей к документации.
Фактически, это может быть определяющей характеристикой, которая разделяет пользовательскую документацию и документацию разработчика. Пользовательская документация обычно имеет единственный путь для достижения результата. Документация для разработчиков, больше похожа на кухню хорошего кулинара: есть соль, мука, разрыхлитель, яйца, ваниль, пищевая сода, специи и так далее. Разработчик может использовать что-то из API в одном месте, что-то в другом, иногда сочетая все друг с другом, все для достижения определенной цели. Такая конкретная цель является более открытой и гибкой в зависимости от того, что разработчик строит (выпекает). И еще одно отличие заключается в том, что разработчики не едят свой код.
Заключение
В целом, благодаря этому исследованию появилось много идей и выводов. В статье рассматриваются многие проблемы, связанные с документацией кода, а также представлено комплексное представление о каждом из аспектов: если документировать код, то когда это делать, где размещать документацию, когда писать документацию, какие вопросы решать и многое другое. Не всегда есть четкий путь для подражания (он грязный), поэтому при разработке стратегии документирования должны учитываться многие аспекты: среда, продукт, аудитория… Тем не менее, эта статья содержит подробные исследования, которые рассматриваются с разных сторон.
Как разработчики используют документацию API: изучение наблюдений
Теперь давайте перейдем к другой bynthtcyjq статье, в которой рассматриваются лучшие методы документирования кода. В выпуске SIGDOC (the Special Interest Group for Design of Communication), вышедшем в январе 2019 года в издании Communication Design Quarterly, опубликована статья под названием «Как разработчики используют документацию API: исследование наблюдений». Несколько исследователей из Университета Мерзебурга в Германии - Майкл Мэн, Стефани Штайнхардт и Андреас Шуберт - решили «понять, как разработчики используют документацию, когда начинают работать с новым API».
В своих исследованиях они попросили разработчиков программного обеспечения решить набор предопределенных задач с использованием общедоступного незнакомого API, пользуясь документацией, опубликованной поставщиком API, а затем наблюдали за их поведением. По сути, разработчики должны были выяснить, как создавать запросы API REST с правильными параметрами, конфигурациями, отправлять запросы, которые возвращали бы необходимую информацию. Затем исследователи наблюдали, как разработчики использовали документацию API для определения задач.
В этой статье много замечательных наблюдений и выводов. Здесь просто заостряем внимание на информации из статьи. Статья мастрид для получения ценной информации.
Систематическое поведение против оппортунистического
Авторы указывают предыдущие исследования о систематическом и оппортунистическом поведении обучения. Эти термины используются предыдущими исследователями, как описание контрастного поведения пользователей.
Многие, несомненно, знакомы с этими двумя типами поведения. Иногда, получая новое устройство, мы просто начинаем нажимать кнопки и изучаем, как оно работает, основываясь на вводимых данных и ответах, пробах и ошибках и т.д. Это называется «оппортунистическим» поведением. В других случаях мы открываем руководство пользователя и читаем с страницы 1, прежде чем нажимать кнопки на устройстве (это называется «систематическим» поведением). Иногда можно смешивать оба типа, это будет уже «прагматичное» поведение. Так же ведут себя и разработчики, использующие API.
Паттерны оппортунистического поведения в исследовании описаны следующим образом:
Мы обнаружили, что оппортунистические разработчики в нашем тесте начали первую задачу с примера кода из документации, которую они затем модифицировали и расширили. Как только задача была выполнена, часть кода, которая решала задачу, использовалась в качестве отправной точки для следующей задачи, которая снова была потенциальным источником ошибки. Разработчики в этой группе работали с высокой степенью управляемости задачами, но также пробовали вещи, которые не были связаны с задачей, но, возможно, помогли им наладить более широкое понимание API. Например, P9 [человек 9] отправил запрос на услугу UPS (United Parcel Service), которая не требовалась ни для одной из задач, просто для того, чтобы увидеть, что произойдет.
Мы отметили, что разработчики, которых мы привязали к оппортунистической группе, не тратили время на изучение общего обзора API, прежде чем приступать к первой задаче. Они кратко просматривали некоторые страницы документации, проверили доступные инструменты и затем приступили к выполнению первого задания. Разработчики из оппортунистической группы хотели быстрого и прямого доступа к информации. Они систематически не читали большие разделы документации, но обычно искали определенную часть информации и затем сканировали документацию.
В общем, оппортунистические разработчики учатся на практике. Они смотрят на кусок кода, пробуют его, экспериментируют с параметрами, видят, что возвращается в ответе, и т.д. Они учатся с помощью экспериментов, проб и ошибок.
Напротив, систематические разработчики подходили к задачам, сначала изучая документацию:
Короче говоря, систематические разработчики следуют подходу «сначала прочти, потом попробуй» (в то время как разработчики-оппортунисты следуют подходу «сначала пробуй, потом прочти»). Прагматичные разработчики смешивают два варианта: «попробуй-прочитай-прочитай-попробуй».
Хотя может показаться удобным разделить стили обучения на систематическое, оппортунистическое и прагматическое поведение, исследователи обнаружили, что одни и те же разработчики не всегда ведут себя одинаково. Подход к решению задачи оппортунистический, систематический или прагматичный может очень зависеть от характера проблемы. Для простых запросов API, тщательное чтение документации, вероятно, лишнее. Но для сложных запросов API, когда разработчику может быть многое непонятно с самого начала, имеет смысл систематическое чтение документации.
Исследователи объясняют, что «стратегия, которой придерживается разработчик, похоже, не предсказывает тенденцию к использованию информации со страницы Концепции в нашем тесте». Другими словами, то, что вы - оппортунистический пользователь, не означает, что вы всегда пропускаете концептуальные объяснения - просто не всегда начинаете с начальных понятий. Нелинейный читатель может начать с кода, попробовать его самостоятельно и вернуться к вводной концептуальной информации, когда код работает не так, как ожидалось.
Принятие решения об одном типе поведения за счет другого может оказаться непрактичным, поскольку поведение и подходы к обучению, по-видимому, находятся в постоянном движении.
Когда автор курса пишет документацию и структурирует справочную систему, он часто имею в виду систематического разработчика - того, кто будет читать материал от начала до конца, того, кто начинает с первого шага, читает концептуальные введения и затем переходит к примерам кода и тому подобное. Но такое предпочтение не затрагивает огромный процент учеников. Вероятно, лучше спроектировать и для типа с оппортунистическим поведением, поскольку эта модель поведения идет вразрез с нашими естественными склонностями к линейному информационному дизайну. Линейное / систематическое поведение может быть учтено по умолчанию (поскольку мы склонны писать линейно), в то время как нелинейный / оппортунистический характер поведения, скорее всего, будет игнорироваться.
Проектирование для оппортунистического поведения
Как относиться к оппортунистическому поведению? Если понять, что пользователи учатся на экспериментах и действиях, то лучше уделять больше внимания комментариям и образцам кода, сообщениям об ошибках, устранению неполадок, интерактивному интерфейсу (например, Swagger UI), чтобы разработчики могли пробовать запросы, понимать навигацию, чтобы им было легче искать конкретную информацию.
Исследователи выделяют некоторые из этих шаблонов проектирования в своих рекомендациях. Вторая половина статьи содержит рекомендации:
- «Обеспечить прозрачную навигацию и мощную функцию поиска»;
- «Предоставить чистые и рабочие примеры кода»;
- «Включить быстрое использование API»;
- «Предоставлять важную информацию с избыточностью»;
- «Организовать контент в соответствии с функциональностью API».
Стоит заметить, что термин «оппортунистический» не является выбором автора (это термин, использовался и ранее). Исследователи пишут, что оппортунистическое поведение имеет много общего с исследовательским и активным подходом, описанным Джоном Кэрроллом, имея в виду основополагающую работу Кэрролла в «Воронке Нюрнберга», которая связана со статьей Марка Бейкера «Каждая страница - первая страница» и нелинейным подходом к чтению. Читатели рыскают по документации, собирая информацию после знакомста с системой методом проб и ошибок.
Вместо термина «оппортунистический» (который имеет несколько негативную коннотацию) предлагается также полльзоваться терминами «исследовательский», «активный» или «восходящий». Больше информации можно почерпнуть в постах How to design documentation for non-linear reading behavior и Principle 2: Make information discoverable as the user needs it.
Где разработчики тратят больше времени
Если разработчики переходят от кода к общим понятиям и другим местам, где они проводят большую часть своего времени в документации? Если мы можем измерить время в одном типе документации больше, чем в другом, мы сможем уделять больше внимания нужному виду документации. Исследователи измерили время, проведенное пользователями в различных частях документации, следующим образом:
Как и в предыдущем исследовании Head et al., «Когда не нужно комментировать», разработчики большую часть времени тратили на справочную информацию API (например, параметры). Но здесь исследователи получили интересное наблюдение, которое нарушает другие предположения: разработчики искали темы, а не категории информации - иными словами, они не различали понятия между типами справочной информации, когда искали что-то. Им нужно было решить проблему, и они искали информацию, связанную с этой проблемой, независимо от того, может ли эта информация быть классифицирована как концепция, задача, ссылка, устранение неполадок или другой тип темы. Поэтому исследователи рекомендуют более тематическую организационную стратегию:
Такая, довольно радикальная рекомендация, поскольку почти вся документация API четко выделяет справочную информацию и обозначает ее как таковую. Но, возможно, концептуальная информация может легче интегрироваться и повторно использоваться из справочного раздела безболезненным, унифицированным образом. Таким образом, если искать информацию об обработке отправлений (пример из исследования), можно увидеть соответствующие конечные точки и параметры обработки отправлений, а также вводные руководства и руководства по обработке отправлений прямо в одном месте (вместо того, чтобы переходить по ссылке на конечную точку обработки отгрузки, затем возвращаться к описанию, чтобы понять, как ее можно использовать, и затем идти к концепциям для получения другой информации об обработке отгрузки).
Имеет смысл делать справочный раздел, в котором перечислены все конечные точки, но если это единственное место, где описаны эти конечные точки, такой шаблон может быть не самым удобным для пользователей.
Авторы исследований также рекомендуют интегрировать концепции с соответствующими задачами:
Поскольку разработчикам нужна вся информация при решении проблемы, желание тех. писателя разделять информацию на различные темы (концепция, задачи, справка, устранение неполадок и т.д.) может стать большой помехой. При разделении информацию, следует структурировать справочную систему таким образом, чтобы информация была тесно связана или интегрирована друг с другом.
Заключение
Хотя стили обучения, обсуждаемые в этой статье, могут показаться более применимыми к общей документации (а не к документации по коду), вывод довольно очевиден: при документировании кода, должна быть возможность экспериментировать с кодом. Могут ли пользователи копировать и вставлять его в свои собственные интегрированные среды разработки и запускать его? Могут ли они копировать и вставлять запросы в Postman и получать ответы, из которых они могут извлечь уроки?
Получается, что при документировании кода существует прямая возможность нацелиться на оппортунистический стиль обучения с возможностями эксперимента, больше чем при написании других типов API документации.
Выводы исследований
Подведем итоги и выделим ключевые моменты:
- не используем документацию, если код прост и понятен;
- создаем документацию пока проект свежий и на уме разработчика;
- отслеживаем актуальность справочной документации (например, параметров), потому что этой частью документации разработчики пользуются активнее всего;
- размещаем документацию как в ожидаемых местах, так и непосредственно в коде, в виде комментариев;
- чтобы приспособиться к нелинейному, оппортунистическому поведению, проектируем справочную систему с разумными дозами кода, интерактивными инструментами поиска API, функциями поиска, информацией об устранении неполадок и перекрестными ссылками;
- организуем информацию по функции, которую она предоставляет, а не по типу информации (задача, концепция, ссылка и т.д.);
- упрощаем код для экспериментирования, чтобы люди могли понимать его опытным путем.
Такая стратегия обеспечивают основу для лучших практик, которые мы рассматривали подробно с помощью конкретных, осязаемых методов в наших модулях.