宋黎晓的空间

我们一直在努力....

关于组件化系统如何实现的一点想法

标签: 业务组件 组件化开发 业务平台 组件化
        组件化的业务系统架构观念据说已经提出来20多年了,可是至今没有见到让人信服的组件化业务系统(注:组件化≠模块化).关于业务组件是什么,长什么样子,如何实现,又有什么样的远景? 大家也都做了很多思考和讨论.
看了社区里的一些内容,再加上平时跟同事们的交流和讨论,对组件化业务系统的实现产生了一点想法。下面我说下我的想法,欢迎大家来拍砖讨论。
        我觉得目前大家对业务组件有一个共识:就是各个业务组件相对独立,并且具有可组装性和可插拔性。
        每个组件的运行仅依赖于平台或者容器,组件与组件之间不存才直接的耦合关系。同时,组件与组件之间又并非绝对的独立。组件经过组装后可以与其他的组件进行业务上的交互。比如销售组件与财务组件,一笔销售业务的完成必定会产生一笔或几笔财务的业务,如销售发票的开出和一笔新的应收应付或者现金银行的记账。又比如,采购与库存管理,当采购的需求被提出,那么是不是要先看看仓库是不是有存货呢?如果本仓库没有,是否允许从其他仓库调拨呢?等等等等……,诸如此类的业务场景无法穷尽,而不同行业不同规模的用户他们的业务过程又各自不同。
        也就是说,组件之间的交互在业务上存在着不可规范和不可穷尽的特点.这是个比较头疼的问题,暂且记下,稍后再做讨论。
        另外,我的理解:组件化是介于模块化与应用系统集成之间的一个概念.关于组件化、模块化、应用的不同,社区中的一篇文章写得很好。这篇文章的最后,提到了组件化不同于模块化,引文:模块化开发不同于组件开发,模块化开发只是在逻辑上做了切分,物理上(开发出的系统代码)通常并没有真正意义上的隔离,一切都只是在文档中。文章中间也提到过组件化与应用集成的不同,引文:EAR或者WAR部署的是一个企业应用,请注意EJB规范中明确说:The Enterprise JavaBeans architecture is a architecture for the development and deployment of component-based (distributed) business applications(EJB 2.x和3.x唯一的区别是2.x有distributed),它们有自己的应用域,彼此相互隔离(简单的看,它们有各自独立的会话管理)。.NET也是有自己的应用域概念。
        根据上面所描述,结合我把组件化放置到模块化和应用集成之间的定位。组件化应比模块化更独立,但比应用集成结合得更加紧密。借助上面提到的那篇文章分析的,引文:基于应用的部署导致了三个隔离问题:交互(界面)隔离程序访问隔离数据隔离.来看看组件化、模块化、应用集成的区别,以更清晰的看清楚组件化的位置。
  用户交互(界面) 程序访问 数据
