Почему я должен использовать генераторы кода - PullRequest
28 голосов
/ 23 марта 2010

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

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

Примеры будут отличными, и откуда я смогу изучить эту тему немного подробнее.

Ответы [ 15 ]

19 голосов
/ 23 марта 2010

По крайней мере, вы поставили вопрос с правильной точки зрения =)

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

Классическим примером этого является доступ к данным; вы можете сгенерировать 250 классов (по 1 для каждой таблицы в схеме), эффективно создавая решение для шлюза таблиц, или вы можете создать что-то более похожее на модель домена и использовать NHibernate / ActiveRecord / LightSpeed ​​/ [выберите вашу форму] для сопоставления модели расширенного домена на базу данных.

Хотя решение, созданное вручную, и ORM фактически являются генераторами кода, основное отличие заключается в том, когда генерируется код. С ORM это неявный шаг, который происходит во время выполнения и, следовательно, является односторонним по своей природе. Ручное решение требует и явного шага для генерации кода во время разработки, и вероятность того, что сгенерированные классы нуждаются в настройке в какой-то момент, что создает проблемы при повторной генерации кода. Явный шаг, который должен произойти во время разработки, вносит трения в процесс разработки и часто приводит к коду, который нарушает DRY (хотя некоторые утверждают, что сгенерированный код никогда не может нарушать DRY).

Еще одна причина создания кода для создания кода связана с миром MDA / MDE (Model Driven Architecture / Engineering). Я не особо подчеркиваю это, но вместо того, чтобы приводить ряд плохо выраженных аргументов, я просто собираюсь выбрать кого-то другого - http://www.infoq.com/articles/8-reasons-why-MDE-fails.

ИМХО генерация кода является единственным решением в чрезвычайно узком наборе проблем, и всякий раз, когда вы его рассматриваете, вам, вероятно, следует еще раз взглянуть на проблему real , которую вы пытаетесь решить, и посмотреть, есть ли это лучшее решение.

Одним из типов генерации кода, который действительно повышает производительность, является «генерация микрокода», когда использование макросов и шаблонов позволяет разработчику генерировать новый код непосредственно в IDE и вкладывать / вводить свой путь через заполнители (например, пространство имен / имя класса и т. д.). Этот вид генерации кода является функцией resharper, и я интенсивно использую его каждый день. Причина, по которой микрогенерация выгодна в случае сбоя большинства крупномасштабных кодов, состоит в том, что сгенерированный код не привязан к какому-либо другому ресурсу, который должен быть синхронизирован, и, следовательно, как только код сгенерирован, он точно такой же, как и весь другой код решение.

@ Джон
Перемещение создания «базовых классов» из среды IDE в xml / dsl часто наблюдается при разработке большого взрыва - классическим примером могут быть разработчики, пытающиеся преобразовать базу данных в модель предметной области. Если генератор кода не очень хорошо написан, он просто создает дополнительную нагрузку для разработчика, заключающуюся в том, что каждый раз, когда ему нужно обновить модель домена, им нужно либо переключать контекст и обновлять xml / dsl, либо расширять модель домена. а затем перенесите эти изменения обратно в xml / dsl (эффективно выполняя эту работу дважды).

Есть некоторые генераторы кода, которые очень хорошо работают в этом пространстве (дизайнер LightSpeed ​​- единственный, о котором я могу подумать), выступая в качестве движка для поверхности проектирования, но часто эти генераторы кода генерируют ужасный код, который не может быть поддержан (например, поверхности разработки winforms / webforms, поверхность дизайна EF1) и, следовательно, быстро отменяют любые преимущества производительности, полученные в первую очередь от использования генератора кода.

17 голосов
/ 23 марта 2010

Ну, это либо:

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

OR

  • вы потратите 30 минут на создание шаблона кода и дадите механизму генерации справиться с тяжелой работой еще через 30 минут

Итак, генератор кода дает вам:

  • скорость
  • 1018 * воспроизводимость *
  • намного меньше ошибок
  • намного больше свободного времени! : -)

Отличные примеры:

  • Шаблоны Linq-to-SQL T4 от Damien Guard для создания одного отдельного файла для каждого класса в вашей модели базы данных с использованием лучшего секрета Visual Studio 2008 - шаблоны T4

  • PLINQO - то же самое, но для генератора Кодесмита

и бесчисленное множество .....

6 голосов
/ 23 марта 2010

В любое время, когда вам нужно создать большое количество повторяющегося шаблонного кода, генератор кода - это то, что вам нужно. В последний раз я использовал генератор кода при создании пользовательского уровня доступа к данным для проекта, где был создан каркас для различных действий CRUD на основе объектной модели. Вместо того, чтобы вручную кодировать все эти классы, я собрал генератор кода на основе шаблонов (используя StringTemplate ), чтобы сделать его для меня. Преимущества этой процедуры:

  • Это было быстрее (генерировалось большое количество кода)
  • Я мог бы перегенерировать код по своему усмотрению в случае обнаружения ошибки (в ранних версиях кода иногда могут быть ошибки)
  • Меньше ошибок; когда у нас была ошибка в сгенерированном коде, она была везде , что означает, что она была с большей вероятностью найдена (и, как отмечалось в предыдущем пункте, ее было легко исправить и восстановить код).
4 голосов
/ 25 марта 2010

Каноническим примером этого является доступ к данным, но у меня есть другой пример.Я работал над системой обмена сообщениями, которая связывается через последовательный порт, сокеты и т. Д., И я обнаружил, что мне постоянно приходится писать такие классы снова и снова:

public class FooMessage
{
    public FooMessage()
    {
    }

    public FooMessage(int bar, string baz, DateTime blah)
    {
        this.Bar = bar;
        this.Baz = baz;
        this.Blah = blah;
    }

