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


105

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

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

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

Що ви думаєте про цю тему? Це щось, що дійсно підвищить вашу продуктивність? Які є хороші ресурси з цього приводу, серед книг, блогів, слайд-шоу тощо?


Деякі приклади коду будуть дуже вдячні, щоб я міг краще зрозуміти його реалізацію.


Ось сторінка вікі з цього питання з різними відповідними методами програмування, такими як метапрограмування, генеративне програмування та генерація коду.


32
Я колись писав код, який написав код, який написав код ... :)
Benjol

9
@Benjol: Ви писали на Ліспі?
комман

11
Додатково серверні мови роблять це постійно, створюючи HTML, CSS та JavaScript. Ви могли б мати серверний скрипт , який створює серверний скрипт , який створює HTML з JavaScript , який створює більше HTML, і ніхто з них буде битою очей про це з - за того , як загальне це.
zzzzBov

8
Якщо ви ще цього не зробили, перегляньте цю статтю IBM developerWorks: " Мистецтво метапрограмування " Частина 1 , Частина 2 та Частина 3 .
Джон Тоблер

3
AtomWeaver ( atomweaver.com ) - хороший приклад автоматичного програмування: По-перше, ви створюєте міні-програми для багаторазового використання в Луа. Потім ви моделюєте свою систему, використовуючи ці активи. Тоді AtomWeaver вбудовує програму Lua, яка містить ваші "міні-генератори" для створення остаточного вихідного коду системи. Потім ви можете налаштувати свою модель та знову генерувати.
Руй Курадо

Відповіді:


49

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

Щодо продуктивності: я використовую метапрограмування як домінуючу техніку майже у всій своїй роботі з розробки, і це, очевидно, дуже допомагає, як зменшуючи розмір коду, так і збільшуючи його читабельність. Ключовим моментом є використання мов , визначених для домену , а метапрограмування - один з найефективніших способів їх реалізації.


67

Я вважаю за краще піти трохи далі, а замість того, щоб писати код, який пише код, писати код, який генерує об’єкти, методи, функції. Цього можна досягти, наприклад, за допомогою макросів Lisp або можливостей динамічної модифікації програми Ruby.

Невелика різниця полягає в тому, що ви не закінчуєтесь вихідними файлами, які автоматично генеруються. Зазвичай ці файли не читаються людьми і не можуть бути змінені, тому навіщо їм заважати. Мені не подобається ідея збільшувати свою кодову базу тим, що я не можу контролювати.

Одна книга, яку мені сподобалось читати на цю тему, була метапрограмування Ruby (якщо ви знаєте мову Ruby)


Редагувати після наступного запитання в коментарі:

Чому це повинно бути корисним, мені все ж доводиться кодувати генеруючий код? Чи потрібно писати код, здатний генерувати різні речі залежно від введення користувача, щоб я міг повторно використовувати його знову і знову?

По-перше, метапрограмування - не мета, а інструмент. Не використовуйте метапрограмування, оскільки "його круто" або "X сказав, що кожен розробник повинен використовувати це".

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

За словами Джордана , одним типовим випадком використання є обробка бази даних та ОРМ (Об'єктивне відношення об'єктів). Ще раз, в Ruby, ви повинні подивитися на ActiveRecord, який є чудовим прикладом метапрограмування, застосованого до ORM.

Як остаточна примітка:

Не думайте, "я хочу застосувати метапрограмування, де я можу застосувати це у своєму коді?".

Подумайте: "Я бачу цю модель, яка повторюється в усьому моєму коді, я не можу знайти спосіб перефабрикувати код на щось менше та більш багаторазове використання. Може, метапрограмування може мені допомогти?"


3
@Jose: Найчастіше ви генеруєте код за допомогою шаблонів. Наприклад, швидкість apache (N-), наприклад, або візуальні шаблони студії T4. Тоді у вас просто програма, яка подає метадані у ваші шаблони і створює з цього часу нові файли. Це досить просто, і я роблю це весь час для створення UI-скелетів, об'єктів тощо
Falcon

2
@Jose Faeti, уважно подивіться на макроси Lisp (або Clojure, або Nemerle, залежно від ваших переваг платформи).
SK-логіка

