2012-10-04 72 views
2

我正在爲我公司的軟件產品設計一個新的架構。我對單元測試相當陌生。我讀了一些關於使用單例和靜態方法的恐怖故事,但我並不清楚使用它們的問題,並且會感激一些啓發。PHP靜態方法/ Singleton模式

這是我在做什麼:

我有一個多層架構。在服務器端,我使用一系列可重用對象來表示數據庫表,稱爲「處理程序」。這些處理程序使用其他對象,如XMLObjects,XMLTables,不同的數據結構等。其中大多數是自制的,而不是預先包裝的對象。無論如何,在這層之上是一個僞單體層。這樣做的主要目的是簡化更高級別的服務器端代碼並​​創建無縫的類管理。我可以說:

$tablehandler = databasename::Handler('tablename') 

...得到一個表。我沒有看到這個固有的問題。我正在使用一堆處理程序(一個關聯數組)來包含不同對象的實例。我沒有使用全局變量,並且所有靜態數據成員都是受保護的或私有的。我的問題是如何導致單元測試出現問題。我不是在尋找潮流的言辭,我正在尋找因果關係。我也希望對此有所瞭解。我覺得這是一個非常靈活和高效的架構。這裏的任何幫助都會很棒。

+4

你真的不喜歡白色空間.... – Baba

+0

這是一個很好的設計模式,實際上。不能幫助你與單身辯論,但肯定很有創意的想法 –

+0

我想說的最大的區別是利用[接口](http://php.net/manual/en/language.oop5.interfaces.php) – Ohgodwhy

回答

4

使用靜態方法提供對受管實例的訪問 - 無論它們是單例,共用對象還是即時實例 - 只要您爲測試提供一種方法,就不是測試的問題根據需要注入他們自己的模擬和存根,並在完成後刪除它們。根據你的描述,我沒有看到任何會阻止這種能力的東西。只有在必要時才能建立它。

如果您有一個類可以靜態調用執行沒有擴展點或通過實例的工作的方法,那麼您將遇到困難。例如,像這樣

UserTable::findByEmail($email); 

一個電話使測試困難,因爲你不能在一個模擬的,只有內存表等插上然而,將其更改爲

UserTable::get()->findByEmail($email); 

解決了,因爲測試的問題可以在設置代碼中調用UserTable::set($mock)。有關更詳細的示例,請參閱this answer

+0

謝謝你的回覆!幫助很多 –

+4

當然,應該指出的是,「解決問題」的第二個例子是公然違反德米特法。 – rdlowrey

+0

@rdlowrey - 鑑於OP已決定使用靜態方法,它似乎相當無害。 LoD更多的是不暴露內部狀態,例如'$ order-> addItem($ item)'而不是'$ order-> getItems() - > add($ item)',而不是關於服務定位器或者單例圖案。 –