返回介绍

8.3 通过测试改良设计

发布于 2024-01-21 17:11:03 字数 1519 浏览 0 评论 0 收藏 0

前面我们谈了一系列仅执行测试对象的测试。不知各位在写测试时是否觉得举步维艰,是否把 mock 写得非常复杂?为什么测试会变得复杂呢?要知道,组件之间的结合度越高,给测试做准备就越花时间,测试也就越复杂。光是替换 mock 都已经要绞尽脑汁,怎么可能轻松添加新功能呢?因此我们要根据测试结果来改良设计。

便于测试的设计

什么样的设计便于测试呢?首先结合度要低。模块间的关联越少,测试起来就越简单。另外就是内聚度要高。模块做的事越少测试越简单。

◉ 面向对象原则

面向对象程序设计有几个原则。遵守这些原则能让我们的设计更加便于测试。当然,有时也要勇于打破它们。不过,如果没有特殊原因,应尽量遵循面向对象原则进行设计。

单一职责原则

保证一个对象只具有一项职责,一项职责只由一个对象来负责。如果只顾眼前方便而盲目追求对象的通用性,就很容易生成大得吓人的类。所以我们应根据单一职责原则,将正确的方法放到正确的类中。名如 HogeManager 的类往往都是未经过整理的类。给类起这种名字自然无妨,但具体的处理最好别写在 HogeManager 中。具体的处理应该在 Model 中实现,然后让 HogeManager 只负责调用即可。这样做有助于提高内聚度。

接口隔离原则

即不依赖于没有必要的接口。Python 的语法中没有接口的概念,但仍然会遇到类似问题。比如一旦我们进行了类检查,那么传值参数将只能接受该类或其子类。然而 Python 支持鸭子类型(Duck Typing),非子类也可以替换使用,所以最好不要做类型检验,而是根据类内是否存在某方法来判定传值参数,从而使模型结构更加灵活。

开放封闭原则

对扩展开放,对修改封闭。一个模块的修改不带来额外的派生,同时模块具有可扩展性。将某个类的对象替换为其子类的对象时,不需在扩展的基础上再修改其他模块。

这类替换必须遵循特定条件,并不是说用类和继承随时都能实现。

里氏替换原则

子类替换父类的过程对调用方透明。这要求我们在定义子类时,宽松对待其能接受的内容,严格把关其返回的内容。

在下述情况下,父类不可以替换为子类。

· 子类会发生父类不允许发生的例外

· 子类不接受父类已有的参数

· 子类返回父类不返回的值

· 父类中实现的内容在子类中被重载,但并未实现相关处理

如果只是想加强代码的通用性,那么应该尽量重视复用,少用继承。

复用优先于继承

继承是一种紧密的结合,因为我们无法将子类与父类彻底分离。复用则不同,它也是对已有代码的一种再利用,但不会产生继承关系。另外,复用允许我们在测试时用虚拟对象替换原对象。从对象角度看,父类与子类属于同一个东西,从模块角度看则不然。

NOTE

面向对象程序设计的原则并不止这 5 个。本章仅是从活用测试结果的角度挑选了几个加以说明。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文