Главная страница   /   1.1. Определения метапрограммирования (Метапрограммирование в .NET

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

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

Кевин Хазард

1.1. Определения метапрограммирования

Классическое определение метапрограммы звучит так: это "компьютерная программа, которая пишет новые компьютерные программы". Это очень похоже на определение компилятора. Компилятор для языка программирования C# можно, конечно, рассматривать в качестве конечной метапрограммы, потому что его единственная задача – создание других программ из исходного кода. Но назвать C# компилятор метапрограммой можно лишь с большой натяжкой. Неустановленной в определении традиционного компилятора является идея, что шаг выполнения фиксируется во времени, и существование скомпилированных выходных данных является невидимым для конечных пользователей. Кроме того, методики метапрограммирования явно отличаются, потому что они почти всегда используется для работы с какими-то меняющимися факторами.

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

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

Определение

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

Также присущим классическому определению метапрограммирования является представление о том, что процесс генерации кода встраивается в приложение для выполнения некоторых типов динамической логики обработки. Слово динамический часто встречается в дискуссиях о метапрограммировании, потому что оно часто используется для добавления адаптивных интерфейсов к программе во время выполнения. Например, динамическое XML приложение может читать во время выполнения описания структуры XML (XSD), чтобы построить и собрать высокопроизводительные XML парсеры, которые можно использовать сразу или сохранить для использования в будущем. Такое приложение будет хорошо выполняться и быть хорошо адаптируемым к новым XML типам без необходимости перекомпиляции.

Другое распространенное определение метапрограммирование – "компьютерная программа, которая манипулирует другими программами во время выполнения". Скриптовые языки часто соответствуют этой форме, обеспечивая простой, но мощный инструмент для метапрограммирования. Программа, которая манипулирует другой программой, вовсе не должна быть скриптовым языком. Ключевое слово dynamic в C# можно использовать, чтобы вставить манипулятивный код в скомпилированное приложение, например:

dynamic document = DocumentFactory.Create();
document.Open();

Использование ключевого слова dynamic, вызов метода Open(), показанные здесь, встроены в часть C# кода, известного как CallSite. Мы очень подробно рассмотрим CallSite позже, в главе 8. На данный момент, все, что нужно понимать - то, что кажется безопасным вызовом метода Open() в объекте документа реализуется через механизм связывания во время выполнения С# с использованием литеральной строки "Open". Когда вы покопаетесь в Intermediate Language (IL), выделенного компилятором для предыдущего фрагмента, вы можете удивиться, когда увидите строку "Open", переданную механизму связывания для вызова метода. Код C#, конечно, не похож на язык скриптов, но то, что вы увидели, несомненно, имеет сходство. Благодаря различным механизмам связывания в время выполнения для взаимодействия с простыми объектами CLR (POCO), Python скриптами, Ruby скриптами и COM объектами, C# CallSites очень хорошо показывает второе определение метапрограммирования. В главе 8 мы покажем вам, как взаимодействовать со всеми этими языками и типами объектов с использованием динамической типизации C#.

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

Больше жаргона метапрограммирования

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

Другими терминами, которые вы, вероятно, слышали, являются целевой язык или объектный язык, относительно кода, сгенерированного метапрограммой. Оба эти термины обозначают, что есть промежуточный язык, с которым работает метапрограммист в данном процессе. Как вы скоро увидите, выходными данными метапрограммы .NET может быть Common Intermediate Language (CIL), который, для всех намерений и целей вы можете считать машинным кодом. В таких случаях нет никакого целевого языка в классическом смысле.