Pull to refresh
16
0
Владимир Гладков @vovkos

User

Send message

Ваша правда, мой косяк.


Акелла промахнулся — дважды! ;) На хабре окошко с редактором находится сразу за последним комментарием, отчего складывается впечатление, что отвечаешь на него. А перенести комментарий после создания уже нельзя.

Поправьте меня, если ошибаюсь, но беглый осмотр выявил несоответствие списку требований, сформулированных в начале:


  • GitLab CI бесплатен только если проект хостится на GitLab
  • Semaphore CI не поддерживает Mac OS X
  • Circle CI не бесплатен для Mac OS X

На самом деле, при выборе сервисов я прежде всего просканировал, что в основном используют opensource разработчики, хостящиеся на GitHub — с большим отрывом лидирует Travis и AppVeyor.


В принципе, производительность Travis меня вполне устраивает — как мне кажется, CI далеко не является критической по времени задачей. А вот что вполне могло бы заставить меня мигрировать на другой сервис, так это наличие более широкого спектра платформ для сборки/тестирования: Ubuntu посвежее, Arch, Fedora, и т.д.


Не подскажете, есть ли такие?

Тут дело даже не в том, запускается или нет Docker на Windows или Mac OS X (как вы верно отметили, да, запускается). Проблема в том, что Travis CI предоставляет Docker-контейнер для сборки только под Linux, а AppVeyor вообще не даёт возможности выбирать между полновесной виртуальной машиной и Docker-контейнером.


Но это, на мой взгляд, и не важно. Выигрыш всего в минуту (!) в таком длительном, да и, чего уж там, совсем не критичном по времени исполнения процессе, как непрерывная интеграция, просто не стоит того, чтоб с ним заморачиваться.

Ну я собственно и не противопоставлял — просто сказал, что и с Doxyrest тоже можно создавать самостоятельные страницы с документацией как обычные .rst файлы. И конечно, и с Doxygen, и с Doxyrest из этих самостоятельных страниц можно ссылаться на авто-сгенерированные страницы API.


Другое дело что Doxyrest перекладывает всю работу по созданию финальной красивой HTML страницы на инструмент, который прекрасно с этим справляется (значительно лучше, чем Doxygen). Вот и всё.

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

А мне кажется, визуальные акценты помогают-таки при просматривании статей по диагонали. Вопрос количества и баланса, конечно, открытый (и во многом субъективный). Но вообще я за акценты. Как говорится, let's agree to disagree :)


Вопрос по сути статьи — скажите, а doxygen вроде бы умеет выдавать выхлоп в docbook-формате. а уж для него всяких генераторов в разных форматов написано немало. Такой вариант чем-то не устроил?

Если честно, то не пробовал генерировать HTML из доксигеновского DocBook выхода. Навскидку не вижу причин, почему это может давать намного лучший результат, чем просто подкрутка CSS и шапок у доксигеновского HTML. Впрочем, если у вас пример красивой документации, полученной таким методом — кидайте, можно будет обсудить более предметно.

Что правда то правда. Тогда я переформулирую:


Даже в тех (редких) случаях, когда разработчики и рады были бы написать нечто толковое в документации, их останавливает то, что… и дальше по тексту ;)

Всё правильно. А в случае с использованием Doxyrest, отдельные страницы с абстрактным описанием — это будут просто .rst файлы, скармливаемые Sphinx напрямую.

В чём разница между поддержанием документации в отдельном файле или в коде?

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


По личному опыту документация Doxygen совершенно бестолкова.

Бестолковость абсолютного большинства примеров Доксигеновской документации, действительно имеет место быть. Но это проблема конкретного контента, а не подхода, согласитесь? Можно ведь взять и написать толковую документацию, а не просто: open открывает, get возвращает. Но у меня есть смелая теория, почему сейчас всё обстоит именно так.


Разработчики не хотят тратить усилия на написание толковых комментариев, потому что — барабанная дробь — конечная Доксигеновская документация всё равно будет выглядеть как говно!


Исправить это — и есть главная цель проекта Doxyrest.

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


