Точка использования инъекции зависимостей (и, если уж на то пошло, контейнера IoC) в LISP



Я прочитал эссе ESR под названием " Как стать хакером?"несколько лет назад (ссылку можно найти в моем профиле) Эрик и предложил изучать шепелявость. Ну, я изучаю LISP довольно долго, и мне это так нравится, что я решил написать веб-приложение, используя его.



Поскольку я использую Spring в течение некоторого времени, я думаю, что это хорошая идея, чтобы написать развязанные компоненты и склеить их вместе с помощью контейнера IoC и инъекции depencency. Я сделал мощный поиск в google и оказалось, что там нет ли такой идеи, реализованной в LISP. Я что-то упустил? Есть ли хорошая реализация этой концепции в LISP или нет смысла использовать ее по какой-то причине, которая мне пока не ясна?

575   2  

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

    Ничего не найдено.