Posts Tagged ‘design’

基于CakePHP的模块化应用系统设计

和robert讨论WEB系统插件化、模块化设计,虽然大家最终意见都倾向于不对原系统作大的改动,只增加一些开关来实现模块可配置化,但Spark这边还是稍微花了点时间写了一个模块化系统的设计demo。
这个demo是基于CakePHP的插件机制来写的,但CakePHP对于插件间的交互和互操作并没有提供什么机制。先来看一个demo的样子:

这个demo系统有两个模块(CakePHP插件)module1和module2,圆圈的地方是菜单,这里的菜单被设计成可扩展的,每个子模块都可以按自己需要往菜单上添加项。来看看添加菜单的代码:

exts.php文件位于module1的plugin目录下。每个插件目录下都可以有这个文件,并且会在全局app_controller的beforeFilter中被vendors下的extloader.php文件读取。
这里的代码首先判断了module1模块是否被启用,然后声明(export)了两个扩展点,接着对全局的菜单global/menu作了一个扩展。
再来看看在app_controller.php里global menu是如何被构造的:

然后在default.thtml layout里面输出menu的代码即可:

上面基本展示了如果构建一个可扩展的菜单系统。在这个demo中还有一个module1的post查看功能被module2提供的bookmark功能扩展的例子,原理是一样的:

最后来看看vendors/extloader.php是如何工作的:

这里主要是遍历CakePHP的每一个plugin,load其目录下的exts.php文件,并且把每个plugin作为一个模块装入 extloader的Modules数组,在首页我们看到了可以对module是否启用进行配置,因为是demo,所以这里使用了Session作为数据 存储,呵呵。
细心的同学可能会发现其实extloader的export方法根本没什么用,之所以写出来是设想每个export出来的extention point是有一定规范的,可以用一定的数据结构描述出来。这里偷懒就没有去写了!
最后一个特性,在命令行下试试下面的操作:
cd app/plugins
mv module2 ../
再刷新页面看看,module2的菜单以及module1 post operations里的bookmark button是不是没了?真正的可插拨哦,呵呵!
demo的代码下载:extphp.zip

软件设计中的幂等性哲学

幂等性有个前提就是它不以时间为转移的,比方说你不可能要求腾讯网新闻首页每次打开都是一样的。当然这里面有个对幂等性级别和层次上的要求,如果你只要求数据格式上的完整性、一致性,你甚至可以认为一个股票行情查询接口也具有幂等性。(股票行情查询接口需要情况下也可以被设计为具有幂等性)
幂等性通常在分布式软件系统设计中被提到。这主要是由于请求方和响应方的协议来完成的,这个对协议的设计要求其实是比较高的。好的协议设计不仅要可可靠地完成应有功能,还要保证契约双方在所有情况下对数据理解上的一致性。这个所有情况就很复杂了,比较典型的是请求失败下的重试情况。这个是事务设计中的需要重点考虑的。银行的ATM通信线路不见得完全可靠,但你必须保证在重新请求主机时客户的帐户不会有重复的扣减。
幂等性在REST的设计思想中也有充分的体现。因为WEB系统本身就是一个分布式系统。REST没有细致的规范,所以很多时间做这件事情的时候是上升到哲学和艺术的层次的。一个好的设计不仅在GET上有一致性,在做POST的应该同样具有一致性。如果你有遇到过客户在浏览器端因为前端页面失败的情况下,重复提交导致系统中创建了重复的记录,你就应该去思考了幂等性的问题了。简单的做法可以仿照事务的做法给“每一份”表单一个标识。
另外,无状态系统的设计避免了分布数据在时间转移后的不一致问题,可以让你的系统更具有更高的幂等性,从而不会因为重启服务器而丢失数据或者导致数据的不一致性。幂等性是以时间转移后的等效性为假设前提的,如果你在设计过程中去贯穿这个哲学,经常假设契约各方是“不可靠”的,反之你的软件系统在质量上就可以上升一个级别。

FireStats icon Powered by FireStats MC Inside