三、架构的开发成本以及品质问题解决讨论
架构一个重要的关注点在于控制开发成本,这点很重要,因为通常讲维护成本是开发成本的3倍。降低开发成本核心,在于提高效率,这也意味着提高了开发对需求的响应时间,而时间对公司来说是重要的。
1. 问题域
问题域可分解为两种类型,业务上和技术上。(又见分解,分而治之真是老祖宗传下的灵丹妙药啊)
1. 业务上。问题域分解为,逻辑的纵向抽象层次,以及逻辑的横向模块分解和集成。
2. 技术上。问题域分解为,纵向的技术主题,以及横向的技术职责的分解和集成。
A. 领域基本问题
所以通常而言,领域模型设计中,模块分解,抽象分层和职责分层都是重要手段。问题域为:流程,业务实体和计算(包括规则)。
- 对象的抽象分解和集成
- 对象的依赖分解和集成(模块内和模块外)
- 流程的分解和集成(页面流,工作流以及计算流程)
- 进程边界:用户请求重定向,以及业务数据持久化等。
B. 领域组件问题
面向对象语言本身没有提供的组件级别的依赖关系集成能力。语言不提供,因为领域组件的粒度太大,超越了语言的范畴。但我们可以通过框架提供,在Java体系中,目前已经有一个较好的解决方案:OSGi(JSR291)。可以完美的解决组件服务依赖关系管理,包括热替换。
同时另一个问题——逻辑分层的问题:保险产品面临的核心层,国家层以及公司层三个逻辑层次分解和集成能力。这点的解决方案可以通过OSGi + Spring来解决,包括了静态差异性替换和动态差异性替换。
还有组件边界保护问题,我们希望限制别的组件访问本组件内部实现,有两种手段可以完成,1是提交部署时,通过在代码提交时的代码检查工具,或者发布时编译工具完成;2是通过OSGi的边界限制能力。
C. 逻辑替换问题
逻辑的替换根据开发方式不同,有两种类型:基于接口和基于继承;
A. 基于接口(包括了静态替换和动态替换)
1. 静态替换是override,在OSGi中只要停止原有服务,启用新服务即可,而在Spring中更改相应配置文件即可;
2. 动态替换,其实是指运行时Condition Service Locator,在OSGi中可以利用Extension Point(Plug-in)解决,而Spring中只要提供一个类似Service Locator就可以。
B. 基于继承(或者静态类)
1.开发时,直接修改源代码编译;
2.编译时,采用AspectJ,在编译时提供替换;
3.加载时,开发一个新逻辑的同名类,但其加载路径优先于原有类;
2. 基本手段
提高开发效率和品质的基本手段是分解——即充分的分离系统中不同的关注点,好处不用说了,可以并发的工作,每个人面对的问题都简单而容易操作。而与分解对应的集成,只有提供了好的集成能力,分解才成为现实,而只有分解了,才能清晰的提供业务更多适应性。
分解和集成的手段分为编程语言和技术框架两个层面。所谓语言就是强框架,而框架就是弱语言。
A. 语言
现代面向对象的语言提供如下能力:抽象和派生能力,以及接口隔离能力。实际提供两种分解和集成能力:
1. 把逻辑分解在两个层次中,而通过继承的方式把两个部分集成在一起。
2. 把逻辑的外观和实现分解在两个地方,而通过接口实现的方式把两部分集成在一起。
另一种语言AspectJ或者C#语言2.0之后提供的特性:把流程逻辑,分解在不同的地方,而通过签名匹配,利用代码生成的方式来把几部分集成在一起。
B. 框架
然而语言提供的集成能力,毕竟底层,而且有限,扩展起来也格外小心。因而技术框架提供另外的集成能力就格外重要:
1. 对象关联关系的分解和集成,如Spring提供容器管理能力
2. 模块间关联关系的分解和集成,如OSGi,ESB等
3. 不同系统的类型分解和集成,如Spring利用动态代理提供的Exporter模式。
4. 流程逻辑的分解和集成,如Spring Web Flow以及jBPM。
C. 设计
说起集成,就不得不提到一种类型的对象存在——VO对象。VO对象是为了集成而存在的;其意义是:1. 保护系统的信息边界,提供一种结构可以使其它系统或者组件通过编码方式获取系统内信息的方式;2. 保护系统的事务边界,领域对象技术上携带着持久化信息,通过VO可以屏蔽得以屏蔽。常见的VO对象存在于Web层和Domain层。
因此,VO对象的存在只是为了集成而存在,其是否存在的取决于框架的两个方面:对象路径访问能力以及事务边界管理。
Web层VO对象,以SWF为例,早在SWF 1.x时代,框架就提供了丰富的对象路径访问能力,但其Web交互是典型的MVC2方式,事务边界在view的render前关闭,因而导致需要特定的VO对象来避免持久化信息问题;而SWF 2.x时代,view的render是在事务边界内,VO不在需要。
Domain层VO对象,通常是用于不同领域组件间的交互,但随着架构的改进,集成代码独立存在而不再嵌入到组件内部,组件的边界问题保护不复存在;更进一步的是,框架提供自动化的接口适配映射能力的增强。因而VO对象也失去存在的意义。
BTW:通常语言作为架构的基础引入和更换是有巨大风险的;而通过提供强大的框架能力,框架尽可能多的完成技术问题,并通过元数据,模式以及约定降低业务和框架的耦合。避免因为框架升级带来不必要的成本。
3. 其它手段
从技术手段上,提高开发效率的另外两个手段是代码生成和类库引用。但代码生成和类库引用,都只解决了逻辑的分解能力,没有提供集成能力,所以一般情况下需要提供框架集成,尤其代码生成需要在系统的最外层,避免集成带来的问题。
4. 学习成本
对于开发团队来说,额外面临一个问题,组织内部的学习成本问题。
1. 需要保持分解以及集成能力本身的简约性
这个……其实是一个culture问题,不再罗唆!
2. 采用模式和约定是减少学习成本的另一种手段。ROR的兴起就是最好的例证。
成本还表现在组织的划分上,应用开发/框架开发,而在每个层面又划分为横向模块划分。
总结一下,解决架构面临开发成本问题需要如下几个方面:
0. 问题域
1. 分解与分层
2. 架构与类库,Spring,Hibernate。起支撑性作用。
3. 模式和技巧
4. 领域模型
5. 方法论
5.1.开发方法:OO(设计模式),FP(函数式编程)。
5.2.设计方法:Domain Model Prototype和业务行为的分析模式。
5. 质量问题
架构面临的品质问题,则通过自动化测试,代码检测工具来完成。
必须大量应用自动化测试,减少人工硬调试的复杂性,重复性和不确定性。
自动化测试包括单元测试和集成测试。无论是单元测试还是集成测试对面临需要脱离隔离依赖关系并保证开发的并行性。
单元测试面临的项目执行问题:
5.1. 设计的粒度问题。设计的粒度大小将直接决定单元测试的难易程度。开发分工如果是设计和开发两种角色集一体的,问题自我消化;但如果是分开,就会带来一些分工认识问题。
5.2. 遗留系统风险。遗留系统通常依赖关系复杂,设计结构以及粒度也不好,同时缺乏既有测试用例。在遗留系统维护成本很高,为了满足测试用例,通常需要对遗留系统重构,风险很高。
5.3. 测试用例评估与考核。测试用例不是越多越好,通常系统重构也会导致一些测试用例被抛弃,过多非核心用例反而是在重构中带来成本。因此对于测试用例进行评估成为一种必要,评估的标准较难确定。
5.4. 工作量评估。写测试用例技术上并非难题,但不代表没有工作量。如果评估工作量也是一个问题。
5.5. 测试用例的简易度。虽然技术上非难题,但是业务开发面临的种种问题,还是需要项目做一定的封装,以便提高测试用例的开发和运行的效率。
以上几点都是直接影响项目的进度,因此如果不能有效处理好,很难说服项目经理在项目计划中执行单元测试。
6. 文档的思考
6.1. 文档的分类
架构文档,high level设计文档和detail设计文档
6.2. Detail设计文档面临的问题
A. 维护成本高。开发过程中设计到的具体而维的细节变化较频繁,导致维护成本偏高;而开发成本和维护成本1:3的比例,导致这些文档在后期维护的成本也很高;
B. 验收成本高。目前缺乏自动化的验收工作;ST是黑盒测试,验收的是系统,而非文档;独立验收人员的学习曲线太高;而开发人员自我验收的效果不好,即便是交叉验收也容易达成私下协议;
C. 收益低。文档的维护人员,工作缺乏成就感;这些文档的阅读者通常是IT人员,使用代码阅读无疑具有更好的阅读效果;
本文地址http://www.chengxuyuans.com/software_design/176.html
今天的文章
软件架构优化_软件常见问题汇总分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/81104.html