2012-02-06 47 views
2

我有一個類BigStructure,它從某些輸入構建了一個複雜的數據結構。它還包括對該數據結構執行操作的方法。拆分過大的類

這個班級變得太大了,所以我試圖把它分成兩部分來幫助可維護性。我認爲將這些行動轉移到一個新班級是很自然的,例如OperationsOnBigStructure班。

不幸的是,由於類BigStructure是相當獨特的,OperationsOnBigStructure不能合理地重用任何其他類。從某種意義上說,它永遠與BigStructure聯繫在一起。例如,一個典型的操作可能包括遍歷一個大結構實例,只對一個BigStructure對象有意義。

現在,我有兩個班,但感覺就像我沒有改善任何東西。事實上,我做了一些更復雜的工作,因爲我現在需要將BigStructure對象傳遞給OperationsOnBigStructure中的方法,並且他們需要在內部存儲該對象。

我應該住在一個大班嗎?

+0

有多大? – Blender 2012-02-06 04:42:10

+4

從你所說的話來看,這聽起來像你應該與一個大班生活在一起。但是,如果您可以發佈此課程,我們將能夠更好地爲您提供幫助。 – 2012-02-06 04:43:50

+0

我同意其他評論者的觀點:有時你最終會選擇一個大班,那只是生活。如果這是你的問題中最糟糕的,你的表現比平均水平要好。 – 2012-02-06 05:20:40

回答

2

我在想,把操作轉移到一個新的類中是很自然的,比如說OperationsOnBigStructure類。

我會說,這與面向對象設計的完全相反。 OOD背後的想法是將數據和方法保持在一起。

通常一個(太)大班是太多責任的標誌:即你的班級太簡單了。看起來你首先定義了一個數據結構,然後添加了一些功能。您可以嘗試將數據結構分解爲子結構併爲它們定義獨立的類(即使用聚合)。但不知道更多這是很難說......

當然有時,一個程序運行良好,一個大班。但如果你自己感到不舒服,這是一個強烈的暗示,開始做一些反對...

0

例如,一個典型的操作可以由在一個方式,是僅對於BigStructure 對象有意義遍歷大 結構實例的。

也許你可以寫一些生成器作爲BigStructure的方法,它可以完成遍歷的繁瑣工作。然後,OperationsOnBigStructure可以在執行任務時循環迭代器,這可能會提高代碼的可讀性。

所以,通過兩個類而不是一個類,你在兩個階段提高抽象層次。

0

「」「現在,我有兩個類,但它感覺我沒有改善任何東西。使事情稍微複雜一點,因爲我現在需要將BigStructure對象傳遞給OperationsOnBigStructure中的方法,並且需要在內部存儲該對象。「」「」

我認爲一種自然的方法是將「OperationsOnBigStructure」從大結構繼承 - 因此您將所有相關的代碼放在一個地方,而不需要傳遞額外的參數,因爲它需要操作的數據將包含在「self」中。

0

首先確保你有很高的測試覆蓋率,這會提升你的重構體驗。如果沒有或沒有足夠的單元測試,請創建它們。

然後做出合理的小重構步驟,並保留單元測試工作:

作爲一個經驗法則嘗試在大班一起保持的核心功能。如果耦合太多,儘量不要畫出邊框。

首先在分離庫中重構子功能到函數。如果有可能抽象出東西,則將該功能移至庫。

然後讓代碼更乾淨並重新排序,直到你能看到它真正想要的結構。

如果最終你覺得你仍然可以將它分成兩個等級,根據內部結構,這是非常自然的,然後考慮真正做到這一點。

始終保持足夠高的測試覆蓋率,並在進行一些更改後始終重構。等一段時間你會有更美麗的代碼。

5

我爲這個問題提出的解決方案是創建一個包含類的包。 東西沿着線:

MyClass/ 
    __init__.py 
    method_a.py 
    method_b.py 
    ... 

在我的情況__init__.py包含實際數據結構的定義,但沒有方法。要將方法「附加」到類中,只需將它們導入到類的名稱空間中。

內容的method_a.py:中__init__.py

def method_a(self, msg): 
    print 'a: %s' % str(msg) 

內容:

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 

這很適合我。

+0

這看起來就像我要用我的項目解決方案,但我不知道這是多麼標準。這個解決方案是pythonic嗎?您是否因爲此代碼結構而遇到過任何問題? – 2015-09-14 16:19:43

+2

@NickSweet我一直在生產中使用這個解決方案大約2年,到目前爲止我一直很好。奇怪的是,這似乎不是一種首選的方法(PEP)。 – 2015-09-15 09:05:48

+1

@NickSweet你有沒有在你的項目上採取這條路線?我很想知道你的經驗。 – 2015-10-15 12:49:29