Обзор некоторых методов, которые я использую при написании документации.
Введение
Как, вероятно, знакомы те, кто увлечен функциональной манией, которой является мой блог на Medium, я уже некоторое время работаю над фреймворком веб-разработки для Джулии. Фреймворк работает очень хорошо, и, поскольку я думаю, что другие могут захотеть начать его использовать, я хотел подумать, насколько хороша документация на самом деле. Одна из существенных проблем при создании качественной документации заключается в том, что человек, пишущий документацию, обычно очень хорошо знаком с используемыми методами. Хотя это может облегчить объяснение использования другим, это также может создать существенный разрыв между ними и кем-то, кто еще не понимает документируемую вещь.
Однако есть несколько хитрых способов избежать этой распространенной ошибки при написании документации по программному обеспечению. Один из методов, который, по моему опыту, определенно хорошо работает, заключается в следовании набору рекомендаций, которые помогают сделать документацию не только подробной, но и подробной в плане написания и, что, возможно, более важно, последовательной. Сегодня я хотел поделиться некоторыми из этих методов, которые я использовал при создании своего фреймворка для веб-разработки, так как я приложил много усилий к документации этого модуля, и я считаю, что он стал вполне интерпретируемым!
Последовательность
Первое, на что я хотел обратить внимание и что часто не делается, когда дело доходит до документации, — это согласованность. Чтобы документация была эффективной, она должна быть последовательной! Причина, по которой постоянство так важно, заключается в знакомстве. Поскольку пользователь уже так много знает о вашем пакете, вам, вероятно, не следует перегружать его 18 различными форматами строк документации.
Также следует сказать о согласованности с соглашениями вашего языка программирования, когда дело доходит до документации. В случае с Julia мы можем выполнить поиск в базовой документации, чтобы найти некоторые выдающиеся примеры того, как это обычно делается. При этом у меня также есть некоторые вещи, которые мне не нравятся в некоторых из этих строк документации.
В некотором смысле это отличная строка документа. Строка документа является информативной, она обеспечивает надежное описание, а также все конструкторы, которые нам могут понадобиться, и их соответствующие аргументы. Однако, используя информацию из этой строки документа, держу пари, вы не знали, что String является подтипом AbstractString.
String <: AbstractString true
Учитывая, что вы просматриваете строку документа для строки, также возможно, что вы хотите просмотреть поля строки документа. К счастью, что касается String, не о чем беспокоиться в отношении имен полей, однако это довольно распространено в базе Джулии. Также нет примеров использования конструктора String, что всегда имеет смысл из-за того, как много людей ознакомятся с вашим методом, скопировав и вставив ваши примеры. Это особенно важно, если вы хотите привлечь новых программистов и сделать свое программное обеспечение как можно более доступным — что и должно быть целью хорошей документации.
В контексте строк в некотором смысле имеет смысл, что документация не так хороша. В большинстве случаев строки будут создаваться с помощью методов и разделителей строк. Хотя я, конечно, не самый большой поклонник этой строки документации, безусловно, есть некоторые веские причины, по которым мы можем считать, что это именно так. Одна из областей, в которой Джулия действительно хорошо документировала свою базу, — это методы:
Толчок! строка документа — фантастический пример строки документа, которая работает очень хорошо. Этот метод обычно отправляется по всему спектру базовых типов Julia и имеет общие имена, отражающие это свойство. Строка документа также включает пример, а также другие подобные методы и краткое описание.
База Джулии следует определенному уровню согласованности, и это здорово, потому что теперь, после прочтения строки документации для метода push, может быть проще прочитать ту же документацию для contains:
Обе эти строки документации также содержат как информацию об аргументах, так и информацию о возврате, что действительно дает хорошее представление о том, как использовать документацию. Причина, по которой я хотел затронуть документацию Julia’s Base, заключается в том, что это хороший пример, а также обеспечивает некоторые последовательности, которые мы можем использовать всякий раз, когда мы создаем нашу собственную документацию для наших проектов Julia. В наших строках документов мы, вероятно, захотим, чтобы расположение было довольно близко к этому, чтобы те, кто работает в Джулии, также автоматически распознавали формат нашей документации и то, как ее читать!
""" """ myfunc(x::String, y::Integer) = string(y) * x
Давайте создадим док-строку!
Включить примеры
Еще одна вещь, которую определенно стоит сделать, это включить примеры. Сила примеров в том, что они могут показать отличное представление ввода и вывода, которые можно ожидать от данной функции. В примерах мы можем дать набор фиктивных данных, которые имеют правильную форму и подготовлены для правильной передачи через функцию, или лучше согласовать нюансы различных синтаксисов, предоставив разные примеры использования.
Кроме того, примеры также делают вашу документацию более доступной для новых пользователей. Если говорить из собственного опыта, а также из анекдотических описаний друзей, примеры — это абсолютный хлеб и масло для обучения программированию. Что происходит с примерами, так это то, что кто-то берет пример и определяет «это рабочий способ вызова этой функции», а затем он может изменить этот конкретный способ вызова функции или данные перед ним, чтобы применить их к своему конкретному проекту. Излишне говорить, что примеры важны, а методы определенно требуют примеров, чтобы действительно донести ввод и вывод до пользователя.
""" ### example ``` x = "px" y = 50 myfunc(x, y) "50px" ``` """ myfunc(x::String, y::Integer) = string(y) * x
Ввод и вывод
Еще одна очень важная вещь, на которую следует обратить внимание, — это ввод и вывод, когда речь идет о функциях. Во многих более типичных и низкоуровневых приложениях, таких как документация на основе комментариев к сборке, документация обычно включает только краткое описание, только если имя не описывает функцию, а также ввод и вывод. При этом ввод и вывод иногда могут быть единственной особенностью документации; так что это, вероятно, ключ к отличной документации. Обычно это то, на что захотят взглянуть опытные или ссылающиеся программисты, поэтому очень важно, чтобы эти типы аргументов были очень четкими и определенными в документации.
Это еще один пример, где согласованность, особенно с вашим языком программирования, может быть невероятно важна. У Джулии обычно есть процесс описания ввода и вывода, который по существу включает в себя создание вашей функции, похожей на анонимную функцию.
""" myfunc(x::String, y::Integer) -> ::String ### example ``` x = "px" y = 50 myfunc(x, y) "50px" ``` """ myfunc(x::String, y::Integer) = string(y) * x
Имена аргументов
Еще кое-что, что также очень важно как для разработчиков, работающих над вашим кодом, так и для документации, — это имена аргументов. Имеет смысл, чтобы имена аргументов в документации соответствовали именам того, что они на самом деле представляют с точки зрения данных. При этом лучше всего сделать так, чтобы все имена аргументов были одинаковыми во всем вашем коде. На самом деле это недооцененная мера написания отличного кода. То же самое можно сказать и об имени функции. Если вы хотите увидеть больше недооцененных показателей отличного кода, я написал еще одну классную небольшую статью об этом здесь:
""" ## iwith_suffix(suffix::String, number::Integer) -> ::String ### example ``` suffix = "px" number = 50 myfunc(suffix, number) "50px" ``` """ iwith_suffix(suffix::String, number::Integer) = string(suffix) * number
Определить согласованность типов
Еще одна отличная идея — также определить и сообщить пользователям о любых различиях между типами, с которыми они могут работать. Многие современные языки программирования используют некоторые виды наследования. Учитывая это, вы, вероятно, не захотите делать больше функций, чем нужно; поэтому вы, вероятно, будете использовать наследование при работе с этими языками. Конечно, способ, которым это делается, будет меняться от языка к языку. В Julia типы описываются в иерархии как обычных типов, так и категорий, которые являются просто абстрактными представлениями группы типов с заданным именем. Вот абстрактный тип Servable в Julia из моей среды веб-разработки, который определяет согласованность между всеми своими подтипами:
Поля/атрибуты
Если вы работаете с типом, вероятно, также будет хорошей идеей предоставить поля или атрибуты типа, который вы пытаетесь задокументировать. Описания этих значений тоже очень хороши! Вот пример, где поля довольно хорошо задокументированы из Toolips в форме ServerTemplate:
Заключение
Хотя у нашего маленького метода нет над ним супертипа и нет полей, наша doc-строка все же оказалась довольно богатой событиями!
""" ## iwith_suffix(suffix::String, number::Integer) -> ::String ### example ``` suffix = "px" number = 50 myfunc(suffix, number) "50px" ``` """ iwith_suffix(suffix::String, number::Integer) = string(suffix) * number
Излишне говорить, что документация — невероятно важный аспект кода, который вы пишете. Каким бы хорошим ни был ваш код, без документации его будет сложно использовать кому-либо. Особенно это касается языков с менеджерами пакетов, где ваши конечные пользователи могут даже никогда не увидеть код вашего пакета. Не каждый, кто использует ваш пакет, поймет его код!
Большое спасибо за чтение, и я надеюсь, что использование некоторых из этих замечательных советов поможет сделать ваш код намного лучше, предоставив соответствующую документацию! Как только вы привыкнете к ее написанию, написание документации действительно станет веселым и полезным! Еще раз, спасибо за проверку моей статьи, и счастливого документирования!