模块化 统一 模块间直接依赖访问 统一存储
应用 独立 对外部开放访问接口 独立
      
         组件化既然是介于上面两者之间的,那么这三个方面又该如何定位,如何实现呢?
        1. 界面交互
        我认为用户交互应该统一,因为组件化的各个业务组件最终拼装成同一套企业应用,UI作为用户操作接口,必须看起来是统一的而不是独立的。这一点与模块化实现的各种系统类似,虽然属于不同的模块但用户界面使用起来始终如一。另外,开发和部署上我认为应该根据组件不同来分离。
        于是矛盾出现了,既然要看起来统一,又要可以分开来开发,可以分开来部署。首先如何保证不同的开发小组开发出的界面风格一致。其次分开部署使用什么手段整合到一个界面中呢?
        针对第一个问题我们可以模仿模块化开发的经验,复杂一点:使用统一的UI工具开发;简单一点:也可以基于约定。至于UI整合的事情我们可能需要有一个门户组件来搞定了。
        2. 程序访问
        这个问题比较纠结。
        基于“组件仅依赖于平台运行,而不依赖其他组件运行”这个前提.组件之间的交互就不能像模块化那样直接访问。那么像应用集成那样开放访问接口如何呢?
        我认为也不妥。为什么呢?让我们想一下系统集成发生的场景。某公司已经有一套某业务领域的系统,现在又要上另一套其他业务领域的系统。当这两套系统在业务上出现了交互时,找来两套系统的开发商,制定方案,进行二次开发,彼此开放接口修改程序相互调用。从这里我们可以看出,这种方案首先从诞生的那天起就是一个出于无奈的方案。注定被结合的两方不够紧密,其次开放访问接口存在一定的安全隐患。另外,加上我们前面留下的那个难题:“组件之间的交互在业务上存在着不可规范和不可穷尽的特点。”这样的集成方案是不是不适合我们的组件呢?首先,组件之间会存在如此频繁复杂的交互,我们需要更紧密的结合,或者说是无缝的结合。另外,我们在开发组件的时候,不可能预想到那么多的其他组件它们期望从我们这里得到什么,我们不可能事先为它们准备那么多的服务接口。
        那么程序间的访问,又有什么样的介于模块化和应用集成两者之间的方案呢?这个平衡点在哪里呢?我有个还不太清晰的想法,这里提一下,大家来拍吧。
        先说一下常规的方案.比较常规的想法,可能多数人(包括我)会想到引入总线,或类似于主板和插槽的概念,把我们的组件插上去,组件与总线结合,通过总线与其他组件实现交互。这样做确实能实现交互和通信,可我总觉得这样的方案不是最好的,组件的结合还是不够直接不够紧密,依然存在我们无法穷尽哪些服务需要提供给总线,供其他组件调用的问题。而且,既然是总线就有类似于带宽的问题,当业务高峰期,组件间的交互频繁,势必会发生拥堵,带来效率问题.
        我认为我们需要更灵活、更直接的组装结合.
        我们来创造一个“粘合层”或者“胶水层”怎么样?由“胶水层”来负责各个组件之间的交互和粘合问题.组件的组装,我们经常比喻成搭积木或者拼图。但实际上我们不能够像积木和拼图那样,事先定义出明确的尺寸大小和足够的插槽或接口,我们的组件实际形状是比较灵活的、形状不一、大小不一的。对于这样形状体的组合,我认为使用强力“胶水”来粘合比较合适。当我们选定了两个组件,并要将他们联合起来使用的时候,我们在中间涂上一层“胶水”把他们粘合起来,“胶水”实际是一种导体,它作为信息传输的介质,在两个组件中进行程序的调用和数据的传输。某一个组件可能会与多个组件进行结合交互,我们在它们之间分别加入“胶水”进行组合,使他们之间各有单独的组合介质,而不是统一通过唯一的总线。这样可以让组合更加灵活,交互更直接。
至于胶水层的实现问题,可能需要一些技术上的突破。需要进一步的探讨研究。目前考虑Python或者Ruby这样的动态语言。这里存在有诸如:事务控制,同步异步,并发控制等问题,也需要进一步研究。
另外,引入胶水层可能会对人员的布局产生一些影响。不仅仅有负责各种组件开发的开发团队,还可能需要有负责胶水组合的实施团队(这个实施团队貌似技术门槛有些高,我们可能需要考虑做一个工具来减轻这个团队的技术门槛,使之尽可能多关注业务,少关注技术。当然,对于经常组合的组件我们会积累下他们之间的“胶水”代码来复用)。
        3. 数据
        介于模块化与系统集成之间。我认为各组件的业务数据应该分别存储,各个组件数据库上实现大部分的数据自治。这部分自治的数据包括业务数据和元数据,至于主数据考虑使用冗余的方式,通过引入主数据组件来同步分发给各个业务组件。注意,这里我们叫做“主数据组件”,而不叫做“主数据总线”,表示其在系统中的地位与其他组件无异。
        关于查询和统计分析。简单的查询,数据仅涉及本组件内的,可以直接查询本组件内数据库获得。一些跨组件数据的查询或者报表、报告,考虑进行数据抽取进入BI组件,利用BI组件进行分析。          
        我简单画了一个基于业务组件的系统的布局图,也顺带提一下关于容器的事情。

        每个容器内可以部署1-N个业务组件,容器可以有多个(注:容器≠物理服务器,一台物理服务器上可以有多个容器)。组件间的程序调用通过胶水层实现粘合,与本容器内或其他容器内的组件进行交互(胶水图上不好画,就不画了)。这些组件中包括我们的功能权限组件、数据权限组件、主数据管理组件等一些我们常称之为系统级组件的组件。另外,需要有一个对用户的出口,必须有一个容器上需要部署门户组件。门户组件将其他业务组件的操作界面嵌入到用户页面中,提供一致的人机交互出入口。
        上面这些只是些想法,尚未形成实际的方案,这里先发出来抛个砖,大家集思广益一下能扔块玉回来就最好了。
 
        提供该文档的机构为 OECP社区,更多的博客文章可以到 OECP社区查看。该文档附件欢迎各位转载,但是在没有获得文章作者许可之前,不得对文章内容或者版权信息进行更改,版权归OECP社区所有,仅此声明。

