在LISP中使用依赖注入(以及IoC容器)的要点

Ada*_*old 4 spring dependency-injection common-lisp inversion-of-control

我读过ESR的文章"如何成为一名黑客?" 几年前(链接可以在我的个人资料中找到),Eric建议学习LISP.好吧,我正在学习LISP很长一段时间,我非常喜欢它,所以我决定使用它来编写一个Web应用程序.

由于我使用Spring一段时间,我认为编写分离的组件并使用IoC容器和依赖注入将它们粘合在一起是个好主意.我在google上进行了一次强力搜索,结果证明在LISP中没有实现这样的想法.我错过了什么吗?在LISP中有没有很好地实现这个概念,或者出于某种原因使用它是没有意义的,这对我来说还不清楚?

Rai*_*wig 19

"反转控制"在Lisp中被广泛使用.它非常简单,因为函数和闭包是一流的对象.

依赖注入是微不足道的.可以通过符号和第一类来配置类和函数.

在Common Lisp中,您通常不需要IoC或DI的"框架",因为内置了许多配置和参数化应用程序和库的功能.

"第一类"意味着某些东西可以存储在变量中,作为参数传递或作为结果返回.

在Common Lisp这样的语言中,函数和类是第一类对象.另外,通过后期绑定进行解耦,您可以使用符号作为其名称.Common Lisp对象系统将元类和符号知道为类的名称.即使是泛型函数和方法也是对象并且具有元类.

如果concurrent-secure-server是一个类并且default-response是一个函数,你可以这样做:

(make-instance 'web-services
               :server-class 'concurrent-secure-server
               :default-response-function 'default-reponse)
Run Code Online (Sandbox Code Playgroud)

上面使用符号作为类和函数的名称.如果该函数获得新版本,则Web服务可能稍后调用新版本.

或者:

(make-instance 'web-services
               :server-class (find-class 'concurrent-secure-server)
               :default-response-function #'default-reponse)
Run Code Online (Sandbox Code Playgroud)

在上面的例子中,我们传递了类对象和函数对象.

在Common Lisp软件中,模块可以有全局变量,您可以使用正确的信息进行设置:

 (defvar *default-server-class* 'concurrent-secure-server)
Run Code Online (Sandbox Code Playgroud)

或者,您可以在下面的插槽中设置它们.

(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))
Run Code Online (Sandbox Code Playgroud)

您甚至可以创建对象,然后在配置阶段更改其类.Common Lisp对象系统允许您更改类并使现有对象更新.

如果您创建实例,则可以根据需要灵活地进行操作:

  • 你可以通过课堂
  • 你可以传递参数

像这样:

(let ((my-class 'foo-class)
      (my-args  `(:response-function ',*some-reponse-function)))
  (apply #'make-instance my-class my-args))
Run Code Online (Sandbox Code Playgroud)

有时您会看到在运行时计算此类参数列表的Lisp库.

您可以在运行时配置Lisp应用程序的另一个方面是通用泛型函数.通用函数允许:before,:after和:around方法 - 它们甚至允许您自己的自定义调用方案.因此,通过使用自己继承自其他类和mixin类的类,可以重新配置泛型函数.这就像你有内置面向方面编程的基本机制.

对于那些对这些更高级的面向对象概念感兴趣的人,Xerox PARC提供了一些文献,在创建CLOS时已经研究过这些问题.它被称为'开放实施'然后:

http://www2.parc.com/csl/groups/sda/publications.shtml

在开放实施方法中,模块允许客户单独控制模块自己的实施策略.这允许客户端定制模块的实现策略以更好地满足他们的需求,有效地使模块更可重用,并且客户端代码更简单.该控件通过精心设计的辅助界面提供给客户端.

你不需要的一件事:XML.Common Lisp是它自己的配置语言.编写扩展以便于配置可以例如通过宏来完成.可以通过以下方式轻松完成这些配置的加载LOAD.