Почему я должен использовать генераторы кода
В последнее время я столкнулся с этой темой и не мог понять, зачем они нужны.
Можете ли вы объяснить, почему я должен использовать их в своих проектах и как они могут облегчить мою жизнь.
Примеры будут большими, и где я могу узнать эту тему еще немного.
Ответы
Ответ 1
По крайней мере, вы поставили вопрос с правильной точки зрения =)
Обычные причины использования генератора кода задаются как производительность и согласованность, поскольку они предполагают, что решение последовательной и повторяющейся проблемы заключается в том, чтобы набросить на него больше кода. Я бы сказал, что в любое время, когда вы рассматриваете генерацию кода, посмотрите, почему вы генерируете код и видите, можете ли вы решить проблему с помощью других средств.
Классическим примером этого является доступ к данным; вы могли бы генерировать 250 классов (1 для каждой таблицы в схеме), эффективно создавая решение для табличного шлюза, или вы могли бы построить нечто большее как модель домена и использовать NHibernate/ActiveRecord/LightSpeed /[выбрать свой orm] для сопоставления модели с богатым доменом в базу данных.
Хотя и ручное решение, и ORM - эффективные генераторы кода, основное различие заключается в генерации кода. С ORM это неявный шаг, который происходит во время выполнения и поэтому является односторонним по своей природе. Для ручного решения требуется и явный шаг для генерации кода во время разработки и вероятность того, что сгенерированные классы будут нуждаться в настройке в какой-то момент, что создает проблемы при повторном генерации кода. Явный шаг, который должен произойти во время разработки, вводит трение в процесс разработки и часто приводит к коду, который нарушает DRY (хотя некоторые утверждают, что сгенерированный код никогда не может нарушать DRY).
Другая причина, по которой рекламируется генерация кода, поступает из мира MDA/MDE (Model Driven Architecture/Engineering). Я не вкладываю в это много акций, но вместо того, чтобы предлагать несколько слабо выраженных аргументов, я просто собираюсь кооптировать кого-то elses - http://www.infoq.com/articles/8-reasons-why-MDE-fails.
Генерация кода IMHO - единственное решение в чрезвычайно узком наборе проблем и всякий раз, когда вы его рассматриваете, вам, вероятно, следует взглянуть на реальную проблему, которую вы пытаетесь решить, и посмотреть, есть ли лучшее решение.
Один тип генерации кода, который действительно повышает производительность, - это "генерация микрокодов", где использование макросов и шаблонов позволяет разработчику генерировать новый код непосредственно в среде IDE и вносить вкладку/вводить свой путь через заполнители (например, пространство имен/имя класса и т.д.). Такое генерирование кода является особенностью resharper, и я использую его сильно каждый день. Причина, по которой преимущества микро-генерации вызывают неудачу в генерации большинства больших масштабов, заключается в том, что сгенерированный код не привязан к какому-либо другому ресурсу, который должен храниться в синхронизации, и поэтому, как только код будет сгенерирован, он точно так же, как и весь другой код в решение.
@John
Перемещение создания "базовых классов" из IDE в xml/dsl часто наблюдается при разработке большого взрыва - классический пример - разработчики попытаются перестроить базу данных в модель домена. Если генератор кода не очень хорошо написан, он просто вводит дополнительную нагрузку на разработчика, поскольку каждый раз, когда им необходимо обновить модель домена, им либо приходится переключать контекст и обновлять xml/dsl, либо им необходимо расширить модель домена и затем переносите эти изменения обратно в xml/dsl (эффективно выполняя работу дважды).
Есть некоторые генераторы кода, которые работают очень хорошо в этом пространстве (дизайнер LightSpeed - единственный, который я могу думать о atm), действуя как двигатель для поверхности дизайна, но часто
эти генераторы кода генерируют ужасный код, который не может быть сохранен (например, поверхности дизайна winforms/webforms, поверхность проектирования EF1) и, следовательно, быстро отменяет любые преимущества производительности, полученные от использования генератора кода в первую очередь.
Ответ 2
Ну, это либо:
- вы пишете 250 классов, все почти одинаковые, но немного разные, например. для доступа к данным; занимает неделю, и она скучна и подвержена ошибкам и раздражает.
ИЛИ
- вы вкладываете 30 минут в создание шаблона кода и позволяете движку генерации обрабатывать работу в течение 30 минут.
Итак, генератор кода дает вам:
- скорость
- воспроизводимость
- намного меньше ошибок
- намного больше свободного времени!: -)
Отличные примеры:
-
Linq-to-SQL T4 templates от Damien Guard, чтобы генерировать один отдельный файл для каждого класса в вашей модели базы данных, используя лучшие хранит Visual Studio 2008 секрет - T4 шаблоны
-
PLINQO - то же самое, но для генератора Codesmith
и еще бесчисленное количество...
Ответ 3
В любое время, когда вам нужно произвести большое количество повторяющихся шаблонов, генератор кода является парнем для работы. В прошлый раз я использовал генератор кода при создании пользовательского уровня доступа к данным для проекта, где скелет для различных действий CRUD был создан на основе объектной модели. Вместо ручного кодирования всех этих классов я собрал генератор кода с шаблоном (используя StringTemplate), чтобы сделать это для меня. Преимуществом этой процедуры было:
- Это было быстрее (было создано большое количество кода)
- Я мог бы восстановить код в капризе, если я обнаружил ошибку (иногда код может иметь ошибки в ранних версиях)
- Меньше ошибок; когда у нас была ошибка в сгенерированном коде, она была везде, что означает, что ее можно было бы найти (и, как отмечалось в предыдущем пункте, было легко исправить ее и восстановить код).
Ответ 4
Использование GUI-сборщиков, которые будут генерировать код для вас, является обычной практикой. Благодаря этому вам не нужно вручную создавать все виджеты. Вы просто перетаскиваете их и используете сгенерированный код. Для простых виджетов это экономит время (я использовал это для wxWidgets).
Ответ 5
Действительно, когда вы используете почти любой язык программирования, вы используете "генератор кода" (за исключением сборки или машинного кода.) Я часто пишу мало 200-строчных скриптов, которые выкатывают несколько тысяч строк C. Там также программное обеспечение, которое вы можете получить, которое помогает генерировать определенные типы кода (например, yacc и lex используются для генерации парсеров для создания языков программирования.)
Ключевым моментом здесь является мысль о вводе вашего кода в качестве исходного кода, и думать о том, что он выплескивает как часть процесса сборки. В этом случае вы пишете на языке более высокого уровня с меньшим количеством фактических строк кода для обработки.
Например, вот очень длинный и утомительный файл, который я (не сделал) написал как часть моей работы, модифицирующей Quake2-основанный игровой движок CRX. Он принимает целочисленные значения всех #defined констант из двух заголовков и превращает их в "cvars" (переменные для игровой консоли.)
http://meliaserlow.dyndns.tv:8000/alienarena/lua_source/game/cvar_constants.c
Вот короткий Bash script, который сгенерировал этот код во время компиляции:
http://meliaserlow.dyndns.tv:8000/alienarena/lua_source/autogen/constant_cvars.sh
Теперь, что бы вы предпочли сохранить? Они оба эквивалентны с точки зрения того, что они описывают, но один из них намного дольше и более раздражает.
Ответ 6
Канонический пример этого - доступ к данным, но у меня есть другой пример. Я работал над системой обмена сообщениями, которая обменивается данными по последовательному порту, сокетам и т.д., И я обнаружил, что мне пришлось писать такие классы снова и снова:
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 из них, прежде чем я решил, что мне будет проще писать генератор кода, поэтому я и сделал.
Я не буду публиковать код-код, это много загадочных вещей 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 строк кода и превратив 3-недельную задачу в 3-дневную задачу (ну плюс пара дней, необходимых для написания кода-gen).
Заключение: генерация кода подходит только для относительно небольшого количества проблем, но когда вы сможете использовать его, это спасет ваше разумность.
Ответ 7
Генератор кода полезен, если:
-
Стоимость написания и обслуживания генератора кода меньше стоимости написания и сохранения повторения, которое оно заменяет.
-
Консистенция, полученная с помощью генератора кода, приведет к уменьшению ошибок до степени, которая делает ее полезной.
-
Дополнительная проблема отладки сгенерированного кода не сделает отладки недостаточно эффективной, чтобы перевесить преимущества от 1 до 2.
Ответ 8
Как пример хорошего использования генератора кода?
Здесь используются t4-шаблоны (генератор кода, встроенный в визуальную студию) для создания сжатых css из .less файлов:
http://haacked.com/archive/2009/12/02/t4-template-for-less-css.aspx
В принципе, он позволяет вам определять переменные, реальное наследование и даже поведение в ваших таблицах стилей, а затем создавать нормальные css из них во время компиляции.
Ответ 9
Для доменных или многоуровневых приложений генерация кода - отличный способ создать начальную модель или уровень доступа к данным. Он может объединить 250 классов сущностей через 30 секунд (или в моем случае 750 классов за 5 минут). Это оставляет программиста сосредоточиться на улучшении модели с отношениями, бизнес-правилами или получением представлений в MVC.
Ключевая вещь здесь, когда я говорю о начальной модели. Если вы полагаетесь на генерацию кода для поддержки кода, то настоящая работа выполняется в шаблонах. (Как указано Max E.). Остерегайтесь этого, потому что существует риск и сложность в поддержании кода на основе шаблонов.
Если вы просто хотите, чтобы слой данных был "автоматически создан", поэтому вы можете "сделать работу с графическим интерфейсом за 2 дня", тогда я предлагаю пойти с продуктом/набором инструментов, который ориентирован на данные или два сценарий приложения.
Наконец, имейте в виду "мусор в = мусор". Если весь слой данных является однородным и не абстрагируется от базы данных, пожалуйста, спросите себя, почему вы вообще пытаетесь получить слой данных. (Если вам не нужно выглядеть продуктивно:))
Ответ 10
Все говорят здесь о простом генерации кода, но как насчет генерации кода с помощью модели (например, MDSD или DSM)? Это поможет вам выйти за рамки простых генераторов ORM/элементов/генераторов шаблонов и в генерации кода концепций более высокого уровня для вашей проблемной области.
Это неэффективно для одноразовых проектов, но даже для них разработка с использованием моделей предполагает дополнительную дисциплину, лучшее понимание используемых решений и, как правило, лучший путь эволюции.
Как и 3GL и ООП, увеличение абстракции создавало большое количество ассемблерного кода на основе спецификации более высокого уровня, разработка, основанная на модели, позволяет нам снова увеличить уровень абстракции с еще одним усилением производительности.
MetaEdit + из MetaCase (зрелый) и ABSE от Isomeris (мой проект, в alpha, info at http://www.abse.info) - это две технологии на авангард генерации кода, управляемой моделью.
На самом деле нужно изменить менталитет (например, ООП, необходимый в 90-е годы)...
Ответ 11
Я фактически добавляю последние штрихи к генератору кода, который я использую для проекта, на который я был нанят. У нас есть огромные XML файлы определений, и за несколько дней работы я смог создать более 500 классов С#. Если я хочу добавить функциональность ко всем классам, скажу, что я хочу добавить атрибут ко всем свойствам. Я просто добавляю его в свой код-gen, нажимаю go и bam! Я закончил.
Это действительно хорошо, действительно.
Ответ 12
Существует много применений для генерации кода.
Написание кода на знакомом языке и генерация кода для другого целевого языка.
- GWT -
Java -> Javascript
- MonoTouch -
C# -> Objective-C
Написание кода на более высоком уровне абстракции.
- Составители
- Доменные языки
Автоматизация повторяющихся задач.
- Уровни доступа к данным
- Начальные модели данных
Игнорируя все предвзятые понятия генерации кода, он в основном преобразует одно представление (обычно более высокий уровень) в другое (обычно более низкое). Помня это определение, это очень мощный инструмент.
Текущее состояние языков программирования никоим образом не достигло своего полного потенциала, и этого никогда не будет. Мы всегда будем абстрагироваться, чтобы выйти на более высокий уровень, чем сегодня. Генерация кода - это то, что нас достает. Мы можем либо зависеть от создателей языка, чтобы создать эту абстракцию для нас, либо сделать это сами. Языки сегодня достаточно сложны, чтобы позволить кому-либо сделать это легко.
Ответ 13
Если с генератором кода вы также собираетесь использовать фрагменты, попробуйте разницу между вводом ctor + TAB и записью конструктора каждый раз в ваших классах. Или проверьте, сколько времени вы зарабатываете с помощью фрагмента, чтобы создать оператор switch, относящийся к перечислению со многими значениями.
Ответ 14
Если вам платят LOC и работают для людей, которые не понимают, что такое генерация кода, это имеет большой смысл. Между прочим, это не шутка - я работал с несколькими программистами, которые используют эту технику именно для этой цели. В любом случае, никто не получает LOC формально (что я знаю, во всяком случае), но программисты, как правило, ожидают, что они будут продуктивными, а сбивание больших объемов кода может заставить кого-то выглядеть продуктивно.
В качестве единственной слегка касательной точки, я думаю, это также объясняет стремление некоторых кодеров разбить единую логическую единицу кода на как можно большее количество различных классов (когда-либо наследуйте проект с LastName
, FirstName
и MiddleInitial
классы?).
Ответ 15
Вот некоторые ереси:
Если задача настолько глупа, что ее можно автоматизировать во время записи программы (т.е. исходный код может быть сгенерирован с помощью script from, let say XML), то то же самое можно сделать и во время выполнения (т.е. некоторые представление этого XML может быть интерпретировано во время выполнения) или с использованием некоторого метапрограммирования. Таким образом, по сути, программист ленился, не пытался решить настоящую проблему, но сделал легкий выход и написал генератор кода. В Java/С# посмотрите на отражение, а в С++ посмотрите на шаблоны