任何人都可以建议一种可用于编写JavaScript API 包装器的模式,其中多个实现之间没有共享代码?我们的想法是为客户端消费者提供一个包装API,用于运行时确定的许多可能API之一。 API调用可以是已经在应用程序环境中的对象/库,也可以是Web服务调用。
以下伪代码是我考虑过的两种方法:
var apiWrapper = {
init: function() {
// *runtime* context of which API to call
this.context = App.getContext();
},
getName: function() {
switch(context) {
case a:
return a.getDeviceName() // real api call
case b:
return b.deviceName // real api call
etc...
}
// More methods ...
}
}
优点:可以为库使用者维护一致的API。
缺点:会导致庞大的整体库,难以维护。
// set apiWrapper to the correct implementation determined at runtime
require([App.getContext()], function(api) {
var apiWrapper = api;
});
// Implementation for API A
define(function() {
var module = {
getName: function() {
return deviceA.getDeviceName();
}
};
return module;
});
// Implementation for API B
define(function() {
var module = {
getName: function() {
// could also potentially be a web service call
return deviceB.getName;
}
};
return module;
});
优点:更易于维护。
缺点:开发人员需要注意API保持一致。不是特别干。
这种情况下, Interface 的某些内容会很有用,但据我所知,没有办法在Js中强制执行合同。
这种问题是否有最佳实践方法?
答案 0 :(得分:4)
我从this artice开始,它有很多链接引用其他JS开发人员。
最好采用模块化方式:
这里是我经历过的链接(主要是视频),它们传达了模块化方法的全部内容以及为什么要使用它:
答案 1 :(得分:3)
第二种方法更好,因为它是模块化的,您或第三方可以轻松扩展它以包含其他服务。 “API保持一致”的观点并不是那么有效,因为正确的单元测试可以使事情保持一致。
第二种方法也是未来的证据,因为你不知道为服务C实现说getName
可能需要做些什么难以想象的事情,在这种情况下,最好有一个单独的module_c.js整体单一模块中的并发症而不是意大利面条代码。
对于真实接口IMO的需求并不那么重要,单元测试的文档化界面就足够了。
答案 2 :(得分:2)
我去了模块化解决方案。虽然没有内置的方法来强制执行合同,但你仍然可以决定一个,然后去TDD并构建一个测试模块的测试套件。接口合规性。
然后,您的测试套件基本上会采用具有显式接口的语言编译的角色:如果接口未正确实现,则会抱怨。