《C++代码整洁之道:C++17 可持续软件开发模式实践》 —2.5.10 不要混淆测试代码和产品代码

举报
华章计算机 发表于 2020/02/09 14:09:37 2020/02/09
【摘要】 本节书摘来自华章计算机《C++代码整洁之道:C++17 可持续软件开发模式实践》 一书中第2章,第2.5.10节,作者是[德]斯蒂芬·罗斯(Stephan Roth),连少华 郭发阳 陈涛 译。

2.5.10 不要混淆测试代码和产品代码

有时开发人员产生了一个想法,用测试代码来装备他们的生产代码。例如,在测试期间,一个类可能以如下方式包含了处理协作类的依赖关系的代码:

代码2-6 在测试过程中处理依赖关系的一种可能的解决方案

 image.png

 

DataAccessObject是特定DAO(数据访问对象)的抽象基类,在本例中为CustomerDAO和FakeDAOForTest,后者就是所谓的测试替身(fake object),这是一个用于测试的虚拟对象(参见本章后面的2.5.12节),目的是替换真正的DAO,因为我们不想测试它,并且我们不想在测试期间保存Customer的数据(谨记我关于数据库的建议)。使用两个DAO中的哪一个由布尔数据成员inTestMode控制。

这段代码虽然可行,但这一解决方案有几个缺点。

首先,我们的生产代码会混杂测试代码,虽然初看并不显眼,但它会增加产品复杂度并降低代码的可读性。我们需要一个额外的成员来区分系统的测试模式和生产使用,这个布尔成员与客户无关,更不用说系统的域了。而且不难想象系统中的许多类都需要这种类型的成员。

此外,Customer类依赖于CustomerDAO和FakeDAOForTest,你可以在源代码头部的包含文件列表中看到它,这意味着在生产环境中测试虚拟类FakeDAOForTest也是系统的一部分,我们寄希望于测试替身的代码永远不会在生产中被调用,但是它确实被编译、链接并部署在了生产中。

当然,也有一些更优雅的方法来处理这些依赖关系,并保证生产代码不受测试代码的影响。例如,我们可以在Customer::save()中注入特定的DAO作为一个参考参数。

代码2-7 避免依赖测试代码(1)

 image.png

 

或者,也可以在构造Customer类型的实例期间完成。在这种情况下,我们必须将DAO的一个引用作为类的成员属性。此外,我们必须通过编译器禁止自动生成默认构造函数,因为我们不希望Customer的任何用户可以创建一个未正确初始化的实例。

代码2-8 避免依赖测试代码(2)

 image.png

 image.png

 

deleted函数[C++11]

在C++中,如果有些类型成员没有被定义,编译器会自动为这些类型生成所谓的特殊成员函数(默认构造函数、拷贝构造函数、拷贝赋值运算符和析构函数)。从C++11开始,这个特殊成员函数列表多了移动构造函数和移动赋值运算符。C++11(及更高版本)提供了一种简单且声明性的方法来阻止自动创建任何特殊成员函数、普通成员函数和非成员函数,你可以删除它们。例如,你可以通过以下方式阻止创建默认构造函数:

 image.png

另一个例子:你可以删除new运算符以防止在堆上动态分配一个类:

 image.png

第三种替代方案是特定的DAO可以由Customer类已知的一个工厂(请参阅第9章中有关设计模式的Factory模式部分)来创建。如果系统在测试环境中运行,我们可以从外部配置Factory以创建所需的DAO。无论你选择哪种可能的解决方案,Customer类都能与测试代码脱离,Customer与特定的DAO没有依赖关系。


【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。