我认为代码共享是不可避免的,而且这种信仰趋势我从八十年代就开始从事自己的工作。软件应该从组件创建,这个组件在点对点的基础上,通过显示接口协作。这是解决这个大泥球问题(big ball of mud)的唯一途径,这里的大泥球指维护和修改代码基变得越来越难,由于这些代码相互纠缠。如果你的软件依赖范式看起来像Jackson Pollock(20世纪美国抽象绘画的奠基人之一。
)的绘画,你就知道什么是大泥球了。 为一个模糊的基础架构塑型的方法之一就是模块化,和更加基于组件的模型。在一个组件模型中,我们将开发者(组件制造者)的角色和组装者(将组件组合成一个应用)的角色分离开。组件开发者应该不了解其他组……
我们一直都在努力坚持原创.......请不要一声不吭,就悄悄拿走。
我原创,你原创,我们的内容世界才会更加精彩!
【所有原创内容版权均属TechTarget,欢迎大家转发分享。但未经授权,严禁任何媒体(平面媒体、网络媒体、自媒体等)以及微信公众号复制、转载、摘编或以其他方式进行使用。】
微信公众号
TechTarget
官方微博
TechTarget中国
我认为代码共享是不可避免的,而且这种信仰趋势我从八十年代就开始从事自己的工作。软件应该从组件创建,这个组件在点对点的基础上,通过显示接口协作。这是解决这个大泥球问题(big ball of mud)的唯一途径,这里的大泥球指维护和修改代码基变得越来越难,由于这些代码相互纠缠。如果你的软件依赖范式看起来像Jackson Pollock(20世纪美国抽象绘画的奠基人之一。)的绘画,你就知道什么是大泥球了。
为一个模糊的基础架构塑型的方法之一就是模块化,和更加基于组件的模型。在一个组件模型中,我们将开发者(组件制造者)的角色和组装者(将组件组合成一个应用)的角色分离开。组件开发者应该不了解其他组件(即便是协作组件)。这种盲区可以组织实施中不必要的依赖。假设组件少,BUG也就少。只有契约做组件开发中应该是可视的。
业界很多的工作对于不同软件子系统更好的自主权具有指导意义。SOA很明显是基于点到点的模型,但是大型软件库也有自己的线程和控制模型,而这些都是独立于主应用的。开源项目更接近组件,但是不幸的是,我们没有选定一个模块化的系统,这个系统可以让这些组件更易于使用。
这种更高层次的自主权的逻辑结论就是需要共享接口,还要允许组件尽可能在循环的最后链接在一起,以便最大化灵活性。一套组件可以组装在一起形成一个统一的应用。
1998年,因为这种协作模型的想法,我们开始开发OSGi。我们希望这个模型可以再没有优先知道其他组件的情况下,以点到点的形式,同来自不同厂商的组件进行协作。我们希望这个组件可以同其他组件集合起来共同工作,取代约束孤岛。为了实现这个目标,我们知道我们必须解决共享问题:DLL Hell。
在这十三年中,我们从模块化中学到了什么?
执行
如果模块化没有执行,就不用存在了。在你违反模块边界的时候,除非有人打你的手掌,否则你就不能模块化。这也是人们转向OSGi时最沮丧的一点:找出代码基并不像模块化架构和依赖范式那样让人信服。
隐藏
有时,你必须保守秘密。共享问题最好的解决方案有时候不是简单的共享一切。任何共享的事物在晚期维护组件的阶段都有一个隐藏成本。任何共享方面必须小心描述,限制其发展。共享是昂贵的。
因为这个原因,OSGi在你的bundle中为你提供一个私有Java命名域,用于尽可能多地隐藏其他地方的代码。在这里无论你做什么都有保证不会影响到bundle外的其他任何人。不同的bundle实际包含同样的类,而不会导致命名问题。
依赖成本
每一个依赖都有一个成本,但是你可能会吃惊于,如此多的人不能精确知道自己的依赖来自哪里。一旦我发现超过30M的依赖,就会把他们放到一个单线程中,参照apache公共资源集合。很多WAR和Maven项目都有很多模糊的依赖链,因为很难估计出在现今的Java中实际有多少依赖。
我们发现,对于JAVA,包是共享的正确粒度。类对于共享来说粒度过细。在同一个包中,它们过多地链接到与其相邻的类中。输出类在Java包中也重叠了。JAR对于共享来说,太难处理,因为是一个在代码中共享的包聚合。这种聚合在版本控制和依赖管理上有让人不爽的副作用。
基于API编程的意外结果
基于API编程,指的是,一个API可以通过不同的实体实现,要求每一个再访问版本为我们所知道。在Unix包管理系统中,它是软件依赖管理模型的鼻祖,版本控制基于请求提供者的消费者。在Java中倾向于盲目追随这些模型,但是模型是错误的。对于白费力气重复工作而言是个很好的战略,但是使用基于API编程模型,我们实际上得到了一个第三方:API/接口/契约。结果是这个三元组对于兼容性规则具有重大意义,这就是依赖模型。
为了让组件可以是当地连接,需要独立于其他组件的功能分解其需求。在这样一个线路模型中,包的正确描述是最重要的。
OSGi中,一个输出可以声明版本,输入可以根据兼容性声明一个版本范围。OSGi规范指出了语义版本的规则,模型是版本的一部分,意味着有一个良好顶合一的兼容性。很多其他的模式只是执行反向兼容性,没有认识到消费者/接口/提供者这个三元组。OSGi版本模式通过自动化工具很好地实现了这个。
OSGi中,你可以清晰无疑地声明,你不会和优先版本和谐相处。能表达你不支持旧版本的反向兼容性是组件系统中必不可少的内容。
多版本依赖
依赖于同一包的多版本不是每个人都渴求的,但是当应用使用了足够的外部依赖,就称为不可避免的了。在JAVA社区中,有一种倾向于忽略这种麻烦多版本的趋势,就好象他们没有这个问题。
例如,Maven中第一个版本在依赖中还在使用,尽管随后的依赖有了更高的版本。在大型类路径上发现相同库的多版本很正常,之所以奇怪是因为我们希望花更多的时间在语言的类型安全上,但由于忽略版本,远离了运行时的诸多好处。
OSGi中,依赖需要小心管理,它是一项精密科学,没有模糊性和启发性。OSGi框架通过链接bundle到期正确的版本解决了域问题,但是之允许没有冲突的bundle之间的协作。
例如,通用的LOG DLL很有欢迎。WIDGET DLL将该库作为COMM DLL很好地运用,看下图:
在这个DLL例子中,OSGi可以轻松处理App和COMM以及App和WIDGET之间的协作,而不用交换LOG对象。实际上,OSGi支持协作和共享,但是当需求的关键原因之一是应用服务器厂商过多地使用OSGi,它也是孤立的。
总结
OSGi核心规范的大部分是在模块层,这一层中我们定义了共享规则。这些规则通常是复杂的,难以理解,而且需要很多关于命名域、类型系统以及Java内部的知识。然而,这些规则只需要少量OSGi框架开发者理解。作为回馈,OSGi为模型开发者提供了稳固的共享模型,这个模型强大,而且具有惊人的易用性。
作者
相关推荐
-
Java模块化项目Jigsaw能否重回正轨?
模块化的粉丝们会很高兴的听到这一消息,Jigsaw项目已经重新提上日程,至少也是部分回到了正轨。
-
OSGi中该使用Blueprint还是声明式服务?
在OSGi中,服务是实现bundle间交互和应用灵活性的基石。借助于服务,我们能够降低bundle之间的耦合,更加有利于软件的重用。
-
OSGi中的服务模型与扩展者模型
在OSGi中,实现bundle间交互和扩展性有两种常见的方式,也就是服务模型(service model)和扩展者模型(extender model)。
-
如何用XML设备进行版本控制及治理
说明如何使用XML装置进行版本控制及治理的例子有哪些?其实在提供与版本控制及治理相关的能力上,XML装置或任何其他中介(如企业服务总线ESB)之间没有区别。