Python 拆分过大的类

Python 拆分过大的类,python,class,Python,Class,我有一个类BigStructure,它从一些输入构建复杂的数据结构。它还包括对该数据结构执行操作的方法 这个类变得太大了,所以我试图将它一分为二以帮助维护。我认为将操作移动到一个新类中是很自然的,比如classoperationbigstructure 不幸的是,由于类BigStructure是非常独特的,operationbigstructure不能合理地与任何其他类一起重用。从某种意义上说,它永远与BigStructure联系在一起。例如,典型的操作可能包括以仅对BigStructure对象

我有一个类
BigStructure
,它从一些输入构建复杂的数据结构。它还包括对该数据结构执行操作的方法

这个类变得太大了,所以我试图将它一分为二以帮助维护。我认为将操作移动到一个新类中是很自然的,比如class
operationbigstructure

不幸的是,由于类
BigStructure
是非常独特的,
operationbigstructure
不能合理地与任何其他类一起重用。从某种意义上说,它永远与
BigStructure
联系在一起。例如,典型的操作可能包括以仅对
BigStructure
对象有意义的方式遍历大结构实例


现在,我上了两节课,但感觉我什么都没有进步。事实上,我使事情稍微复杂一些,因为我现在需要将
BigStructure
对象传递给
operationbigstructure
中的方法,并且它们需要在内部存储该对象

我应该和一个大班同住吗

例如,一个典型的操作可能包括遍历一个大的 以仅对BigStructure有意义的方式构造实例 反对

也许您可以编写一些生成器作为BigStructure的方法来完成繁重的遍历工作。然后,OperationsOnBigStructure可以在执行任务时在迭代器上循环,这可能会提高代码的可读性

因此,通过使用两个类而不是一个类,可以在两个阶段提高抽象级别

我认为将操作移动到一个新类中是很自然的,比如说类OperationsOnBigStructure

我会说,这与面向对象设计完全相反。OOD背后的思想是将数据和方法保持在一起

通常,一个(太)大的班级是一种责任太多的表现:也就是说,你的班级做的太多了。似乎您首先定义了一个数据结构,然后向其中添加了函数。您可以尝试将数据结构分解为子结构,并为这些子结构定义独立的类(即使用聚合)。但是如果不知道更多,很难说

当然,有时一个程序只需要一个大班就可以正常运行。但是,如果你自己感到不舒服,这是一个强烈的暗示,开始做一些反对…

““现在,我上了两节课,但感觉我什么都没有进步。事实上,我使事情稍微复杂一些,因为我现在需要将BigStructure对象传递给OperationsOnBigStructure中的方法,并且它们需要在内部存储该对象


我认为一种自然的方法是让“OperationsOnBigStructure”从bigstructure继承-因此您将所有相关代码放在一个地方,而不需要传递额外的参数,因为它需要操作的数据将包含在“self”中“

首先确保您具有高测试覆盖率,这将提高您的重构体验。如果没有或没有足够的单元测试,请创建它们

然后进行合理的小重构步骤,并保持unittests正常工作:

根据经验,在大类中尽量保持核心功能。如果耦合太多,尽量不要绘制边界

首先,将子任务重构为独立库中的函数。如果可以抽象事物,请将该功能移动到库中

然后使代码更干净并重新排序,直到您能够看到它真正“想要”的结构

如果你最终觉得你仍然可以在两个类中切割它,这是很自然的,根据内部结构,然后考虑真的去做。< /P>
始终保持足够高的测试覆盖率,并始终在进行一些更改后重构。一段时间后,您将拥有更漂亮的代码。

我为这个问题提出的解决方案是创建一个包含该类的包。 大致如下:

MyClass/
    __init__.py
    method_a.py
    method_b.py
    ...
在我的例子中,
包含实际的数据结构定义,但没有方法。要将方法“附加”到类中,我只需将它们导入到类的命名空间中

方法a.py的内容

def method_a(self, msg):
    print 'a: %s' % str(msg)
\uuuu init\uuuuu.py的内容

class MyClass():
    from method_a import method_a
    from method_b import method_b

    def method_c(self):
        print 'c'
在python控制台中:

>>> from MyClass import MyClass
>>> a = MyClass()
>>> dir(a)
['__doc__', '__module__', 'method_a', 'method_b', 'method_c']
>>> a.method_a('hello world')
a: hello world
>>> a.method_c()
c

这对我很有用。

从你所说的,听起来你应该和一个大班同住。然而,如果你能发布这门课,我们将能更好地帮助你。我同意其他评论者的观点:有时你会以一门大课结束,这就是生活。如果这是你的问题中最糟糕的一个,那么你做得比平均水平要好。@Blender:这个类大约有600行代码(不包括空格/注释),大约有30个方法。坏的是它只能变得更大。。。我可能会把它贴出来,如果我能把它清理干净,使它在隔离状态下有意义的话。这看起来正是我将在我的项目中采用的解决方案,但我不知道这有多标准。这个解决方案是肾盂的吗?由于这种代码结构,您是否遇到过任何问题?@NickSweet我已经在生产中使用此解决方案大约2年了,到目前为止,我一直很好。奇怪的是,似乎没有一种更喜欢的方法(PEP)来做这件事。@NickSweet您在项目中采用过这种方法吗?我很想知道你在这方面的经验。我做了,而且效果很好!我在循环依赖项方面遇到了一些问题,但我只是通过在需要外部函数/方法的函数中导入来解决这些问题。感谢您的反馈!我想我也会继续这样做:)