1
Я б додав, що метапрограмування може замінити такий шаблон, як політика чи стан, але без витрат на виконання. Це стосується не лише проблем, яких неможливо досягти загальним рефакторингом, але й дещо кращою альтернативою.
deadalnix

1
@Jose Faeti: Я бачу, що ти знаєш якогось Python. Він також має можливості метапрограмування, хоча я не дуже використовував їх. Подивіться на небезпечно розширений PDF-файл Python
Kit

3
@Falcon: IMO - це найгірший спосіб генерування коду; це дуже погана робота з мовами без вбудованого засобу метапрограмування. Замість того, щоб генерувати Java або C #, було б краще написати цей код на JVM або .NET мові вищого рівня.
Кевін Клайн

19

Ще краще використовувати код, який написав хтось інший, який пише ваш код для вас.

Автоматизація коду, як правило, хороша для ORM та іншого коду взаємодії з базами даних, і, звичайно, для повторного, але подібного побудови коду.

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

Це сприймає багато людей, хоча програмне забезпечення, позначене як генератор коду, часто зустрічається.

Перегляньте такі компанії та продукти, як CodeSmith та MyGeneration, або перегляньте цю статтю у Вікіпедії: http://en.wikipedia.org/wiki/Comppare_of_code_generation_tools


6
Це не краще. Вашим дорогоцінним маленьким та дуже власним кодом не може бути належним чином керований інший інструмент генерації коду блоку, оскільки цей інший не знає нічого про вашу специфіку. Найпродуктивніше використання метапрограмування - це реалізація мов, що належать до домену, і, як випливає з назви, вони характерні для вашої дуже проблемної області, їх не може реалізувати ніхто інший, як ви.
SK-логіка

@ SK-логіка: як щодо коду, створеного ORM? Він створений іншим інструментом / бібліотекою і все ще відповідає безлічі потреб проекту.
Девід

@David, якщо чесно, я не зовсім переконаний у загальних ORM. У мене було так багато проблем з ними в минулому, що часто вдавалися до впровадження моїх власних конкретних ORM.
SK-логіка

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

1
@AtillaOzgur, вони можуть бути "дуже хорошими", правда. Але вони не кращі, ніж eDSL. Автономне генерування коду, очевидно, набагато більш обмежене та набагато менш гнучке, ніж макрометопрограмування.
SK-логіка

16

Один з класичних прикладів - lex and yacc. Їх головне призначення - уникнути зухвалості написання будь-якого типу парсера. Попутно вони набагато швидше створюють складні аналізатори з безліччю правил і штатів, а також уникають усіх несподіваних помилок, допущених людьми, котившись самостійно.

Це також ідея c, яка є інструментом для написання асемблера. Те саме стосується будь-якої мови високого рівня, яку ви хочете назвати. Для інструментів, які пишуть код для вас, існує кілька простих парадигм.

Належний IDE допомагає, надаючи документацію під рукою, інтелектуальне автоматичне завершення та фрагменти коду. IDE також включає різні шаблони, тому вам не потрібно запускати програму з нуля. Існують програми для прийняття uml-діаграми та розбиття класів на мові високого рівня.

Нарешті, ви можете написати власні інструменти для генерації коду у своєму наборі проблем. Саме так вперше розпочали роботу lex та yacc. Будь-який тип мовного домену існує саме з цієї причини. Ви створюєте кілька будівельних блоків, які описують ваше рішення, щоб простіше зрозуміти код, завершуючи звичайні дії або складні розділи простими командами. Ви не шукаєте рішення кожної проблеми, а простіше визначити конкретну, з якою ви маєте справу.

У певному сенсі все, що ви робите над бінарним шаром, - це автоматизація коду.


Це дійсно приємний вид. Загалом, це лише ще один із багатьох методів, які програмісти намагаються використовувати для полегшення своїх операцій та зосередження уваги на більш високому рівні кодування замість деталей синтаксичного коду.
Хосе Фаети

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

У досить потужних мовах (наприклад, C ++ на відміну від C) зовнішні інструменти, такі як lex та yacc, не потрібні.
Кевін Клайн

YACC не пише "будь-якого аналізатора". Він пише один конкретний вид парсера (LALR), який дуже важко отримати без автоматичної допомоги. Існує ще один тип парсера (рекурсивний спуск), який набагато простіше написати і правильно підійти, і відповідно простіше читати і розуміти, що відбувається.
Мейсон Уілер

