Автоматическое программирование: написать код, который пишет код [закрыто]


105

После прочтения книги «Прагматичный программист» одним из наиболее интересных аргументов мне показалось «написать код, который пишет код».

Я попытался найти в сети еще несколько объяснений или статей по этому поводу, и хотя я нашел несколько хороших статей по этому вопросу, я до сих пор не нашел какой-либо конкретной реализации кода или хороших примеров.

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

Что вы думаете о предмете? Это то, что действительно увеличит вашу производительность? Какие хорошие ресурсы по этой теме, среди книг, блогов, слайд-шоу и т. Д.?


Буду признателен за некоторые примеры кода, которые позволят мне лучше понять его реализацию.


Вот вики-страница на эту тему с различными актуальными методами программирования, такими как метапрограммирование, генеративное программирование и генерация кода.


32
Я однажды написал код, который написал код, который написал код ... :)
Benjol

9
@Benjol: ты писал на Лиспе?
Compan

11
Кроме того, серверные языки делают это постоянно, генерируя HTML, CSS и JavaScript. Вы можете иметь серверный сценарий, который создает серверный сценарий, который создает HTML с javascript, который создает больше HTML, и никто не будет смотреть на это из-за его распространенности .
zzzzBov

8
Если вы еще этого не сделали, ознакомьтесь с этой статьей IBM developerWorks: « Искусство метапрограммирования », часть 1 , часть 2 и часть 3 .
Джон Тоблер

3
AtomWeaver ( atomweaver.com ) является хорошим примером автоматического программирования: во-первых, вы создаете многоразовые мини-программы на Lua. Затем вы моделируете свою систему, повторно используя эти ресурсы. Затем AtomWeaver создает программу Lua, которая содержит ваши «мини-генераторы» для генерации окончательного исходного кода системы. Затем вы можете настроить свою модель и заново сгенерировать.
Руи Курадо

Ответы:


49

В мире Lisp довольно часто можно увидеть код, который пишет код, который пишет код (и так далее). Таким образом, любой пример проекта Lisp или Scheme приличного размера послужит хорошим примером кода. Я бы порекомендовал взглянуть на компилятор Racket и исходники времени выполнения, а также на Bigloo , их библиотеки просто великолепны.

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


67

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

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

Одной из книг, которую я с удовольствием читал на эту тему, был Metaprogramming Ruby (если вы знаете язык Ruby)


Изменить после комментария следующий вопрос:

Почему это должно быть полезно, я все еще должен кодировать генерирующий код? Должен ли я написать код, способный генерировать разные вещи в зависимости от пользовательского ввода, чтобы я мог использовать его снова и снова?

Во-первых, метапрограммирование - это не цель, а инструмент. Не используйте метапрограммирование, потому что «это круто» или «X сказал, что каждый разработчик должен использовать это».

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

По словам Джордана , одним из типичных вариантов использования является обработка базы данных и ORM (Object Relation Mapping). Еще раз, в Ruby, вы должны взглянуть на ActiveRecord, который является отличным примером метапрограммирования, примененного к ORM.

В качестве заключительного замечания:

Не думайте: «Я хочу применить метапрограммирование, где я могу применить его в своем коде?».

Подумайте: «Я вижу этот шаблон, который повторяется по всему моему коду, я не могу найти способ преобразовать код во что-то меньшее и более повторно используемое. Может быть, метапрограммирование может мне помочь?»


3
@Jose: чаще всего вы генерируете код с помощью шаблонов. Например, есть скорость apache (N-) или шаблоны T4 для визуальной студии. Тогда у вас просто есть программа, которая подает метаданные в ваши шаблоны и с тех пор создает новые файлы. Это довольно легко, и я делаю это все время для генерации UI-скелетов, сущностей и т. Д.
Сокол

2
@Jose Faeti, присмотритесь к макросам Lisp (или Clojure, или Nemerle, в зависимости от предпочтений вашей платформы).
SK-logic

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

1
@Jose Faeti: я вижу, что ты знаешь Python. У этого также есть возможности метапрограммирования, хотя я действительно не использовал их. Взгляните на « Опасно продвинутый Python PDF»
Kit

3
@Falcon: IMO, это худший способ генерировать код; это очень плохой обходной путь для языков без встроенного средства метапрограммирования. Вместо создания Java или C # было бы лучше написать этот код на языке JVM или .NET более высокого уровня.
Кевин Клайн