附件:


    评分: 请先登录再投票,同一篇博客一月只能投票一次!
    1人投票,平均4.00分

相关博客:


评论

谭明智 2010-10-22 23:04:15   回复
非常好,我们就需要这样详细的,深刻的,独特的理解。只要大家都积极的去思考这种模式,提出相应的思路,我相信业务组件的工作才能很好的进行下去,而基于业务组件的生态链就能很好的建立起来。
游客 2010-10-23 10:25:13  
分析的很好,有点像SOA、web服务,esb等,但它们好像还像云一样在天上飘着,博主探索的是实际应用,更深层次更新的业务事务处理架构吧。
张东丰 2010-11-10 17:06:03   回复
这篇文章写的非常好,很系统,比较全面,拜读了。我谈一点自己的看法。业务组件只是操作级的,不涉及到管理级的报表和复杂查询。应该只是单据级的查询和关联查询。对于组件间的数据交换,我还是倾向于总线方式。通过总线缓存数据,统一单据格式,每个独立的业务组件需要数据时直接到总线去取,组件中的接口只要针对总线设计就可以了,减少了组件间的相互依赖和耦合。BI可以从总线直接提取数据做查询和报表。这只是我的观点,欢迎拍砖。
李挺 2010-11-10 20:47:14   回复
每个独立的业务组件需要数据时直接到总线去取,组件中的接口只要针对总线设计就可以了
------------------------------------------------------------------------------------------------------------------------
的确,总线实际上是一个很大的类似工厂的服务层,比如销售组件取财务组件的客户信用值这一规则,都不是直接访问财务组件,而是向服务层发出请求,服务层中注册着许多服务,服务是属于组件的,数据块也是属于组件的,两个组件中有相同的数据拷贝,是冗余性设计,镜像级,总线是管理层,不仅可以进行数据复制,还可以包括定时器、任务和工作流等引擎。
谭明智 2010-11-10 22:44:25   回复

面向服务的体系架构(SOA)和业务组件(BC)的思考
这篇文章从JavaEE平台上详细阐述了业务组件是如何架构,如何实现的,写的非常好,理解的非常到位,也和我们的思路不谋而合。我认为这篇文章阐述的两部分是构建业务组件系统核心。
1、OSGI(分离组件)
2、企业服务总线(组合组件)
业务组件以 Web 服务的方式提供接口,通过企业服务总线连接,业务组件内部为了实现高可复用性和高效性,采用基于 OSGi 标准进行构建模块,实现内部模块之间的松耦合,即在业务组件内部基于 OSGi 标准进行模块化设计,将业务组件进一步分解为松耦合的模块(Bundle),使得业务组件本身更加灵活。
 