@MasonWheeler Тип аналізатора мав на увазі граматики, які можна створити для вирішення задач у широкому, неточному сенсі. Читаючи це через рік, це не так зрозуміло, як я б хотів. Я не впевнений, що згоден з вами щодо того, що LL (*) парсери простіше писати та використовувати.
Спенсер Ратбун

13

Метапрограмування

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

Плюси

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

Мінуси

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

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

Однак це не означає, що я думаю, що всі програмісти повинні цим займатися. Я бачив і повинен був виправити великі проблеми, створені метапрограмуванням. Зазвичай з тих випадків, коли люди, які не розуміють поняття та намагалися розширити функціонал, або просто виправили помилку. Це потребує певного розумового набору, орієнтованого як мінімум на деталі. Питання про використання методів метапрограмування повинно бути командним рішенням . Якщо у вас є члени команди, які не розуміють, не маєте темпераменту до цього або просто проти цього, жодна команда не повинна використовувати метапрограмування.


Дякуємо за корисні міркування! Чи можете ви запропонувати мені дійсно просте і основне завдання, яке я зможу реалізувати за допомогою метапрограмування, що заощадить мені час на звичайному кодуванні, невеликий приклад коду?
Хосе Фаети

ха-ха, змушуй мене згадати помилку, яку я мала кілька років тому з GCC. 162 рядки, щоб помістити повідомлення про помилку на мій екран. Рекурсивне метапрограмування FTW!
deadalnix

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

2
@ SK-логіка: Не всі мови добре підтримують метапрограмування. Тому іноді такі речі, як безпека типу, приносяться в жертву (т. Е. С) . Також метапрограмування - це не лише DSL. Він включає такі речі, як програмування стилів диспетчеризації, генеричні засоби, каррінг, перевірка об'єктів, динамічне застосування тощо. Щодо складності, я думаю, що нам (людям з досвідом метапрограмування) легко сказати, що це не складно. Я бачив іншу боротьбу з розумінням усіх справ, під якими буде виконано код. В основному це залежить від їх досвіду та техніки.
дієтабудда

@dietbuddha, ви можете, будь ласка, докладно пояснити, чому варто жертвувати безпекою свого власного DSL, незалежно від того, як він реалізований? Ви можете написати спеціальний перекладач у чистому С із сильною системою типу (див., Наприклад, Hugs). Ви можете написати генератор коду, орієнтований на C, який виконує всю перевірку типу, не покладаючись на систему типів цільової мови. Складність: більшість людей роблять це непотрібно складним способом, тоді як всі ті ж методології проектування можуть застосовуватися до генерації коду, як і в "звичайному" програмуванні. Майже не потрібно нових знань.
SK-логіка

9

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

У широкому розумінні ми можемо вважати обчислення як написання кодів, які записують коди рекурсивно, утворюючи стек, який припиняється, коли він стикається з фізичною реальністю кодів, з'єднаних в апаратне забезпечення.


3
Я б не назвав html мовою програмування. Це синтаксис документів
Саймон Берго

3
@Simon - цікавий момент. Існує вся різноманітність виразних повноважень для різних кодів, які ми використовуємо. Код може писати слабшою мовою, сильнішою або власною мовою.
Бен Хейлі

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.

Насправді, ви можете стверджувати, що кожен компілятор - це лише інша метапрограма - вони містять текст програми та вихідну машину або код VM. І, життя без укладачів? Сова.


Це правильно, але як ви можете реально реалізувати його у власній мові програмування, щоб фактично підвищити свою продуктивність? Ось чого мені не вистачає.
Хосе Фаети

5

Ось конкретний приклад з мого минулого.