19

Более того, используйте код, который написал кто-то другой, который пишет ваш код для вас.

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

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

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

Просмотрите компании и продукты, такие как CodeSmith и MyGeneration, или просмотрите эту статью в Википедии: http://en.wikipedia.org/wiki/Comparison_of_code_generation_tools


6
Это не лучше. Ваш драгоценный маленький, настолько собственный код не может должным образом управляться с помощью инструмента генерации кода другого пользователя, так как этот другой пользователь ничего не знает о вашей специфике. Наиболее продуктивное использование метапрограммирования - реализация специфичных для предметной области языков, и, как следует из названия, они специфичны для вашей самой проблемной области и не могут быть реализованы кем-либо еще, кроме вас.
SK-logic

@ SK-логика: как насчет кода, сгенерированного ORM? Он генерируется другим инструментом / библиотекой и до сих пор отвечает многим потребностям проекта.
Дэвид

@ Дэвид, если честно, я не совсем убежден в общих ORM. В прошлом у меня было очень много проблем с ними, и я часто прибегал к реализации своих маленьких специальных ORM.
SK-logic

1
@ Джордан, все эти инструменты слишком специфичны (и, что еще хуже, основаны на тексте , то есть уступают по дизайну). Вместо этого я говорю о правильном метапрограммировании.
SK-logic

1
@AtillaOzgur, они могут быть "очень хорошими", правда. Но они не лучше, чем eDSL. Автономная генерация кода, очевидно, намного более ограничена и гораздо менее гибка, чем макропрограммирование макросов.
SK-logic

16

Один из классических примеров - lex и yacc. Их основная цель - избежать трудной работы по написанию любого вида парсера. Кроме того, они значительно ускоряют создание сложных синтаксических анализаторов со многими правилами и состояниями, а также избегают неожиданных ошибок, совершаемых самими людьми.

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

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

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

В некотором смысле все, что вы делаете над бинарным уровнем, является автоматизацией кода.


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

1
@Jose Faeti Статья в Википедии en.wikipedia.org/wiki/Automatic_programming содержит ссылки на различные инструменты, если вас интересуют некоторые подробности. Я бы также посоветовал почитать о lex и yacc, поскольку для них есть немного больше документации и описания.
Спенсер Ратбун

В достаточно мощных языках (например, C ++ в отличие от C) внешние инструменты, такие как lex и yacc, не нужны.
Кевин Клайн

YACC не пишет "любой вид парсера". Он пишет один конкретный вид синтаксического анализатора (LALR), который очень трудно понять без автоматической помощи. Есть еще один тип парсера (рекурсивное спуск), который намного проще написать и понять правильно, и соответственно легче читать и понимать, что происходит.
Мейсон Уилер

@MasonWheeler Тип парсера - это грамматика, которая может быть создана для решения проблем в широком, неточном смысле. Прочитав это год спустя, это не так ясно, как мне бы хотелось. Я не уверен, что согласен с вами в том, что парсеры LL (*) проще в написании и использовании.
Спенсер Рэтбун

13

Метапрограммирование

Метапрограммирование спорный метод во многих магазинах. Причина в том, что, как и в любом мощном инструменте, величина помощи или вреда велика.

Pros

  • Более выразительный, меньше кода для написания и поддержки (часто на порядок и более)
  • Последовательность, более последовательное поведение в классе проблем, которые вы решаете с помощью кода.
  • Производительность, меньше кода для решения большего проблемного пространства

Cons

  • Сложность, это может быть очень сложно, хотя кода меньше
  • Безопасность, иногда безопасность типов и статический анализ в целом будут принесены в жертву
  • Ошибки влияют больше, небольшие ошибки будут иметь большее влияние

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

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


Спасибо за полезные соображения! Не могли бы вы предложить мне действительно простую и основную задачу, которую я смогу реализовать, используя метапрограммирование, которое сэкономит мне время по сравнению с обычным кодированием, например, небольшой код?
Хосе Фаети

хаха, я вспомнил об ошибке, которая у меня была несколько лет назад с GCC. 162 строки, чтобы разместить сообщение об ошибке на моем экране. Рекурсивное метапрограммирование FTW!
Deadalnix

