Javascript 函数式编程中的依赖注入
通过一个例子可以更好地说明这个问题。我将使用Javascript(实际上是为了语法的缘故而使用Coffeescript),但仅仅因为Javascript只是另一种,对吗 因此,假设我正在编写一个web应用程序,它(显然)执行ajax请求。我实现了一个函数来处理:Javascript 函数式编程中的依赖注入,javascript,dependency-injection,Javascript,Dependency Injection,通过一个例子可以更好地说明这个问题。我将使用Javascript(实际上是为了语法的缘故而使用Coffeescript),但仅仅因为Javascript只是另一种,对吗 因此,假设我正在编写一个web应用程序,它(显然)执行ajax请求。我实现了一个函数来处理: ajaxRequest = (url, params, callback) -> # implementation goes here 现在,假设我有一个从服务器获取数据的网格。在我的代码中,我必须执行以下操作: use
ajaxRequest = (url, params, callback) ->
# implementation goes here
现在,假设我有一个从服务器获取数据的网格。在我的代码中,我必须执行以下操作:
userGrid.onMustFetch = ->
ajaxRequest '/fetch/users', { surname: 'MacGyver' }, (data) ->
# fill grid with data
class UserGrid {
private AjaxService ajaxService;
@Inject
public UserGrid(AjaxService ajaxService) {
this.ajaxService = ajaxService;
}
public void onMustFetch() {
HashMap<String, String> params = new HashMap<String, String>();
params.put("surname", "MacGyver");
ajaxService.request("/fetch/users", params, new AjaxCallback(data) {
// fill grid with data
});
}
}
这里到底有什么问题?如果我想测试onMustFetch的实现,我将无法这样做,因为在onMustFetch内部,正在调用一个依赖项,并且测试环境无法控制该依赖项
为了解决这个问题,我将依赖性注入到我想要测试的函数中。这意味着将onCustomFetch更改为:
现在,测试代码可以将ajaxRequest的模拟传递给onCustomFetch并成功地测试该行为
文德巴,对吗?错了!现在我有第二个问题,必须将正确的ajaxRequest实例绑定到正确的OnCustomFetch实例
在Java这样的语言中,我可以使用依赖注入框架来完成这项工作,我的代码如下所示:
userGrid.onMustFetch = ->
ajaxRequest '/fetch/users', { surname: 'MacGyver' }, (data) ->
# fill grid with data
class UserGrid {
private AjaxService ajaxService;
@Inject
public UserGrid(AjaxService ajaxService) {
this.ajaxService = ajaxService;
}
public void onMustFetch() {
HashMap<String, String> params = new HashMap<String, String>();
params.put("surname", "MacGyver");
ajaxService.request("/fetch/users", params, new AjaxCallback(data) {
// fill grid with data
});
}
}
class用户网格{
私人AjaxService AjaxService;
@注入
公共用户网格(AjaxService AjaxService){
this.ajaxService=ajaxService;
}
onMustFetch()上的公共void{
HashMap params=新的HashMap();
params.put(“姓氏”、“麦基弗”);
请求(“/fetch/users”,参数,新的AjaxCallback(数据){
//用数据填充网格
});
}
}
令人毛骨悚然,我知道。。。但实际上DI框架完成了所有的布线,所以至少这部分问题更容易解决
现在回到我们的web应用和Javascript。即使我成功地设法始终使用正确的ajaxRequest引用调用onCustomFetch(毕竟在本例中这并不难做到),也必须有一种更简单的方法。当我的代码增长时,依赖关系就会增加。我可以想象传递ajaxRequest的引用,但是当我有一个securityService、browserService、eventBusService等时会怎么样
现在这里真正的问题是:类似lisp的语言如何解决管理依赖关系的问题?
(在我看来,依赖关系必须在整个应用程序中不断传递,但我确信一定有更好的方法…在Javascript中,我不知道为什么不能使用类似于任何OO语言的技术。一个非常基本的JS实现(对不起,我不知道Coffescript) 创建:
var userGrid = diController.create(UserGrid);
因此,
diController
执行与java依赖项注入器相同的操作。在java中,它可以使用反射来确定需要什么类型的对象。Javascript中没有太多的反映需要做,因此创建一个约定来告诉系统需要什么。在本例中,我使用了一个名为“dependencies”的数组,但您可以使用任何您喜欢的构造。这通常是使用闭包/套用来完成的。您将依赖项作为参数传入。在JS中,您可以执行以下操作:
buildUserGrid = function(dependency){
return {
onMustFetch = function(){
depenency.doSomething();
},
doSomethingElse = function(){
dependency.doSomethingElse();
}
}
}
var userGrid = buildUserGrid(ajaxRequest);
userGrid.onMustFetch();
类似Lisp的语言彼此不同。它们有不同的对象系统,等等。这个问题实际上是关于Javascript的:如何在Javascript中实现Java设计模式(依赖项注入)。我正在删除非主题标记[clojure][lisp]和[scheme]。这与javascript无关。Javascript恰好是我所熟悉的表达问题的方式。我对lisp语言处理这个问题的方式很感兴趣,所以如果你能把标签放回去,我将不胜感激。请随意用一种对Lisp、Clojure或Scheme有意义的方式来重新表述这个问题。是的,我可以使用一种在OO中使用的技术。但我的问题和兴趣是函数式语言,特别是lisp语言,如何管理依赖关系。我知道在我的问题中这可能不够清楚,但是读一下我对这个问题的评论,你就会明白为什么。不过,谢谢……如果是那样的话,我认为最初的评论是非常相关的。或者,您是在问如何在没有全局或工厂概念的情况下管理依赖关系吗?你为什么要这么做?可用于创建此类结构的工具非常特定于语言。如果没有任何类型的全局构造,那么您已经回答了自己的问题,您将传递东西。事实上,到目前为止,我得到的选项是依赖注入、共享全局、工厂或传递东西。我试图找出在类似Lisp的语言中通常做什么。所以,也许你是对的,也许在我提出的背景下,我的问题没有其他答案。