Я працював на сайті, де було близько 50 Мб вихідного коду Delphi, використовуючи BDE для доступу до даних. Вони хотіли перейти до використання Direct Oracle Access, щоб дозволити оновлення Oracle минулого найвищої версії, підтримуваної BDE (8i, якщо я правильно пам'ятаю).

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

  1. Проаналізував DFM (файл форми) та виявив усі об'єкти TQuery, TTable, TStoredProcedure & TDatabase - зберігання елементів у списку.

  2. Проаналізував PAS (код) та визначив використання об'єктів - чи TQuery робив оновлення чи вибирав? Крім того, він ідентифікував будь-які об’єкти, створені в коді, а не потрапляли на форму в IDE.

  3. Перепишіть DFM & PAS, змінивши типи об'єктів відповідним чином (наприклад, TTable -> TOracleDataSet із властивістю SQL, встановленою на "select * from" тощо) та методом викликів. Крім того, додаткові виклики методів були додані, якщо потрібно, для закриття, відкриття та встановлення параметрів.

Коротше кажучи, 3 тижні працюють над налаштуванням сценарію для роботи над різними програмами, написаними різними командами з різними стилями кодування замість оригінальної оцінки 5+ розробників, які працюють протягом 6 місяців.

І тому я навіть думав використовувати цей підхід через читання «Прагматичного програміста»


Це чудово, я зараз перебуваю в Perl через пару днів, і я вже створив кілька інструментів продуктивності, щоб генерувати базові робочі простори для веб-розробки, з усіма каталогами, файлами тощо, просто ввівши «створити робочу область»! :)
Хосе Фаети

1
@Jose Це ідея. Використовуйте мови сценаріїв для автоматизації повторюваних матеріалів. Це може бути одноразово, коли ви отримуєте 8-кратне підвищення продуктивності, або, як у вашому випадку, щось забирає багато часу, що ви будете робити знову і знову.
mcottle

4

Ви запитуєте приклади….

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

Наприклад, до введення типу даних DATE на сервер MS SQl, єдиним вибором для стовпців дати був DATETIME, який має часову частину - тимчасову частину, що робить обмін даними трохи складніше. Після оновлення до версії з типом даних Date, можливо, ви захочете оновити стовпці, де час завжди 00:00. У базі даних з десятками, а то й сотнями колонок DateTime це забирає багато часу. Але легко написати сценарій, який запитує всі таблиці, перевіряючи кожен стовпець із типом даних DATETIME, щоб побачити, чи не час коли-небудь, окрім 00:00, і якщо не створити ALTER-заяву для зміни таблиці / стовпця тип даних до DATE. Престо, код, який пише код.


3

Погляньте на макроси CL (звичайні губи). На мою думку, це саме те, що ти хочеш. Губи ідеально підходять для метапрограмування.

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

Але якщо ви хочете справжнього двигуна генерації коду, погляньте на ощадливість Apache


3

Я просто працюю над таким інструментом. У нашому конкретному випадку ми створюємо код VB.NET на основі рівня даних на підписах функцій у базі даних.

Починати працювати над створенням коду та над його створенням важко спочатку, оскільки ви не маєте уявлення про те, як слід створювати код, але, як тільки у вас є встановлений набір правил, і код, який повинен бути створений, завжди може бути сформований на основі цих правил , працювати з цим кодом не так вже й складно. Звичайно, залежно від складності створення коду та кількості правил, завдання може стати складнішим. Але по суті, генерація автоматичного коду використовується для повторних завдань кодування, а не для розширеного коду, який сильно відрізняється.

Тестування виходу є дворазовим. Спочатку ви повинні переконатися, що код збирається, і це легко. Тоді ви повинні переконатися, що висновок виконує те, що ви мали намір робити, виходячи з параметрів, на яких він був згенерований .., а складність цього залежить від складності коду, який ви створюєте.

Моя щира рекомендація полягає в тому, що якщо вам здається, що ви пишете код повторюваним способом , і ви можете собі дозволити час. Постарайтеся подумати, чи не те, що ви робите, не можна зробити згенерованим кодом. І якщо так (якщо це повторюваний код, ніж це майже завжди), подумайте, скільки разів вам доведеться розширити, трохи змініть цей код, а також скільки разів вам доведеться писати саме такий код. Якщо відповідь на будь-яке з них "багато", то слід серйозно розглянути можливість створення генератора для цього коду .

Сподіваюся, що допоможе,
IPP


Дякуємо за відповідь! Як реально реалізуються правила у вашому прикладі?
Хосе Фаети