6
Сложность метапрограммирования сильно переоценена. В этом нет ничего сложного, если вы используете правильные инструменты. А DSL гораздо проще отлаживать и обслуживать, чем типовой стандартный код. Кроме того, я не могу понять, почему нужно жертвовать безопасностью типов - напротив, DSL также могут иметь доменные, высокоэффективные системы типов.
SK-logic

2
@ SK-logic: не все языки хорошо поддерживают метапрограммирование. Поэтому иногда такие вещи, как безопасность типов, приносятся в жертву (например, C) . Также метапрограммирование - это не просто DSL. Он включает в себя такие вещи, как программирование в стиле диспетчеризации, универсальные шаблоны, каррирование, проверка объектов, динамическое приложение и т. Д. Что касается сложности, я думаю, что нам (людям с опытом метапрограммирования) легко сказать, что это не сложно. Я видел другую борьбу с пониманием всех случаев, в которых код будет выполняться. В основном это зависит от их опыта и техники.
dietbuddha

@dietbuddha, не могли бы вы пояснить, почему нужно жертвовать безопасностью типов своих собственных DSL, независимо от того, как это реализовано? Вы можете написать специальный интерпретатор на чистом C с сильной системой типов (см., Например, Hugs). Вы можете написать генератор кода, ориентированный на C, который выполняет всю проверку типов, не полагаясь на систему типов целевого языка. Для сложности: большинство людей делают это излишне сложным способом, тогда как для генерации кода могут применяться все те же методологии проектирования, что и при «нормальном» программировании. Практически никаких новых знаний не требуется.
SK-logic

9

Большая часть кода пишет код. Например, PHP-код помогает писать HTML. Библиотека php pdo помогает писать вызовы SQL. Файловые функции ввода / вывода пишут код для связи с ОС. Даже обычный вызов функции является ссылкой на другой блок кода, который выполняется. Так что ваши вызовы функций пишут код.

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


3
Я бы не назвал html языком программирования. Это синтаксис для документов
Симон Бергот

3
@ Симон это интересный момент. Для различных кодов, которые мы используем, есть все разнообразие выразительных возможностей. Код может писать на более слабом языке, более сильном языке или на своем собственном языке.
Бен Хейли

5

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

Моим последним проектом, связанным с этим, были некоторые базовые экраны ASP.NET CRUD (генерация кода хороша для этого). Процесс пошел определить сущности как метаданные в XML-файлах. Написание шаблонов для покрытия различных необходимых артефактов (классов сущностей, репозиториев, классов обслуживания, элементов управления asp.net, страниц asp.net и т. Д.). Запустите процесс генерации и стиль вывода.

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

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


5

В нашей компании мы используем некоторые инструменты, которые фактически генерируют классы C ++ или C # с данными, загруженными из Интернета. Эти классы являются контейнерами данных и содержат большое количество объектов в списках.


Что-то вроде фрагментов кода, найденных в некоторых IDE, например, в Visual Studio?
Хосе Фаети

@Jose Наш инструмент - это просто приложение для преобразования вывода HTML в класс. Таким образом, вместо того, чтобы загружать данные каждый раз, когда приложение запускается, мы загружаем их один раз и делаем из них класс.
Холли

5

Метапрограммирование уже давно является частью программирования. Рассмотрим не только инструменты, такие как SWIG, или WYSIWYG-дизайнеры, которые создают код, но также и инструменты на языке, такие как препроцессор C, или даже шаблоны C ++ и дженерики C # / Java, не говоря уже о Reflection.

На самом деле, вы можете утверждать, что каждый компилятор - это просто другая метапрограмма - они принимают текст программы и выходной компьютер или код виртуальной машины. А жизнь без компиляторов? Owch.


Это верно, но как вы можете на самом деле реализовать это на своем собственном языке программирования, чтобы реально повысить свою производительность? Вот чего мне не хватает.
Хосе Фаети

5

Вот конкретный пример из моего прошлого.

Я работал на сайте, на котором было около 50 МБ исходного кода Delphi, используя BDE для доступа к данным. Они хотели перейти на использование Direct Oracle Access, чтобы разрешить обновление Oracle до последней версии, поддерживаемой BDE (8i, если я правильно помню).

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

  1. Проанализировал DFM (файл формы) и определил все объекты TQuery, TTable, TStoredProcedure и TDatabase - сохранив элементы в списке.

  2. Проанализировал PAS (код) и определил использование объектов - TQueries выполнял обновления или выбор? Кроме того, он идентифицировал любые объекты, созданные в коде, а не помещенные в форму в среде IDE.

  3. Переписали DFM & PAS, изменив типы объектов соответствующим образом (например, TTable -> TOracleDataSet со свойством SQL, установленным в «select * from» и т. Д.), И вызовы метода. Также были добавлены дополнительные вызовы методов, если это необходимо, чтобы закрыть, открыть и установить параметры.

