8

我一直在閱讀多個PHP框架,特別是Zend框架,但我對正確的前進方向感到困惑。DataMapper模式是否打破MVC?

Zend Framework不使用ActiveRecords,而是使用Table Data Gateway和Row Data Gateway模式,並使用DataMapper將行數據網關的內容映射到模型,因爲ActiveRecord在您的模型不與您的數據庫表有1:1映射。 Zend Quickstart指南中有一個example of this

對我來說,他們的例子看起來非常臃腫,各地都有大量的getter和setter。我遇到過各種關於領域驅動設計的博客文章,他們認爲使用如此多的getter和setter是不好的做法,因爲它將所有內部模型數據公開給外部,所以它沒有優於公共屬性。 Here is one example

我的問題:如果你刪除了這些getter和setters,你將如何渲染你的視圖?在某些時候,數據必須顯示在視圖上,以便您可以向用戶顯示某些內容。遵循DDD的建議似乎打破了MVC中M和V之間的分離。遵循MVC和Zend的例子似乎打破了DDD,讓我爲我的所有模型輸入了大量的getter,setters和DataMapper。除了做很多工作外,它似乎也違反了DRY。

我真的很感激一些(鏈接)好的例子或更多關於它如何融合在一起的信息。我試圖在這裏提高我的建築和設計技能。

回答

2

使用Value Objects,可以消除一些公共setter方法。這裏是對the difference between Entity and Value Objects的描述。值對象是不可變的,通常與實體關聯。如果使用構造函數傳遞所有值,則不需要從外部代碼設置這些屬性。

額外的東西,不直接相關的答案,但更側重於DDD:

(聲明:我知道了Zend框架的唯一的事情是我所鏈接的文章中讀出。)Zend框架使用DataMapper而不是存儲庫。這真的是DDD-ISH嗎?那麼,Fowler's interpretation of a Repository可能會說不。但是,埃裏克埃文斯說,一個DDD倉庫可以非常簡單。最簡單的說,存儲庫 DataMapper(見DDD書)。對於更復雜和仍然DDD的東西,請參閱福勒的文章。 DDD有一個可能與模式定義不同的概念性存儲庫。

我強烈建議您繼續閱讀關於領域驅動設計。我認爲,假設吸收者和制定者違反DDD是有缺陷的。 DDD主要關注領域模型和最佳實踐。訪問者只是一個小細節。

+0

謝謝。那篇惡毒的文章能夠很好的閱讀。我還會讀到系列的其餘部分。 – 2009-06-24 08:14:38

+0

這是一個很好的答案,我會補充說,getters,setters有什麼不對。事實上,擁有它們是增加驗證邏輯的絕佳方式。公開物業是快速和骯髒的,可以在原型製作時使用,但不是一個很好的長期解決方案。假設你想改變一個屬性的名字。如果你這樣做,每一個訪問該屬性的代碼都需要改變。如果您使用訪問器方法的通用名稱,則不必更改客戶端代碼。另外,Doctrine是比Zend DB更豐富的解決方案。我不會推薦Doctrine1,但是請嘗試Doctrine2。 – 2010-08-20 08:26:49

2

你不需要實現所有的getter/setter,你可以使用_get()和__set()。那麼問題是什麼?

1

從我閱讀帖子來看,這個問題更具哲理性而非實用性。

我沒有時間寫深入,但這裏是我的兩美分。雖然我同意你想限制get和set請求的數量,因爲一個類應該隱藏它的內部,但你也需要考慮到Java和PHP是不同的工具並且有不同的目的。在Web環境中,每個請求都會構建和取下類,因此您編寫的代碼不應依賴於大型類。在你指出的文章中,作者建議將視圖邏輯放在類中。這可能在網絡上沒有意義,因爲我可能想要以多種格式(rss,html等)呈現視圖。因此使用訪問器方法(獲取&集)是一個必要的罪惡。你仍然想要好好地使用它們,這樣你就不會在腳下開槍。關鍵是要讓你的班級爲你做好工作,而不是試圖迫使他們在外面做工作。通過用方法而不是直接訪問你的屬性,你可以隱藏你想要的內部。

再次,這篇文章可以使用一些例子,但我現在沒有時間。

其他人可以提供一些爲什麼accessor方法不邪惡的例子嗎?

+0

謝謝。我的問題確實比實際更具哲理性。將視圖邏輯放在域模型中對我來說似乎有問題(因爲它違反了MVC),這就是問題的原因。我真正希望看到的是一些實際例子,清楚地表明理論在實踐中。如果它確實是域驅動設計和MVC之間的平衡,那麼我很想看看其他人如何解決它們之間的明顯衝突。 – 2009-06-22 22:40:38

0

實現getter和setter方法有兩個好處,在我的眼前:

  1. 你可以選擇屬性,使公衆,所以你不必去揭露所有的模型內部的
  2. 如果您使用帶有自動完成功能的IDE,當你開始輸入「get」或「set」時,所有可用的屬性都會被TAB帶走 - 這對我來說已經足夠了。
1

這裏有兩種方法:我稱之爲「告訴不問問題的方法」,另一種方法是ViewModel/DTO方法。 本質上,問題圍繞着你的觀點中的「模型」展開。 告訴別問,要求對象可以被外化的唯一方式是來自對象本身。換句話說,爲了渲染一個對象,你需要一個渲染方法,但是這個渲染方法需要與一個接口進行通信。 事情是這樣的:

class DomainObject { 
    .... 
    public function render(DomainObjectRenderer $renderer) { 
     return $renderer->renderDomainObject(array $thegorydetails); 
    } 
} 

在Zend框架的情況下,你也可以繼承的Zend_View和你的子類實現此接口。

我以前做過這個,但它有點笨拙。

第二種選擇是將您的域模型轉換爲ViewModel對象,它類似於爲每個特定視圖(每個視圖使用一個ViewModel)自定義的數據的簡化,展平,「放大」視圖,以及在回來的路上,將POST數據轉換爲EditModel。

這是ASP.NET MVC世界中非常流行的模式,但它也類似於用於在應用程序中的「圖層」之間傳輸數據的類「DTO」模式。您需要創建映射器來爲您執行骯髒的工作(與DataMapper實際上不同)。在PHP 5.3中,你可以使用反射來改變私有屬性,所以你的DomainObject甚至不需要暴露自己!

相關問題