8.Python 编程中优化货币对象的方法实现与测试解耦
写在前面
**
这本书是我们老板推荐过的,我在《价值心法》的推荐书单里也看到了它。用了一段时间 Cursor 软件后,我突然思考,对于测试开发工程师来说,什么才更有价值呢?如何让 AI 工具更好地辅助自己写代码,或许优质的单元测试是一个切入点。
就我个人而言,这本书确实很有帮助。第一次读的时候,很多细节我都不太懂,但将书中内容应用到工作中后,我受益匪浅。比如面对一些让人抓狂的代码设计时,书里的方法能让我逐步深入理解代码的逻辑与设计。
作为一名测试开发工程师,我想把学习这本书的经验分享给大家,希望能给大家带来帮助。因为现在工作中大多使用 Python 代码,所以我把书中JAVA案例都用 Python 代码进行了改写 。
**[
在测试驱动开发(TDD)的实践中,当处理像Franc(法郎)和Dollar(美元)这样的货币对象时,我们常常会遇到代码重复和类结构优化的问题。本章主要围绕如何优化这些货币对象的方法实现,以及通过引入工厂方法来解耦测试代码展开。
一、发现方法实现的相似性
Franc和Dollar类中的times方法实现方式高度相似。在 Python 中,它们的代码如下:
class Franc:
def __init__(self, amount):
self.amount = amount
def times(self, multiplier):
return Franc(self.amount * multiplier)
class Dollar:
def __init__(self, amount):
self.amount = amount
def times(self, multiplier):
return Dollar(self.amount * multiplier)
这种相似性提示我们可以采取措施来融合这两个方法,减少代码重复。
二、融合方法的尝试
为了融合times方法,我们可以让这两个方法分别返回一个Money实例。修改后的代码如下:
class Money:
def __init__(self, amount):
self.amount = amount
class Franc(Money):
def times(self, multiplier):
return Franc(self.amount * multiplier)
class Dollar(Money):
def times(self, multiplier):
return Dollar(self.amount * multiplier)
然而,此时Money的两个子类Franc和Dollar在代码结构中的作用不够突出,我们考虑去掉它们,但需要谨慎操作以遵循 TDD 原则。
三、引入工厂方法
为了减少对子类的直接引用,我们在Money类中引入返回Dollar实例的工厂方法:
class Money:
def __init__(self, amount):
self.amount = amount
@staticmethod
def dollar(amount):
return Dollar(amount)
class Dollar(Money):
def __init__(self, amount):
super().__init__(amount)
同时,我们需要在测试代码中更改相关声明,以适应这种变化。
四、将Money定义为抽象类
由于在测试中times方法在Money类中未定义,我们将Money定义为抽象类,并声明抽象的times方法:
from abc import ABC, abstractmethod
class Money(ABC):
def __init__(self, amount):
self.amount = amount
@abstractmethod
def times(self, multiplier):
pass
class Dollar(Money):
def __init__(self, amount):
super().__init__(amount)
def times(self, multiplier):
return Dollar(self.amount * multiplier)
这样修改后,测试全部通过,我们可以在测试代码的任何地方使用工厂方法,从而解耦了现有子类与测试代码之间的关系。
五、类似的Franc工厂方法
类似地,我们为Franc类也实现一个类似的工厂方法:
class Franc(Money):
def __init__(self, amount):
super().__init__(amount)
@staticmethod
def franc(amount):
return Franc(amount)
def times(self, multiplier):
return Franc(self.amount * multiplier)
六、总结
在本章中,我们完成了以下关键任务:
- 消除方法重复:通过融合Franc和Dollar类中times方法的签名,减少了代码重复。
- 抽象方法声明:将times方法的一个声明抽到了公共超类Money中,并将Money定义为抽象类。
- 解耦测试代码:通过引入工厂方法,成功地从现有具体子类对测试代码进行了解耦,使得客户端代码不再依赖于具体的子类。
- 识别多余测试:注意到当子类在代码中逐渐消失时,某些测试可能变得多余,但在本章中暂未对这些多余测试采取行动。
通过这些优化措施,我们在代码结构和测试方面都取得了一定的进步,为后续进一步优化代码奠定了基础。希望这些经验能对大家在 Python 编程和 TDD 实践中有所帮助。