Короче говоря, 3 недели работают над настройкой сценария для работы с различными приложениями, написанными разными командами с разными стилями кодирования, вместо первоначальной оценки 5+ разработчиков, работающих в течение 6 месяцев.

И причина, по которой я даже подумал об использовании этого подхода, заключалась в чтении «Прагматичного программиста».


Это здорово, я сейчас в Perl уже пару дней, и я уже создал несколько инструментов для повышения производительности, чтобы генерировать основные рабочие пространства для веб-разработки со всеми каталогами, файлами и т. Д., Просто набрав «create workspace»! :)
Хосе Фаэти

1
@Jose Это идея. Используйте скриптовые языки для автоматизации повторяющихся вещей. Это может быть один раз, когда вы получаете 8-кратное повышение производительности или, как в вашем случае, что занимает много времени, что вы будете делать снова и снова.
Маккотл

4

Вы просите примеров ....

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

Например, до того, как тип данных DATE был представлен на MS SQl Server, единственным столбцом даты был выбор DATETIME, который имеет временную часть - временную часть, которая делает работу с данными немного сложнее. При обновлении до версии с типом данных Date вы можете обновить столбцы, в которых время всегда равно 00:00. В базе данных с десятками или даже сотнями столбцов DateTime это может занять довольно много времени. Но легко написать сценарий, который запрашивает все таблицы, проверяя каждый столбец с типом данных DATETIME, чтобы определить, когда время когда-либо, кроме 00:00, и если нет, создать инструкцию ALTER для таблицы / столбца, чтобы изменить тип данных для ДАТА. Presto, код, который пишет код.


3

Посмотрите на CL (Common Lips) Macros. На мой взгляд, это именно то, что вы хотите. Губы идеальны в метапрограммировании.

Также я предлагаю Nemerle, если вы хотите иметь возможности .NET с идеальной поддержкой метапрограммирования (включая макросы)

Но если вы хотите настоящий механизм генерации кода, обратите внимание на Apache Thrift


3

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

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

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

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

Надеюсь, что помогает,
IPP


Спасибо за ответ! Как на самом деле реализованы правила в вашем примере?
Хосе Фаети

1
Я не могу рассказать вам все правила, но могу привести несколько примеров. Мы анализируем интерфейс, предоставляемый базой данных Oracle, и учитываем сигнатуры функций в интерфейсе Oracle. На основе подписи мы генерируем имя функции уровня данных. мы знаем, что в результате мы всегда получаем из таблицы данных оракула db, которую мы анализируем и сохраняем в массив специального типа объекта, который мы используем для хранения наших данных. также, основываясь на параметрах ввода / вывода сигнатуры функции db, мы добавляем соответствующие входные и выходные параметры к функциям, которые мы генерируем, и т. д.
Иоан Пол Пирау

3

У меня есть модуль PHP, который выводит веб-страницу, содержащую код JavaScript, который генерирует HTML. Это три слоя прямо там. Мальчик был так трудно читать!

В классе программирования мы должны были написать программу, которая получит строку формулы у пользователя, проанализирует ее и отобразит значение. Самый впечатляющий решатель просто взял пользовательский ввод, обернул его в main () {printf ("% d", ...);} и запустил скрипт для его компиляции, компоновки и запуска. Он не написал парсер! Сегодня вы можете сделать это с помощью оператора SQL SELECT.

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


Это то же самое, что я пытался реализовать! :) Но потом я решил закодировать его с помощью Perl в автономном режиме, и он отлично работает. У меня есть тонна функций, которые я хочу добавить!
Хосе Фаети

Я пишу код, содержащий до 20 слоев преобразования языка в язык, без каких-либо проблем. Это не сложнее, чем иметь глубину стека вызовов в 20 слоев. Поэтому я категорически не согласен с тем, что это инструмент для « хранения» на будущее, когда это будет удобно »- генерация кода всегда удобна.
SK-logic

