四、精准化测试第二式:技术治理
1、技术耦合(由强到弱)
- 内容耦合
* 一个模块直接访问另一个模块的内部数据
* 一个模块不通过正常入口转到另一模块内部
* 两个模块有一部分程序代码重叠(只可能出现在汇编语言中)
* 一个模块有多个入口
- 公共耦合
一组模块都访问同一个公共数据环境(全局覆盖结构、共享的通信区、内存的公共覆盖区等)
- 外部耦合
一组模块都访问同一全局变量而不是同一全局数据结构,而且不是通过参数表传递该全局变量的信息
- 控制耦合
一个模块通过传送开关、标志、名字等控制信息,明显地控制选择另一模块的功能
- 标记耦合
一组模块通过参数表传递记录信息,这个记录是某一数据结构的子结构,而不是简单变量
- 数据耦合
一个模块访问另一个模块时,彼此之间是通过简单数据参数(不是控制参数、公共数据结构或外部变量)来交换输入、输出信息
- 非直接耦合
两个模块之间没有直接关系,它们之间的关系完全是通过主模块的控制和调用来实现
2、通常需要考虑的耦合类型
- 数据库/文件/缓存区耦合
- 同步耦合,如函数/方法/类的直接调用,WebService、EJB或分布式事务
- 异步耦合,如异步消息,短连接请求等
3、技术治理
* 差异化解决:改什么,测试什么
* 技术治理弄清:改什么,影响什么
技术治理:一种递进的关系,采取分而治之的策略
- 系统内治理----系统内耦合类型主要:直接调用、数据共用(内存/数据库/文件)和传递等
直接调用最常见,批量治理的方法:
* 最简单-关键词索引法,得调用关系全图,重名是干扰因素。
* 需要编译的高级语言领域(C、C++等),利用分析二进制的逆向方法,动态解析调用关系。
* 动态解析的方法,区别是针对java领域,通过java自带的方法,在Java虚拟机汇中,对字节码进行增强,通过对Java程序运行过程中的调用路径进行记录,从而跟踪到类/方法之间的调用关系
- 系统间治理----系统间耦合主要有:基于消息的异步调用或回调。如MQ(B/S),管道(Windows客户端)等;通过WebService,EJB等同步调用。
举例:分布式服务框架Dubbo
Dubbo通过控制系统服务间服务调用的权限(服务需要注册后才能对外发布服务,同样服务使用方也要先跟Dubbo申请权限后方可调用对应的服务),来完成对所有暴露外部服务和调用方的管理。对开发和测试来说,有了这个就可以画出系统间服务调用的全图,从而可以轻而易举地去判断服务之间的影响关系了。
- 数据库治理
从治标要治本的角度看,错综复杂的数据库对象之间的关联是不太好的一种应用架构方式。关系型数据库尽管非常强大,也能承担起一些应用逻辑,但如果把太多的业务逻辑都放在关系型数据库里,是不太方便后期的跟踪和维护的。数据库的任何读写也会伴随着大量的I/O产生,对性能也会带来很明显的瓶颈。
数据库还是尽可能回归到数据存储和读写这个根本的定位上来,而把更多的业务处理放到应用服务器中。因此,如果在实际的项目中存在关系型数据库内部的大量耦合,是一定要首先考虑督促项目团队去超以上方向努力的。
- 系统/服务治理的工程实践建议
技术治理说白了就是一个大型的系统关系链的拼图。比如B/S系统,有系统内,系统间,数据库各个板块治理拼起来的最终结果。
在工程实践上大致分为两个部分:
一部分是输入,就是说要从各个地方把这个关系链收集上来,这可能需要根据不同的领域去开发不同的自动化获取关系链结果的工具。
另一部分是输出。有了输入数据,就可以开始进行拼图游戏。拼图结束后,我们应该可以很简单地通过输入任何一个对象,来知道任何一个对象应用的各种拓关系,包括谁调用了我,谁和我公用了通过数据表甚至同一个字段。
- 函数调用链工具可以考虑
* 是否需要依赖源码
* 是否可以获取跨模块函数调用的关系
* 是否可以获取模块之间的调用关系
* 性能
* 准确度
- 静态函数调用链获取--站在逆向二进制角度观察函数调用关系,函数分以下类型
* 普通函数的调用分两种:一个是call指令调用,另一个是跳转指令调用
* 函数指针的调用函数是,将函数作为参数进行传递,通过参数/变量进行调用
* 类中虚函数的调用,通过虚表指针间接调用具体的子类函数
- 动静结合函数调用链-----静态多但有缺失,动态虽少但不会缺失,把静态的当做一个基础库,每次动态补齐,最终还是能建立一个完善的无缺失函数调用链库的。
读者思考:
1、我们为什么要有技术治理?
2、治理有什么其他作用和衍生产出?
3、技术耦合梳理对测试人员的好处又是什么?