Что не так c документацией в Ruby

Updated on May 1, 2021

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

Взгляните на стандарт C++ (draft) - это же идеал перфекциониста. Полная и детальная спецификация библиотечных классов и функций. Описаны тончайшие детали поведения. И это следствие потребности индустрии - плохая документации обходится слишком дорого. Взгляните на документацию по Java (Language Specification, API Specification) или в том же Python (Language Reference, Standard Library). Посмотрите на документацию по Go (Language Reference, Standard Library) - там даже есть интерактивная online консоль (в разделе A Tour of Go).

А теперь давайте вернемся к Ruby. Официальный ресурс проекта - ruby-lang.org. Хотя официальная документация по стандартной библиотеке находится на docs.ruby-lang.org, есть еще и независимый ruby-doc.org с более приятным и функциональным дизайном и несколько других ресурсов (apidock.com, rubydocs.org).

Недавно появился новый интересный сторонний проект rubyapi.org c RDoc документацией Ruby Core-lib и Std-lib. Отличается приятным дизайном, удобным поиском с auto-suggestion. Примеры из документации можно запустить и выполнить прямо в браузере. Есть еще один экспериментальный подраздел, на который пока нет прямой ссылки с главной страницы, онлайн Ruby REPL, где можно поиграться с разными Ruby (CRuby 2.3-3.0, JRuby и даже Artichoke). Это самые настоящие Ruby, которые запускаются где-то в облаке (AWS Lambda, по-моему).

Официльный сайт (ruby-lang.org) вроде бы современный и с приятным дизайном. Есть и документация по Core-lib с Std-lib и ссылки на Getting Started и какие-то туториалы. Но если приглядеться повнимательнее, то появятся много “Но”.

Очевидные проблемы

  1. Документация по Std-lib сильно отстает по полноте и количеству примеров от Core-lib. За долгие года она превратилась в свалку странных подчас случайных и плохо документированных библиотек. И когда вам внезапно нужно сделать какую-то несложную вещь (например с OpenSSL) вы можете оказаться беспомощными и спасти может разве что эксперты на StackOverflow (пример вопроса по OpenSSL).

  2. Большая часть ссылок на туториалы и Getting Started ведут на внешние ресурсы, которые годами не обновляются. Некоторые ссылки даже успели протухнуть.

  3. Единственный раздел с синтаксисом языка, который находится на самом сайте ruby-lang.org, оказывается книгой “Programming Ruby”, первой редакцией, которая доступна в сети бесплатно. По полноте она недалеко ушла от туториалов и морально устарела еще лет 10 эдак назад.

  4. Ruby можно потрогать online. Есть официальная страничка “Try Ruby” с серией простых заданий, которые можно запускать прямо в браузере. Звучит отлично. Но это не настоящий Ruby. Это альтернативная реализация Opal сделанная на JavaScript, в которой доступно только подмножество как синтаксиса так и стандартных библиотек.

Синтаксис

А теперь давайте откроем документацию по синтаксису Ruby.

Хм, не получается? Давайте поищем внимательнее.

Как это, нет такой документации?

Хмм. И вы совершенно правы. Официальной (и актуальной) документации по синтаксису Ruby не существует в природе. Единственный авторитетный источник который нам доступен - это книга Matz’а, автора языка, “The Ruby Programming Language: Everything You Need to Know”. Ее издали в далеком 2008 году еще до выхода Ruby 1.9, но тем не менее она покрывает и нововведения в 1.9. Сама книга прекрасна и определенно must read. Но это книжный формат, а не структурированная online документация с перекрестными ссылками и поиском. К тому же это стоит денег. К тому же за последние 11 лет она ни разу не переиздавалась.

Кто-то может вспомнить, что существует стандарт Ruby ISO/IEC 30170:2012, который разрабатывали согласно требованиям японского правительства (т.е. их похоже вынудили, и это делалось не для, хм, сообщества). Он очень напоминает взрослые стандартны С++ и С, достаточно объемный (335 страниц) и описывает как синтаксис (формальная грамматика в виде BNF) так и Core-lib.