3

Я разработал аккуратные решения для метапрограммирования с помощью Пролога . Где основное приложение (на языке C ++) переводит абстрактное определение проблемы в приложение Prolog во время выполнения, которое затем делегируется. Часто написание эквивалентной функциональности в C ++ заняло бы вечность.

Я думаю, что этот сценарий является отличным случаем в пользу аргумента code-writing-code .


3

Что вы думаете о предмете?

Метапрограммирование чаще всего ассоциируется с нединамическими языками, так как труднее достичь определенного поведения (например, реализовать ORM) без большого количества непродуктивных и неинтеллектуальных строк кода.

Но даже в более динамичных языках, таких как PHP, генерация кода может быть действительно спасительной для жизни и значительно увеличить производительность. В современных средах очень часто встречаются леса, которые генерируют большинство общих моделей, форм, тестов и действий для определенного бизнес-объекта, который вы объявляете. Это одна из причин того, что фреймворки, такие как symfony или RoR, имеют такой большой успех, эти инструменты генерации кода очень быстро создают согласованный код и повышают производительность труда программистов.

На веб-сайтах большая часть взаимодействия вращается вокруг четырех основных действий:

  • Создать элемент
  • Получить набор элементов (с возможной фильтрацией)
  • Обновить элемент новыми атрибутами
  • Удалить набор элементов

По крайней мере все, что вращается вокруг этих 4 основных действий, может и ИМХО ДОЛЖНО быть достигнуто с помощью инструментов генерации кода для достижения максимальной производительности.

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

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

Это то, что действительно увеличит вашу производительность?

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

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

Какие хорошие ресурсы по этой теме, среди книг, блогов, слайд-шоу и т. Д.?

Лучший ресурс для понимания программирования - это всегда хороший и хорошо прокомментированный исходный код. Я бы сказал, что изучать генераторы администраторов RubyOnRails и Symfony - хорошая идея.


3

Хотя многие ответы здесь относятся к тому, что обычно известно как метапрограммирование, на самом деле было поле, связанное с ИИ, известное как автоматическое программирование, которое было связано с пониманием или синтезом программ [1].

Любой компилятор (или метапрограмма, генератор кода, транслятор, макросистема ...) работают с преобразованиями, генерируя выходные данные из входных данных, выполняя свой фиксированный алгоритм преобразования. Но традиционный компилятор или метапрограмма, учитывая определение, описание или пример того, что такое сортировка списка (например, [5, 3, 9] => [3,5,9]), не создает алгоритм сортировки. Такие проблемы, где интерес этой области "автоматического программирования".

[1] - Отчет о проделанной работе по системам понимания программ ftp://db.stanford.edu/pub/cstr/reports/cs/.../CS-TR-74-444.pdfShare


2

Мета-программирование может быть очень трудно поддерживать. Сначала это выглядит элегантно, но когда вы начинаете сталкиваться с угловыми случаями, ошибки обнаруживаются поздно (в сгенерированном коде), и все это становится кошмаром для использования / отладки.

Я в основном написал код на Python, и по моему опыту мета-программирование - плохой выбор для этого языка. Вы всегда можете реорганизовать вещи, чтобы сделать это со скучными обычными языковыми функциями. Результат менее прикольный, но с ним легче жить.


любой код может быть очень трудно поддерживать. И может быть очень легко, если все сделано правильно. Метапрограммирование может увеличить ремонтопригодность на самом деле на порядки. Ваш опыт работы с Python, скорее всего, не имеет отношения к реальному метапрограммированию, поскольку Python не очень подходит для этого способа мышления с его неуклюжим слишком глубоким AST. Но даже с Python я использовал библиотеку Tempita с высокой эффективностью, и у меня никогда не было проблем с обслуживаемостью, даже с командой, у которой почти не было опыта работы с Python.
SK-logic

Меня интересует ваша точка зрения по поводу python AST. Вы использовали tempita для целей метапрограммирования?
Саймон Бергот

это ( docs.python.org/library/ast.html ) довольно специальное AST, и анализатор выдает неоптимизированное, перегруженное дерево, что делает анализ проблематичным (особенно из-за отсутствия надлежащего сопоставления с образцом в Python). Генерация такого AST также не очень удобна. Я использовал tempita для создания кода как на Python, так и на C (т. Е. Чисто текстовое метапрограммирование), он отлично работал для этой конкретной задачи (генерация стандартного кода). Я также часто использовал Python для генерации кода C из некоторых высокоуровневых описаний XML.
SK-logic

