最近,Java社区内,围绕的组件化的探讨主要是关于OSGi和Jigsaw之间谁才是实现组件化的正确途径进行争辩。Jigsaw阵营组件基于Java类,而OSGi组件基于封装。Peter Kriens强烈支持用OSGi系统来编写组件化代码。在这篇文章中,Kriens通过解释Java组件封装接口到类:是最小化组件间耦合关系的安全途径。
关于Jigsaw读的越多,我越发感觉Jigsaw只是想解决相对次要的类路径装配(class path assembly)问题。应用本身就有数以百计的依赖装配类路径,这已经很困难了,Jigsaw试图要自动化这些,期望组件路径调用类路径的时候,可以让痛点消失。然而,如果问题是类路径地狱(JAR hell、DLL hell)的话,简化类路径就像用吗啡治疗癌症一样。可能临时去痛,但是还是不能解决根本问题。
谈到Maven,它以一种类似Jigsaw依赖架构的方式,基本上已经解决了类路径装配问题。在JavaOne的Demo中,Jigsaw实际上使用Maven来自动化创建Jigsaw组件,但是发现他们必须修正依赖性,因为这些都是错的,或者指向组件路径不兼容的版本。
并不是说Maven不好或者手工编程开发者很傻,只是这种具体的组件到组件的组件依赖由于其聚合和传递属性,很大程度上增加了耦合。这种依赖架构是很难预防从网上下载maven的根本原因。这种模型依赖比吗啡还糟糕,这个痛点杀手实际上让根本的耦合问题更糟糕。
有趣的是,这种聚合/传递依赖问题是一个伪装的软件老问题。1996年,Java出现之前,类实际上遭遇了同样的问题。试图包含来自大型应用的类,常常拉进来大量其他的类,这些类又拉进来更多的类,以至于无穷无尽。这个问题可以用Brian Foote的大泥球理论(越滚越大)来描述。
根本原因是类的实现聚合了大量的依赖来简化结构;使用库来让结构变得容易。然而,这些实现依赖,在类成为传递依赖链的一部分时就变成了问题,然后总是通过原始类重用将比实际需要多得多的类拖进来。
每一个Java程序员都知道解决方案,但是不系统:接口。通过打破实现类和客户端类之间的依赖,接口可以最小化耦合。接口确实让我们的类图看起来更加的解耦,而且尽可能利用了当今流行的反转控制系统。基于程序的接口成为可论证的Java最佳实践之一。
所以如果Jigsaw组件类似地类实现,那么接口的组件类似物是什么呢?目前的Jigsaw文档有组件为这个角色提供了计划陈述。其用例是组件可以提供任何的事情。在提议中,这只是一个名字和一个版本,所有的语义都是隐式名字,没有任何契约实施。
提供的主要用例是IBM可以说他们在其VM版本中提供了JDK 7。只是用一个名字来模拟接口,而忽略了Java类型系统;不能在实现和客户端通过编译器和VM来证实。如果这样制造了接口,又没有包含任何方法,就是一个名字而已。例如Runnable不能指定the run()方法。如果客户端调用run()同一个编译器只是认为客户端想做什么事情。尽管在某种程度上可以减少键入,那还是Java吗?
对于Jigsaw组件,我们能不只是命名一个契约吗?没有一个使用现有Java类型系统的解决方案来核对一个组件是否提供了它所做的承诺吗?就像为类而生的接口?
那么,什么才是个真正的接口呢?一个接口的关键在于抽象描述了类实现的一部分,所以类实现随后就可以免费使用他所需要的任何东西来简化其实现工作。其外部契约因此不是隐含实现的聚合和传递依赖,多重实现可以同不同的依赖共存。接口是方法的命名集,用于合适实现和用户之间的契约。
我们关注组件的时候,接口本身粒度很低,因为组件的粒度要比类大。取代一套方法(接口),一套类型是组件更为固有的契约,因为可以在软件契约中组件化不同角色(服务器、事件监听器、域类型等)。类型命名集本身是组件间更为安全的具体契约粒度。
Java已经具有类型命名集的概念,称之为封装。封装本身就是适合组件契约的自然属性,因为在很多JSR和开源项目中,它已经作为具体的契约来使用了。最好的是,封装已经和Java类型系统完全集成。间接地满足了当今软件系统架构解耦和灵活性的需求。
基于模型依赖的组件封装可以提供很多封装,并且可以消费很多封装。就像类可以实现很多接口并使用很多类型一样。封装可以为组件提供类似接口组件的好处;允许组件优化实现选择,而不影响其提供的契约。
OSGi提供了Jigsaw所使用的直接的组件到组件的依赖(Require-Bundle),以及类似接口的封装所实现的(Import-Package)轻量型耦合。长期OSGi用户一关于Import-Package的优势,所以害怕Require-Bundle的长期破坏。
经过多年的经验,我们知道封装导入工作比在系统中请求bundles好得多。不幸的是,我们缺少语言来向人们解释,而人们对于这种类型的模块化缺少经验。在C(++)之后开始学习Java的人,可能记得他们第一次看到接口的时候觉得多奇怪,新概念很难解释。也是最近我才明白封装实际上为类执行了接口起到的解耦作用;这个现在提供给了一种语言可以用来向Java用户解释OSGi。
所以,如果太多的狂热分子加入到Java模块化的谈论,我理解。但是说实在的,如果有人建议从Java中移除接口,你感觉怎么样?
我们一直都在努力坚持原创.......请不要一声不吭,就悄悄拿走。
我原创,你原创,我们的内容世界才会更加精彩!
【所有原创内容版权均属TechTarget,欢迎大家转发分享。但未经授权,严禁任何媒体(平面媒体、网络媒体、自媒体等)以及微信公众号复制、转载、摘编或以其他方式进行使用。】
微信公众号
TechTarget
官方微博
TechTarget中国
作者
相关推荐
-
云计算与SOA组件之间属于互补还是互斥?
在SOA和云计算环境中,我们假定应用程序组件化后都能达到最高工作效率,并且通过组件化处理,按照逻辑标准,SOA和云计算会变得非常协调。
-
Java模块化项目Jigsaw能否重回正轨?
模块化的粉丝们会很高兴的听到这一消息,Jigsaw项目已经重新提上日程,至少也是部分回到了正轨。
-
OSGi中该使用Blueprint还是声明式服务?
在OSGi中,服务是实现bundle间交互和应用灵活性的基石。借助于服务,我们能够降低bundle之间的耦合,更加有利于软件的重用。
-
OSGi中的服务模型与扩展者模型
在OSGi中,实现bundle间交互和扩展性有两种常见的方式,也就是服务模型(service model)和扩展者模型(extender model)。