我正在尝试学习开发一个 Web 应用程序(最好是 NodeJS/MongoDB,尽管我之前使用过 PHP 和 Python),它具有高度可扩展性和可定制性,可通过插件启用禁用的功能。
一种可能的选择是使用带有挂钩的 Wordpress 插件和小部件来挂钩,但是它缺乏视图和逻辑代码的适当分离。这仍然是一种可供学习的选择。还有其他选择吗?
你有任何我可以学习的代码片段或示例应用程序吗?语言或框架不是那么重要,我大概可以大致弄清楚背后的概念
我正在尝试学习开发一个 Web 应用程序(最好是 NodeJS/MongoDB,尽管我之前使用过 PHP 和 Python),它具有高度可扩展性和可定制性,可通过插件启用禁用的功能。
一种可能的选择是使用带有挂钩的 Wordpress 插件和小部件来挂钩,但是它缺乏视图和逻辑代码的适当分离。这仍然是一种可供学习的选择。还有其他选择吗?
你有任何我可以学习的代码片段或示例应用程序吗?语言或框架不是那么重要,我大概可以大致弄清楚背后的概念
一个好的插件架构很难从头开始实现,但它提供了自己的回报。它通过本地化复杂性使软件灵活且易于维护。它需要的首要技能是编写松散耦合代码的能力。这需要非常牢固地掌握多态性、得墨忒耳定律和相关的好莱坞原理。
我建议您首先熟悉这些,然后再熟悉以下设计模式,这将显着降低难度:
一旦你掌握了这些,研究一些现有的插件框架实现和架构,看看它们是如何被使用的。Apache 有几个在Struts、Geronimo 自定义服务器程序集和Tomcat JNDI 资源;还有Eclipse 插件框架。
我们还没有这样的插件架构,但我将解释我们如何保持我们的客户端代码松散耦合,也许它会给你一些想法。
我们正在使用 asp.net。我们提供一个 main.aspx 页面,该页面首先包含一个中介 javascript 文件。它定义了一个全局对象——称之为中介者——这是我们定义的唯一全局对象。
中介者公开了一个简单的接口,其中包含发布和订阅消息:
mediator.subscribe(messageName, callback);
mediator.publish(messageName);
在 mediator.js 文件之后,主页包含许多其他 javaScript 文件,每个文件都包含一个立即函数,该函数将其功能注册到调解器。可以在此处找到有关此模式的更多信息,或在此处查看我以前的问题。
您可以采用类似的方法 - 定义一个全局对象(例如 pluginFramework),它为插件提供一个接口来注册其功能。当您构建 html 页面以交付给客户端时,首先包含 pluginFramework 文件,然后动态包含所需的 JavaScript 插件文件,这可能取决于用户或设备(例如,如果设备启用了触摸,则需要不同的插件?)。这些插件文件将通过即时函数将其功能添加到 pluginFramework。
以下是如何允许插件向 UI 中的菜单添加功能的示例:
插件框架.js:
var pluginFramework = (function() {
var menuItems = [];
function addMenuItemPrivate(itemName, callback) {
// e.g. add itemName and callback to menuItems
}
return {
addMenuItem: addMenuItemPrivate;
}
})());
照片插件.js:
(function() {
function addPhoto() {
//...
}
pluginFramework.addMenuItem('add photo', addPhoto)
})());
希望这在某种程度上有所帮助!
您的评论表明您正在构建的是多租户架构。
这是一项复杂的要求——而且通常很难改造;这在很大程度上取决于您从哪里开始。
首先,您首先需要有一个体面的 Web 应用程序;如果您使用的是 MVC 框架,那么您就有了一个起点。
其次,您需要决定在哪里支持扩展;例如,客户可以为其 UI 拥有一个完全独立的皮肤吗?如果是这样,您需要一个皮肤框架。客户是否可以更改所有内容,或者只是在关键点插入不同的组件(例如自定义支付提供商或自定义身份验证方案)。支持一组有限的扩展点比设计一个允许扩展任何东西的框架要容易得多。
接下来,您的数据策略;MSDN 上有一篇关于多租户的好文章;它面向关系数据库,但提供了可以应用于 Mongo 的想法。
最后,你必须想出一个支持你需要的扩展点的组件架构。在处理 Web 应用程序时,您需要能够修改模型、视图、控制器和持久性;最好的解决方案是使用你的 MVC 框架想要工作的方式,并将“对于租户 x,做 y;对于租户 z,做 w”逻辑放在控制器层。玩这个,让它适用于你需要的一些情况,然后找出问题所在并修复它。