Интервью с Иваном Шихалевым об RDot и не только

Иван, добрый день! Представься пожалуйста читателям RubyDev и расскажи кратко о себе: где работаешь, чем увлекаешься?..

Posted by Марк Мельник on October 8, 2011

Иван, добрый день! Представься пожалуйста читателям RubyDev и расскажи кратко о себе: где работаешь, чем увлекаешься?

Ну, кратенько: Иван Шихалев, временно безработный, живу в поселке Арти Свердловской области. Интересы у меня разнообразные, иногда кажется, что будь их поменьше, было бы проще жить. Отмечу, пожалуй, следующее: я являюсь одним из редакторов FreePascal.ru (и вообще, имею непосредственное отношение к формированию русскоязычного сообщества Free Pascal), а еще играю в спортивное «Что? Где? Когда?</a>. Веду блог — http://shikhalev.blogspot.com/.

Расскажи пожалуйста о своем проекте RDot, его преимуществами перед аналогами и о том, почему была выбрана именно библиотека Graphitz?

RDot — это такой визуализатор структуры классов Ruby — именно такой, какой был нужен лично мне — с указанием не только наследования, но и подмешивания модулей посредством как include, так и extend, и с перечислением методов и констант. Его основное, пожалуй, отличие от аналогов — он не анализирует текст Ruby-библиотеки, а загружает ее и работает с реально сформированной структурой, т.е. отображает классы, модули и их методы, созданные динамически в процессе загрузки. Собственно, именно такая задача у меня изначально и возникла — увидеть динамическую структуру классов, которую не показывают стандартные средства документирования (под которыми я подразумеваю RDoc и YARD). Задача несколько экзотическая, согласен, но вполне реальная.

Почему GraphViz? Это то, что называется Unix-way — есть программа, которая визуализирует произвольные графы и делает это хорошо, кроме того — является своего рода стандартом и есть во всех серьезных дистрибутивах. Вполне логично не изобретать велосипед, а сформировать соответствующий входной поток для этой программы. Кстати, замечу, что RDot изначально ориентирован на выдачу результата в stdout и, соответственно, на встраивание в потоковую обработку. Лично я его запускаю почти исключительно так:

$ rdot <параметры> | dot -Tpdf -oфайл.pdf

Еще про GraphViz — помимо иерархического дерева, каковое я показываю во всех примерах, он умеет рисовать графы и по другим правилам (подробнее см. на GraphViz.org). Это уже не для документирования, а для внутреннего, условно говоря, потребления — лично мне такие схемы помогают окинуть взглядом общую картину и подумать.

Вообще, не стоит недооценивать визуализацию и инфографику в целом — хотя текста она не заменит, да и не надо, она очень полезна именно для того, чтобы увидеть структуру, связи и т.д. Зрительные образы лучше всего воспринимаются нашим мышлением, и такой «взгляд сверху» зачастую позволяет лучше понять структуру изучаемой системы, чем изучение деталей. Детали тоже нужны, но на всё нужно смотреть с разных сторон и в разных масштабах.

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

Кстати, я подготовил специально для интервью демонстрацию RDot:

module MixMod

  def mix_func a, b = nil, &block
  end

end

class Aplha < String
  include MixMod

  def alpha
  end

  attr_accessor :beta

end

class Beta

  ALPHA = 100

  attr_reader :epsilon

end

class Gamma < Beta
  extend MixMod

  def gamma *args
  end

end

class Delta < Beta

  def self.delta
  end

end

(картинка кликабельна)

Мой блог по техническим вопросам: http://shikhalev.blogspot.com/

Расскажи пожалуйста подробнее о задачах для которых разрабатывался RDot.

Изначально задумка появилась для проекта, в котором я активно использовал динамическое (через eval) создание классов. Там при наследовании от некоего класса (условно Item) автоматом создавался Item::List для манипулирования этими элементами. Про сам проект рассказывать все-таки не буду, поскольку он крайне далек от рабочего состояния пока, к тому же я не уверен, что такой подход в нем продержится, когда я снова им займусь…

Иван, планируешь ли портировать RDot на Ruby 1.9?

