组合对象的设计模式

1 投票
1 回答
678 浏览
提问于 2025-04-18 15:07

我有一个很复杂的函数,想要对它进行重构。简单来说,这个函数接收两个对象,访问这两个对象的多个属性和方法,然后把它们结合起来,最后用这些结合的结果来创建一个新的结果对象。

它的样子是这样的:

def ugly(obj_a, obj_b):
    a_1 = obj_a.a_1
    sub_a_1 = obj_a.get_sub()
    r_1 = obj_b.combine(a_1)
    if r_1 < 0:
       raise ValueError
    if not sub_a_1.validate():
       raise Exception
    return ResultObj(a_1, r_1, sub_a_1.get_matrix(), obj_b.some_other_attribute)

不过实际上,这两个对象上访问的属性和方法非常多,而且传给结果对象的构造值也很多。

这个函数在单元测试和集成测试时简直是一场噩梦。现在的情况是,我得模拟 obj_a 和 obj_b 以及它们所有的方法和属性。

你有什么建议可以用来重构这种代码吗?理想情况下,我不想改变 obj_a 和 obj_b 的实现。

这是用 Python 写的,所以面向对象和函数式的设计都可以用。
谢谢!

1 个回答

1

让这种过程性代码更容易测试的一种方法是添加“缝隙”,也就是说把代码分成可以单独运行的部分。因为没有实际的代码,逻辑上的缝隙很难看出来,所以很难抽象地回答你的问题。

你可以返回一个参数列表来创建一个结果对象,而不是直接创建一个。这让你可以测试处理过程,而不需要同时测试结果对象。而且,之后用 ResultObj(*args) 来创建结果对象也很简单。不过,这样你还是要处理很多值。

你也可以考虑写几个独立的函数,分别从A和B获取并验证数据,然后返回简单的“扁平”数据结构(比如命名元组),再由第三个函数将它们组合起来。

除此之外,重构类本身对我来说是最有意义的,尽管你说你想避免这样做。如果创建A和B对象没有副作用或者依赖关系不太多,那就更好了,但这还是要看你具体的代码情况。

另外要考虑的是,“把两个对象合并成一个超级对象”本质上更像是一个集成测试案例,而不是单元测试案例。

撰写回答