1
Я не можу сказати вам усі правила, але можу навести кілька прикладів. Ми розбираємо інтерфейс, оголений базою даних oracle, і беремо до уваги підписи функцій в інтерфейсі oracle. На основі підпису ми формуємо назву функції рівня даних. ми знаємо, що ми завжди отримуємо з таблиці даних db oracle oracle, в результаті чого ми аналізуємо і зберігаємо в масив спеціального типу об’єктів, який ми використовуємо для зберігання наших даних. також, виходячи з вхідних / вихідних параметрів підпису функції db, ми додаємо відповідні вхідні та вихідні параметри до функцій, які ми генеруємо і так далі ..
Іоан Пол Піра

3

У мене є модуль PHP, який видає веб-сторінку, що містить код JavaScript, який генерує HTML. Це три шари саме там. Хлопчику було так важко читати!

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

Це інструмент, з яким слід грати, а потім зберігати його подалі на якийсь майбутній день, коли він стане у нагоді.


Це насправді те саме, що я намагався здійснити! :) Але тоді я вирішив зашифрувати це в режимі офлайн Perl, і він чудово працює. У мене є маса функцій, які я думаю додати!
Хосе Фаети

Я пишу код з до 20 шарів мови до мовних перетворень, без проблем. Це не є більш складним, ніж мати глибину стеку викликів у 20 шарів. Тому я категорично не згоден, що це інструмент " зберігати його подалі на якийсь майбутній день, коли це буде зручно " - генерація коду завжди зручна.
SK-логіка

3

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

Я думаю, що цей сценарій є чудовим випадком на користь аргументу коду-написання коду .


3

Що ви думаєте про цю тему?

Метапрограмування найчастіше асоціюється з нединамічними мовами, оскільки там важче досягти певної поведінки (наприклад, впровадження ORM) без безлічі непродуктивних та неінтелектуальних ліній коду.

Але навіть у більш динамічних мовах, таких як PHP, генерування коду може бути дійсно безпечним та збільшувати продуктивність у величезній кількості. У сучасних рамках дуже часто зустрічаються риштування, які створюють більшу частину загальної моделі, форми, тесту та дій для певного бізнес-об'єкта, про який ви заявляєте. Це одна з причин того, що такі рамки, як symfony або RoR, мають такий великий успіх, ці засоби генерації коду дуже швидко узгоджують код і підвищують продуктивність програмістів.

На веб-сайтах більша частина взаємодії обертається навколо чотирьох основних дій:

  • Створіть елемент
  • Отримайте набір елементів (з можливою фільтрацією)
  • Оновіть елемент новими атрибутами
  • Видаліть набір елементів

Принаймні, все, що обертається навколо цих 4 основних дій, могло б і IMHO ДОБРЕ досягти, використовуючи засоби генерації коду для досягнення максимальної продуктивності.

У моїй компанії ми використовуємо symfony, а його адміністратор-генератор - винятковий інструмент, який навіть генерує код під час виконання (і кешує його), а це означає, що нам навіть не потрібно використовувати якісь завдання чи зовнішній інструмент для генерувати новий код, нам просто потрібно очистити кеш. Я настійно раджу використовувати цей інструмент для операцій з CRUD.

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

Це щось, що дійсно підвищить вашу продуктивність?

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

Використання генерації коду без всякого питання є головним підвищенням продуктивності. Реалізація власних інструментів генерації коду - не так багато, якщо ви самі не будуєте рамки.

Які є хороші ресурси з цього приводу, серед книг, блогів, слайд-шоу тощо?

Найкращий ресурс для розуміння програмування - це завжди добре та добре прокоментований вихідний код. Я б сказав, що вивчити генератори адміністрування RubyOnRails та Symfony - це гарна ідея.


3

Хоча багато відповідей тут стосуються того, що зазвичай називають метапрограмуванням, насправді було поле, пов'язане з AI, відоме як автоматичне програмування, яке стосувалося програм, що розуміють або синтезують програми [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-логіка

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

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

2

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

Можливо, вам здається цікавим наш інструментарій з перевтілення програмного забезпечення DMS . Це чистий інструмент метапрограмування, покликаний створити інструменти аналізу та трансформації спеціальних програм.

[Для коментаря до питання ОП, коли використовується для побудови певного інструменту перетворення, DMS - це лінія продуктів, що пише код, який пише код:]

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

І як ОС, 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 для веб-нердів" у наборі переміщені до ( 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.