Но хотя стандарт принимался в 2012 году (а это было довольно давно), сам он создавался в 2010 и описывает только Ruby 1.8. За последние 9 лет (сейчас актуальная версия Ruby 2.6) и синтаксис и еще ,более Core-lib заметно расширились сохраняя, правда, обратную совместимость. Больше половины сегодняшней Core-lib в стандарте просто нет. Очевидно как и всей Std-lib.

Приведу пример BNF для alias оператора из этого стандарта:

alias-statement ::
    alias new-name aliased-name

new-name ::
    defined-method-name
    | symbol

aliased-name ::
    defined-method-name
    | symbol

Если поискать в Google запрос “ruby syntax” то первой же ссылкой выдаст “Ruby Syntax - Ruby-Doc.org”. Это древний раздел “Ruby Language Reference Manual”, который не обновлялся с 1998 года, и судя по URL описывает версию Ruby 1.4. Помню, именно по нему я когда-то сам знакомился Ruby. На удивление, он достаточно большой и пригодится даже спустя 20 лет. В конце есть даже формальная грамматика в виде BNF. Ссылки на этот раздел нет ни на ruby-doc.org ни на ruby-lang.org.

Есть еще один источник информации, на который обычно не обращают внимание, хотя он и представляет некоторый интерес. Прямо в git-репозитории Ruby в директории “/doc” лежат несколько разрозненных документов посвященных разным аспектам Ruby - синтаксис (literals, assignment, modules and classes etc), стандартная библиотека (regex, marshal etc) и общие вопросы (security, globals, extensions etc). Эти статьи доступны как на ruby-lang.org так и на ruby-doc.org.

А зачем надо что-то еще?

Может возникнуть закономерная мысль: - “Я пишу на Rails и мне с головой хватает ее документации. И так все хорошо”. Действительно, если решать шаблонные задачи собирая приложение из готовых gem‘ов как из кубиков, тогда действительно хватит Guide‘ов по Rails и документации по Core-lib на всякий случай.

К сожалению, иногда этого мало и я сам не раз оказывался в тупике, когда не помогал ни Google, ни коллеги, ни чтение исходников.

Еще в далеком 2009 году я столкнулся с нехваткой документации. Это касалось обертки OpenSSL в Ruby Std-lib. Передо мной стояла простая задача - генерировать электронную подпись XML документов для исходящих запросов во внешнюю систему и проверять подпись во входящих ответах. Сложность была в том, что надо было использовать не стандартные SHA-256, MD5 или аналогичные хеш-функции, а сертификаты в специальных форматах и особые алгоритмы шифрования. Это было реализовано в OpenSSL и должно было быть доступным в Ruby. Но документация в Std-lib оказалась практически пустой и бесполезной, и поиск в Google не помог. В отчаянии была даже скачана книжка по OpenSSL но в итоге я отложил ее на неопределенный срок. Помощь пришла со StackOverflow, где я получил отличный ответ. Как и ожидалось, автор нашел нужную информацию в документации по самому OpenSSL. К слову, сейчас документация по OpenSSL в Ruby сильно дополнена и, хотя и не содержит готового ответа на мой вопрос, но есть много примеров и уже есть от чего отталкиваться.

Я еще раз уткнулся носом в не задокументированное поведение уже не так давно, в 2016-м году, и уже в Core-lib. Мы стали получать странный exception на тестовых серверах связанный с конкатенацией строк и несовместимыми кодировками, не вспомню уже точно детали. И оказалось, что в документации нигде не описано в каких случаях это исключение бросается. Засучив рукава я полез в исходники MRI и по дороге заблудился в дебрях Си-кода. Затем бросил взгляд на исходники Rubinius - там должны были быть чистые и красивые абстракции, понятный и простой код на С++ и Ruby. Меня опять ждала неудача - наскоком не получилось найти место, где проверялась кодировка строк. Ответ я нашел только в проекте RubySpec, где четко и ясно простым английским языком были выписаны все варианты при конкатенации строк, в том числе и бросаемые исключения. Проблема была решена и баг побежден, но сколько на это ушло времени и сил…

