- 引言
- 本书涉及的内容
- 第 1 部分 Python 开发入门
- 第 1 章 Python 入门
- 第 2 章 开发 Web 应用
- 第 3 章 Python 项目的结构与包的创建
- 第 4 章 面向团队开发的工具
- 第 5 章 项目管理与审查
- 第 6 章 用 Mercurial 管理源码
- 第 7 章 完备文档的基础
- 第 8 章 模块分割设计与单元测试
- 第 9 章 Python 封装及其运用
- 第 10 章 用 Jenkins 持续集成
- 第 11 章 环境搭建与部署的自动化
- 第 12 章 应用的性能改善
- 第 13 章 让测试为我们服务
- 第 14 章 轻松使用 Django
- 第 15 章 方便好用的 Python 模块
- 附录 A VirtualBox 的设置
- 附录 B OS(Ubuntu)的设置
8.3 通过测试改良设计
前面我们谈了一系列仅执行测试对象的测试。不知各位在写测试时是否觉得举步维艰,是否把 mock 写得非常复杂?为什么测试会变得复杂呢?要知道,组件之间的结合度越高,给测试做准备就越花时间,测试也就越复杂。光是替换 mock 都已经要绞尽脑汁,怎么可能轻松添加新功能呢?因此我们要根据测试结果来改良设计。
便于测试的设计
什么样的设计便于测试呢?首先结合度要低。模块间的关联越少,测试起来就越简单。另外就是内聚度要高。模块做的事越少测试越简单。
◉ 面向对象原则
面向对象程序设计有几个原则。遵守这些原则能让我们的设计更加便于测试。当然,有时也要勇于打破它们。不过,如果没有特殊原因,应尽量遵循面向对象原则进行设计。
○ 单一职责原则
保证一个对象只具有一项职责,一项职责只由一个对象来负责。如果只顾眼前方便而盲目追求对象的通用性,就很容易生成大得吓人的类。所以我们应根据单一职责原则,将正确的方法放到正确的类中。名如 HogeManager 的类往往都是未经过整理的类。给类起这种名字自然无妨,但具体的处理最好别写在 HogeManager 中。具体的处理应该在 Model 中实现,然后让 HogeManager 只负责调用即可。这样做有助于提高内聚度。
○ 接口隔离原则
即不依赖于没有必要的接口。Python 的语法中没有接口的概念,但仍然会遇到类似问题。比如一旦我们进行了类检查,那么传值参数将只能接受该类或其子类。然而 Python 支持鸭子类型(Duck Typing),非子类也可以替换使用,所以最好不要做类型检验,而是根据类内是否存在某方法来判定传值参数,从而使模型结构更加灵活。
○ 开放封闭原则
对扩展开放,对修改封闭。一个模块的修改不带来额外的派生,同时模块具有可扩展性。将某个类的对象替换为其子类的对象时,不需在扩展的基础上再修改其他模块。
这类替换必须遵循特定条件,并不是说用类和继承随时都能实现。
○ 里氏替换原则
子类替换父类的过程对调用方透明。这要求我们在定义子类时,宽松对待其能接受的内容,严格把关其返回的内容。
在下述情况下,父类不可以替换为子类。
· 子类会发生父类不允许发生的例外
· 子类不接受父类已有的参数
· 子类返回父类不返回的值
· 父类中实现的内容在子类中被重载,但并未实现相关处理
如果只是想加强代码的通用性,那么应该尽量重视复用,少用继承。
○ 复用优先于继承
继承是一种紧密的结合,因为我们无法将子类与父类彻底分离。复用则不同,它也是对已有代码的一种再利用,但不会产生继承关系。另外,复用允许我们在测试时用虚拟对象替换原对象。从对象角度看,父类与子类属于同一个东西,从模块角度看则不然。
NOTE
面向对象程序设计的原则并不止这 5 个。本章仅是从活用测试结果的角度挑选了几个加以说明。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论