четверг, 12 февраля 2009 г.

Интересное мнение о кодогенерации

В книге Flow-Based Programming наткнулся на интересное высказывание по поводу кодогенерации (стр.20):

A related type of tool are program generators - this is also source-level reuse with a slightly different emphasis. As above, an important question is whether you can modify the generated code. If you can't, you are limited to the choices built into the generator; if you can, your original source material becomes useless from a maintenance point of view, and can only be regarded as a high-level (and perhaps even misleading) specification. Like out of date documentation, it might almost be safer to throw it away...

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

Я могу вспомнить следующие характерные случаи использования кодогенерации в своей практике:

  • генерация кода синтаксических парсеров (вроде Yacc, Coco/R, Antlr). Гибкость тут достигается возможностью включения фрагментов пользовательского кода в спецификацию грамматики;
  • генерация кода для сериализации/десериализации данных (вроде ASN.1, IDL или моей ObjESSty). Здесь гибкость, в общем-то и не нужна: что заложено в механизм преобразования данных, то и используется;
  • генерация кода GUI-форм из описания GUI-формы в Qt3 (когда из ui-файлов генерировались h/cpp-файлы с заготовкой класса для GUI-формы). Гибкость тут достигается тем, что для создания результирующего класса для GUI-формы программист наследуется от сгенерированной заготовки и в классе-наследнике реализует необходимое ему поведение. Нужно добавить, что в Qt4 данный подход серьезно изменился: теперь из ui-файлов генерируется специальный класс, который должен быть атрибутом (а не базовым классом) в пользовательском классе GUI-формы;
  • мои собственные генераторы C++ кода для различных целей (простых структур с набором полей и методами getter-ами/setter-ами, классов для представления PDU протокола EMI).

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

Но вот в последнем случае события, обычно, развиваются интереснее. Как правило, первые версии генератора работают на ура и делают все, что нужно на данный момент. Но время идет, к существующему коду появляются новые требования. Например, в сгенерированные классы/структуры нужно добавить новые поля. И здесь разработчику предстоит сделать важный выбор: либо заниматься развитием дальнейшим кодогенератора (что изначально совсем не входило в его планы), либо же отказаться от кодогенератора вообще. Иногда кажется, что развивать кодогенератор проще. Но это только кажется. А отсюда мораль: нужно очень сильно подумать, прежде чем использовать кодогенераторы для мелких вещей (вроде генерации простых структур с наборами getter-ов/setter-ов).

Комментариев нет: