Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

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

1,581 views

Published on

Слайды доклада с OdessaJS

Published in: Engineering
  • Be the first to comment

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

  1. 1. Метапрограммирование на JavaScript Шемсединов Тимур НИИ Системных Технологий
  2. 2. Что такое метапрограммирование? • Шаблоны и макросы, используемые при компиляции • Программа, которая изменяет саму себя • Программа, генерирующая другую программу • еще варианты ?
  3. 3. Что такое метапрограммирование? 1. Это ни каким боком не искусственный интеллект. 2. Метапрограммирование это не что-то новое, вы всегда его использовали. Нельзя начать, но можно осознать и применять метапрограммирование осознанно. 3. Без метаданных вообще ничего не происходит в языках программирования для фоннеймановской архитектуры (т.е. для архитектуры, в которой данные и инструкции хранятся в одной памяти, и нужно различать где число, где строка, где длина строки, где адрес, где инструкция).
  4. 4. Что такое метапрограммирование? Парадигма программирования, построенная на программном изменении структуры и поведения программ
  5. 5. Что такое метапрограммирование? «Вот что я имею в виду под производящим произведением или, как я называл его в прошлый раз, «opera operans». В философии существует различение между «natura naturata» и «natura naturans» – порожденная природа и порождающая природа. По аналогии можно было бы образовать – «cultura culturata» и «cultura culturans». Скажем, роман «В поисках утраченного времени» строится не как произведение, а как «cultura culturans» или «opera operans». Это и есть то, что у греков называлось Логосом.» // Мераб Мамардашвили «Лекции по античной философии»
  6. 6. Как работает метапрограммирование? Парадигма программирования, построенная на программном изменении структуры и поведения программ 1. Когда происходят изменения? 2. Что именно изменяется? 3. При помощи чего происходят изменения?
  7. 7. Как работает метапрограммирование? Когда происходят изменения? • во время разработки (Design time) • во время компиляции (Compile time) • во время работы приложения (Run time) • во время выполнения задачи (Just-in-Time) • между задачами (Lazy) • по времени (Timer) • по внешнему вызову (Pull) • по событию (Push)
  8. 8. Как работает метапрограммирование? Что именно изменяется? • типы данных и структуры данных • идентификаторы (имена классов, типов, переменных) • вызовы (имена методов, динамическое связывание) • параметры алгоритмов • подстановка формул, регулярных выражений и т.д. • динамически интерпретируется сам код • сериализация/десериализация данных
  9. 9. Как работает метапрограммирование? При помощи чего происходят изменения? • Парсинг и трансляция синтаксических структур • Доступ к идентификаторам по имени • Полная интроспекция • Индивидуация объектов первого класса: • функций, через замыкания • объектов, через динамическое создание и примеси
  10. 10. Постановка задачи Для чего нам нужно метапрограммирование? • Расширение функциональности, повышение универсальности ПО • Динамические предметные области, когда изменения являются штатным режимом • Упрощение межсистемной интеграции, это отдельная тема, но очень помогает
  11. 11. Пример 1: данные var names = [ "Marcus Aurelius Antoninus Augustus", "Darth Vader", "Victor Michailovich Glushkov", "Gottfried Wilhelm von Leibniz", "Mao Zedong", "Vladimir Sergeevich Soloviov", "Ibn Arabi", "Lev Nikolayevich Tolstoy", "Muammar Muhammad Abu Minyar al-Gaddafi", "Rene Descartes", "Fyodor Mikhailovich Dostoyevsky", "Benedito de Espinosa" ];
  12. 12. Пример 1: логика (без метапрограммирования) function filter(names) { var result = [], name; for (var i=0; i<names.length; i++) { name = names[i]; if ( name.length >= 10 && name.length <= 200 && name.indexOf("Mich") > -1 && name.indexOf("V") === 0 && name.slice(-2) == "ov" && !( name.length >= 50 && name.length <= 65 && name.indexOf("Abu") > -1 && name.indexOf("Lev") === 0 && name.slice(-3) == "iov") ) result.push(name); } return result; }
  13. 13. Пример 1: выделяем метаданные var conditions = { length: [10, 200], contains: "Mich", starts: "V", ends: "ov", not: { length: [50, 65], contains: "Abu", starts: "Lev", ends: "iov" } };
  14. 14. Пример 1: строим метамодель function filter(names, conditions) { var operations = { length: function(s,v) { return s.length>=v[0] && s.length<=v[1] }, contains: function(s,v) { return s.indexOf(v) > -1 }, starts: function(s,v) { return s.indexOf(v) === 0 }, ends: function(s,v) { return s.slice(-v.length) == v }, not: function(s,v) { return !check(s,v) } }; function check(s, conditions) { var valid = true; for (var key in conditions) valid &= operations[key](s, conditions[key]); return valid; } return names.filter(function(s) { return check(s, conditions); }); }
  15. 15. Обобщенная модель модуля
  16. 16. Пример 2: описание задачи var tasks = [ { interval:5000, get:"http://127.0.0.1/api/method1.json", expect:"OK", save:"file1.json" }, { interval:"8s", get:"http://127.0.0.1/api/method2.json", put:"http://127.0.0.1/api/method4.json", save:"file2.json" }, { interval:"7s", get:"http://127.0.0.1/api/method3.json", expect:"Done", post:"http://127.0.0.1/api/method5.json" }, { interval:"4s", load:"file1.json", expect:"OK", put:"http://127.0.0.1/api/method6.json" }, { interval:"9s", load:"file2.json", save:"file1.json", post:"http://127.0.0.1/api/method7.json" }, { interval:"3s", load:"file1.json", save:"file3.json" }, ];
  17. 17. Пример 2: метамодель function iterate(tasks) { function closureTask(task) { return function () { console.dir(task); var source; if (task.get) source = request.get(task.get); if (task.load) source = fs.createReadStream(task.load); if (task.save) source.pipe(fs.createWriteStream(task.save)); if (task.post) source.pipe(request.post(task.post)); if (task.put) source.pipe(request.put(task.put)); } }; for (var i=0; i<tasks.length; i++) setInterval(closureTask(tasks[i]), duration(tasks[i].interval)); }
  18. 18. Пример 2: метамодель (конфигурируемая метаданными) function iterate(tasks) { var sources = { get: request.get, load: fs.createReadStream }; var destinations = { save: fs.createWriteStream, post: request.post, put: request.put }; function closureTask(task) { return function () { console.dir(task); var verb, source, destination; for (key in sources) if (task[key]) source = sources[key](task[key]); for (key in destinations) if (task[key]) source.pipe(destinations[key](task[key])); } }; for (var i=0; i<tasks.length; i++) setInterval(closureTask(tasks[i]), duration(tasks[i].interval)); }
  19. 19. Пример 3: интерпретация // Parse duration to seconds, example: duration("1d 10h 7m 13s") function duration(s) { var result = 0; if (typeof(s) == 'string') { var days = s.match(/(d+)s*d/), hours = s.match(/(d+)s*h/), minutes = s.match(/(d+)s*m/), seconds = s.match(/(d+)s*s/); if (days) result += parseInt(days[1])*86400; if (hours) result += parseInt(hours[1])*3600; if (minutes) result += parseInt(minutes[1])*60; if (seconds) result += parseInt(seconds[1]); result = result*1000; } if (typeof(s) == 'number') result = s; return result; }
  20. 20. Пример 3: интерпретация (конфигурируемая метаданными) function duration(s) { if (typeof(s) == 'number') return s; var units = { days: { rx:/(d+)s*d/, mul:86400 }, hours: { rx:/(d+)s*h/, mul:3600 }, minutes: { rx:/(d+)s*m/, mul:60 }, seconds: { rx:/(d+)s*s/, mul:1 } }; var result = 0, unit, match; if (typeof(s) == 'string') for (var key in units) { unit = units[key]; match = s.match(unit.rx); if (match) result += parseInt(match[1])*unit.mul; } return result*1000; }
  21. 21. Пример 4: метапрограммирование и интроспекция
  22. 22. Пример 4: метапрограммирование и интроспекция var ds = wcl.AjaxDataSource({ read: { get: "examples/person/read.json" }, insert: { post: "examples/person/insert.json" }, update: { post: "examples/person/update.json" }, delete: { post: "examples/person/delete.json" }, find: { post: "examples/person/find.json" }, metadata: { post: "examples/person/metadata.json" } }); ds.read({ id:5 }, function(err, data) { data.phone ="+0123456789"; ds.update(data, function(err) { console.log('Data saved'); }); });
  23. 23. Пример 4: метапрограммирование и интроспекция var ds = wcl.AjaxDataSource({ introspect: { post: "examples/person/introspect.json" } }); ds.read({ id:3 }, function(err, data) { data.phone ="+0123456789"; ds.update(data, function(err) { console.log('Data saved'); }); });
  24. 24. Пример 4: метапрограммирование и интроспекция var ds = wcl.MemoryDataSource({ data: [ { id:1, name:"Person 1", phone:"+380501002011", emails:[ "person1@domain.com" ], age: 25 }, { id:2, name:"Person 2", phone:"+380501002022", emails:[ "person2@domain.com", "person2@domain2.com" ], address: { city: "Kiev", street:"Khreschatit", building: "26" } }, { id:3, name:"Person 3", phone:"+380501002033", emails:[ "person3@domain.com" ], tags: [ {tag:"tag1", color:"red"}, {tag:"tag2", color:"green"} ] }, ]}); ds.read({ id:3 }, function(err, data) { data.phone ="+0123456789"; ds.update(data, function(err) { console.log('Data saved'); }); });
  25. 25. Приемы метапрограммирования • Стиль описания задачи: декларативный (метаданные), использование императивных и функциональных вставок • Хеши (ассоциативные массивы) заранее не знаем ключ: var a = {}; a[key] = value; • Интерпретация строк, придумываем свои синтаксисы или берем общепринятые (json, js, regexp ...) • Примеси (mixins): заранее не знаем куда добавим function mixin(a) { a.fn=function(){ ... } } • Замыкания (closures): персонализируем функции fn = (function(a) { return function() { return a*2 } })(value)
  26. 26. Последствия метапрограммирования • Размер кода: чаще резко уменьшается, но иногда может немного увеличиваться • Быстродействие: незначительно снижаться, но при грамотной реализации остается примерно тем же • Гибкость: программный код становится более универсальным, сфера применения ПО расширяется • Интеграция: обычно значительно упрощается и требует меньше изменений кода • Удовольствие от работы: метапрограммировать интереснее поэтому удовольствия и мотивации больше • Скорость разработки: разрабатывать дольше, а поддерживать значительно проще, экономится уйма времени
  27. 27. Метапрограммирование на JavaScript На Github: https://github.com/tshemsedinov/metaprogramming На Хабре: http://habrahabr.ru/post/227753/
  28. 28. Метапрограммирование на JavaScript Спасибо за внимание Прошу задавать вопросы Шемсединов Тимур НИИ Системных Технологий

×