2009-10-15 24 views
2

我重構一些代碼,發現這個(簡化當然,但總的想法):在構造函數中修改其他對象的狀態:設計no-no?

class Variable: 
    def __init__(self): 
     self.__constraints = [] 

    def addConstraint(self, c): 
     self.__constraints.append(c) 

class Constraint: 
    def __init__(self, variables): 
     for v in variables: 
      v.addConstraint(self) 

該約束的構造函數修改其他對象的狀態,而不是它自己的味道有點時髦給我的事實。其他人認爲 - 這是好的,還是重構的主要候選者?

編輯:我關心的不是父/子關係,而是它在構造函數中而不是在單獨的方法中進行關聯。

+0

在初始化做它(不是構造函數,這將是法'__new__' - 由你運行'__init__'的實例已建成的時候,雖然尚未初始化)保證類不變量,例如「每個約束總是存在於一定數量的變量中「。否則將意味着據稱「初始化」約束實際上不符合類不變式;爲什麼你會以任何方式想到這樣的情況?請看我的答案更多的例子...! – 2009-10-15 18:01:08

回答

0

我同意你的意見。這是倒退。爲什麼會有一些很好的理由,但是編程不清楚,如果腳遲早出現,它可能會咬人。

4

我把它看作一種自我註冊模式。 「你好我是新來的,請允許我加入。」

我可能更喜歡使用不同名稱的方法,以便目的更清晰,但我確實非常喜歡這種方法。

+2

國際海事組織做到這一點非常好。在構造函數中進行自注冊而不是另一種方法意味着a)無法忘記它,並且b)做兩次的可能性更少 – 2009-10-15 15:44:27

0

當您有兩個密切相關的對象(即只有其中一個沒有意義)時,這是常用的。最常見的情況是:父母的孩子關係。將子項添加到父項(即parent.children.append(child))時,通常也會更新child.parent指針。

+0

我知道這是一個常見的設計,這就是爲什麼我要重構它。區別在於它不是在一個單獨的方法中完成的,它是通過將父項傳遞給子構造函數並在構造函數中執行更新來完成的。 – tbocek 2009-10-15 15:28:28

+0

在構造函數或方法中做這件事情我看不出有什麼大不同。構造函數只是一次被調用的特殊方法。所以如果孩子沒有父母沒有意義,我會添加孩子的構造函數來將所有的代碼放在一個地方。 – 2009-10-15 15:59:48

0

我個人並不反對這一點,但...

我會選擇一個使用模式,並堅持下去。在你的情況,因爲變量已經有一個乾淨的addConstraint方法,我的首選是使用它。否則,您需要添加良好的檢查以防止用戶構建約束,然後將其添加到Variable類(從而將其添加兩次)。

這就是說,像一個約束,但我可能不會這樣做。約束似乎是一個來自變量的概念獨立實體。我看不出任何合乎邏輯的理由,相同的約束不能添加到兩個單獨的變量中。我只是讓它構建你的約束,然後手動添加它們,特別是出於這個原因。

+0

如果一個約束可以明顯地「附加到沒有變量」(這似乎很少或根本沒有意義),那麼它可能是合理的建立它作爲獨立的;但是在常見的情況下,給定的習慣用法更好,其中一個約束總是附加到1+個變量上('__init__'中的'assert variables'將使晶體清晰,但如果'variables'可以是任何可迭代的,那麼assert可以「消費」它,給定的代碼仍然完美)。 – 2009-10-15 18:04:46

2

我完全同意@ djna的回答,即特定的用例是完全合法的 - 在這裏,它是一個對象的例子,需要在「出生時」註冊一組指定的註冊表。

一個非常尖銳和極其常見的子表達式將是一個觀察者對象,嚴格地說是爲了觀察給定的observable而存在 - 完全可以將observable傳遞給觀察者的初始化器,並且確切地說是正確的方式來確保如果僅在完成初始化之後才進行註冊,那麼這個觀察者類的「類不變」實例總是與確切的一個可觀察對象相關聯「,這在出生時不會建立。

其他類似情況包括例如必須始終存在於容器窗口內的小部件對象:除非讓小部件將父母作爲初始化器參數並告訴父親「嗨,我是你的新孩子!「。

至少在那些很多情況下,您可以想象強制父對象或可觀察對象具有創建和註冊新對象的方法。在諸如此類的許多案例中,該方法的內在性質有所揭示 - 因爲約束必須用多個變量進行登記,因此要求其中任何一個特定人員創建「反對穀物」約束。您提供的代碼是完全自然的。

僅適用於那些無法被誣陷爲新對象的情況下「enregistering本身」我會覺得有些懷疑(也有一些其他合法的,如對象創建和出生enregistering其他輔助的,但他們遠不及普通)。

相關問題