Java应用架构设计:模块化模式与OSG
本书中文简体字版由Pearson Education(培生教育出版集团)授权机械工业出版社在中华人民共和国境内(不包括中国台湾地区和中国香港、澳门特别行政区)独家出版发行。未经出版者书面许可,不得以任何方式抄袭、复制或节录本书中的任何部分。 本书封底贴有Pearson Education(培生教育出版集团)激光防伪标签,无标签者不得销售。 本书由全球资深专家撰写,世界级软件开发大师Robert C. Martin与Peter Kriens作序推荐。书中揭示了模块化的重要性,如何实现模块化,以及如何使用OSGi实现模块化架构。 本书分为三部分。第一部分(第1~7章)描述了需要模块化的理由。在这里,你将会看到模块化在设计软件中所扮演的重要角色,与此同时还会学习到为什么需要设计模块化的软件。第二部分(第8~12章)介绍了18个模式,这些模式会帮助你设计更为模块化的软件。第三部分(第13~17章)引入了OSGi,然后阐述了如何使用本书中的模式来设计软件系统并充分发挥模块化平台的优势,并使用代码样例论证了我们的观点。
基本信息
- 外文名
Java Application Architecture: Modularity Patterns with Examples Using OSGi
- 出版社
机械工业出版社
- 作者
克内恩席尔德(Kirk Knoernschild)
- 开本
16
- 译者
张卫滨
基本介绍
内容简介
全球资深Java技术专家的力作,系统、全面地讲解如何将模块化设计思想引入开发中,涵盖18个有助于实现模块化软件架构的模式
作者简介
作者简介 Kirk Knoernschild 资深软件开发专家,系统架构师,软件开发项目经理,敏捷教练,软件开发咨询师。精通Java、OSGi、敏捷方法、系统架构等,拥有丰富的软件开发经验,担任过软件开发团队中的多个职位。同时他还是一位积极的开源社区贡献者,发表了大量经典文章,广受读者好评。曾受邀参与国际大型软件开发会议并发表演讲。著有《Java Design: Objects, UML, and Process》,合著有《No Fluff Just Stuff 2006 Anthology》。他曾培训和指导过成千上万的软件开发人员,讨论的主题涵盖Java/J2EE、建模、软件架构与设计、基于组件的开发、面向服务架构以及软件过程等。 译者简介 张卫滨?资深软件开发专家,精通Java语言,对Java开源框架有较深入的研究。目前主要从事企业级软件的开发,拥有丰富的软件开发经验。熟悉Spring、Hibernate以及Eclipse等开源产品,对Web前端技术有一定的研究,熟悉相关技术以及dojo、jQuery、ExtJS等框架。技术社区的积极实践者,曾参与技术新闻和文章的翻译工作,已出版译著有《Spring实战(第3版)》。
专业推荐
媒体推荐
“基础永远不会过时。在本书中,Kirk介绍了如何立足基础,以低成本有效地构建高质量的软件密集型系统。你会发现这本书写得很好、很及时并且全是务实的理念。” ——Grady Booch,IBM院士 “与GoF的《设计模式》一样,Kirk的这本书应该成为每一位企业级开发人员和架构师的必备品,对Paremus的每一位工程师来说,这本书是必备读物。” ——Richard Nicholson,OSGi联盟主席、Paremus CEO “通过写这本书,Kirk为软件社区做出了重要的贡献:他分享了自己关于模块化的大量真知灼见,这些内容新手能理解、在计算机课堂上能讲授并且有经验的程序员也可参考。我希望本书能够有广泛的读者。” ——Glyn Normington,Eclipse Virgo项目的领导者 “我们的行业需要开始思考模块化这个词——因而需要这本书!” ——Chris Chedgey,Structure 101创始人兼CEO “在本书中,Kirk为我们提供了在现实世界中进行模块化软件开发所需要的设计模式。尽管模块化确实有助于管理复杂性和创建更容易维护的软件,但是天下没有免费的午餐。如果你想获得模块化所提供的收益,那么购买本书吧。” ——Patrick Paulin,Modular Mind咨询师和培训师 “Krik巧妙地记录了使用OSGi和Eclipse运行时技术的最佳实践。为了更好地理解如何创建优秀的软件,每一位高级Java开发人员都需要阅读本书。” ——Mike Milinkovich,Eclipse基金会执行总监
名人推荐
“基础永远不会过时。在本书中,Kirk介绍了如何立足基础,以低成本有效地构建高质量的软件密集型系统。你会发现这本书写得很好、很及时并且全是务实的理念。” ———Grady Booch,IBM院士 “与GoF的《设计模式》一样,Kirk的这本书应该成为每一位企业级开发人员和架构师的必备品,对Paremus的每一位工程师来说,这本书是必备读物。” ——Richard Nicholson,OSGi联盟主席、Paremus CEO “通过写这本书,Kirk为软件社区做出了重要的贡献:他分享了自己关于模块化的大量真知灼见,这些内容新手能理解、在计算机课堂上能讲授并且有经验的程序员也可参考。我希望本书能够有广泛的读者。” ——Glyn Normington,Eclipse Virgo项目的领导者 “我们的行业需要开始思考模块化这个词——因而需要这本书!” ———Cllris Chedgey,Structure 101创始人兼CEO “在本书中,Kirk为我们提供了在现实世界中进行模块化软件开发所需要的设计模式。尽管模块化确实有助于管理复杂性和创建更容易维护的软件,但是天下没有免费的午餐。如果你想获得模块化所提供的收益,那么购买本书吧。” ——Patrick Paulin.Modular Mind咨询师和培训师 “Krik巧妙地记录了使用OSGi和Eclipse运行时技术的最佳实践。为了更好地理解如何创建优秀的软件,每一位高级Java开发人员都需要阅读本书。” ——Mike Milinkovich,Eclipse基金会执行总监
图书目录
本书赞誉 译者序 序1 序2 前言 第一部分模块化的理由 第1章模块定义/2 1.1定义模块/2 1.1.1可部署/3 1.1.2可管理/3 1.1.3可测试/3 1.1.4原生可重用/3 1.1.5可组合/4 1.1.6无状态/4 1.2软件模块的简洁定义/4 1.3结论/4 第2章模块化的两个方面/5 2.1运行时模型/5 2.2开发模型/5 2.2.1编程模型/6 2.2.2设计范式/6 2.3模块化现状/8 2.4结论/10 第3章架构与模块化/11 3.1定义架构/11 3.2关于软件架构的一个故事/12 3.2.1象牙塔/12 3.2.2乌龟和塔/13 3.3架构的目标/15 3.3.1悖论/15 3.3.2消除架构/16 3.4模块化:被忽视的部分/17 3.5回答我们的问题/23 3.6结论/23 3.7参考文献/24 第4章征服复杂性/25 4.1企业级复杂性/25 4.2技术债/26 4.3设计腐化/27 4.3.1干扰可维护性/27 4.3.2阻止可扩展性/28 4.3.3抑制可重用性/28 4.3.4限制可测试性/28 4.3.5妨碍集成/28 4.3.6阻碍理解/29 4.4循环依赖/29 4.4.1循环类型/29 4.4.2悄然引入的循环/32 4.4.3管理循环/33 4.4.4循环总是不好的吗/33 4.5结合点、模块和SOLID/34 4.6管理复杂性/35 4.7模块化的益处/37 4.8结论/37 4.9参考文献/38 第5章实现重用/39 5.1可用/重用悖论/39 5.2关于重用的免责声明/40 5.2.1粒度/40 5.2.2重量级/41 5.3重用还是可用/42 5.4模块化权衡/42 5.5模块化设计/43 5.6结论/44 5.7参考文献/45 第6章模块化与SOA/46 6.1重新审视“自上而下”/46 6.2粒度——架构师的强大对手/48 6.2.1现实世界的一个例子/48 6.2.2提升一个等级/49 6.2.3另一个维度/50 6.2.4全景图/51 6.2.5服务样例/52 6.3另一个视图/54 6.4结论/55 第7章参考实现/56 7.1为什么不用OSGi/56 7.2这个练习的背景:构建系统/57 7.3初始版本/57 7.4第一次重构/59 7.5第二次重构/61 7.6第三次重构/63 7.7第四次重构/66 7.7.1关于OSGi的好处/67 7.7.2小结并准备下一次重构/68 7.8第五次重构/68 7.9第六次重构/69 7.10第七次重构/72 7.11事后剖析/72 7.11.1关于模块测试/74 7.11.2关于管理模块依赖/74 7.11.3关于模块重用/76 7.11.4关于构建/77 7.11.5关于面向对象/77 7.12结论/78 7.13参考文献/78 第二部分模式 第8章基本模式/81 8.1管理关系/81 8.1.1表述/81 8.1.2描述/81 8.1.3多种实现/82 8.1.4影响/85 8.1.5样例/86 8.1.6小结/88 8.2模块重用/89 8.2.1表述/89 8.2.2描述/89 8.2.3多种实现/91 8.2.4效果/92 8.2.5样例/93 8.2.6小结/99 8.3模块内聚/99 8.3.1表述/99 8.3.2描述/100 8.3.3多种实现/100 8.3.4效果/101 8.3.5样例/101 8.3.6小结/104 第9章依赖模式/105 9.1非循环关系/105 9.1.1表述/105 9.1.2描述/105 9.1.3多种实现/106 9.1.4效果/107 9.1.5样例/107 9.1.6小结/113 9.2等级化模块/113 9.2.1表述/113 9.2.2描述/113 9.2.3多种实现/115 9.2.4效果/115 9.2.5样例/116 9.2.6小结/117 9.3物理分层/118 9.3.1表述/118 9.3.2描述/118 9.3.3多种实现/119 9.3.4效果/119 9.3.5样例/120 9.3.6小结/123 9.4容器独立/124 9.4.1表述/124 9.4.2描述/124 9.4.3多种实现/125 9.4.4效果/125 9.4.5样例/126 9.4.6小结/129 9.5独立部署/129 9.5.1表述/129 9.5.2描述/130 9.5.3多种实现/130 9.5.4效果/131 9.5.5样例/132 9.5.6小结/135 9.6参考文献/136 第10章可用性模式/137 10.1发布接口/137 10.1.1表述/137 10.1.2描述/137 10.1.3多种实现/138 10.1.4效果/140 10.1.5样例/141 10.1.6小结/146 10.2外部配置/147 10.2.1表述/147 10.2.2描述/147 10.2.3多种实现/147 10.2.4效果/148 10.2.5样例/149 10.2.6小结/151 10.3默认实现/151 10.3.1表述/151 10.3.2描述/151 10.3.3多种实现/151 10.3.4效果/153 10.3.5样例/153 10.3.6小结/156 10.4模块门面/156 10.4.1表述/156 10.4.2描述/156 10.4.3多种实现/156 10.4.4效果/158 10.4.5样例/158 10.4.6小结/162 第11章扩展性模式/163 11.1抽象化模块/163 11.1.1表述/163 11.1.2描述/163 11.1.3多种实现/164 11.1.4效果/165 11.1.5样例/165 11.1.6小结/168 11.2实现工厂/168 11.2.1表述/168 11.2.2描述/169 11.2.3多种实现/169 11.2.4效果/171 11.2.5样例/171 11.2.6小结/175 11.3分离抽象/175 11.3.1表述/175 11.3.2描述/175 11.3.3多种实现/175 11.3.4效果/178 11.3.5样例/178 11.3.6小结/180 11.4参考文献/181 第12章通用模式/182 12.1就近异常/182 12.1.1表述/182 12.1.2描述/182 12.1.3多种实现/182 12.1.4效果/183 12.1.5样例/184 12.1.6小结/187 12.2等级化构建/187 12.2.1表述/187 12.2.2描述/187 12.2.3多种实现/189 12.2.4效果/190 12.2.5样例/191 12.2.6小结/195 12.3测试模块/195 12.3.1表述/195 12.3.2描述/195 12.3.3多种实现/196 12.3.4效果/197 12.3.5样例/198 12.3.6小结/201 第三部分模块化架构模式与OSGi 第13章OSGi简介/204 13.1一点历史/204 13.2OSGi所能带来的收益/204 13.2.1模块化开发/205 13.2.2管理依赖/205 13.2.3模块平台/205 13.2.4版本化的bundle/206 13.2.5动态(重)部署/206 13.2.6环境相关的控制/206 13.3深入理解OSGi/206 13.4OSGibundle/207 13.4.1bundle状态/207 13.4.2OSGi?Service/208 13.5OSGi运行时管理/209 13.6重新查看模块化的两个方面/209 13.7OSGi与模式/209 13.7.1管理依赖/210 13.7.2动态性/210 13.7.3Blueprint规范/211 第14章贷款样例与OSGi/212 14.1起步/212 14.2清单文件/214 14.3?Service/215 14.3.1Blueprint服务/215 14.3.2贷款样例配置/215 14.3.3OSGi?Service声明/218 14.4安装与执行/219 14.5结论/220 第15章OSGi与Scala/221 15.1起步/221 15.2Scala代码/221 15.3Scalabean配置/224 15.4Scala?Service配置/224 15.5构建Scala模块/225 15.6安装与执行/225 15.7结论/226 第16章OSGi与Groovy/227 16.1起步/227 16.2Groovy代码/227 16.3Groovybean配置/230 16.4Groovy?Service配置/230 16.5构建Groovy模块/230 16.6安装与执行/231 16.7结论/232 第17章OSGi的未来/233 17.1将OSGi作为推动者/233 17.2颠覆性/234 17.3生态系统的威力/236 17.3.1生态系统与模块化的两个方面/236 17.3.2基于组件的开发(CBD)不是已经成功了吗/236 17.4生态系统/237 17.5结论/238 附录A类设计的SOLID原则/239
序言
前 言 在1995年的时候,设计模式曾经风靡一时。今天,我却发现情况完全相反。模式变得司空见惯,大多数的开发人员在日常工作中会不假思索地使用模式。现在,很少会出现像“四人组”(Gang of Four,GoF)模式2那样有影响力的新模式。实际上,这个产业从模式运动以来已经有了很大的改进。模式变得不再那么时尚,它们成了开发人员工具箱中的一部分并用来帮助设计软件系统。 但是,设计模式在过去十多年所扮演的角色不应被低估。它作为催化剂,推动面向对象开发成为主流。它们帮助大批开发人员理解了继承的真正价值以及如何有效使用它。模式提供了如何构建灵活且有弹性软件系统的深刻见解。借助金子般的智慧,如“优先使用组合而不是类继承”以及“面向接口编程而不是面向实现”(Gamma 1995),模式帮助一代软件开发人员接受了一种新的编程范式。 今天,模式还在广泛使用,但对很多开发人员来说,它们是很自然的事情。开发人员不再争论使用策略模式(Strategy pattern)的好处,他们也不必再参考GoF的书来识别哪个模式最适合当前的需要。相反,好的开发人员能够本能地设计面向对象的软件系统。 很多模式是永恒的。它们与特定的平台、编程语言或者编程时代无关。做一些细微的修改并且对细节稍加关注,一个模式就能变成适合给定上下文的形式。很多事情是与上下文相关的,包括平台、语言以及要解决问题的复杂程度。随着更多地学习模式,我们提供了在特定语言下如何使用模式的样例,并将其称为习语(idiom)。 我认为本书中的模块化模式也是永恒的。它们与特定的平台或语言无关。不管你是使用Java还是.NET、OSGi3还是Jigsaw4,或者是想构建更加模块化的软件,本书中的模式都会帮助到你。随着时间的推移,我们将会看到一些习语出现,它们将描述如何将这些模式应用到支持模块化的平台上,并且会有工具帮助我们使用这些模式重构软件系统。我希望当有工具出现的时候,它们能够不断地进化来帮助开发模块化的软件。但最重要的是,我希望在你们的帮助下,这些模式能够进化并且变成有助于设计更好软件的模式语言——这些软件将会实现模块化的优点。时间将会告诉我们一切。 面向对象的设计 在过去的几年中,出现了一些面向对象的设计原则。很多设计原则体现在设计模式中。Bob大叔提出的SOLID设计原则(参见附录)是最突出的例子。深入分析GOF模式,会发现它们中的很多都符合这些原则。 这些形成共识的知识以及所带来的收益有助于指导面向对象开发,但是创建大型的软件系统依然是很困难的。这些大型的系统依旧难以维护、扩展和管理。现有的原则和面向对象开发模式不能帮助管理大型软件系统的复杂性,这是因为它们所解决的是不同的问题。它们有助于解决逻辑设计相关的问题但是无助于解决物理设计方面的挑战。 逻辑设计与物理设计 有些原则和模式可以帮助解决软件设计和架构所面临的问题,这些问题几乎都是关于逻辑设计的。5逻辑设计是关于语言结构的,如类、操作符、方法以及包。识别类的方法、类之间的关系以及系统中包的结构都是逻辑设计问题。 毫无意外,因为大多数的原则和模式强调的都是逻辑设计,所以开发人员将大多数时间都用来处理与逻辑设计相关的问题。在设计类及其方法的时候,你是在定义系统的逻辑设计。决定一个类是否为单例(singleton)是逻辑设计问题。确定一个操作是否为抽象的或者决定要继承自一个类还是要包含它,这些同样也是逻辑设计问题。开发人员生存在代码中,就会不断地处理逻辑设计的问题。 能够很好地使用面向对象设计原则和模式是很重要的。要适应大多数业务应用中所需要的复杂行为是很有挑战性的任务,如果不能创建灵活的类结构,将会对未来的增长和可扩展性带来负面的影响。但是逻辑设计并不是本书关注的焦点。有很多其他的图书和文章提供了必要的指导,它们能提供足够的智慧以保证创建良好的逻辑设计。逻辑设计只是软件设计和架构所面临挑战的一个方面。挑战的另一方面就是物理设计。如果你没有考虑系统的物理设计,那么不管你的逻辑设计多么漂亮,可能都不会带来预期的收益。换句话说,缺乏物理设计的逻辑设计并不会带来预期的影响。 物理设计表现为软件系统中的物理实体。确定如何将软件系统打包到部署单元中是物理设计问题。决定哪个类属于哪一个部署单元也是物理设计问题。同样,管理可部署实体之间的关系也是物理设计问题。如果我们不说物理设计比逻辑设计更重要的话,起码它们是同等重要的。 例如,定义接口可以使客户端与实现该接口的类解除耦合,这是一个逻辑设计问题。按照这种方式解耦显然能够让你在不影响客户端的情况下,创建这个接口的新实现。但是,要将接口和它的实现类放到物理实体中就是物理设计问题了。如果这个接口有多个不同的实现,并且每个实现类都有底层的依赖,那么如何放置接口和实现就会对系统的整体软件架构质量产生巨大的影响。将接口和实现放在同一个模块中将会引入不必要的部署依赖。如果其中的一个实现依赖复杂的底层结构,那么不管你选择使用哪一个实现,都需要在所有的部署环境中包含这个依赖结构。尽管逻辑设计的质量很高,但是物理实体之间的依赖将会阻碍可重用性、可维护性以及很多在设计时试图要获得的其他收益。 令人遗憾的是,尽管众多团队付出了很大一部分时间在逻辑设计上,但是很少有团队在物理设计上下工夫。物理设计是关于如何将软件系统拆分为模块系统的,物理设计是关于软件模块化的。 模块化 在开发和维护方面,大型的软件系统天生就比小型的系统更复杂。模块化会涉及将大型的系统拆分为单独的物理实体,最终会使系统更易于理解。通过理解模块中的行为以及模块间存在的依赖,我们可以更容易地识别和评估变化所带来的连带影响。 例如,要修改具有很少输入依赖的软件模块比那些具有众多输入依赖的模块更容易。同样,具有很少输出依赖的软件模块比那些具有众多输出依赖的模块更易于重用。当设计软件模块时,重用和可维护性是重要的考虑因素,而依赖在其中扮演了重要的角色。但是,依赖并不是唯一的因素。 在设计高质量的软件模块方面,模块内聚也扮演着重要的角色。具有很少行为的模块对于其他的模块并没有做太多有用的事情,因此所提供的价值很小。与此相反,如果模块所做的事情太多将会难以重用,因为它所提供的行为超过了其他模块的期望。当设计模块时,识别合适的粒度等级是很重要的。太细粒度的模块提供的价值很小,可能还需要其他的模块协作才能发挥作用。太粗粒度的模块则会难以重用。 本书中的原则为设计模块化的软件提供了指导。它们探讨了一些方式,这些方式可以让你尽可能地减少模块之间的依赖同时又能最大化模块的重用能力。如果没有面向对象设计的原则和模式,其中的很多原则是无法实现的。你将会发现,对模块化系统所做的物理设计决策经常会影响逻辑设计决策。 模块化单元:JAR文件 在Java平台中,物理设计是通过仔细设计JAR文件的关系和行为实现的,模块化的单元就是JAR文件。尽管这些原则可以应用到其他的单元,如包中,但是将其应用在设计JAR文件中会特别有价值(关于模块的定义,参见第1章)。 OSGi OSGi服务平台(OSGi Service Platform)是Java中的动态模块化系统。在OSGi的术语中,模块称为bundle。OSGi提供了一个框架来管理bundle,bundle被打包成普通的Java JAR文件,里面包含了清单文件(manifest)。在清单文件中包含了重要的元数据信息,这些信息描述了bundle以及对OSGi框架的依赖(关于OSGi,参见第13章)。 贯穿本书,你会发现使用OSGi的例子。但是,要使用模块化模式,OSGi并不是先决条件。OSGi只是提供一个运行时环境,它使得在Java平台中实现模块化成为可能,同时它也会强制要求这种模块化。OSGi提供了如下功能。 * 模块化:使得在Java平台中实现模块化成为可能,同时也会强制要求模块化。 * 版本管理:支持相同软件模块的多个版本部署在同一个Java虚拟机(JVM)实例中。 * 热部署:允许在运行时系统中进行部署和更新,不必重新启动应用或JVM。 * 封装:允许模块对它们的使用者隐藏实现细节。 * 面向服务:鼓励在更细的粒度上,在同一个JVM中使用面向服务的设计原则。为了做到这一点,OSGi使用的是μService。 * 依赖管理:需要明确声明模块之间的依赖。 本书所面向的读者 本书面向负责开发软件应用的开发人员和架构师。如果你对提升系统的设计感兴趣,那么本书也适合你。 本书并不只针对那些使用原生模块化平台的人们。例如,如果你正在使用OSGi,那么本书会帮助你使用OSGi设计更为模块化的软件。但是如果没有使用OSGi,本书所讨论的技术依然是很有价值的,它会帮助你使用这些技术来提升软件系统的模块化水平。本书也不是仅仅面向Java开发人员的。尽管本书中的例子使用的都是Java,但是所讨论的技术却可以很容易地用于其他平台,如.NET。 如果你想更深入地理解模块化的好处并且要开始设计模块化的软件系统,本书就是为你而作!本书为以下问题提供了答案。 * 模块化所能带来的收益是什么以及它为何如此重要? * 如何让其他开发人员相信模块化的重要性? * 要增加软件系统的模块化程度,可以采用什么技术? * 在没有OSGi这样的原生模块化平台上进行开发,如何实现模块化? * 如何将大规模的整体应用迁移为具备模块化架构的应用? 本书是如何组织的 本书分为三部分。第一部分描述模块化的理由。在这里,你将会看到模块化在设计软件时所扮演的重要角色,与此同时还会学习需要设计模块化软件的原因。第二部分是18个模式的列表,这些模式会帮助你设计更为模块化的软件。第三部分引入OSGi,然后阐述如何使用本书中的模式来设计软件系统并充分发挥模块化平台的优势。第三部分使用代码样例论证我们的观点。 显然,我建议你逐页阅读本书。但是,在阅读的时候你可能会愿意从一章跳到另一章。尽可以这么做!在本书中,你可能会发现许多与当前主题有关的向前或向后的交叉引用。这会帮助你进行导航并且更容易理解某个理念。以下是每章的概述。 第一部分:模块化的理由 第一部分阐述了模块化为何如此重要。这是采用模块化的理由。第一部分各章的概述如下。 * 第?1?章:该章引入模块化,正式地定义和识别软件模块的特征。建议每个读者都阅读这个简短的章节。 * 第?2?章:模块化有两个方面,即运行时模型和开发模型。一直以来,很多的关注集中在运行时模块化支持方面。随着越来越多的平台提供运行时模块化的支持,开发模型的重要性将会得到更多的关注。开发模型由编程模型和设计范式组成。 * 第?3?章:模块化在软件架构方面扮演着重要的角色。它填补了一项空白,这项空白从团队开发企业级软件系统以来就一直存在。该章将会探讨软件架构的目标以及模块化在实现这一目标时所扮演的重要角色。 * 第?4?章:企业级软件系统充满复杂性。团队会面临技术债的挑战,因为设计腐化,系统会面临崩溃。该章展现模块化如何帮助我们征服软件系统不断增长的复杂性。 * 第?5?章:重用是软件开发的灵丹妙药。但是,很少有组织能够真正实现高度的重用。该章考察阻止实现重用的障碍并探讨模块化如何帮助我们提高成功的可能性。 * 第?6?章:模块化与SOA在很多方面都是互补的。该章探讨模块化与SOA如何成为强大的组合。 * 第?7?章:为要讨论的理念提供一些合适的样例是很重要的。这一章有两个目的。首先,它将前6章的材料组织在一起,这样就能够看到这些理念是如何得到运用的。其次,它为第二部分要讨论的很多模式奠定了基础。 第二部分:模式 这一部分是由模块化模式的集合组成的。它们分成五类,每一类的目的稍有不同。不同的类别之间又会有所权衡。例如,可用性模式的目的在于使模块更易于使用,而扩展性模式会使模块更易于重用。可用与重用之间的权衡在第5章中会进行进一步的讨论。 * 第?8?章:基本模式是其他很多模式赖以生存的基础。它们为设计模块化的架构奠定切实可行的思考过程。它们关注将模块作为可重用单元、依赖管理以及内聚。如果要实现设计良好的软件系统,这些都是很重要的。 * 第?9?章:我很惊讶地发现开发团队花了如此多的时间来设计类之间的关系,但是在创建支撑的物理结构方面几乎不会花什么时间。在这里,你会看到帮助你创建模块间低耦合结构的一些指导。你也会看到模块设计会如何影响部署的讨论。 * 第?10?章:尽管耦合是很重要的测量指标,但内聚也同样重要。如果将所有的类都扔到两三个JAR文件中,这很容易创建并且管理依赖也很简单。但如果这样做,会使维护很困难。在该章中,我们将会看到那些有助于确保模块是内聚单元的模式。你会发现在依赖模式和可用模式之间会有一些很有意思的权衡。我会讨论这种权衡,以及你可以做些什么来对其进行管理。 * 第?11?章:设计软件系统的一个目标就是能够在不修改已有代码库的前提下对系统进行扩展。在达成这个目标时,抽象扮演了核心的角色,但是往已有系统中添加新功能只是我们所面临的挑战的一部分。我们还希望能够在不重新部署整个应用的情况下,部署这些新增的功能。扩展性模式的关注点在于帮助我们达成这个目标。 * 第?12?章:通用模式有助于实现模块化开发。与其他的那些模式不同,它们不强调重用、可扩展性以及可用性。相反,通用模式会讨论强制实现模块化的方式并有助于解决与质量相关的问题。 第三部分:模块化架构模式与OSGi 要使用本书中的模式,标准Java已经为你提供了所需的所有内容。但毫无疑问,你会希望在良好支持模块化的环境中查看这些模式。在这一部分,我们会这样做并借助OSGi框架以样例的方式进行阐述。 * 第?13?章:该章对OSGi进行简要的介绍,包括其功能和收益。该章并不想成为一个教程,我们假设读者已经掌握了OSGi的基本知识。这里会讨论模块化与OSGi,包括μService与Blueprint规范。除此之外,你还会看到OSGi的动态性如何为运行时环境带来模块化。最后,我们会探讨模式如何与OSGi中的开发相关联。借助OSGi,我们可以更容易地以最纯粹的形式使用某些模块化模式。 * 第?14?章:在模式讨论的过程中,我们使用了一个通用的贷款样例系统。在该章中,我们将会再次使用这个贷款样例,但是会将应用进行重构使其能够运行在OSGi环境中。你会很惊讶地发现,一旦具备了模块化的架构,OSGi只有一步之遥。 * 第?15?章:Java平台支持多种语言,OSGi并不会阻碍你使用Java平台上的替代语言。该章将会展示如何创建Scala模块并将其插入系统中。你会发现这有两个主要的优势。首先,模块化的架构能够很容易地添加代码,而不用对系统中已有的代码做任何修改。其次,它清晰地阐述了OSGi的动态性。 * 第?16?章:就像第15章的Scala样例一样,我们使用Groovy编程语言开发另外一个模块来进一步阐述模块化运行时环境所具备的灵活性和动态性。 * 第?17?章:模块化和OSGi的未来是什么?它会如何改变我们对大型企业级软件系统的思考方式?在本章中,将会以非常超前的方式探讨模块化和OSGi的未来。 模式形式 每个模式都具备一致的结构,从而保证有尽可能强的可读性。每个模式同时还会有一个配套样例阐述如何应用其底层的理念,但并不是每个模式都具有所有的部分。在有些场景下,某些部分可能会被忽略,因为前面的讨论已经引用过了。模式的主要结构类似于“四人组”(GoF)的格式,也就在《设计模式:可复用面向对象软件的基础》一书中所用的格式,它们的结构如下: 模式名称 首先,呈现的是模式名称。名称很重要,因为它有助于在开发人员之间建立一个通用的词汇表。 模式表述 模式表述概要地描述该模式,这个表述有助于理解模式的意图。 图示 图示以图形化的形式展现模式的整体结构。通常,这里会使用统一建模语言(Unified Modeling Language,UML)。 描述 描述更详细地展现模式所解决的问题。描述会有助于理解模式背后的驱动力。 多种实现 不管何种模式,将其用于解决现实世界中的问题时,很快就会出现微妙的实现细节。当使用模式时,“多种实现”将会讨论你应该考虑的一些重要的替代方案。 效果 所有的设计决策都会有有利的方面和不利的方面,就像软件设计的大多数建议一样,使用模式也要进行明智的判断。尽管它们提供了大量的灵活性,但是这些灵活性也是有代价的。“效果”这一部分会讨论一些有趣的事情,也就是使用模式时可能会遇到的问题以及可能出现的效果,由此可以判断在何种情况下应该忽略这个模式。在阅读完它的效果之后,关于何时使用这个模式以及何时使用替代的方案,你应该会有更好的理解。归纳起来,这一部分呈现使用这个模式的优势和劣势、你要付出的代价以及所能实现的收益。 样例 当关注样例的时候,你可能会更容易理解模式。这一部分会通过样例来阐述如何使用模式。有时候,我们会使用一些代码,而有时候,可视化的图片能够清晰地传达信息。最重要的是,样例不会存在于真空中。当在现实世界中使用模式的时候,模式之间会协同使用以创建更灵活的定制方案。在这种情况下,有些样例会建立在其他模式所讨论的样例之上。样例所能达成的结果就是让你更深刻地理解在实际工作中如何有效地使用这个模式。 小结 这一部分提供关于该模式的一些结论。 模式目录 以下为模块化模式的列表。 * 基本模式(Base Pattern) * 管理关系(Manage Relationship):设计模块关系。 * 模块重用(Module Reuse):强调模块级别的重用。 * 模块内聚(Cohesive Module):模块的行为应该只服务于一个目的。 * 依赖模式(Dependency Pattern) * 非循环关系(Acyclic Relationship):模块关系必须是非循环的。 * 等级化模块(Levelize Module):模块关系应该是等级化的。 * 物理分层(Physical Layer):模块关系不应该违反概念上的分层。 * 容器独立(Container Independence):模块应该独立于运行时容器。 * 独立部署(Independent Deployment):模块应该是独立的可部署单元。 * 可用性模式(Usability Pattern) * 发布接口(Published Interface):使模块的发布接口众所周知。 * 外部配置(External Configuration):模块应该可以在外部进行配置。 * 默认实现(Default Implementation):为模块提供一个默认实现。 * 模块门面(Module Facade):为具有底层实现的细粒度模块创建一个门面,使其成为细粒度模块的一个粗粒度入口。 * 扩展性模式(Extensibility Pattern) * 抽象化模块(Abstract Module):依赖于模块的抽象元素。 * 实现工厂(Implementation Factory):使用工厂来创建模块的实现类。 * 分离抽象(Separate Abstraction):将抽象与实现它们的类放在各自独立的模块中。 * 通用模式(Utility Pattern) * 就近异常(Colocate Exception):异常应该接近抛出它们的类或接口。 * 等级化构建(Levelize Build:):按照模块的等级执行构建。 * 测试模块(Test Module):每个模块应该有一个对应的测试模块。 代码 贯穿整本书有大量的样例,在很多样例中包含代码。本书中所有模式的样例可以在以下的GitHub仓库找到:https://github.com/pragkirk/poma。 如果你想在自己的机器上运行代码却并不熟悉Git,可以通过以下地址查看Git的文档:http://git-scm.com/documentation。 第7章的样例可以在Google Gode Subversion仓库找到,地址为:http://code.google. com/p/kcode/source/browse/#svn/trunk/billpayevolution/billpay。 建议每位读者都能从以上的仓库中下载代码,并在阅读每个模式的“样例”章节时,使用这些例子。尽管在很多模式中都提供了代码,但是模式的样例章节中不可能把所有的代码都包含进来。书中的这些代码会在讨论中给你指导,并且对于模式如何使用会给你一个总体的印象。但是,通过下载并学习代码,你能够对模式的复杂性有更清晰的了解。 模式化模式的开放式想法 当我写作本书的时候,围绕模块化模式有一些争论。有些人建议将它们称为原则更恰当,而有些人更倾向于定律(law)这个词。有些人甚至建议将其称为启发(heuristic)、指导(guideline)、习语(idiom)、秘诀(recipe)或规则(rule)。但是到最后,所有的审校者都表示喜欢这本书的内容和表述方式。所以最终,我依然坚持称其为模式。相对于关注称其为模式、原则、启发或者什么其他方式,我更愿意你关注每一个模式所讨论的主题。这其中的理念才是重要的。 参考文献 Gamma, Erich, et al. 1995. Design Patterns: Elements of Reusable Object-Oriented Software. Reading, MA: Addison-Wesley. 致谢 本书的灵感来源于多个方面,最近几年我得到了他人极大的帮助。但是,我要特别感谢七个人。在我过去二十年的工作中、过去十年研发这些模式以及过去两年完成本书的过程中,他们的理念都给予了我指导。他们是: Robert C. Martin(Bob大叔):Bob在面向对象设计原则方面(即SOLID原则)的工作是本书所讨论的很多技术的基石。实际上,这本书是他的这个系列的一部分,附录A提供了一些原则的整体介绍。 Clemens Szyperski:Clemens的《Component Software: Beyond Object Oriented Programming》6一书作为基础定义了模块的概念,这个概念贯穿本书。 John Lakos:John的《大规模C++程序设计》是我见过的唯一一本讨论物理设计的书。在那本书中,John的理念激发了我的灵感和对物理设计的兴趣,这使得我在过去的十年中使用并提炼技术,最终形成了这些模块化模式。 Ralph Johnson、John Vlissides、Erich Gamma以及Richard Helm(即GoF):除了提供本书中所使用的模式模板外,《设计模式》一书加深了我对面向对象理念的理解。 除此之外,我还要感谢下面这些人,得益于他们的反馈,我才能极大地改进本书所传递的信息。 尤其是,OSGi联盟的技术总监Peter Kriens:Peter提供了很多的反馈,以至于我应该将其列为合著者。 我还要感谢Brad Appleton、Kevin Bodie、Alex Buckley、Robert Bogetti、Chris Chedgey、Michael Haupt、Richard Nicholson、Glyn Normington、Patrick Paulin、John Pantone以及Vineet Sinha,他们提供了深刻的评论和有价值的反馈,帮助我更清晰地确定本书的范围并在讨论中加入更多视角。当然,在这个过程之中,还有很多人对我的著作产生了影响。令人遗憾的是,我肯定落下了其中一些人的名字。你们知道我说的是谁。谢谢你们! 当然,我还要感谢Prentice Hall团队,正是他们使这一切成为可能。编辑Chris Guzikowski多年以来给我了很多的机会来完成本书,这甚至超出了我的预期。策划编辑Sheri Cain给了我格式化方面的很多建议,回答了我所提出的一些很愚蠢的问题,并且将很粗糙的手稿进行了结构化和改善。编辑助理Olivia Basegio和Raina Chrobak在整个过程中都给予了我指导。项目编辑Anna Popick掌控了整个项目的完成。文字编辑Kim Wimpsett帮助出版了最终的手稿。 最后,我要感谢我的家庭。如果没有他们的爱,几乎什么事情都做不了,什么事情都没有意义。感谢父亲和母亲,他们的温柔陪伴着我的整个生命旅程。我相信很多时候他们都不明白我要成为什么样子。我的祖母Maude,您是有史以来最伟大的老师。我的孩子,Cory、Cody、Izi以及Chloe,他们使得生活充满了乐趣。当然还有我的妻子Tammy。她是我最好的朋友,正是她的鼓励让我抹去旧书稿的灰尘并重新开始。谢谢你们。感谢所有的人!