А теперь позитивные моменты

За последние годы документация по Std-lib заметно дополнилась. Это видно невооруженным глазом на примере той же OpenSSL.

Начался процесс gem-ификации - библиотеки из Std-lib выносят в отдельные “стандартные” гемы, которые делятся в свою очередь на default и bundled. Все “стандартные” gem-ы будут по прежнему доступны из коробки, но default gem-ы будут разрабатываться Ruby core team, цикл разработки и релизов будет как у самого Ruby. А bundled gem-ы будут поддерживаться непонятно кем, иметь свой цикл релизов и их можно будет обновлять вручную или даже удалять как самые обычные gem-ы. Думается, это должно снять нагрузку с Ruby core team и может положительно повлиять и на качество документации.

Нельзя забывать, что появился проект RubySpec. Это набор тестов покрывающий синтаксис, Core-lib и Std-lib. И хотя это не совсем обычная спецификация языка и предназначена она скорее для разработчиков самого Ruby, MRI и альтернативных реализаций (JRuby, TruffleRuby, Opal etc), тем не менее это полезный источник информации и для прикладных разработчиков. В данный момент в его поддержке и обновлении активно участвует Ruby core team.

Также среди всего хлама на ruby-lang.org можно выделить ссылки на вполне годные ресурсы и статьи:

К сожалению этот список очень неполный и не исчерпывает существующие отличные ресурсы посвященные Ruby.

К чему же можно стремиться?

А теперь мои 5 копеек на тему, что же такое хорошая документация языка программирования.

Вместо кучи ссылок на сторонние устаревшие туториалы - новые актуальные обновляемые разделы:

  1. Getting started - раздел с кратким введением
  2. Language Reference - всеобъемлющий раздел с описанием синтаксиса и его семантики в строгом стиле ISO стандарта с примерами и пояснениями (в объеме книги Matz’а по Ruby)
  3. Формальное описание грамматики в виде BNF

Любые примеры в документации должны быть runnable online на настоящей версии Ruby. Возможно ли запустить полноценную MRI на WebAssembly - это хороший вопрос. Такие попытки уже были, правда до конца ни одну не довели (например runrb.io).

Документация в Core-lib и Std-lib - в строгом стиле ISO стандарта. Сейчас это скорее правило опускать подробное формальное описание и взамен приводить только лаконичные примеры или краткие схемы (пример, еще один и еще). В документации Std-lib заполнены пробелы примерами и пояснениями.

Что можем сделать мы, Ruby сообщество

Во-первых, можно улучшить документацию по Core-lib и Std-lib. Она генерируется из комментариев в исходниках Ruby используя rdoc. Чтобы обновить эти комментарии, как впрочем и сделать любое изменение в самом Ruby, нужно создать issue и прикрепить patch на Ruby Issue Tracking System (guide). Есть даже специальный ресурс (ныне немного запрошенный) для предварительного review изменений в документации documenting-ruby.org.

Во-вторых, можно принять участие в сторонних проектах по созданию нового Language Reference, например The Ruby Reference.

И наконец, можно поучаствовать в проекте RubySpec, добавляя новые или улучшая существующие тесты. Каждый год выходит новый релиз Ruby с многочисленными обновлениями библиотек, которые требуют и обновления тестов.

Вместо послесловия

Нужно ли такие улучшения документации сообществу? Однозначно да. Нужно ли это индустрии? Мы видим, что пока не очень.

Увидим ли мы значительные улучшения в ближайшем будущем? Я сильно сомневаюсь в этом. И пока за Ruby не будет стоят какая-нибудь серьезная компания вроде Google/Facebook/Mozilla Foundation/Oracle или целый комитет по стандартизации ничего радикально не изменится.

Как-то так все грустно (.