А сделать красивый вывод по информации, полученной Доксигеном — в этом и есть вся соль предлагаемого мной проекта. Доксиген умеет доставать информацию из исходников. Sphinx умеет генерировать красивый — и, что главное, настраиваемый, — HTML. Doxyrest — мост между этими двумя товарищами.

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

Посмотрел описание языка шаблонизации — ой, зря они свой язык стали писать, ой зря...


Им бы взять Lua или Python — и то, и другое легко встраивается в плюсовые приложения. Сейчас вся эта кухня с новым языком даёт слишком уж ограниченные возможности по настройке вывода — на неизвестном и неотлаженном языке, без стандартной библиотеки, да ещё и с вырвиглазным синтаксисом (standardese_for, standardese_else_if и т.д.).


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


Вполне возможно, я что-то упсутил, но у них, увы, нет примеров использования этих шаблонов — в репозитории только плюсы, bash и cmake..

Если они не используют шаблонизатор (а судя по составу репозитория, там есть только CPP и Bash), то наступают на те же самые грабли, что и Doxygen — нельзя хардкодить генерацию HTML.

То есть всё, что они получат в итоге — это Doxygen с Clang в качестве парсера, но с таким же деревянным выходом. Кстати, если не ошибаюсь, автор Doxygen уже начал прикручивать Clang и сам.
Болд или италик это, наверно, всё-таки личные предпочтения. А замечание по количеству акцентов принято.
Дело в том, что если сначала пишется API как получится, а потом пост-фактум под него пишется документация, то качество этого API будет стремиться к нулю или даже дальше в минус бесконечность. При правильном подходе, документация пишется на этапе проектирования и всегда опережает код. А код и тесты пишутся уже в соответствии с документацией. При таком подходе, и код будет чище, и если имплементация в результате будет отличаться от документации, тесты это покажут.


Это работает только для сферических проектов в вакууме. На практике же набросанные на этапе проектирования интерфейсы безжалостно корёжатся при столкновениях с действительностью. Добавляются и убираются аргументы, методы и целые классы. Именно поэтому документация должна генерироваться по исходникам, а не быть написана отдельно (заранее или нет).

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


Разница очень большая. Безусловно вы правы в том, что при любом подходе смысловой контент документации может отстать от эволюционирующего API. Но вот дерево объявлений в случае с авто-генерацией всегда будет релеванто — в отличие от отдельной документации. Глядя в авто-сгенерированную документацию вы всегда видите, какие аргументы принимает метод и что он возвращает. И всегда можно покликать и попутешествовать по типам, посмотреть, гда есть какие поля, методы, свойства и т.д.

Дальше не читал.


Ваше право.
Спасибо, поправил
Никаких рамок, только лоск =)

Вы вольны использовать любые конструкции Sphinx внутри комментариев, а от Доксигена брать только синтаксис привязки комментария с документацией к конкретному объекту исходников.

Типа:

/*!
	Detailed documentation for ``foo`` with some **reStructuredText** markup.

	Usage:

	.. code:: cpp

		foo ("bar"); // <-- OK
		foo (NULL);  // error, name can't be NULL

	In master conf.py you can add your own Sphinx extensions and then invoke custom directives:

	.. my-custom-directive::

		my-custom-directive-content
 */

 void foo (const char* name);


А вообще по-моему мы сходимся в оценке Sphinx как удачного средства генерации финального варианта документации. Что предлагается в данном продукте — так это автоматическая генерация объявлений и автоматическая же привязка к ним смыслового наполнения документации.
Встречал и прямо противополжное мнение — что использование смысловых акцентов здорово помогает при чтении при диагонали. Я раньше вот тоже не любил жирные акценты, а сейчас склоняюсь к тому, что и вправду помогает. Одно очевидно — всем не угодишь.
В реакторе возможны два типа стейтментов (ниже выдержка из файла грамматики):

reactor_body
    :   '{' reactor_stmt+ '}'
    ;

reactor_stmt
    :   reactor_expression_stmt
    |   reactor_onevent_stmt
    |   ';'
    ;