    public void Read(BinaryReader reader)
    {
        this.Bar = reader.ReadInt32();
        this.Baz = Encoding.ASCII.GetString(reader.ReadBytes(30));
        this.Blah = new DateTime(reader.ReadInt16(), reader.ReadByte(),
            reader.ReadByte());
    }

    public void Write(BinaryWriter writer)
    {
        writer.Write(this.Bar);
        writer.Write(Encoding.ASCII.GetBytes(
            this.Baz.PadRight(30).Substring(0, 30)));
        writer.Write((Int16)this.Blah.Year);
        writer.Write((byte)this.Blah.Month);
        writer.Write((byte)this.Blah.Day);
    }

    public int Bar { get; set; }
    public string Baz { get; set; }
    public DateTime Blah { get; set; }
}

Попробуйте представить, если выбудет, написав этот код для не менее 300 различных типов сообщений.Один и тот же скучный, утомительный, подверженный ошибкам код пишется снова и снова.Мне удалось написать около 3-х из них, прежде чем я решил, что мне будет проще написать генератор кода, поэтому я так и сделал.

Я не буду публиковать код code-gen, это очень загадочноМатериал CodeDom, но суть в том, что мне удалось сжать всю систему до одного XML-файла:

<Messages>
    <Message ID="12345" Name="Foo">
        <ByteField Name="Bar"/>
        <TextField Name="Baz" Length="30"/>
        <DateTimeField Name="Blah" Precision="Day"/>
    </Message>
    (More messages)
</Messages>

Насколько это проще?(Риторический вопрос.) Я мог наконец дышать.Я даже добавил несколько звонков и свистков, чтобы он мог генерировать «прокси», и я мог написать такой код:

var p = new MyMessagingProtocol(...);
SetFooResult result = p.SetFoo(3, "Hello", DateTime.Today);

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

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

4 голосов
/ 23 марта 2010

Действительно, когда вы используете практически любой язык программирования, вы используете «генератор кода» (за исключением ассемблера или машинного кода). Я часто пишу маленькие 200-строчные сценарии, которые запускают несколько тысяч строк C. это также программное обеспечение, которое вы можете получить, которое помогает генерировать определенные типы кода (например, yacc и lex используются для генерации анализаторов для создания языков программирования.)

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

Например, вот очень длинный и утомительный файл, который я (не) написал как часть моей работы, модифицирующей игровой движок CRX на базе Quake2. Он берет целочисленные значения всех # определенных констант из двух заголовков и превращает их в "cvars" (переменные для игровой консоли.)
http://meliaserlow.dyndns.tv:8000/alienarena/lua_source/game/cvar_constants.c

Вот короткий Bash-скрипт, который сгенерировал этот код во время компиляции:
http://meliaserlow.dyndns.tv:8000/alienarena/lua_source/autogen/constant_cvars.sh

Теперь, что бы вы предпочли сохранить? Они оба эквивалентны с точки зрения того, что они описывают, но один из них гораздо длиннее и раздражает в обращении.

4 голосов
/ 23 марта 2010

Использование GUI-компоновщиков, которые будут генерировать код для вас, является обычной практикой. Благодаря этому вам не нужно вручную создавать все виджеты. Вы просто перетаскиваете их и используете сгенерированный код. Для простых виджетов это действительно экономит время (я много использовал это для wxWidgets).

3 голосов
/ 29 марта 2010

Генератор кода полезен, если:

  1. Стоимость написания и обслуживания генератора кода меньше, чем стоимость написания и поддержки повторения, которое он заменяет.

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

  3. Дополнительная проблема отладки сгенерированного кода не сделает отладку недостаточно эффективной, чтобы перевесить преимущества от 1 и 2.

2 голосов
/ 29 марта 2010

Все говорят здесь о простой генерации кода, но как насчет генерации кода на основе моделей (например, MDSD или DSM)? Это поможет вам выйти за пределы простых ORM / участников-участников / генераторов шаблонов и перейти к генерации кода высокоуровневых концепций для вашей проблемной области.

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

Подобно тому, как 3GL и ООП обеспечили увеличение абстракции за счет генерации большого количества кода сборки на основе спецификации более высокого уровня, разработка на основе моделей позволяет нам снова повысить уровень абстракции с еще одним повышением производительности.

MetaEdit + от MetaCase (для взрослых) и ABSE от Isomeris (мой проект, в альфа-версии, информация на http://www.abse.info) - две технологии на переднем крае генерации кода, управляемого моделями.

Что действительно нужно, так это изменение мышления (как, например, ООП в 90-х годах) ...

2 голосов
/ 23 марта 2010

Для доменных или многоуровневых приложений генерация кода является отличным способом создания исходной модели или уровня доступа к данным.Он может произвести 250 классов сущностей за 30 секунд (или в моем случае 750 классов за 5 минут).После этого программисту остается сосредоточиться на расширении модели с помощью отношений, бизнес-правил или получения представлений в MVC.

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

Если вы просто хотите, чтобы слой данных был «автоматически создан», чтобы вы могли «заставить графический интерфейс работать за 2 дня», то я бы предложил использовать продукт / набор инструментов, ориентированный на данные.управляемый или двухуровневый сценарий приложения.

Наконец, имейте в виду "garbage in = garbage out".Если весь ваш уровень данных однороден и не абстрагируется от базы данных, пожалуйста, спросите себя, зачем вам вообще нужен уровень данных.(Если вам не нужно выглядеть продуктивно :))

2 голосов
/ 23 марта 2010

Как насчет примера хорошего использования генератора кода?

При этом используются шаблоны t4 (генератор кода, встроенный в Visual Studio) для генерации сжатых CSS из файлов .less: http://haacked.com/archive/2009/12/02/t4-template-for-less-css.aspx

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

...