После прочтения книги «Прагматичный программист» одним из наиболее интересных аргументов мне показалось «написать код, который пишет код».
Я попытался найти в сети еще несколько объяснений или статей по этому поводу, и хотя я нашел несколько хороших статей по этому вопросу, я до сих пор не нашел какой-либо конкретной реализации кода или хороших примеров.
Я чувствую, что это все еще не очень распространенный аргумент, что-то, в чем отсутствует документация или что его не принимают многие люди, и я хотел бы узнать об этом больше.
Что вы думаете о предмете? Это то, что действительно увеличит вашу производительность? Какие хорошие ресурсы по этой теме, среди книг, блогов, слайд-шоу и т. Д.?
Буду признателен за некоторые примеры кода, которые позволят мне лучше понять его реализацию.
Вот вики-страница на эту тему с различными актуальными методами программирования, такими как метапрограммирование, генеративное программирование и генерация кода.
Ответы:
В мире Lisp довольно часто можно увидеть код, который пишет код, который пишет код (и так далее). Таким образом, любой пример проекта Lisp или Scheme приличного размера послужит хорошим примером кода. Я бы порекомендовал взглянуть на компилятор Racket и исходники времени выполнения, а также на Bigloo , их библиотеки просто великолепны.
Что касается производительности: я использую метапрограммирование в качестве доминирующего метода почти во всех моих разработках, и это, безусловно, очень помогает, уменьшая размер кода и повышая его читабельность. Ключ к использованию доменных языков , и метапрограммирование является одним из наиболее эффективных способов их реализации.
источник
Я предпочитаю идти немного дальше, и вместо того, чтобы писать код, который пишет код, писать код, который генерирует объекты, методы, функции. Это может быть достигнуто, например, с помощью макросов Lisp или возможностей динамической модификации программ Ruby.
Небольшая разница в том, что вы не заканчиваете исходными файлами, которые были сгенерированы автоматически. Обычно эти файлы не читаются человеком и не могут быть изменены, так что зачем их использовать? Мне не нравится идея увеличения моей кодовой базы чем-то, что я не могу контролировать.
Одной из книг, которую я с удовольствием читал на эту тему, был Metaprogramming Ruby (если вы знаете язык Ruby)
Изменить после комментария следующий вопрос:
Во-первых, метапрограммирование - это не цель, а инструмент. Не используйте метапрограммирование, потому что «это круто» или «X сказал, что каждый разработчик должен использовать это».
Я думаю, что одной из веских причин для использования метапрограммирования является обобщение некоторого общего паттерна (паттерна как повторяющегося), который вы нашли в своем коде и который не может достичь никакая другая обычная техника программирования (наследование, шаблоны проектирования и т. Д.).
По словам Джордана , одним из типичных вариантов использования является обработка базы данных и ORM (Object Relation Mapping). Еще раз, в Ruby, вы должны взглянуть на ActiveRecord, который является отличным примером метапрограммирования, примененного к ORM.
В качестве заключительного замечания:
Не думайте: «Я хочу применить метапрограммирование, где я могу применить его в своем коде?».
Подумайте: «Я вижу этот шаблон, который повторяется по всему моему коду, я не могу найти способ преобразовать код во что-то меньшее и более повторно используемое. Может быть, метапрограммирование может мне помочь?»
источник
Более того, используйте код, который написал кто-то другой, который пишет ваш код для вас.
Автоматизация кода, как правило, хороша для ORM и другого кода взаимодействия с базой данных, и, конечно, для повторяющегося, но схожего построения кода.
Конечно, если вы создаете много похожих классов, возможно, вы могли бы добиться того же в динамическом языке гораздо раньше, но я отвлекся.
Это воспринимается многими людьми, хотя вы часто найдете программное обеспечение, помеченное как генераторы кода.
Просмотрите компании и продукты, такие как CodeSmith и MyGeneration, или просмотрите эту статью в Википедии: http://en.wikipedia.org/wiki/Comparison_of_code_generation_tools
источник
Один из классических примеров - lex и yacc. Их основная цель - избежать трудной работы по написанию любого вида парсера. Кроме того, они значительно ускоряют создание сложных синтаксических анализаторов со многими правилами и состояниями, а также избегают неожиданных ошибок, совершаемых самими людьми.
Это также идея C, который является инструментом для написания ассемблера. То же самое касается любого языка высокого уровня, который вы хотите назвать. Для инструментов, которые пишут код для вас, есть несколько простых парадигм.
Правильная IDE помогает, предоставляя документацию под рукой, интеллектуальное автозаполнение и фрагменты кода. IDE также включают в себя различные шаблоны, поэтому вам не нужно запускать программу с нуля. Существуют программы для построения диаграмм uml и проработки классов на языке высокого уровня.
Наконец, вы можете написать свои собственные инструменты для генерации кода в вашем наборе задач. Вот как Лекс и Якк впервые начали. По этой причине существует любой вид доменного языка. Вы создаете некоторые строительные блоки, которые описывают ваше решение в виде более понятного кода, оборачивая общие действия или сложные разделы простыми командами. Вы ищете не решение для каждой проблемы, а просто определение конкретной проблемы, с которой вы имеете дело.
В некотором смысле все, что вы делаете над бинарным уровнем, является автоматизацией кода.
источник
Метапрограммирование
Метапрограммирование спорный метод во многих магазинах. Причина в том, что, как и в любом мощном инструменте, величина помощи или вреда велика.
Pros
Cons
Я большой поклонник метапрограммирования, но я занимаюсь этим уже давно. Для меня компромисс между уменьшенным размером кода и последовательным поведением более чем компенсирует риски. Меньше кода означает меньше ошибок, меньше кода для обслуживания, и я обычно могу очень быстро добавлять большие функциональные возможности.
Однако это не означает, что я думаю, что все программисты должны участвовать в этом. Я видел и должен был исправить большие проблемы, созданные метапрограммированием. Обычно, когда люди, которые не понимают концепцию и пытались расширить функциональность или просто исправить ошибку. Это требует особого мышления, которое как минимум ориентировано на детали. Вопрос об использовании методов метапрограммирования должен приниматься командой . Если у вас есть члены команды, которые не понимают, не имеют темперамента за это или просто против этого, ни одна команда не должна использовать метапрограммирование.
источник
Большая часть кода пишет код. Например, PHP-код помогает писать HTML. Библиотека php pdo помогает писать вызовы SQL. Файловые функции ввода / вывода пишут код для связи с ОС. Даже обычный вызов функции является ссылкой на другой блок кода, который выполняется. Так что ваши вызовы функций пишут код.
В общих чертах, мы можем думать о вычислениях как о написании кодов, которые рекурсивно пишут коды, образуя стек, который завершается, когда он сталкивается с физической реальностью кодов, подключенных к аппаратному обеспечению.
источник
Как вы это делаете, зависит от ваших требований. Предполагая, что вы используете статическую генерацию кода, вы можете написать всю инфраструктуру самостоятельно или использовать существующий генератор, такой как CodeSmith или MyGeneration. Используя их, вам просто нужно написать необходимые шаблоны.
Моим последним проектом, связанным с этим, были некоторые базовые экраны ASP.NET CRUD (генерация кода хороша для этого). Процесс пошел определить сущности как метаданные в XML-файлах. Написание шаблонов для покрытия различных необходимых артефактов (классов сущностей, репозиториев, классов обслуживания, элементов управления asp.net, страниц asp.net и т. Д.). Запустите процесс генерации и стиль вывода.
При написании шаблонов есть некоторые накладные расходы, но они могут быть использованы для последующих аналогичных проектов. Аналогичным образом изменения в базовых данных обрабатываются путем изменения метаданных и повторного запуска генерации, что делает изменения проще и быстрее для реализации.
Что касается тестирования. Поскольку это система на основе шаблонов, вам потребуется некоторое время для первоначальной проверки выходных данных процесса, если ваш шаблон неправильный, все выходные данные из этого шаблона также будут неправильными. После того, как вы довольны этим, вы также можете использовать генераторы кода для создания базовых тестов из метаданных xml, которые затем можно расширить для особых случаев. Однако помните, что вам, возможно, все равно придется сдавать тесты кода для удовлетворения конкретных задач, генерация кода сокращает вашу работу, но не устраняет ее полностью.
источник
В нашей компании мы используем некоторые инструменты, которые фактически генерируют классы C ++ или C # с данными, загруженными из Интернета. Эти классы являются контейнерами данных и содержат большое количество объектов в списках.
источник
Метапрограммирование уже давно является частью программирования. Рассмотрим не только инструменты, такие как SWIG, или WYSIWYG-дизайнеры, которые создают код, но также и инструменты на языке, такие как препроцессор C, или даже шаблоны C ++ и дженерики C # / Java, не говоря уже о Reflection.
На самом деле, вы можете утверждать, что каждый компилятор - это просто другая метапрограмма - они принимают текст программы и выходной компьютер или код виртуальной машины. А жизнь без компиляторов? Owch.
источник
Вот конкретный пример из моего прошлого.
Я работал на сайте, на котором было около 50 МБ исходного кода Delphi, используя BDE для доступа к данным. Они хотели перейти на использование Direct Oracle Access, чтобы разрешить обновление Oracle до последней версии, поддерживаемой BDE (8i, если я правильно помню).
Таким образом, вместо того, чтобы заставить команду кодеров работать с каждой формой и модулем данных, меняя каждый компонент вручную, я написал сценарий PERL, который:
Проанализировал DFM (файл формы) и определил все объекты TQuery, TTable, TStoredProcedure и TDatabase - сохранив элементы в списке.
Проанализировал PAS (код) и определил использование объектов - TQueries выполнял обновления или выбор? Кроме того, он идентифицировал любые объекты, созданные в коде, а не помещенные в форму в среде IDE.
Переписали DFM & PAS, изменив типы объектов соответствующим образом (например, TTable -> TOracleDataSet со свойством SQL, установленным в «select * from» и т. Д.), И вызовы метода. Также были добавлены дополнительные вызовы методов, если это необходимо, чтобы закрыть, открыть и установить параметры.
Короче говоря, 3 недели работают над настройкой сценария для работы с различными приложениями, написанными разными командами с разными стилями кодирования, вместо первоначальной оценки 5+ разработчиков, работающих в течение 6 месяцев.
И причина, по которой я даже подумал об использовании этого подхода, заключалась в чтении «Прагматичного программиста».
источник
Вы просите примеров ....
При работе с SQL вы не должны изменять базу данных напрямую, а должны выполнять сценарии, которые вносят любые необходимые изменения, включая структурные изменения в базу данных (добавление таблиц, столбцов, первичных ключей, ограничений и т. Д.) , Довольно часто вам придется выполнять одно и то же действие в отношении большого количества таблиц или столбцов одновременно, и выполнение их по одной будет утомительным, короткий сценарий, который выводит более крупный сценарий, который выполняет то, что вы хотите, может быть реальным. экономит время.
Например, до того, как тип данных DATE был представлен на MS SQl Server, единственным столбцом даты был выбор DATETIME, который имеет временную часть - временную часть, которая делает работу с данными немного сложнее. При обновлении до версии с типом данных Date вы можете обновить столбцы, в которых время всегда равно 00:00. В базе данных с десятками или даже сотнями столбцов DateTime это может занять довольно много времени. Но легко написать сценарий, который запрашивает все таблицы, проверяя каждый столбец с типом данных DATETIME, чтобы определить, когда время когда-либо, кроме 00:00, и если нет, создать инструкцию ALTER для таблицы / столбца, чтобы изменить тип данных для ДАТА. Presto, код, который пишет код.
источник
Посмотрите на CL (Common Lips) Macros. На мой взгляд, это именно то, что вы хотите. Губы идеальны в метапрограммировании.
Также я предлагаю Nemerle, если вы хотите иметь возможности .NET с идеальной поддержкой метапрограммирования (включая макросы)
Но если вы хотите настоящий механизм генерации кода, обратите внимание на Apache Thrift
источник
Я просто работаю над таким инструментом. В нашем конкретном случае мы генерируем код VB.NET для уровня данных на основе сигнатур функций в базе данных.
Начать работать с генерацией кода и с ним сначала трудно, так как вы понятия не имеете, как должен генерироваться код, но как только у вас есть установленный набор правил, и код, который должен быть сгенерирован, всегда можно сгенерировать на основе этих правил. работать с этим кодом не так сложно. Конечно, в зависимости от сложности генерации кода и количества правил задача может стать более сложной. Но по сути, автоматическая генерация кода используется для повторяющихся задач кодирования, а не для сложного кода, который сильно различается.
Тестирование на выходе является двойным. Сначала вы должны убедиться, что код компилируется, и это легко. Затем вы должны убедиться, что вывод выполняет то, что вы предполагали, основываясь на параметрах, на которых он был сгенерирован ... и сложность этого зависит от сложности генерируемого вами кода.
Моя искренняя рекомендация: если вы чувствуете, что пишете код многократно , и вы можете позволить себе время. Постарайтесь подумать, не может ли то, что вы делаете, сгенерированным кодом. И если это так (если это повторяющийся код, чем почти всегда), подумайте, сколько раз вам придется расширять, немного модифицировать этот код, а также сколько раз вам приходится писать именно такой код. Если ответ на любой из них «много», то вам следует серьезно подумать о создании генератора для этого кода .
Надеюсь, что помогает,
IPP
источник
У меня есть модуль PHP, который выводит веб-страницу, содержащую код JavaScript, который генерирует HTML. Это три слоя прямо там. Мальчик был так трудно читать!
В классе программирования мы должны были написать программу, которая получит строку формулы у пользователя, проанализирует ее и отобразит значение. Самый впечатляющий решатель просто взял пользовательский ввод, обернул его в main () {printf ("% d", ...);} и запустил скрипт для его компиляции, компоновки и запуска. Он не написал парсер! Сегодня вы можете сделать это с помощью оператора SQL SELECT.
Это инструмент, с которым вы должны поиграть, а затем сохранить его на следующий день, когда он пригодится.
источник
Я разработал аккуратные решения для метапрограммирования с помощью Пролога . Где основное приложение (на языке C ++) переводит абстрактное определение проблемы в приложение Prolog во время выполнения, которое затем делегируется. Часто написание эквивалентной функциональности в C ++ заняло бы вечность.
Я думаю, что этот сценарий является отличным случаем в пользу аргумента code-writing-code .
источник
Что вы думаете о предмете?
Метапрограммирование чаще всего ассоциируется с нединамическими языками, так как труднее достичь определенного поведения (например, реализовать ORM) без большого количества непродуктивных и неинтеллектуальных строк кода.
Но даже в более динамичных языках, таких как PHP, генерация кода может быть действительно спасительной для жизни и значительно увеличить производительность. В современных средах очень часто встречаются леса, которые генерируют большинство общих моделей, форм, тестов и действий для определенного бизнес-объекта, который вы объявляете. Это одна из причин того, что фреймворки, такие как symfony или RoR, имеют такой большой успех, эти инструменты генерации кода очень быстро создают согласованный код и повышают производительность труда программистов.
На веб-сайтах большая часть взаимодействия вращается вокруг четырех основных действий:
По крайней мере все, что вращается вокруг этих 4 основных действий, может и ИМХО ДОЛЖНО быть достигнуто с помощью инструментов генерации кода для достижения максимальной производительности.
В моей компании мы используем symfony, а его администратор-генератор является исключительным инструментом, который даже генерирует код во время выполнения (и кэширует его), что означает, что нам даже не нужно использовать какие-либо задачи или внешние инструменты для генерировать новый код, нам просто нужно очистить наш кеш. Я настоятельно советую использовать этот вид инструмента для операций CRUD.
Но делать то, что сделали удивительные участники Symfony, задача не из легких. Я сам реализовал некоторые задачи генерации кода, и сделать что-то действительно последовательное и с широкой реализацией, охватывающей большинство угловых случаев, нелегко.
Это то, что действительно увеличит вашу производительность?
Я считаю, что метапрограммирование очень и очень важно на низших уровнях работы (фреймворки, кэширование, компиляторы и т. Д.), Но к этому мы должны подходить с особой осторожностью, если мы делаем что-то на бизнес-уровне.
Использование генерации кода, без сомнения, является основным фактором повышения производительности. Реализация ваших собственных инструментов генерации кода, не так много, если вы сами не создаете фреймворк.
Какие хорошие ресурсы по этой теме, среди книг, блогов, слайд-шоу и т. Д.?
Лучший ресурс для понимания программирования - это всегда хороший и хорошо прокомментированный исходный код. Я бы сказал, что изучать генераторы администраторов RubyOnRails и Symfony - хорошая идея.
источник
Хотя многие ответы здесь относятся к тому, что обычно известно как метапрограммирование, на самом деле было поле, связанное с ИИ, известное как автоматическое программирование, которое было связано с пониманием или синтезом программ [1].
Любой компилятор (или метапрограмма, генератор кода, транслятор, макросистема ...) работают с преобразованиями, генерируя выходные данные из входных данных, выполняя свой фиксированный алгоритм преобразования. Но традиционный компилятор или метапрограмма, учитывая определение, описание или пример того, что такое сортировка списка (например, [5, 3, 9] => [3,5,9]), не создает алгоритм сортировки. Такие проблемы, где интерес этой области "автоматического программирования".
[1] - Отчет о проделанной работе по системам понимания программ ftp://db.stanford.edu/pub/cstr/reports/cs/.../CS-TR-74-444.pdfShare
источник
Мета-программирование может быть очень трудно поддерживать. Сначала это выглядит элегантно, но когда вы начинаете сталкиваться с угловыми случаями, ошибки обнаруживаются поздно (в сгенерированном коде), и все это становится кошмаром для использования / отладки.
Я в основном написал код на Python, и по моему опыту мета-программирование - плохой выбор для этого языка. Вы всегда можете реорганизовать вещи, чтобы сделать это со скучными обычными языковыми функциями. Результат менее прикольный, но с ним легче жить.
источник
ОП просит ресурсы.
Вам может быть интересен наш инструментарий реинжиниринга программного обеспечения DMS . Это чистый инструмент метапрограммирования, предназначенный для создания пользовательских инструментов анализа и преобразования программ.
[Чтобы следовать за комментарием к вопросу OP, при использовании для создания определенного инструмента преобразования, DMS - это линейка продуктов, которая пишет код, который пишет код:]
DMS достигает этого, будучи независимым (но не независимым) от целевых языков программирования. DMS предоставляют стандартные сервисы, необходимые для широкого круга задач метапрограммирования, подобно тому, как ОС предоставляет широкий спектр сервисов для стандартных задач программирования. Эти сервисы включают сильный синтаксический анализ, автоматическое построение деревьев с синтаксическим синтаксисом, сопоставление с образцом и переписывание на деревьях, библиотеки таблиц символов, которые легко управляют языками с неприятными правилами области видимости, такими как множественное наследование, поток управления, поток данных, точки и вызов анализ графиков. Ничто из этого не имеет смысла при отсутствии определенных языков для обработки, поэтому DMS принимает определения языка, которые привязаны к этим общим элементам механизма, обеспечивая анализ на языке, построение AST, сопоставление / переписывание паттерна целевого языка с использованием target- синтаксис языка,
Как и ОС, DMS спроектирована так, чтобы иметь очень мало мнений или ограничений относительно того, какие (мета) программы вы хотите написать, что означает, что ее можно использовать для самых разных целей: извлечения метрик, поиска мертвого кода, реализации ткачей аспектов, перевода языки, генерация кодов из DSL, реорганизация больших приложений. (DMS уже использовался для всех этих задач).
Нужны надежные определения языка, если вы не хотите тратить время на кодирование всего в справочном руководстве по языку (подумайте, что это значит для Java и C ++). DMS решает эту проблему, имея библиотеку полных определений языка. Аналог здесь напоминает наличие базы данных avaialbe для вашей ОС; вам не нужно реализовывать один из них, чтобы продолжить работу над приложением, ориентированным на базу данных.
источник
См. Набор задач Филиппа Гринспуна 4 из курса MIT 6.916: разработка программного обеспечения для инновационных веб-сервисов ( http://philip.greenspun.com/teaching/psets/ps4/ps4.adp ).
Его цель гласит: «Обучить студентов достоинствам метаданных. В частности, они узнают, как формально представить требования веб-службы, а затем создать компьютерную программу для генерации компьютерных программ, реализующих эту службу».
Это одна из проблем, которые необходимо решить потенциальным новобранцам ArsDigita ( http://en.wikipedia.org/wiki/ArsDigita ) во время первого пузыря.
Книга «SQL for Web Nerds», на которую ссылается Филипп в pset, была перемещена в ( http://philip.greenspun.com/sql/ ).
источник
Примерно в 2001 году я начал работать над проектом, в котором широко использовались бизнес-объекты и объекты данных. Я собирался создать интерфейсный веб-сайт, но повесил трубку, потому что бизнес-уровень и уровень доступа к данным не были полностью разработаны. Через пару недель я начал внимательно смотреть на то, что делали эти слои. По сути, они представляли данные, возвращенные из хранимых процедур, как наборы объектов со свойствами, соответствующими полям в данных, или принимали входные параметры и отправляли их в хранимые процедуры для сохранения в таблицах базы данных. Между этими двумя уровнями происходило много сериализации / десериализации, был задействован Microsoft Transaction Server, библиотека типов IDL / ODL ... но все это соответствовало шаблону.
Спустя 2 недели у меня был разработан генератор кода, который выводил бы IDL / ODL, а также выводил бизнес и объекты данных. Парню, строящему объекты бизнес-уровня и уровня данных, потребовалось 2 года, чтобы приступить к отладке и тестированию этих объектов. Через 2 недели, с генерацией кода, у нас был тот же результат, но, поскольку он был сгенерирован, он был практически без ошибок.
Этот генератор кода (низкоуровневый инструмент CASE) следовал за мной через много разных итераций, в течение 8-10 лет, потому что принцип был очень прост: вы делаете что-то, что нужно делать, когда вы разговариваете с базами данных, это довольно много повторяющегося кодирования, и как только вы все сделаете правильно, вам больше не придется с этим беспокоиться.
Итак, да: используйте генератор кода, особенно когда кодирование повторяется и соответствует четко определенному шаблону.
Я знал людей, которые использовали макросы RegX для выполнения похожих задач или формулы Excel для выполнения аналогичных действий (я тоже так делаю).
источник
Пример метапрограммирования
У меня есть библиотека авторизации Ruby, которая называется Authority . Это позволяет разработчикам задавать вопросы в своем приложении такими методами, как
current_user.can_read?(@post)
и@post.readable_by?(current_user)
. На эти вопросы отвечают централизованные классы авторизатора.Это важная часть: администрация не знает, какие методы определить, пока не увидит конфигурацию пользователя . Конфигурация пользователя может содержать:
В этом случае должен быть такой метод, как
current_user.can_microwave?(@post)
.Метапрограммирование делает это возможным: после прочтения конфигурации я знаю, какие методы определить :
источник