Секретная киллер-фича JavaScript

предыдущая серия

У шаблона Property Pattern много других имен. Например, он известен как Do-It-Yourself Reflection или Adaptive Object Modeling. Но самое интересное, во-первых — как только мы с ним познакомимся, мы сразу же начнем его видеть повсюду — он просто по-разному маскируется. И во-вторых, этот шаблон можно масштабировать неограниченно! Он может использоваться просто как аннотации к классам в виде прицепляемых списков, а может представлять собой полноценную прототипную структуру, которая будет моделировать в нашей системе вообще всё!

Итак, начнем знакомство с этим паттерном на реальных примерах.

Eclipse Java Development Tools (JDT)

Это пример небольшого масштаба: набор Java-классов, которые сами по себе моделируют язык Java (абстрактное синтаксическое дерево, метаданные, символические графы и т. п.). Он используется бэкендом Eclipse чтобы делать всю магию с исходным кодом, представляя его в виде удобных структур данных.

Когда мы заберемся внутрь JDT Core и org.eclipse.jdt.core.dom, то обнаружим там строго типизированные классы и интерфейсы для моделирования Java. И вот когда мы погрузимся, например, в любой класс унаследованный от ASTNode, то обнаружим там такой комментарий от javadoc:

Each AST node is capable of carrying an open-ended collection of client-defined properties. Newly created nodes have none. getProperty and setProperty are used to access these properties.

Вот это — самое простое и наглядное использование паттерна свойств. Он не испортит в Java ничего — ни сериализацию, ни прототипирование, ни метапрограммирование. При этом он засунут в самую сердцевину строго типизированной системы, что отлично показывает, что ни объектное моделирование, ни моделирование на основе системы типов совершенно не конфликтуют с этим паттерном, прекрасно уживаются и дополняют друг друга. Но при этом данная система свойств сама по себе сильно типизирована! Это например классы StructuralPropertyDescriptor, SimplePropertyDescriptor, ChildListPropertyDescriptor для контроля за свойствами клиентов.

JavaScript

Примером, полностью противоположным предыдущему, будет язык JavaScript, где паттерн свойств помещен в самое сердце. Причем наличие этого паттерна в ядре языка, на самом деле, качественно отличает JavaScript от других динамических языков наподобие Python или Ruby! Хотя в мэйнстриме принято считать, что JavaScript — это всего лишь их облегченный наследник. Сейчас мы развеем это многолетнее заблуждение.

JavaScript принципиально отличается не только от Python или Perl, но даже, страшно сказать, и от Lisp! Потому что только в js центральным механизмом моделирования сделан рассматриваемый нами паттерн.

В JavaScript любой объект наследуется от Object, который имеет собственный встроенный список свойств. Наследование прототипа (вспомним случай с футболистом А.К.!) в этом языке отлично работает, и он предлагает разный синтаксический сахар для доступа к спискам свойств (например, литералы объектов).

JavaScript на самом деле активно ругается уже наверное лет 10-15, однако причина этой критики в том, что его сравнивают с, например, Python или Java — или даже пытаются перейти на него с этих языков, но это реально вызывает огромные проблемы, и совершенно справедливо. Потому что JavaScript подразумевает работу в совершенно иной школе моделирования! А так как практически ни у кого из нас нету осознанного опыта работы с паттерном прототипирования, такие несправедливые претензии немудрены.

Отличительная фишка JavaScript, как ни парадоксально это прозвучит — это неплохая поддержка метапрограммирования.

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

JavaScript предлагает, например, __noSuchMethod__, который позволяет перехватывать неудачные попытки вызова несуществующих функций у объектов. Но к сожалению, нету хука __noSuchField__, а в общем слувчае не хватает стандартных механизмов уведомлений об изменениях свойств (ни даже механизма для организации такого механизма). Поэтому, скорее всего по соображениям производительности, JavaScript не предлагает развитую и расширяемую систему метапрограммирования — какую, например, предоставляет SmallTalk и, частично, Ruby и Python.

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

продолжение

Поделиться статьей ...Share on Facebook0Share on Google+0Tweet about this on TwitterShare on LinkedIn0Share on VKPrint this page

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *