解决侵入的根本方法讨论?最近又看到一些关于框架侵入性的讨论, 有些想法, 谨此抛砖引玉.我觉得软件开发框
解决侵入的根本方法讨论
?
最近又看到一些关于框架侵入性的讨论, 有些想法, 谨此抛砖引玉.
我觉得软件开发框架之所以跟侵入性纠缠不清, 根本的原因还是框架要支持应用的某种/某些逻辑和功能, 可以说是部分的去实现应用的目标. 但是这些功能如果不能让应用去定制, 其现实应用代价就又很微渺了. 所以框架是需要和应用交流的, 而交流的主要目的是为了定制.
想到这个地方, 我的反应是声明式编程, 让应用通过某种方式表达出自己的定制需求, 这个表达的方式就可以是多种多样的了: 通过遵循约定, 继承特定框架基类, 实现特定框架接口, 标注Annotation, 编写配置文件, 调用框架API, 等等.
而像Java这样的静态语言所能支持的表达方式, 无论怎么看都可以挂上 "侵入性" 的标签, 因为如果框架一旦定了它要求应用采纳的方式, 应用就得跟着它走. 在应用需求表达方式问题上, 框架之间的相容性既没有理论研究, 更没有实践习惯.
这里提到 "框架的侵入性" 好像用的是它最宽泛的涵义, 就是对应用编程行为的影响. 要是这么说任何框架都不可能没有侵入性了, 只是有些让应用开发人员的日子很难过, 有些则好一点. 不过以目前的软件体系局势来看, 绝对的 "侵入性" 问题还没有办法解决, 更现实一点, 似乎只有它对单元化开发和测试的影响比较有可能解决, 眼下讨论才比较有现实意义.
不过对下一代软件框架体系, 我倒是感到有些期望, 随着Annotation的成熟和普及, 对于基于Java的开发来说, 我觉得这个趋势已经临近了. 我的想法是可以运用一下逆向思维, 既然应用与框架的交互无可避免, 那么与其被动的接受框架的 "侵入" 不如由应用自身采取主动行为, 进行 "引入".
应用的主动引入可以从已有的 声明式编程 出发, 对于比较大的综合应用方向, 比如 Web应用, 以制定通用的应用需求表达规范为手段, 通过公开的规范, 协调应用程序和系统框架之间的交流. 这听起来就是JCP要为JavaEE做的事情, 是的, 以截至到目前的软件体系局势, 这个事情还不得不由人力, 物力, 财力丰厚的商业实体去完成, 它们也必须在这个领域有足够的商业利益吸引也才有动力去做.
但是同样是JCP出来的J2EE规范, Servlet很成功, 而EJB却不是. 并且Servlet很好的解决了它那个年代的Web开发问题, 而软硬件的发展所推动出来的新需求, 新问题又飞快增长, 对新规范的需求不仅是本身增长很快, 它的增长速度也会随着时间增长. JCP已经开始显得笨拙且乏力了.
一个本质性的问题是: 目前的规范是基于少量编程语言API的大部分的自然语言描述. 基于这样的模式, 成本太高, 就算是目前的大型开源社区要开发自己的体系规范也会是难上加难.
在这个方向上, DSL(Domain Specific Language)是个很好的创意, 可以有针对性的简化专门领域的规约方式. 不过, 我觉得还有DSL没有特别关注的一点, 就是同一种语言中声明与实现语法的分离与融汇:
? DSL倾向于作为一种声明式的语言, 被设计为独立使用, 它很可能由另一种通用语言进行解释而实现. 它的语法很可能可以直接调用实现语言, 但很难变成编写应用所用语言的一部分. (我很期望它变成应用代码的声明部分)
回到解决侵入性的问题上来, 我设想的方式是目前还没有的, 至少还没有系统化. 那就是可以用一种语法给应用编程语言增加用于声明的语法, 同时这种语法也照顾到给应用声明的需求提供实现的系统编程语言语法, 从而这样的语法可以同时 表达/约束/支持 应用声明和系统实现.
看上去动态语言在这个方向上有最深厚的长远潜力, 不过用于有分析需求的通用工业开发领域, 动态语言要走的路还有点长.
目前基于Java的开发, 利用起Annotation机制会在这个方向上有长足进展, 应用通过引用标注来声明需求, 系统在编译时通过Annotation Processor以及Language Model, 在运行时通过反射, 两者结合起来去理解和实现应用的需求. 而定义和引用Annotation都受到新增的Java语法约束.
不过基于Annotation机制的 应用/系统 交流有时候还是需要一些自然语言描述的规范, 好在这个已经比纯粹描述/理解大篇的约定和接口调用逻辑顺序简易多了. 同时Annotation引用只能放在modifier的位置还是一个过大的约束, 这个还需要Java语言进一步的演进去解决.
总结下来, 系统框架通过 "侵入" 要达到的 应用定制 目的是不可避免的, 而要解决被动的受到 "侵入" 的局面, 我所能想到的最好方法就是去主动 "引入". 而 "引入" 所能达到的 "主动" 程度取决于其方式方法的灵活程度和负面影响大小. 当应用的特定需求可以通过统一的(声明)方式利用大多不同系统(包括测试时的Mock系统)而实现时, 应用的 "引入" 行为也就达到了一个比较理想的主动程度, 从而可以视为没有被特定系统 "侵入" 了.
框架.registerComponent(MyComponent.class, "请用initService1()来设置service1的依赖")
这里用的是自然语言来和框架交互。事实上框架当然不会这么聪明,肯定是要用某种框架理解的api来和框架交互。但是基本的意思就是这样,对MyComponent完全无侵入。
其实,这和用xml配置文件来配置没有本质区别。于是,又回到了原始的“xml配置也是侵入”,“框架理解的api也是侵入”的悖论。
而且,这种配置从实际角度不见得有通过annotation侵入MyComponent来得方便。
spring对这类非标准的问题的解决方案和我提的不同。它回避了困难,放弃了“无侵入性”的目标,转而用侵入这个万应灵丹来解决问题(BeanFactoryAware等等)。可以看作一种折衷吧。
对此,我要说的有两点:
1。在组建级别的侵入和在和框架集成部分的侵入本质上是不同的。和框架集成的地方侵入是自然的。或者根本不能叫做“侵入”。叫“依赖”可能更合理些。
2。考验功夫的就是这个xml配置或者api是否很麻烦。框架的目标应该是这部分做起来很简单,而且还足够灵活。如果它足够简单(搭配上convention over configuration),花在集成部分的工作量可以忽略,那么就可以在方便性上和annotation的declarative方法媲美,而且从侵入性上又优越,那么无论理论还是实际都可以站得上风了。不幸的是,spring这点上作的不好,配置文件繁琐地让人根本不敢考虑移植问题。而acegi之类的框架又走回了框架侵入的老路。当然,这并不妨碍spring的成功。(或者甚至有所帮助?)
这个想法, 不知道 ajoo 是什么看法?
这个想法, 不知道 ajoo 是什么看法?
我和你的看法不太一致。
一个框架到底定制能力要多强,这很难说,而且很容易陷入过渡设计或者设计不足之间的两难。
当然,通过侵入确实可以实现一些方便的定制,但是,几乎必然地,它同时也会影响一些其它的定制。只不过我们可以争辩说侵入实现的定制是有用的,而它妨碍的是你根本不需要的之类。
我对“侵入”的反感更多的是一种先验的哲学化倾向。本能地我就反感侵入。
今天看佛本,看到“圣人不死,大盗不止”。一个框架如果自以为是地说“我的侵入是为了给你提供方便性1,2,3”,在我看来这就是一种“自以为圣人”的倾向。
当然,现实中,有的“圣人”做的很失败,如ejb。而有的圣人则作得很成功,如spring,拥有大量的圣人门徒(acegi等)。
基本上,“圣人”就是说:放下你的锄头,跟我走,永远不要背叛,你就有福了。你要泡妞?一个好人不应该这么想的。你要在公共场合拉屎?你不觉得羞耻吗?
我认为好的框架不是这种圣人式框架,而是那些甘愿谦虚地作为一种工具,它不对你的编程方式作任何指手画脚的框架。
没有侵入性的副产品,是定制性几乎无穷,你愿意怎么使用这个框架都可以,即使是匪夷所思的方式。比如,你愿意拿砖头来磨成粉末然后放到烤箱里面去烤,可以,做就是了。框架并不需要弄个Grindable, Bakable接口来特地“支持”这个定制(当然,圣人的门徒会说,除了圣人提供的定制性,其它的都是你绝对不需要的。你为什么会想磨砖头?有病?),再就是你可以任意组合这些框架,你的生活你做主,这些框架只处理自己职责范围内的事情,绝对不会互相打架(当然,如果你的圣人说,你只许相信我,不许根别人钩三搭四,那就没办法了。实际上很多圣人系统的代价之一就是你不能随便和别人搭讪了,或者搭讪的代价比较大。看看那些“spring integrated”的广告语吧。难道一个组件不是天然就可以用在IoC容器里面吗?什么时候开始“IoC容器集成”居然也堂而皇之地算一个可以吹嘘的特性了?)
另一个考虑,是自恰性。很多有侵入的系统不是自恰的。比如spring里面,你的对象可以实现任意接口,
除了以下几个:
BeanFactoryAware, ApplicationContextAware, BlahBlahAware (本列表持续更新中)
你可能觉得没什么阿。也许吧。反正我写和spring的集成代码时就很头疼这个持续更新的列表。如果明天spring又加了一个YetAnotherAware的marker interface,我还要回来增加一个"if(obj instanceof YetAnotherAware)",crap!
就像我们现实生活中没有人会用到String[][][][][]这种类型吧?我也没用过。但是如果某位圣人作了一个语言或者系统,然后告诉我说String[][][][][]被用作一个特殊的用途,我不能用,我也会觉得不爽的,非常不爽。特殊规则是对一个系统的美感(即使没有其它实际意义上的缺点)的严重伤害。
当然,事实上到底是那种哲学更实用,老实说我不知道。
最早的时候连面向对象的指导思想都没有, 也没有系统程序员与应用程序员之分, 计算机也就是做运算, 比自动计算器强不了多少, 那时候用编程解决问题的主要手段就是设计一个适合的数据结构, 再设计, 利用起一些相应的算法, 最终解决的是一些 "运算问题".
后来这个行业发展飞快, 迅速的向数学以外的应用领域延伸, 于是软件被开始用于解决 "自动化管理问题". 大量新问题的引入严重增加了对编程手段的需求, 于是软件开发自然拆分为 "设计" 和 "编码" 两个部分. 算法和数据结构的作用在基本的编码问题以外能发挥的作用不大, "软件设计" 更像是新增加出来的工种, 于是专门从事软件设计的人把一些精妙有效的程序模板归纳总结成 "设计模式" 来加以利用.
不久以前计算机在一些领域(比如互联网网站开发)的应用产生了质的飞跃, 这方面的开发工作从设计原则到编码技巧都已经发展出了成熟的公众基础, 人们已经不再需要自己凭空探索就能从广泛的资源获得可以实际应用的指导原则和解决手段. 于是智力投入的焦点就转移到综合,总结一定的公众知识资源, 转化成可以直接运行, 直接提供一部分软件功能的可重用组件上.
这大概就是框架的来历.
链接库 给应用的只有一堆白纸黑字写好的接口签名和或多或少的说明文档, 应用按照这些库期望的先后顺序和逻辑结构, 通过调用的方式向库代码传递参数和执行控制权, 并获得它们承诺的结果.
通过 链接库 的方式使用第三方软件功能, 应用程序在执行控制上占有绝对主动权, 但在那些功能的实现和定制上却处于绝对的被动地位, 只能通过该库所提供的定制接口调用来显式的定制.
但是到了框架时代应用程序和第三方功能之间的关系发生了微妙的变化, 应用 和 框架 之间变成了协作关系, 框架实现的逻辑 不再像 链接库的逻辑 那样是预先开发好以后就一成不变的了, 而是拥有了对 应用逻辑 的适应性, 能够通过 定义接口规范 以外的一些途径, 比如 约定, 框架基类/接口, 配置文件, Annotation 等等进行为了完成应用目标功能为目的的接触和融合. 这些变化也为目前的 IoC 思维大行其道提供了可能的舞台.
从此也就诞生了 "侵入" 的概念, 我感觉可以大致理解为 "在软件组件接合方式上, 本无必要或者过份的要求" 的意思. 而目前的局势下还没有轮到 应用 可以在语法上给 框架 提要求的份儿, 所以 "侵入" 一般是讨论 框架 对 应用 的非份要求.
但是在编程要求方面, 框架对应用的这种 单边关系 在下一代软件开发体系中是有望改变的, 我的信心来源是 元编程 理论和实践的日渐成熟. 而理想的结果就是 应用 可以通过公认的声明方式提出自己对 框架 的要求, 而各种框架也能够在成熟的公共知识基础上找到简易的方式来解释和实现 应用 的要求. 这里去实现这些 框架 的简易程度是关键因素, 因为这时对框架的丰富性要求也大增, 比如同一套 应用需求声明, 这时已经不仅仅是须要有至少一个框架能支持它的部署和运行就够了, 其他比如在单元测试方面, 就需要另一套框架逻辑的支持. 在不同平台上对相同应用需求的满足也需要它们各自提供的框架能够容易实现.
那时候的框架也许会另有其名, 它们对应用需求的适应性比目前的 框架 是要更提高了一个级别, 如果以我一直在思考研究的 面向能力编程 的思想来命名, 可能会称其为 能力提供者 (Capability Provider). 15 楼 dovecat 2007-03-13 无侵入性框架,应该是,"你需要我的帮助?OK,那你什么都不用做,我给你提供.但是,你至少要告诉我,你需要什么?或者用来做什么?".这种完全服务性质的框架.关键就在于,这种"你至少要告诉我",这个告知的方式是怎样的.
很多是用引入框架的类或接口,稍微人性化点的则是使用xml或者其他配置文件(并不认为使用配置文件是一种侵入,侵入应该是在代码级别).
提供某种或某类服务的框架,不应该强制应用遵循或者执行某种条件来进行交换. 16 楼 抛出异常的爱 2007-03-13 无侵入就是把所有的单元全独立(一进口一出口)
但是如果所有的单元全独立管理又无法管理
好管理了又无法重用.....
根本方法是不重用
只要重用就得侵入
少侵入就扩大了适用面
但减少了重用可能 17 楼 coolwangyu 2007-05-08 如果框架从相对路径方面着手,会不会在侵入性方面有一点突破呢?
比如 某框架对某种定义的异常有特殊处理,那么我们的应用代码如果需要相关的功能就要被框架侵入。
那如果约定对相对路径:web-inf/classes/exception/*****下的所有*.class 自动处理此异常,也许在侵入上会有一点突破,不过还是有 xml配置的另一种说法而已。 当然只是想看看大家是怎么想的 ?
18 楼 抛出异常的爱 2007-05-08 越来越像ror了