谈谈架构模式的优先级别

理解软件体系架构和不同架构间的权衡对理解任何一个软件项目来说都十分重要。无论是内容管理系统如Drupal,编程语言如PHP,或者是一个独立的网站,熟悉系统框架对项目初期体系的建立和后期团队内部沟通都起着决定性作用。

 

为了能够恰当地表达并便于思考架构设计,首先需要理解与该系统相关的权衡。架构设计精于一方面的同时必定在另一方面有所欠缺。因此在搭建系统前就需要明确优先级别是怎么样的,针对Drupal这样一个分布合作式开发环境至少要在很大程度上界定好优先权。

 

接下来就具体分析一下这些考量因素和必须的权衡关系。

架构模式

软件体系架构是构建大型逻辑体系的环节之一。实现方法有许多种,包括无数常见模式和途径。架构模式是一种最普遍的设计模式,典型的有MVC(模型-视图-控制器)设计模式、PAC(表示-抽象-控制)结构模式,还有比较少见的如Pipes and Filters(流水线)模式(Unix命令行基础)、裸体对象模式。

 

架构模式没有好坏之分。就系统本身和优先等级来说,每一种模式都是恰当的。不深刻理解这些优先级就无法正确说出对应的合适的架构模式是怎样的。

 

典型案例并非出自软件领域,而是来自汽车行业(关于的计算机讨论似乎都可以类推到汽车行业)。1960年雪佛兰科维尔推出了一种旋启式轴悬架系统汽车,这种悬架系统更常见于跑车,它对汽车把手进行改造,使跑车在飞驰过程中轮胎触地面积比普通轿车小,而普通轿车驾驶员一般对此不太熟悉。对跑车来说这种系统当然是非常受欢迎的,但是如果在市内道路上尤其当驾驶员不那么习惯使用时行驶就非常危险了。并不是这个系统不够好,只是因为它不适于普通轿车。这也是造成Ralph Nader事件的起因之一。

 

某些情况下,没有架构是最合适的架构,这就是所谓的整体架构,即忽略架构思想仅通过代码实现。这也是广义上的一种架构模式,尤其适用于小型或者短期项目。

架构轴心因素

考量一个架构模式是否合适,需要考虑以下因素:

 

可修改性 - 今后修改程序是否简单?

可延展性 - 添加或删除其他附加功能是否方便?

可测试性 - 代码结构是否利于分段测试?

可验证性 - 能否通过数据证明在任何情况下代码皆可行?

性能 - 程序运行是否快速?完成某项任务需要多久?

可扩展性 - 流量很大的时候程序表现如何?(虽然改进性能通常能改进可扩展性,可扩展性并不等同于性能。)

可用性 - 终端用户使用最终程序是否方便?

易理解性 - 二次开发者理解和改进程序的难度大吗?这对API开发尤其重要。

可维护性 - 软件的更新和问题修复是否方便?

工作量 - 程序编写要多久?

 

这些不同的因素经常是彼此冲突的。例如可延展性和可修改性往往一致,但会使得不易验证和不易测试。良好的性能通常(并不总是)有助于可扩展性,但过度抽象的可扩展性有时会导致性能下降。可维护性和工作量经常是一个非彼即此的问题,因为要书写一个清晰可扩展同时又易维护的软件非常有难度。Perl语言被认为是只读语言,因为从语法上来说它的开发工作量很小性能很好,相比之下可维护性或者可理解性并不理想。

Drupal 的架构

在架构模式的上述因素中,Drupal不很明显的表现出一种厚此薄彼。这不是坏事,对于我们理解和获得共识十分重要——Drupal架构模式的优先级是怎样的,为什么是这样的。

 

例一、Drupal经常强调可延展性。我认为由于Drupal采用了Hooks机制,可延展性一直都是架构优先级中最重要的一个。但是注重可延展性的同时必然导致可测试性和可验证性下降,那么要实行有益的Drupal7自动测试,从其架构上来说很难执行甚至无法执行单元测试。

 

单元测试要求能够完全把一段代码独立出来,这样才能在真空环境下分析。Hooks设计使分割代码变为了不可能,任何一段代码都有可能影响整个程序,而用户会安装何种插件使用什么代码是完全不能控制的。

 

这算是不错的权衡吗?假如开发一个特定领域的模块,确实是的。但是如果要调试程序的话,这个权衡真是糟糕透了。

 

例二、Drupal的Hook 机制以及Giant Undocumented Arrays of Doom(tm) 规范利于模块化和延展,在任何地方可以添加任何一个Hook。假如不熟悉这个特殊的设计模式,就别做梦了。即使熟悉,仍然很难理解又不好维护。要是你习惯的是传统的学院派编程方式,大概要像大多数技术人员一样大骂Drupal了。

 

这样的权衡有利于特定领域的非专业开发者。假如目标开发者已经具备多年PHP系统或CS开发经验,Drupal,还是算了吧。

 

例三、许多开发者都一致认同Drupal 7的可扩展性。这是不错的主意,而在某些情况下会降低性能。例如Field API storage现在是可扩充的,准入非SGL后端。但是它所必须的额外的抽象概念令编程和combined storage都雪上加霜。同样地,获取有效SQL存储设备驱动使得必须放弃Drupal 6中CCK的动态表模式,这就意味着JOINs增强的同时性能减弱。

 

如果你是Examiner.com或Sony BMG 或 Acquia 的Drupal花园,这一点并不坏。对非营利性组织、教堂或租用共享空间的个人站点,绝对不是好的方案。

 

从某些角度来看,Drupal7创造了很大的进步。转换一个角度,它也是一个很大的退步。这就要看需求和优先级别是什么样的了。这并不是说Drupal7不好,也不是开发者做错了。

展望

其实确实如此。我们自己知道优先级别是什么吗?如果必须在可扩展性和可验证性之间做一个选择,我们会选择什么?

 

下面哪一个市场的快速发展更重要:占据了95%市场份额,租用廉价共享空间,没有PHP支持人员的网站?还是拥有独立的服务器集群,可以从容安装Mongo和Varnish,雇佣四个全职开发而首先支付Drupal开发工资的另外5%市场?

如果有办法使这些用户都能快速使用Drupal,并以牺牲可修改性和可延展性为代价,我们应该去做吗?

如果可以令Drupal对新手开发者更易读而不顾性能,我们该做吗?

如果能做到新站用Drupal搭建非常方便而进行二次开发就难度大大提高,我们是否会去实现?

 

这些都是我们需要收集起来反思的。同时正视问题思考如何才能兼而有之。