全文于2008年4月发布在InfoQ中文站上:http://www.infoq.com/cn/news/2008/04/soa-cohesion摘要早在2005年,当时Steve Vinoski还就职于IONA公司,他就发表过一篇关于内聚(Cohesion)和耦合(Coupling)的文章。在文中,他提到了这些年来已识别的3种“恰当的”内聚类型: 功能内聚(Functional Cohesion):一个模块只做一件事。它们表现出了低耦合与高度重用。 顺序内聚(Sequential Cohesion):一个模块包含多个需按一定次序执行的任务。 通讯内聚(Communication Cohesion):一个模块包含多个基于相同输入的操作,但这些操作在执行次序方面没有任何要求。 然后,他又提到了四种“糟糕的”内聚: 过程内聚(Procedural Cohesion):与顺序内聚相似,只不过各个任务所处理的数据各有不同。正如Steve所说:“这种内聚常常是‘为降低耦合度,人为把活动分组’的结果”。 时间内聚(Temporal Cohesion):一个模块里的任务仅在时间上相关。“如果有任务要换在别的时间执行,那么这种模块会带来维护上的难题。” 逻辑内聚(Logical Cohesion):一个模块里的活动由于“看似具有共同的实现”而被聚集起来。 偶然内聚(Coincidental Cohesion):一个模块里的任务的唯一共同之处,就是它们均在此模块之中。 正如Steve所说: 正如同耦合(coupling)一样,内聚(cohesion)对于分布式对象与服务来说仍然重要。例如,如果你仅仅因为一组方法具有相似的实现就把它们放在一个对象里,那么你将犯“创建逻辑内聚对象(logically cohesive object)”的错误。 该文最后总结: 考虑到向“新的”计算方式的转变常常伴随着对旧的方式的直接批评,所以如今对SOA的关注引起对分布式对象的激烈反对并不出乎意料。不幸的是,其实许多适合分布式对象系统的质量标准也同样适用于分布式服务与SOA。因此,有些人为了顺应潮流而被迫忽略它们是十分遗憾的。不过,也许不要紧,因为我们可以直接追溯到对象之前的时期,搞清楚像耦合和内聚这样的度量标准,并重新运用它们。 这在近年来也许已经不怎么被注意了,直到Jim Webber最近写了一篇关于“贫血的服务模型(Anemic Service Model)”的文章。Jim简述了过去对良好的软件工程实践的讨论,他说的一些话跟 Steve 先前的非常相似: 有些软件是高内聚、紧耦合的。这意味着,尽管它经过合理的设计,但由于存在紧密的相互依赖关系,所以不容易被修改。那是很糟糕的;而且很不幸地是,这在企业应用中很常见。还记得若干年前的确给你留下深刻印象,但如今维护起来却令你痛苦不堪的软件吗?原因就在于它是紧耦合的。 松耦合、低内聚的软件是另一种糟糕的软件。这意味着模块之间少有明显的相互依赖;但是,没有一个模块是在系统中某方面处于权威地位的。这进而造成需用“散弹法(scattergun approach)”来解决持续的系统演化,因为即使很小的改动也会波及多个组件或系统。也就是我们今天所认识到的SOA。 接着,该文继续讨论目前的SOA思想完全与这一状况相悖: <略>现在这篇文章吸引了不少值得注意的评论。然而,由这篇文章引发的实质性争论已蔓延到了别处, 尤其是Jean-Jacques Dubray的回应 : <略>Jean-Jacques提出,尽管内聚是一个被充分理解的软件工程原则,不过它跟“当代”SOA并不相关: 有些人老拿他们5年前形成的观念来看“SOA”,而那只是被他们自己错误理解的SOA,这种情形让我觉得越来越不愉快。Jim所展现的是一幅陈旧的、并不能代表2008年的SOA的情景。 之后,Jean-Jacques 又继续讨论了Steve最初那篇文章: <略> 但是争论仍在继续。内聚跟SOA是不是本质对立的?例如,我们是否需要重写软件工程书籍以涵盖跟SOA有关的内聚?当然,内聚本身并无坏处;不过,也许内聚跟耦合一样是分不同程度的,而且不能搞一刀切?