宋黎晓 2010-11-11 17:14:35   回复
有砖自远方来不亦乐乎 ,先谢谢大家的意见。呵呵。
看了大家的回复,我也考虑了下。比较争议的地方主要集中在程序间调用这块。
不可否认,总线是一种比较常规的交互方式,这点是通过项目检验可行的,并且IBM这样的大软件商也有ESB这样的实现。总线式的解决方案是主流。开发一套业务系统,我也会首先考虑这种架构方式的。
胶水层这种想法起初想到,是一种模拟现实世界的思路。我觉得组件间更希望得到一种更为直接的交互方式。可能一两句说不清楚了 呵呵。我再写一篇说说这个想法的由来吧。
不过至于这种想法的实现,没有前车之鉴,实现的难度和可行性,确实存在问题。这个我严重承认!!
游客 2010-11-12 13:59:39  
网状结构与总线结构的优缺点不言而喻,主要是看你看重的是哪方面。是可管理性、可维护性还是执行效率。对于客户信用的处理,我很感兴趣,我觉得它非常具有代表性。客户信用的计算涉及到多个组件的业务数据,它在整个架构中的位置对架构的影响非常大,处理的好,结构会清晰,数据流也顺畅,如处理不好则会导致混乱。李挺谈了他的观点,我觉得大家都来谈一谈看法,看类似的功能要怎样安排。李挺,是我认识的那个李挺吗?
张东丰 2010-11-12 14:18:20   回复
上一个评论是我张东丰写的,不知怎么成了游客。
宋黎晓 2010-11-12 17:14:10   回复
  “网状结构与总线结构 ” 张东风先生这个归纳的很到位。一看就是行家,胶水和总线的事情我就不用多说了,否则有班门弄斧的嫌疑,呵呵。
        客户信用的具体算法,我没有具体研究过。刚才google了一下,算法挺多,而且行业不同适用的算法也有差异。不过这个不是重点啦。
        重点是一定牵扯到与多个组件进行数据的交互。
        销售订单完成时,要确认是否回款,确认回款时冲减信用额度。信用额度一般认为是CRM来管理的,但是回款确认是在销售组件中的一个动作。
昨天与同事王亮讨论组件间的代码交互的形式主要有哪些?我们总结了3条比较常见的:
1.取数(取一个数,或者取一组数)。
2.推送(某业务组件内一个步骤完成,自动形成下游组件的某种业务单据)。
3.订阅(一个业务完成后,发出广播,告知所有其他关注自己动作的组件,至于其他业务组件做什么,自行处理)。

        信用额度的更新,我认为是订阅式(当然信用计算过程中,CRM有可能取财务数据,还有可能再回来取我销售的数据,这部分算做取数)。这种业务场景比较典型,总线和网状的实现也是各有优劣。总线的管理维护比较清晰,网状则比较直接。

        关于信用额度在系统中所处的位置,个人认为还是由CRM来计算和管理,这个计算的触发点在销售回款的确认。
        另外,计算的结果还需要同步到主数据模块客商档案中,而后分发给各个订阅此数据的组件做冗余(如:销售)。这样销售组件使用信用额度时就可以直接从组件内的档案中取数了。

这种设计方式是否合理请大家讨论。嘿嘿

张东丰 2010-11-15 10:03:14   回复
如果假定这样一个前提:业务组件是操作级的。那么关于组件间的业务数据的同步,我们来分析一下:1.数据流量很小,因只是单据的新增或变更;2.采用异步传输,这样不会因为组件间的通信妨碍业务的操作;3.采用2维XML格式传输,这样可以屏蔽相互间的数据结构差异;
我觉得这是通用的规则,具体实现时需要根据实际情况详细的设计同步机制。但有一点,如果我们的业务组件推崇的是自治,则每个业务组件的实现应该与具体的数据同步机制无关,或关联越小越好。
关于是否使用数据总线我在这里再谈点看法。对于一对多的业务关联,使用总线结构可以很好地解决;另外如果考虑到与异构结构的集成,采用总结结构可以将这些差别丢给总线,使业务组件可以不管这些架构上的差异。所以我还是推荐采用总线结构。

发表评论

关注此文的人们还关注