2

ОП просит ресурсы.

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

[Чтобы следовать за комментарием к вопросу OP, при использовании для создания определенного инструмента преобразования, DMS - это линейка продуктов, которая пишет код, который пишет код:]

DMS достигает этого, будучи независимым (но не независимым) от целевых языков программирования. DMS предоставляют стандартные сервисы, необходимые для широкого круга задач метапрограммирования, подобно тому, как ОС предоставляет широкий спектр сервисов для стандартных задач программирования. Эти сервисы включают сильный синтаксический анализ, автоматическое построение деревьев с синтаксическим синтаксисом, сопоставление с образцом и переписывание на деревьях, библиотеки таблиц символов, которые легко управляют языками с неприятными правилами области видимости, такими как множественное наследование, поток управления, поток данных, точки и вызов анализ графиков. Ничто из этого не имеет смысла при отсутствии определенных языков для обработки, поэтому DMS принимает определения языка, которые привязаны к этим общим элементам механизма, обеспечивая анализ на языке, построение AST, сопоставление / переписывание паттерна целевого языка с использованием target- синтаксис языка,

Как и ОС, DMS спроектирована так, чтобы иметь очень мало мнений или ограничений относительно того, какие (мета) программы вы хотите написать, что означает, что ее можно использовать для самых разных целей: извлечения метрик, поиска мертвого кода, реализации ткачей аспектов, перевода языки, генерация кодов из DSL, реорганизация больших приложений. (DMS уже использовался для всех этих задач).

Нужны надежные определения языка, если вы не хотите тратить время на кодирование всего в справочном руководстве по языку (подумайте, что это значит для Java и C ++). DMS решает эту проблему, имея библиотеку полных определений языка. Аналог здесь напоминает наличие базы данных avaialbe для вашей ОС; вам не нужно реализовывать один из них, чтобы продолжить работу над приложением, ориентированным на базу данных.


2

См. Набор задач Филиппа Гринспуна 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/ ).


2

Примерно в 2001 году я начал работать над проектом, в котором широко использовались бизнес-объекты и объекты данных. Я собирался создать интерфейсный веб-сайт, но повесил трубку, потому что бизнес-уровень и уровень доступа к данным не были полностью разработаны. Через пару недель я начал внимательно смотреть на то, что делали эти слои. По сути, они представляли данные, возвращенные из хранимых процедур, как наборы объектов со свойствами, соответствующими полям в данных, или принимали входные параметры и отправляли их в хранимые процедуры для сохранения в таблицах базы данных. Между этими двумя уровнями происходило много сериализации / десериализации, был задействован Microsoft Transaction Server, библиотека типов IDL / ODL ... но все это соответствовало шаблону.

Спустя 2 недели у меня был разработан генератор кода, который выводил бы IDL / ODL, а также выводил бизнес и объекты данных. Парню, строящему объекты бизнес-уровня и уровня данных, потребовалось 2 года, чтобы приступить к отладке и тестированию этих объектов. Через 2 недели, с генерацией кода, у нас был тот же результат, но, поскольку он был сгенерирован, он был практически без ошибок.

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

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

Я знал людей, которые использовали макросы RegX для выполнения похожих задач или формулы Excel для выполнения аналогичных действий (я тоже так делаю).


2

Пример метапрограммирования

У меня есть библиотека авторизации Ruby, которая называется Authority . Это позволяет разработчикам задавать вопросы в своем приложении такими методами, как current_user.can_read?(@post)и @post.readable_by?(current_user). На эти вопросы отвечают централизованные классы авторизатора.

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

config.abilities =  {
  ...
  :read      => 'readable',
  :microwave => 'microwavable',  # user-defined
  ...
}

В этом случае должен быть такой метод, как current_user.can_microwave?(@post).

Метапрограммирование делает это возможным: после прочтения конфигурации я знаю, какие методы определить :

Authority.verbs.each do |verb|
  class_eval <<-RUBY, __FILE__, __LINE__ + 1 # allows for a nice bracktrace
    def can_#{verb}?(resource)
      resource.#{Authority.abilities[verb]}_by?(self)
    end
  RUBY
end
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.