Каждый из стейтментов компилируется в функцию-обработчик, которая при старте подписывается на все свои «управляющие» события (для reactor_expression_stmt — это будет множество связываемых свойств в правой части выражения; для reactor_onevent_stmt — множество событий после ключевого слова onevent). Между самими стейтментами прямой зависимости нет (думайте про каждое из них как про метод), так что в этом плане порядок «формул» и обработчиков «onevent» значения не имеет.

Порядок играет роль лишь при старте реактора — в этот момент нам надо выполнить все стейтменты реактора, чтобы:

  • вычислить адреса управляющих событий — ведь они могут быть и не статическими (например, членами классов)
  • как минимум попытаться обеспечить справедливость всех указанных в реакторе формул (понятно, что реактор можно спроектировать так, что все выражения не могут выполняться одновременно: например a = b + 1; b = a + 1)


Так вот, при старте все стейтменты (за исключением, разумеется, содержимого «onevent») выполняются сверху вниз.
А зачем пробрасывать исключения через границу jancy->c++ или c++->jancy? Подход, который отлично работает не только в случае разных языков, но и просто разных модулей — это ловить все исключения на границе между языками/модулями и преобразовывать их в ошибки, которые понимаются другим языком/модулем. А после перехода границы, можно снова выбрасить исключение имеющее смысл уже для данного модуля. В общем, мне кажется, что ваша «ненадёжность» исключений основывается на их неправильном использовании.

ОК, значит возникло недопонимание. Вы говорили про ABI-стандарт для исключений и я понял так, что предлагается ловить и бросать плюсовые исключения. Хорошо, значит мы сходимся в главном: исключения — в каком бы виде они ни были реализованы — на границах языков надо преобразовывать. Так вот, Jancy предлагает модель исключений, которая является *самой простой* при организации межязыковых взаимодействий. Причём в обе стороны: поймать Jancy-исключение = проверить код возврата и считать расширенную информацию об ошибке из TLS; бросить Jancy-исключение = записать расширенную информацию в TLS и вернуть «ошибочный» код возврата.

Далее, с кодами возврата не всё гладко. Во первых, у вас появляется соглашение о том, что является ошибкой (null, -1, etc), а что нет.

Совершенно верно. «Бросающие» функции должны следовать определённому протоколу.

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

Вступаю на взрывоопасную поверхность, поэтому дисклеймер: нижеследующее является не более, чем моим личным мнением ;) Я считаю, что сама концепция писать разные блоки catch под разные типы исключений — глубоко порочна. По сути стандартные типы исключений решают искусственную проблему — в блоке catch мы как правило хотим ловить *любые* исключения. Безусловно, вы можете придумать примеры, в которых надо проверять тип исключения и обрабатывать их в разных catch-ах. Но эти примеры всегда можно переписать так, что блок catch останется один. А во-вторых, подход Jancy ничему не противоречит — всегда можно проанализировать расширенную информацию об ошибке из TLS и построить соответвующее ветвление.

В третьих, синтаксический сахар для обрабоки ошибок мне показался неудобным. Как пробросить ошибку через несколько уровней вызовов и сделать так, чтобы код промежуточных уровней остался не затронутым, т.е. не знал вообще что на нижнем уровне происходит ошибка, а на верхнем она обрабатывается? В вашем подходе на каждом промежуточном уровне прийдётся писать try.

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

Безусловно, данная модель не универсальна и имеет ряд ограничений — например, нельзя бросать исключения из void-функций или функций, возращающих некие структуры. Обойти всё это можно, несколько подправив прототипы «бросающих» функций — так, чтобы они удовлетворяли протоколу псевдо-исключений Jancy. В целом же, согласитесь, ограничения присущи любой модели, и для эффективного её использования требуется некоторым образом «отформатировать» под неё мозг — уж к плюсовым исключеним это относится в полной мере ;)
Спасибо за развёрнутый комментарий. Да, внутри компании в качестве version control мы используем git. Под опасениями я имел в виду скорее не то, что код на гитхабе пропадёт, а то, что я пока не до конца представляю себе, как заниматься управлением пулл-реквестов от совершенно незнакомых мне людей. Но ничего, разберёмся :)
1

Information

Rating
Does not participate
Location
Тайбэй, Тайвань, Тайвань
Date of birth
Registered
Activity