作者:Richard Nicholson 翻译:刘剑锋 审校:张卫滨
原文发表于Infoq,经译者同意,发布到社区。
在上一篇文章中,介绍了结构性模块化与敏捷之间的关系,在这个系列的第二篇文章中,我们将会研讨OSGi?,在实现JavaTM的结构性模块化方面,OSGi扮演了核心的角色;OSGi与流行的敏捷方法论之间存在着自然的联系。
绝大多数开发人员都同意程序应该模块化。尽管在面向对象的程序设计出现的早期,逻辑性模块化的要求就被迅速满足了(见http://en.wikipedia.org/wiki/Design_Patterns), 但是软件行业花费了很长的时间才理解结构性模块化的重要性。特别是,结构性模块化可以提高程序的可维护性和灵活性,控制和减少环境带来的复杂性。
在《Java Application Architecture》(本书已经由机械工业出版社引进出版,中文书名为《Java应用架构设计:模块化模式与OSGi》——译者注)一书中,Kirk Knoernschild探索研究了结构性的模块化,并建立了一套关于结构化设计的最佳设计模式。Knoernschild认为,在模块化风潮中并不需要开发模块化的框架;对于Java,JAR文件结构就足够了。
事实上,在“敏捷”开发团队中根据代码库的增长将应用分解为较小的JAR文件的做法并不罕见。随着JAR文件大小的增加,他们会被分解为更小的JAR文件的集合。从代码角度,特别是如果遵循Knoernschild的结构化设计模式,我们会认为,从某个结构层看,程序是模块化的。
从创建应用的团队,以及负责随后维护人员的角度来看,应用是更敏捷的。团队了解依赖关系,以及变化的影响。然而,这种知识并没有关联到组件上。一旦团队成员离开了公司,程序和业务就有可能立刻受到影响。同样,对第三方(即使是同一个组织的不同团队)来说,该应用可能依然是单独的巨大代码库。
如果程序中只有一层结构性的模块,它必然不是自描述的。由于缺乏描述模块之间内在关系的元数据,由此产生的业务系统本质上是脆弱的。
Maven文档(项目对象模型,Project Object Model——POM)也能表达组件之间的依赖关系。这些依赖关系由组件的名称定义。
鉴于此,基于Maven的模块化程序可以被任何第三方很容易地整合起来。然而,在上一篇文章我们已经提到,由名称定义依赖关系是有缺陷的。由于组件之间的依赖关系并不能明确表明需求(Requirement)和功能(Capability),第三方不能推断出依赖关系的存在原因和可替代的部分。
程序可以被整合,但却不能变更。这种方式是否使得程序比之前的“JAR文件组合”更为“敏捷”还值得商榷。
就如Knoernschild在《Java应用架构设计》中阐述的那样,一旦实现了结构性模块化,我们很容易就能将它迁移到OSGi 之中,也就是Java领域中的模块化标准。
OSGi不仅帮助我们保证结构性的模块化,它同时提供了必须的元数据来保证我们建立的模块化结构也是敏捷的结构。
OSGi通过需求和功能表达依赖关系。因此,第三方可以立刻知道哪些组件可能是可替换的。因为OSGi同样使用语义化的版本控制,所以第三方可以立即推测出,某个组件的变更是否有破坏系统的潜在危险。
OSGi同样也具有展现结构化层次的能力。
在模块化的一端,我们使用面向服务的架构(Service Oriented Architecture,SOA);在另一端,我们使用Java包和类。然而,正如Knoernschild表述的那样,在这两端之间缺少了必要的层次。
图1: 结构化层次:缺失了中间的部分(Kirk Knoernschild – 2012)
中间缺少层次的问题,在OSGi中得到了直接的解决
图2: 结构化层次: OSGi 服务和Bundle
正如Knoernschild 所描述的,OSGi所提供的模块化层次解决了一些比较关键的问题:
因此,OSGi Bundle和服务作为OSGi联盟开放规范的主要部分,为Java提供了之前缺失的、结构性模块化中的重要层次。原则上,OSGi技术使基于Java的业务系统实现“敏捷——从上至下贯穿各层”成为可能。
我们现在可以看到,OSGi的结构(Bundle和服务)与流行的敏捷方法论很匹配,并且能够促进它们得以实现。
敏捷运动主要关注于实现敏捷的产品开发和交付相关的流程(Process),当前已经存在一些精益与敏捷(Lean&Agile)的方法,其中的每一种都是两种广为人知的方案的变种、混合或延伸。这两种方案就是Scrum和Kanban(http://en.wikipedia.org/wiki/leansoftwaredevelopment)。
为了每种方案更加有效,都需要在某种程度上具有结构性的模块化。
客户一直在改变他们的想法。Scrum承认“需求改动(requirement churn’)”的存在,并且采用基于经验的(empirical ,http://en.wikipedia.org/wiki/empirical)方式完成软件的交付。Scrum承认问题不能完全被理解或被预先定义。Scrum着重于最大限度地提高团队能力,以更快完成交付并解决更多新的需求。
Scrum是迭代式渐进的增长过程,以“Sprint”作为基本的开发单元。每个Sprint都是在“固定时间(time-boxed)”(http://en.wikipedia.org/wiki/Timeboxing)内的工作,即它有一个明确的期限。对于每个Sprint,它的期限是事先固定的,一般在一周到一个月之间。Sprint开始之前会有一个明确任务和目标的计划会议,Sprint之后会有一个回顾会议,这个会议上要评估进度并总结本Sprint的经验教训。
每个Sprint的期间,团队将完成产品的一部分。纳入Sprint的特性来源于产品的backlog,这是一个按顺序排列的需求(http://en.wikipedia.org/wiki/Requirement)列表。
Scrum鼓励创建自组织的团队,这通常需要团队所有成员的协同工作和口头交流实现。
“Kanban”起源于日语,意思是“布告板”或“看板”。它的根源可以追溯到20世纪40年代后期的日本丰田汽车制造公司(见 http://en.wikipedia.org/wiki/Kanban)。Kanban鼓励团队对工作、工作流程、进程、风险等建立共同的理解,以此团队将取得在某个问题上的共识,然后在此基础上提出能够达成一致的改进方案。
从结构性模块化的角度来看,Kanban的重点在于在制件(Work-In-Progress, WIP)、有限的发布和反馈,可能这是该方法中最为有意思的:
由此可见,Kanban鼓励持续的、增量式的以及渐进的系统变更。随着结构性模块化的程度得到提高,流动率也同时增加,而每个更小的模块将消耗更少的时间处于“在制品”状态。.
随着结构性模块化程度的提高,Scrum和Kanban的目标将更容易实现。能力成熟度模型(Capability Maturity Model ,参见http://en.wikipedia.org/wiki/CapabilityMaturityModel),主要被公司或项目用于估测它们在软件开发过程获得的改进。同样的,模块化成熟度模型(Modularity Maturity Model)更倾向于描述组织或项目在模块化方面上的进展,这个概念是由Graham Charters博士在OSGi Community Event 2011 上(see http://slidesha.re/ZzyZ3H 提出的。现在我们扩展一下这个理念,分析模块化成熟度模型对企业在敏捷方面的影响。
模块化成熟度模型的阶段总共分为以下六个阶段:
模块(Module)——不再直接使用类(或者包含类的JAR),而是使用有清晰的版本规范的模块,依赖关系可由模块的标识确定(包括版本名)。Maven、Ivy和RPM就是这类模块化解决方案的例子,在这里依赖通过版本化的标识符进行管理。企业一般都有存储这些模块的库。然而这些库的价值并没有完全体现出来,因为这些模块没有描述它们的功能和需求。
许多企业内部的研发团队都在这一级别的成熟度。象Scrum这样的敏捷流程是可能的,而且也对企业提供了一些价值。然而,流程在有效性和扩展性方面的最终收益将会因为结构性模块化而受到限制。例如模块间的需求和功能通常通过口头进行交流。这些没有良好定义的结构化依赖同时会影响到持续集成 (Continuous Integration, CI)方面的能力。
模块化(Modularity)——模块的标识并不同于真正的模块化。我们已经知道模块的依赖关系可以通过契约关系(即功能和需求)而不是组件名来进行表述。在这一点上,基于功能和需求表述依赖关系的解决方案,成为动态软件组建机制的基础。这个层次的结构性模块化依赖同时会使用语义化的版本。
通过采用如OSGi之类的模块化框架,Scrum过程中扩展性的问题也得到了解决。由于强制封装,并使用功能和要求来定义依赖关系,OSGi使得众多小团队可以进行独立且高效的开发,而且这些开发可以并行。Scrum管理工作的效率也能获得相应的提高。每个Sprint能够关注于一个或多个事先定义好结构实体,也就是OSGi Bundle的开发或重构工作。同时,语义化版本命名规则,使得不同的团队之间能高效地交流。因为OSGi Bundle 提供了有效的模块化和隔离机制,并行的研发团队可以在同一应用中的不同结构范围内安心地工作。
服务(Service)——对于用户而言,基于服务的协作方式隐藏了服务的构建细节。客户端与提供者的实现之间能够实现解耦。由此可知,服务提倡松散耦合。具有动态寻找和绑定功能的OSGi服务直接支持了松耦合、动态结构、应用的整合或装配等功能。更为重要的是,服务是实现运行时敏捷的基础,包括快速增强业务功能或自动适应环境的改变。
结构性的模块化达到了这一层次,企业可以简单而自然地运用Kanban原理,并达到可以持续集成的目标。
委托(Devolution)——文件的所有权移交给模块化的资源库,资源库鼓励协作和统一管理。资产会根据它们所声明的功能自动选择。这样做的好处包括:
动态化(Dynamism)——这个等级建立在模块化、服务和委托的基础之上,并且是敏捷的顶点。
拥有不同的选择以及根据具体的场景实践这些选择,正是我们所期望达到的更加敏捷的环境。
原文地址:https://adaptevolve.paremus.com/?p=1335
作者简介: Richard Nicholson是Paremus 的CEO和创始人,这是一个2001年成立的软件公司,总部位于英国。 在意识到高度可维护以及高度敏捷的系统在本质上必须是高度模块化的之后,Paremus在2004年开始研究下一代的软件系统。这种持续的努力体现在了Paremus Service Fabric产品之中,这是一个高度可适应的、基于OSGi的自装配运行时,可用于企业级和云环境。作为OSGi联盟的主席(2010-2012),Richard开始推进OSGi Cloud并鼓励OSGi联盟参与到敏捷软件社区中。
Richard在很多的研究领域都保持了浓厚的兴趣,这支撑了Service Fabric的研发,他的研究领域包括复杂的适应性系统(Complex Adaptive System)以及敏捷(Agility)、模块化组装(Modular Assembly)、结构化多样性(Structural Diversity)和适应性(Adaption)之间的关系。
成立Paremus之前,Richard在花旗集团/Salomon Smith Barney,领导着欧洲系统工程(European System Engineering)相关的工作。Richard获得了曼切斯特大学的物理学荣誉学位,并在格林尼治皇家天文台( Royal Greenwich Observatory)获得天体学物理博士。
Richard的博客:http://adaptevolve.paremus.com。
Paremus的博客:http://blogs.paremus.com。
联系客服