Планирую. Но не могу сказать, когда это произойдет. Дело в том, что, как я уже говорил, RDot написан из личных потребностей, а на моем Gentoo Ruby 1.9 жестко замаскирован и нормальная работа с ним — не такая уж тривиальная задача (там, кроме собственно версии, нужно размаскировать use-флаг, еще парочку пакетов…) Собственно, когда testing-ветка Gentoo перейдет на Ruby 1.9, тогда и я буду на него переходить, в т.ч. и для RDot. Впрочем, каких-то серьезных изменений я от этого перехода не жду. Надеюсь написать его так, чтобы одинаково адекватно работало и на 1.8 и на 1.9. Хотя там видно будет. Может быть, это произойдет уже тогда, когда 1.9 плавно превратится в 2.0…

Чего новог планируешь добавить в RDot?

Сначала замечу, что мои планы можно отследить по трекеру на GitHub, я хоть и пишу в основном для себя, вовсю пользуюсь этим удобным инструментом — https://github.com/shikhalev/rdot/issues. На данный момент в планах стоит следующее:

 

  1. Сделать вывод хода процесса на stderr. Сейчас при обработке больших библиотек совершенно непонятно, на какой стадии работа и сколько еще предполагается ждать.
  2. Понять, что не так в некоторых особо сложных случаях — я до сих пор не могу получить граф, скажем, для qt-ruby… Не то, чтоб он мне был нужен, но что-то тут не так, буду разбираться.
  3. Провести рефакторинг. Код RDot я начал писать довольно давно, делал правки в несколько приемов… В общем, сейчас этот код далек от идеала. Кроме того, вероятно, предыдущий пункт потребует какой-то оптимизации.
  4. Этот момент под вопросом, но я таки предполагаю добавить возможность объединять классы и модули на графе в кластеры, сообразно файлам, где они описаны, и/или пространствам имен.
  5. Ну и само собой, исправлять баги, буде такие обнаружатся.

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

Пожелания и найденные баги лучше всего отправлять через те же Issues на GitHub. Если кто захочет помочь не только советом, но и кодом — там же есть прекрасные возможности для совместной работы — делаете форк, правите у себя и отправляете в апстрим так называемый Pull Request.

Можешь кратко рассказать об устройстве и принципе работы RDot для тех, кто захочет присоединиться к разработке или сделать какие-нибудь одноразовые полезные pull-request’ы?

Кратко, наверное, не получится… Надеюсь, в скором времени у меня дойдут до него руки и я таки проведу рефакторинг с подробным комментированием.

В чем заключались основные проблемы при разработке RDot? Вообще расскажи о каких-нибудь самых интересных моментах разработки.

Пожалуй, основной проблемой стало то, что каким-либо одним методом (трассировка, переопределение методов типа method_added, или же обзор через ObjectSpace) задача не решается. Пришлось брать данные различными способами и согласовывать друг с другом. Ничего страшного, но это повысило число тонких мест, откуда по невнимательности полезли баги. Да и вообще усложнило структуру.

Впрочем, я хочу отметить, что по-настоящему большим и сложным проектом RDot не является. И серьезных проблем как-то тоже не возникало. Хотя, конечно, смотря что считать сложным и серьезным…

Я привык, что все расширения Ruby и почти все инструменты для разработки на Ruby поставляются в виде gem’ов, почему RDot поставляется в виде скрипта, который нужно распаковывать и устанавливать в ручную? Планируешь ли оформить RDot в виде gem’а?

Это так потому, что я еще не вышел на версию 1.0. Вот когда мой перфекционизм позволит заявить о релизе, я и займусь пакетированием. Да, я планирую сделать гем, а также ebuild для Gentoo (в надежде, что для других дистрибутивов кто-нибудь тоже сделает пакеты — я этим заниматься не хочу, поскольку как сказано выше, исходить надо из потребностей, а лично у меня таких нет).

Расскажи пожалуйста разработкой каких еще интересных вещей кроме RDot занимаешься?

Я пока только про одну такую интересную вещь готов говорить — это проект ppRuby — подключение Ruby к Free Pascal и Lazarus в качестве скриптового движка. Там, правда, стадия разработки еще более ранняя, чем у RDot, но то, что уже есть — вполне рабочее, можно смотреть и пользоваться. Строится это все на том, что FPC, как и Delphi, поддерживает RTTI, то есть информацию о типах объектов во время выполнения. ppRuby позволяет исполнять ruby-скрипты, которые обращаются к свойствам объектов основной программы. А для проектов на Lazarus это все формы, визуальные и невизуальные компоненты…

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

