浅谈企业应用架构(二)
?
开发式编程
声明式编程
产生式编程
开发手段
编码。
如:Java, C#
解析。
如:ANT(spring等的xml不一样,它们是静态描述型的,不那么verb)
生成。
如:AOP(AspectJ),DSL—rools)
开发性质
聚合
声明
组合
代表事物
接口
N/A
DSL
自然语言的表达能力很强大,虽然说有时具有二义性,但是在特定领域下是确定的,既然是讲DSL,那都是特定领域相关的,一定是明确的。
基础设施
?解析器;
编辑器,如jbpm;
元模型;
生成器;
正统的需要编辑器;
元模型
开发方式
?自上向下,声明式编程是解析概念,用统一的概念来理解,把不同差异性交由具体程序解析;
编辑器生成的是xml文件,将由框架程序解析;
声明式是粗粒度的(不能直接比较大小,定义的是无差异性的概念);
自底向上,产生式编程用的思路是组合概念(用小粒度的概念组合生成大粒度的概念);
产生式生成程序代码,不做解析运行;
产生式是相对细粒度的;
???
E. 小结
通常语言作为架构的基础,语言的设计带来的好处远远高于框架和模式,但其引入和更换也是有巨大风险的;而通过提供强大的框架能力,框架尽可能多的完成技术问题,并通过元数据,模式以及约定降低业务和框架的耦合。避免因为框架升级带来不必要的成本。
Meta Programming的最高层次是语言级别直接解决,比如,Smalltalk, Ruby, Python, 还有其他Reflection支持的非常好的语言。甚至STL等template技术,也可以算作语言级别。 Code Generation 是最低级别的Meta Programming解决方案,技术含量也最低。这个级别必须超越,才能够真正达到质变,完全跳出概念炒作的层次。
从技术手段上,提高开发效率的另外两个手段是代码生成和类库引用。但代码生成和类库引用,都只解决了逻辑的分解能力,没有提供集成能力,所以一般情况下需要提供框架集成,尤其代码生成需要在系统的最外层,避免集成带来的问题。
代码生成也没有那么坏,关键在于生成什么,如果是生成结构性的代码,由于往往不是最终的产物,就存在同步维护问题;同时这种代码是大都可以用template完成的。
但如果生成的是功能性代码,这类代码是最终执行代码,那么通常就把用于设计的代码看作是最终产物,最明显的例子是DSL。
(二)核心问题
1. 领域化
领域化,即领域建模。通常而言,领域模型设计中,模块分解,抽象分层和职责分层都是重要手段。问题域为:流程,领域模型和领域服务(包括规则)。
a. 对象的抽象分解和集成
b. 对象的依赖分解和集成(模块内和模块外)
c. 流程的分解和集成(页面流,工作流以及计算流程)
d. 进程边界:用户请求重定向,以及业务数据持久化等。
对于中等项目来说,系统中应该有50-100个领域对象代表了业务抽象;
2. 组件化
面向对象语言本身没有提供的组件级别的依赖关系集成能力。语言不提供,因为领域组件的粒度太大,超越了语言的范畴。但我们可以通过框架提供,在Java体系中,目前已经有两个较好的解决方案:OSGi(JSR291)和SCA。可以很好的解决组件服务依赖关系管理,包括热替换。
同时另一个问题——逻辑分层的问题:如保险产品面临的核心层,国家层以及公司层三个逻辑层次分解和集成能力。这点的解决方案可以通过OSGi + Spring来解决,包括了静态差异性替换和动态差异性替换。
还有组件边界保护问题,我们希望限制别的组件访问本组件内部实现,有两种手段可以完成,1是提交/部署时,通过在代码提交时的代码检查工具,或者发布时编译工具完成;2是通过OSGi的边界限制能力。
3. 产品化
A. 定制化支持
领域定制化涉及到逻辑替换问题。逻辑的替换根据开发方式不同,有两种类型:基于接口和基于继承;
A. 基于接口(包括了静态替换和动态替换)
1. 静态替换是Override,在OSGi中只要停止原有服务,启用新服务即可,而在Spring中更改相应配置文件即可;
2. 动态替换,其实是指运行时Condition Service Locator,在OSGi中可以利用Extension Point(Plug-in)解决,而Spring中只要提供一个类似Service Locator就可以。
B. 基于继承(或者静态类)
1.开发时,直接修改源代码编译;
2.编译时,采用AspectJ,在编译时提供替换;
3.加载时,开发一个新逻辑的同名类,但其加载路径优先于原有类;
B. 升级支持
主要是增量升级支持,以及有限的降级支持。同时要考虑到对于定制化产品的升级支持。
4. 平台化
A.基础设施
基础设施包括:类库和框架。基础设施可以自己开发,或者应用第三方(开源商业)实现。
A1. 基础设施的选型
应考虑几点:1. 商业角度的可维护性和可升级性;2. 组织的学习和管理能力;3. 基础设施自身功能以及所支持的开发效率。以下是详细要求:
客户角度
成熟度要求
基础设施是业界成熟方案;
性能要求
基础设施满足系统运行的性能要求;
稳定性要求
基础设施版本稳定,经过大量测试;
环境性要求
基础设施不会带来额外的软硬件兼容要求;
管理角度
开发成本要求
基础设施的开发维护成本低,最好是业界成熟开源成果;
开发效率要求
基于该基础设施的应用开发效率高;
维护成本要求
分析设计与开发之间的衔接性好;
测试成本要求
基于该基础设施的应用测试成本低,效率高;
培训招聘成本要求
网络上的参考资料丰富性;基础设施的流行度;
内部员工学习培训成本低; 招聘外部员工成本低;
A2. 基础设施的集成
基础设施独立后,出现平台化的发展趋势,这个趋势有两个方向:通用化和专业化。通用化意味着基础设施和应用的距离加大,易用性减低;而专业化意味着适应性的减少。这是一个矛盾体。在基础设施选型后,再进行一定集成工作,可以结合当前情况,平衡易用性和适应性;同时合适的集成也有助于隔离技术和业务两个方面。
从维护升级角度看集成的合适性:对于没有标准的,不要做不必要的封装,封装等于是建立一个标准,而这是不现实的;应当尽可能采用框架方式,屏蔽基础设施对于应用程序的侵入性。如果是标准,就更没有必要封装,画蛇添足。
B.业务支持
B1. 基本原则和手段
基本原则是:应用程序POJO化。减少技术对于业务侵入性。主要手段是:容器上下文;依赖注入;AOP技术;元数据支持;事件机制;开发工具和代码生成;
依赖注入+AOP+元数据构成了简单对象(POJO)的支撑技术。基于此三位一体的技术可以有效的隔离业务问题和技术问题,更为甚者它可以支撑简单对象体系,每个对象做且只做一件事。
B2. 开发模式与最佳实践
基础平台应该提供业务相关的模式封装。
B3. 关于元数据
元数据有多种:语言级别为Annotation(微软.NET为Customer Attribute);框架级别可以是XML文件或者其它配置文件。
元数据可以通过以下几个视角观察
1. 应用层次:元数据代表了业务含义和技术含义;
2. 技术分析:文档类型(开发管理型);编译类型(类加载型);运行期行为。
3. 物理分析,包括Annotation和接口,XML文件,甚至是EL和类。
元数据系统的建立其实是代表了认知过程。
以运行期的元数据为例,代表了系统通过反射获取相关元数据来自适应系统,其实际意义在于将软件设计开发人员对于系统的认知通过技术手段固化下来。
元数据系统的开发目的有两个:
1. 业务应用上,提供业务动态能力;
2. 技术应用上,简化开发减低成本;
这里面有一个误区是:为了技术应用而过分地开发元数据系统,而随着业务的演化导致为技术应用的元数据迅速被抛弃,导致投入的浪费。实践中要避免。
???
(三)应用问题
1.事务管理
A. 成熟的事务技术:如数据库;
B. 合理的并发设计控制;
C. 完整的业务日志;这也是解决业务回退的主要手段;
D. 辅助的数据校验能力;
并发设计控制和完整的业务日志,是架构设计中保障数据一致性主要着力点。并发设计控制,需要结合业务,通过悲观锁定来保障。
而业务日志的获取则面临着诸多困难,主要是业务事务和物理事务的不一致性(即一个业务事务可能横跨多个物理事务,也可能一个物理事务包括多个业务事务);业务日志控制层面有两个:应用系统或基础设计;通过应用系统编码控制,则不可避免的提高了应用系统开发和测试的成本;通过基础设施控制,有助于减低成本,但提高基础设施的设计成本;
?
?
1 楼 liujunsong 2009-05-06 太复杂了,看不懂 2 楼 funnywiser 2009-05-06 真想不到能见到理论基础这么深厚的作品。我们一直都在做类似的产品,最终结果发现其实和上面将的理论目标是一致的。只是我们考虑的没有那么深入。
好好研究一下,又翻了一下楼主以前的帖子。发现
http://www.iteye.com/topic/19111?page=1 这里讲的需要实现的功能就是我们现在现在已经实现的功能。
总算找到了公司产品的知音了,我们就觉得自己的产品好像规则引擎,又不和Ilog等算法差异很大,原来也有人和我们一样,放弃了推理功能。
我们的产品是VisualRules,就是这样实现的。
不知你们提供了什么产品出来没有,有机会交流一下。向你学习学习!