Точка использования инъекции зависимостей (и, если уж на то пошло, контейнера IoC) в LISP
Я прочитал эссе ESR под названием " Как стать хакером?"несколько лет назад (ссылку можно найти в моем профиле) Эрик и предложил изучать шепелявость. Ну, я изучаю LISP довольно долго, и мне это так нравится, что я решил написать веб-приложение, используя его.
Поскольку я использую Spring в течение некоторого времени, я думаю, что это хорошая идея, чтобы написать развязанные компоненты и склеить их вместе с помощью контейнера IoC и инъекции depencency. Я сделал мощный поиск в google и оказалось, что там нет ли такой идеи, реализованной в LISP. Я что-то упустил? Есть ли хорошая реализация этой концепции в LISP или нет смысла использовать ее по какой-то причине, которая мне пока не ясна?
2 ответов:
"инверсия управления" широко используется в Lisp. Это очень просто, так как функции и замыкания являются объектами первого класса.
Инъекция зависимостей тривиальна. Классы и функции могут быть сконфигурированы с помощью символов и классов первого класса.
Обычно не требуется "фреймворк" для IoC или DI в Common Lisp, так как в него встроено множество функций для настройки и параметризации приложений и библиотек.
"первый класс" означает, что что-то может храниться в переменные, передаваемые в качестве аргументов или возвращаемые в качестве результатов.
В таком языке, как Common Lisp, функции и классы являются объектами первого класса. Кроме того, для развязки через позднюю привязку вы можете использовать символы в качестве их имен. Общая объектная система Lisp знает мета-классы и символы как имена классов. Даже универсальные функции и методы являются объектами и имеют метаклассы.
Если
concurrent-secure-serverявляется классом, аdefault-response- функцией, то можно сделать, например:(make-instance 'web-services :server-class 'concurrent-secure-server :default-response-function 'default-reponse)Выше используется символ как имя класса и функции. Если функция получает новую версию, веб-служба может вызвать новую версию позже.
Альтернативно:
(make-instance 'web-services :server-class (find-class 'concurrent-secure-server) :default-response-function #'default-reponse)В приведенном выше случае мы передаем объект класса и объект функции.
В Common Lisp программные модули могут иметь глобальные переменные, которые можно задать с помощью правильной информации:
(defvar *default-server-class* 'concurrent-secure-server)В качестве альтернативы вы можете установить их в слоты, как показано ниже.
(defclass server-object () ((default-response-function :initarg :default-response-function :initform *server-default-response-function*))) (defvar *my-server* (make-instance 'server-object :default-response-function 'my-default-response-function))Вы даже можете создавать объекты, а затем изменять их их класс в фазе конфигурации. Общая объектная система Lisp позволяет изменять классы и обновлять существующие объекты.
Если вы создаете экземпляр, вы можете быть настолько гибкими, насколько захотите:
- вы можете пройти в класс
- вы можете передать аргументы
Вот так:
(let ((my-class 'foo-class) (my-args `(:response-function ',*some-reponse-function))) (apply #'make-instance my-class my-args))Иногда вы видите библиотеки Lisp, которые вычисляют такие списки аргументов во время выполнения.
Еще одна вещь, где вы можете настроить Lisp приложения во время выполнения - через универсальные функции. Универсальные функции позволяют :before,: after и: around методы - они даже позволяют ваши собственные схемы вызова. Поэтому при использовании собственных классов, наследуемых от других классов и смешанных классов, универсальная функция реконфигурируется. Это похоже на то, что у вас есть встроенные базовые механизмы аспектно-ориентированного программирования.
Для людей, интересующихся этими более продвинутыми объектно-ориентированными концепциями, есть некоторая литература Xerox PARC, где эти вопросы был исследован, когда был создан CLOS. Тогда это называлось "открытая реализация":
Http://www2.parc.com/csl/groups/sda/publications.shtml
В подходе открытой реализации модули позволяют своим клиентам осуществлять индивидуальный контроль над собственной стратегией реализации модуля. Это позволяет клиенту адаптировать стратегию реализации модуля в соответствии со своими потребностями, эффективно делая модуль более многоразовым, а клиентский код более простым. Этот управление предоставляется клиентам через хорошо продуманный вспомогательный интерфейс.
Одна вещь, которая вам не нужна: XML. Common Lisp-это собственный язык конфигурации. Написание расширений для более легкой конфигурации может быть выполнено, например, с помощью макросов. Загрузка этих конфигураций может быть легко выполнена через
LOAD.
На самом деле IoC-это принцип построения большинства веб-фреймворков, а не только Java или Lisp. Учитывая, Ди, как отметил Rammaren, это скрытая закономерность в динамичных языков, таких как Lisp. Вы можете убедиться в этом сами, если сравните приложения Hello World в Spring и Restas (один из хорошо поддерживаемых веб-фреймворков CL). Вы увидите, что существует тот же шаблон, за исключением отсутствия необходимости в причудливых объявлениях типа/класса/интерфейса в Lisp.
Comments