Там сейчас основные вещи работают, но еще многое нужно дописывать — поскольку через RTTI доступны только published-свойства, а есть еще много свойств и методов, которые весьма важны и полезны, но находятся в области public. Для корневых объектов типа TComponent я к таким методам написал ruby-обертки, но этого, конечно, мало. И вот здесь как раз я бы очень хотел помощи сообщества, поскольку написание этих оберток представляет собой много мелкой, рутинной и прекрасно распараллеливаемой работы.

О других своих проектах пока говорить не буду. Сначала нужно довести их до первой рабочей версии.

Я так понимаю, что основной профиль твоей работы — это разработка на object pascal, а Ruby ты используешь большей частью как скриптовой довесок? Не планируешь ли полностью переключиться на разработку на Ruby/ Rails?

Нет. Нельзя сказать, что мой основной профиль — это разработка на каком-либо конкретном языке. На данный момент Ruby — один из основных.

Кроме Ruby и Pascal какими еще ЯП владеешь?

Тут смотря как считать владение (да и что относится, а что нет к ЯП)… В первую очередь пусть будет SQL (конкретно — диалекты PostgreSQL и FireBird), во-вторую — не так хорошо владею, но все же достаточно для реальной работы — C, C#, JavaScript, Visual Basic, Bash, PHP, TeX (тут я имею в виду именно тот уровень, на котором его следует считать языком программирования, т.е. написание каких-то своих макрокоманд с логикой и вычислениями). Совсем немного когда-то писал на Java, но это уже можно отнести к «давно и неправда». C++ мне сильно не нравится, поэтому я на нем только читаю, но не пишу. Впрочем, это уже можно не считать, поскольку читать код можно и на совсем незнакомом языке, если он не сильно эзотерический и к нему есть приличный справочник.

Да, чуть не забыл — на отличном уровне (т.е. так же, как Ruby, Pascal и SQL) — встроенный язык 1С версий 7.7 и 8.x.

Любая деятельность — бесконечный путь, есть какие-то планы на саморазвитие как программиста, например участие в каких-нибудь open-source проектах, собственный стартап или изучение новых ЯП?

И того и другого и можно без хлеба, как говорил великий Винни. То есть, про стартап пока конкретных планов нет, но подобного развития я для себя не исключаю. Что же до изучения новых языков и участия в open source — это такие вещи, которые происходят естественным путем и практически неизбежны. Скажем, мои (небольшие и немногочисленные) правки в RTL Free Pascal появились не потому, что я хотел поучаствовать, а просто потому, что мне понадобилась определенная функциональность, а реализовать ее и отправить патч в апстрим было быстрее, чем ждать, пока дойдут руки у основных разработчиков. Что-то такое, полагаю, будет происходить и впредь.

И еще, что касается языков — я уверен, что язык, который требуется долго и нудно изучать, изучать вообще не стоит. Язык программирования — это совершенно особенный инструмент — на нем надо не только писать, но и думать, и тут или логика языка схватывается почти сразу, или думать на нем вообще не получится (необязательно из-за его сложности, может быть просто нужный стиль мышления «не мой»). Только отмечу, что это относится именно к языкам, библиотеки и технологии вполне могут требовать не «схватывания», а долгого изучения.

Я всегда считал Pascal вымирающим языком, которым мало кто пользуется, даже когда-то популярная среда разработки Delphi сейчас практически незаметна. Расскажи в чем причины такого большого падения популярности языка?

Очень сложный вопрос на самом деле. Почему одни языки становятся популярными, а другие — нет? Например, почему Python популярней Ruby, хотя чисто языковые возможности у них примерно равны? (Разница есть в реализациях, но тут уже обратная причинно-следственная связь: Python активнее развивается, поскольку более популярен.)

В случае Pascal — в какой-то момент наложилось множество факторов. Вероятно, важнейшим стало то, что ключевые игроки сделали ставку на C++… Ну и то, что Unix’ы изначально писались на C, соответственно на нем и оказалась вся инфраструктура этих систем. А затем стала работать положительная обратная связь: более популярные языки быстрее развиваются, их чаще требуют в вакансиях, соответственно, их охотнее изучает молодежь…

Тем не менее, умирающим я бы Pascal не назвал. Тем более сейчас, когда многообразие языков стало нормой. Free Pascal и Lazarus весьма активно развиваются — это можно видеть как по сообществу, так и банально по количеству ежедневных коммитов. Вообще, свободному проекту после достижения какой-то критической массы умереть достаточно трудно.

