遗留系统现代化实战
姚琪琳
Thoughtworks 资深咨询师
5615 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 30 讲
用户故事 (1讲)
遗留系统现代化实战
15
15
1.0x
00:00/00:00
登录|注册

08 | 代码现代化:你的代码可测吗?

你好,我是姚琪琳。
从今天开始,我将用三讲来介绍代码现代化的主要模式。它们大体的脉络是这样的:
1. 先对代码做可测试化重构,并添加测试;
2. 在测试的保护下,安全地重构;
3. 在测试的保护下,将代码分层。
我们今天先来看看如何让代码变得可测,这是遗留系统现代化的基本功,希望你重视起来。
一个软件的自动化测试,可以从内部表达这个软件的质量,我们通常管它叫做内建质量(Build Quality In)
然而国内的开发人员普遍缺乏编写自动化测试的能力,一方面是认为没什么技术含量,另一方面是觉得质量是测试人员的工作,与自己无关。然而你有没有想过,正是因为这样的误区,才导致软件的质量越来越差,系统也一步步沦为了遗留系统。
我虽然在第六节课分享了可以不加测试就重构代码的方法,但添加测试再重构的方法更加扎实,一步一个脚印。

你的代码可测吗?

我们先来看看不可测的代码都长什么样,分析出它们不可测的原因,再“按方抓药”。
可测的代码很相似,而不可测的代码各有各的不可测之处。我在第二节课举过一个不可测代码的例子,现在我们来一起复习一下:
public class EmployeeService {
public EmployeeDto getEmployeeDto(long employeeId) {
EmployeeDao employeeDao = new EmployeeDao();
// 访问数据库获取一个Employee
Employee employee = employeeDao.getEmployeeById(employeeId);
// 其他代码
}
}
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

代码现代化的主要模式包括可测试化重构、安全重构和代码分层。作者强调了代码可测性对于遗留系统现代化的基本功,并提出了提取接缝模式和对象接缝、接口接缝两种接缝类型来改善代码可测试性。此外,文章介绍了新生和外覆两种模式,以及如何为复杂遗留代码添加测试。作者还探讨了测试的类型和组织,以及遗留系统中的测试策略。最后,强调了自动化测试的重要性。整体而言,本文提供了实用的代码现代化技术指导,对于开发人员在现代化遗留系统方面具有重要的参考价值。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《遗留系统现代化实战》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(15)

  • 最新
  • 精选
  • 黄叶
    老师的课很棒,这里可以的话可以参考一下下面资料: 1.《重构2》3.8,关于霰弹式修改的问题 2.关于祖传代码:可以去这个网站看看,这是一个针对祖传代码的练习,看他是如何对祖传代码做重构的:https://linesh.gitbook.io/refactoring/xiang-jin-mei-gui/2-project-analyze 3.感觉老师的课,和TDD项目实战70讲很搭,可以结合看看

    作者回复: 感谢分享。

    2022-04-28
    9
  • aoe
    再分享一个测试 public class SplitUtil { public static final List<Long> toLongList(String str) { return Arrays.stream(StringUtils.split(str, ",")) .map(Long::parseLong) .collect(Collectors.toList()); } } class SplitUtilTest { @Test void to_long_list() { List<Long> list = SplitUtil.toLongList(""); assertThat(list).asList(); list = SplitUtil.toLongList("1"); assertThat(list.size() == 1).isTrue(); assertThat(list.contains(1L)).isTrue(); list = SplitUtil.toLongList("1,2"); assertThat(list.size() == 2).isTrue(); assertThat(list.contains(1L)).isTrue(); assertThat(list.contains(2L)).isTrue(); } }

    作者回复: 感谢分享。 不过这里面一共测试了3个场景,应该把它们分解到三个不同的测试中,并用测试名称进行区分

    2022-05-05
    2
    1
  • 2022
    老师,请教一下,如果是端到端的自动化测试,怎么保证结果的正确性呢? 比如,从UI修改配置后,下发到另外一个设备,有什么好的办法得到期望的结果?

    作者回复: 涉及硬件的端到端测试,如果数据发送给了另一个设备,你可以看看该设备有没有接口可以获取这些数据,就能验证了;如果没有,测的时候就把设备隔离,分开测,系统这边的测试可以测数据被发给了一个设备(的mock),设备那边的测试去测接到什么样的数据之后会有什么样的变化。两个测试合起来就是一个端到端测试了(除了连通性没有测到)。

    2022-04-28
    1
  • peter
    请教老师两个问题: Q1:数据比较,有开源工具吗? Q2:网站测试,有比较通用的自动化测试工具吗?

    作者回复: 1. 我目前没有看到专门用于A/B测试的数据对比工具,即使有也不太能适配你自己的数据库,不如自己按项目需要开发一个 2. Cypress是目前比较流行的E2E测试工具

    2022-04-27
    1
  • Geek_682837
    如果遇到需要mock的数据比较多,怎么比较方便构建mock数据,比如我需要mock一个List,可能有几十条数据的大小,自己mock的话就比较麻烦,如果直接访问数据库就可以比较方便拿到,但此时就依赖数据库了

    作者回复: 如果是单元测试,不应该有需要mock这么多数据的场景,你可以具体说说看你的场景是什么样的。

    2023-06-14归属地:广东
  • 跫音
    老师,请教一个问题,将单个类的测试都放在同一个包中,将不同方法的测试放在单独的测试类里。这样会不会导致测试类以及包很多?目前我们都是一个类对应一个测试类

    作者回复: 都可以,测试类和包多本身并不是问题

    2023-04-12归属地:上海
  • Geek_70dc13
    既然访问 db 的操作都是 mock ,那我如何保障 sql 那部分的正确性呢?看老师给的方案是集成测试。然而我一般使用的策略就是起 inmemory db,通过塞测试数据的方式,也会测 sql 那部分,缺点就是造数据和运行稍慢。 另外单元测试和集成测试的界限我可能并没有分的很清,单元测试是指每一层只测自己层的功能吗?比如:service 只测 service 的逻辑,mock掉 dao就是单元测试,不mock 掉dao也算是集成测试,还是说集成测试一定要构造 request 的方式

    作者回复: 如果没有存储过程,那么用内存数据库是可以测试SQL语句的,一般的工具都做好了SQL方言的适配。但如果有存储过程,就只能访问真实数据库了。 集成测试是指需要和当前SUT的外部进行交互的,数据库和其他服务都算,因此直接访问数据库或其他服务的测试都属于集成测试;而只要没有访问这些外部的东西,在我看来都属于单元测试。当然,这一点很多人有不同观点,没必要纠结,重要的是把测试写出来。

    2022-07-23归属地:河北
  • 飞翔
    老师 有没有手把手教怎么创建决策表 还是不是很理解怎么创造出来的

    作者回复: 根据原有代码的分支逻辑一步一步推导出来的

    2022-07-08
  • 飞翔
    老师 决策表里边throw error的测试 在原code中没有throw error的逻辑呀

    作者回复: 好眼力,如果只是重构,可以不加throw error的测试,但这一部分其实是原有代码中缺失的逻辑,后面需要补上。

    2022-07-08
  • IanFaye
    老师,请问浏览器兼容性问题如何测试定位问题呢?

    作者回复: 一般来说,前端的测试框架都是headless的,无法测试浏览器。可以用Selenium等工具编写E2E测试,并指定浏览器。但E2E测试跑起来很慢,又不能写太多,所以最好针对你觉得容易产生问题的点写少量测试。

    2022-06-07
    2
收起评论
显示
设置
留言
15
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部