
序2
大约在两年前(2010年1月),我收到了Kirk Knoernschild的电子邮件,他邀请我为他即将完成的书提供反馈。回头看看随后发生的激烈讨论——大约有50封或更多的邮件——我不得不怀疑他对我会产生一些怨恨。我确信我们之间的交流导致他最初的进度出现了严重的延迟。所以,当Kirk邀请我为本书作序的时候,我感到又惊又喜;他为这本书付出了巨大的努力却让一个对手来给他写序,这说明他拥有足够强大的内心。
现在,我同意Kirk在本书中所说的大部分内容。我们都为模块化的魔力着迷,并且在大多数基础理念上都很有共识。但是,就像通常我们所见到的那样,最热烈的争论往往发生在那些在原则上互相认可但在细节上存在分歧的人群之间。直到在德国达姆施塔特举行的OSGi社区大会(OSGi Community Event)上(也就是这篇序言截止日期的两天前),我才突然理解了Kirk受到的阻力。
在这次大会上,Graham Charters(IBM)提出了“模块成熟度模型”(Modularity Maturity Model),这个模型来源于IBM的SOA成熟度模型(SOA Maturity Model),而后者又显然来源于最初的SEI能力成熟度模型(Capability Maturity Model,CMM)。这是一场很有见地的演讲,它使我认识到在系统设计方面,因为我在模块化的环境中生活了超过13年,我的观点并没有深受其影响。
CMM的一个重要教训就是不可能直接越过某一步。如果你的公司在CMM的第1级(混乱的),那么制订计划大跨步直接迈到第4级(一般称其为“已管理级”)不会是什么好主意。有的公司这样尝试了,但都惨烈失败了。每个中间步骤的转换都是必要的,它会帮助组织了解不同级别的复杂性。每个级别都有一系列自己的问题,这些问题需要在下一级别来解决。
在Graham演讲之后,我清楚地认识到我基本上都是从第5级往下看,而Kirk则是帮助人们从第1级往上看。我们之间争论的具体问题是设计模块化软件时所面临的挑战。当你到达第2级或第3级时,这些挑战是显而易见的,但当你处于第1级时,它们就不那么明显了。我们的大脑有这样一种定式,即只有我们处理过对应的问题,才能理解其解决方案。我试图让Kirk讨论的那些解决方案是他的读者还没有经历和理解的,这些问题位于前面的等级中。
在我的模块成熟度模型中(Graham的会稍有不同)有如下等级:
1)未管理的/混乱的
2)管理依赖
3)适当隔离
4)修改代码库(code base)以最小化耦合
5)面向服务的架构
在第1级中,应用是基于类路径(class path)的,也就是线性的JAR列表。应用包含一系列的JAR或具有类文件的目录,这些形成了类路径。在这个级别,根本不存在什么模块化。这个级别的问题是缺少类或版本混乱。
在第2级中,你已经识别了模块并声明了对其他模块的依赖。模块会有一个名字并且可以进行版本标识。它们依旧是线性查找的,第1级的很多问题依然存在,但是系统的可维护性以及结果的可重复性会更好一些。这个层级的主要问题在于,因为过度的传递性依赖,会过多地“从互联网上下载”。这是Maven目前所处的级别。
在第3级中,模块间会通过导入、导出和私有包真正实现模块间的隔离。依赖现在可以在包级别进行描述,这可以减少“从互联网上下载”。这种隔离为模块提供了内部的命名空间,而这个命名空间是真正在模块内部的,允许存在多个命名空间,这样在一个应用中就可以支持同一个包的不同版本。这个级别的问题通常是由流行Java模式引起的,因为它们基于动态类加载机制,很少能与模块边界和多命名空间兼容。
在第4级中,你的代码库的修改只是为了最大化内聚或最小化耦合。人们越来越认识到某一行代码可能会导致过多数量的依赖。组合或分隔系统的功能可能会对系统的部署产生重要的影响。在这个级别,已有的Java模式使用起来会很痛苦,因为它们通常会依赖中心化的配置,而这个方案更像是平等的点对点(peer-to-peer)模型。在OSGi中,μService变得很有吸引力,因为它们解决了很多问题。
在第5级,也就是最后一个级别中,模块化不再像它们所提供的μService那样重要。这时设计和依赖方案完全是通过μService实现的;模块只是使用和提供μService的容器。
在过去的13年中,我一直生活在第5级中,因为它是在OSGi中实现的。这有时会让我很难设身处地体会那些只使用类路径和简单JAR文件的人们。看到Graham Charter的演讲后,我认识到Kirk的目的是帮助人们理解模块化设计原则的重要性并使他们从第1级到达第2级,最终为他们打下坚实的基础以便使用OSGi实现更好的模块化。我认识到我经常试图把这本书直接提升到第5级,因为前面所提的一些教训对设计模块化软件也是很重要的。那样一本书依然是很必要的,希望有一天我能自己来写作。
现在Kirk的书很重要,因为它提供了开始模块化思考的模式并且能够让你借助最流行的平台、框架和语言构建模块化的软件。是的,我相信本书中的很多问题会有更好的解决方案,但是我也认为有时候追求更好会适得其反。
假设你使用Spring、Guice或者其他流行的依赖注入框架来构建Java应用,但依然面临脆弱和僵硬的软件,维护这些软件会很困难并且代价高昂,那么这本书对你来说真的有用。代码的完全耦合会造成很难添加新的功能或者修改已有的代码库。这本书将教会你很多模块化的基础课程并向你展示模块化的魔力。
也就是说,我还希望你特别关注贯穿本书使用OSGi的例子。它首先出现在第3章结尾处,它向你展示了OSGi如何借助μService来帮助你实现适当的隔离并尽可能最小化耦合的。随着本书所提供的价值不断增加,我相信按照它的建议将会帮助你构建架构上更加完整的软件并引导你正确地将应用迁移到OSGi上。OSGi是迄今为止最成熟的模块化方案。
一直以来,Kirk不仅仅是值得尊敬的对手;他敦促我把自己的想法写出来,通过这种方式让我学到了很多,比近几年任何人教我的都要多。在过去的两年中,在和他讨论这本书的过程中,我享受到了很大的乐趣,我真的希望你在读这本书的时候也会有同样的感觉。
——Peter Kriens
OSGi联盟技术总监