Иван, а почему твой выбор пал именно на Ruby ведь есть множество других замечательных скриптовых языков программирования: perl, python, lua, …?

На вкус и цвет… По большому счету из этого списка Ruby можно сравнивать только с Python — Perl и Lua все-таки создавались для более специфических задач. Что до выбора между Python и Ruby — то он, скорее, эстетический — есть инструменты, с которыми работать приятно, а есть такие, с которыми не очень, даже если они и делают одно и то же.

Твоя заинтересованность в Ruby ограничивается только самим языком или ты используешь различные фреймворки? Расскажи что за фреймворки используешь.

Считать ли Rack фреймворком?.. Его использую, что-то более серьезное вроде Rails — нет. Просто не хочется умножать сущности. Сейчас и так стало очень много лишней сложности, а программы должны быть настолько простые, насколько это возможно. Да, этот принцип подразумевает использование библиотек и фреймворков, когда они нужны, т.е. когда с ними проще. Но в моем случае получается так, что ручной работы при использовании Rails или Sinatra будет столько же, сколько и при «голом» Rack, а проблем при отладке и модификации они только добавят… Вероятно, если у меня появится задача, которая будет хорошо ложиться в какой-нибудь фреймворк, я им воспользуюсь, пока такой задачи нет.

Бритва Оккама хороший принцип, но все же интересно для чего годится голый Rack?

Голый Rack — это прослойка между приложением и веб-сервером, собственно он позволяет получить запрос в удоборазбираемом структурированном виде, и ответить на него так же структурированно… Так что прикрутить к нему можно что угодно с какой угодно логикой. Собственно, это похоже на программирование CGI, только немного более удобно. Фреймворки же ставят программиста в более узкие рамки, и когда надо из них выйти, заставляют писать не просто код, а код, искусно обходящий искусственные ограничения…

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

Расскажи пожалуйста про свое рабочее место.

ОС — Gentoo Linux, тестовая ветка (~amd64). Рабочий стол KDE 4.7.1. Текущая версия Ruby — 1.8.7-p352. Из библиотек активно использую Rack с сервером Thin, Ruby-DBI с библиотеками для PostreSQL, MySQL и SQLite3, основной для меня является PostgreSQL, QtRuby + Korundum и кое-что по мелочи. Для автодокументации предпочитаю YARD — не хочу ничего плохого сказать про «родной» RDoc, но YARD мне как-то показался удобнее.

В качестве редактора почти для всех языков и задач использую Kate (собственно, кроме случаев визуального программирования на Lazarus), терминал — Yakuake.

Браузер — FireFox 7, почту читаю пишу в веб-интерфейсе GMail. IM, календарь/заметки/напоминалки — из стандартного набора KDE. Собственно, тем мне KDE и нравится в первую очередь, что предоставляет полноценный рабочий стол, а не просто графическую запускалку отдельных программ.

У меня установлен LibreOffice, но исключительно для общения с внешним миром — для себя я предпочитаю верстать тексты в LaTeX.

Что используеш для тестирования?

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

Почему из всех дистрибутивов именно Gentoo? В народе ходит множество шуток про красноглазиков и поверий о том, как сложно работать с подобными диструбутивами, почему не какой-нибудь human-friendly Ubuntu или что-то еще?

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

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

Интересно твое пророчество по-поводу нововведений в Ruby 2.0.. Как думаешь, будет добавлен нормальный параллелизм и чего вообще стоит ожидать?

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

Чего стоит ждать? Лично я жду в первую очередь JIT-компиляции и ускорения работы. Изменения в синтаксисе, даже те, которые не являются чистым сахаром, меня пока интересуют не очень.

Чего пожелаешь читателям RubyDev.ru и вообще всем новичкам — Rubyist’ам?

Интересных задач, наверное. Проектов, нужных пользователям и прибыльных для разработчика :) И не терять способности получать удовольствие, как от программирования, так и от изучения всего нового.

Спасибо большое за интервью, Иван. Удачи тебе во всех твоих начинаниях и проектах, и в частности с развитием RDot и ppRuby.

Ссылки:

  • Блог Ивана Шихалева
  • Иван Шихалев на Google+
  • Репозиторий RDot
  • Репозиторий ppRuby

Выводы:

Ruby — замечательный язык и не Rails единым он будет жив.

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