实现JavaScript-API包装器
有人能推荐一种模式,用于编写JavaScript API包装器,其中多个实现之间没有共享代码?其思想是为客户机消费者提供一个包装API,用于运行时确定的许多可能的API之一。API调用可以是对应用程序环境中已有的对象/库的调用,也可以是web服务调用 以下伪代码位是我考虑过的两种方法: 整体解决方案 Pros:可以为库使用者维护一致的API 缺点:将导致一个巨大的单一库,难以维护 模块解决方案 init.js 模块a.js 模块_b.js 优点:更易于维护 缺点:开发人员需要注意API保持一致性。不是特别干燥 在这种情况下,界面上的一些东西会很有用,但据我所知,没有办法在Js中强制执行契约实现JavaScript-API包装器,javascript,design-patterns,Javascript,Design Patterns,有人能推荐一种模式,用于编写JavaScript API包装器,其中多个实现之间没有共享代码?其思想是为客户机消费者提供一个包装API,用于运行时确定的许多可能的API之一。API调用可以是对应用程序环境中已有的对象/库的调用,也可以是web服务调用 以下伪代码位是我考虑过的两种方法: 整体解决方案 Pros:可以为库使用者维护一致的API 缺点:将导致一个巨大的单一库,难以维护 模块解决方案 init.js 模块a.js 模块_b.js 优点:更易于维护 缺点:开发人员需要注意API保持一致性
对于这类问题是否有最佳实践方法?第二种方法更好,因为它是模块化的,您或第三方可以轻松地将其扩展以包含其他服务。“API保持一致”这一点并不是很有效,因为适当的单元测试可以保持事物的一致性 第二种方法也是未来的证明,因为您不知道要为服务C实现say
getName
可能需要做哪些难以想象的事情,在这种情况下,最好有一个单独的模块_C.js和所有复杂的东西,而不是在单一模块中使用意大利面代码
需要真正的接口IMO并不是那么重要,有文档记录的带有单元测试的接口就足够了。我选择模块化解决方案。尽管没有内置的方法来强制执行契约,但您仍然可以选择一种,然后进行TDD并构建一个测试套件来测试模块的接口遵从性
然后,您的测试套件基本上承担了编译在具有显式接口的语言中所扮演的角色:如果接口实现不正确,它会抱怨。真是巧合,有人在做我也在做的事情!最近,我一直在深入研究JS应用程序模式,并且正在探索模块化模式 我从它开始,它有很多指向其他JS开发人员的链接 最好采用模块化:
- 主要是为了避免网站两部分之间的依赖关系
- 虽然一个可以依赖另一个,但它们是“松散耦合”的
- 为了建立一个网站,当你把它拆开的时候,它应该不会坏
- 此外,您需要单独测试部件,而不必使用其他任何东西
- 轻松交换底层库(jQuery、dojo、mootools等),而不影响现有模块(因为您正在构建我们自己的API)
- 在需要更改/升级API的情况下(或在更改基础库时),只需触摸API“backing”,而不触摸API,也不需要重新编码正在使用它的部件
- 如何组织API、库和模块
- 按方式和为什么模块
- by-自动模块事件(呼喊/收听)注册
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 ...
}
}
// 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;
});