我需要的東西,我不能讓我的頭纏着關於庫和服務/用例模式(部分DDD設計),我想在我的下一個(Laravel PHP)項目實施幫助。來自Repository的數據結構可用於所有目的?
一切似乎都很清楚。令人困惑的DDD的一部分是來自存儲庫的數據結構。人們似乎選擇存儲庫應該返回的數據結構(數組或實體),但它都有缺點。其中之一是表現看我過去的經歷。還有一個是你沒有簡單數據結構的接口(數組或簡單對象屬性)。
我將從解釋以前項目的經驗入手。這個項目存在缺陷,但是我從中學到了一些很好的優點,並希望在我的新項目中看到,但解決了一些設計錯誤。
以前的經驗
在過去,我已經建立一個網站,是用Kohana的框架和原則2 ORM(數據映射模式)API爲中心。流程是這樣的:
網站控制器→API客戶端(HMVC調用)→API控制器→自定義庫→學說2 ORM原生庫/實體經理
我的定製庫恢復使用Doctrine2 DQL普通陣列。 Doctrine2建議將數組結果數據用於只讀操作。是的,它使我的網站很好,很輕。 API控制器只是將數組數據轉換爲JSON。就那麼簡單。
在過去,我的公司創建的項目完全依賴加載的Doctrine2實體,這是我們因性能而感到後悔的事情。
我的REST API支持像
/api/users?include_latest_adverts=2&include_location=true
對用戶資源的查詢。 API控制器將include_location
傳遞給直接包含位置關係的存儲庫。控制器讀取latest_adverts=2
並調用廣告資源庫以獲取每個用戶的最新2個廣告。數組被返回。
例如第一用戶陣列:
[
name
avatar
adverts [
advert 1 [
name
price
]
advert 2 [
….
]
]
]
這被證明是非常成功的。我的整個網站使用的是API。添加一個新客戶端會非常容易,因爲API已經完全使用oauth生產了。整個網站運行。
但是這個設計也有缺陷。我的控制器仍然包含許多用於驗證,郵寄,參數或過濾器的邏輯,例如has_adverts=true
,以便僅向用戶提供廣告。這意味着如果我創建了一個新的端口,就像全新的CLI界面一樣,由於所有驗證等原因,我將不得不復制很多這些控制器。但是如果我要創建一個新客戶端,則不會有重複。所以至少有一個問題解決了:-)
我的管理面板完全耦合到doctrine2存儲庫/實體管理器,以加快開發(排序)。爲什麼?因爲我的API只有特別功能的胖控制器(特別驗證,郵寄註冊等)。我將不得不重做或重構很多東西。因此,決定直接使用這些實體,仍然有一些清晰的編寫代碼的方式,而不是重寫所有的API控制器並將它們移動到服務(例如,對於站點& admin)。時間是解決我的設計錯誤的一個問題。
對於我的下一個項目,我希望所有代碼都能通過我自己的定製存儲庫和服務。一個好的分離流程。
新項目(使用DDD的想法),並與兩難數據結構
雖然我喜歡的是API爲中心的想法,我不希望我的下一個項目是在覈心API爲中心的,因爲我覺得相同的功能應該在沒有HTTP協議的情況下可用。我想用DDD的想法設計核心。
但我喜歡這個想法,使用一個只是作爲API講話並返回簡單數組的圖層。任何新港口的完美基礎,包括我自己的前端。我的想法是將我的服務類視爲API接口(返回數組數據),進行驗證等。我可以爲網站(註冊)專門提供服務,管理員或後臺進程使用普通服務。在某些管理案例中,對於簡單的CRUD編輯,無需任何服務,我可以直接使用存儲庫。控制器將非常薄。有了這個創建一個真正的REST API將只是一個問題,使用我的前端控制器類使用相同的服務創建新的控制器。
對於像業務規則這樣的內部邏輯來說,使用實體(清除接口)而不是來自存儲庫的數組會很有用。這樣我就可以從定義一些基於屬性的邏輯中獲益。但如果我將使用Doctrine2,並且我的存儲庫將始終返回實體,那麼我的應用程序將遭受巨大的性能影響!
一個數據結構確保性能,但沒有明確的接口,另一個確保清晰的接口,但在使用類似於Doctrine 2(現在或將來)的數據模式模式時性能較差。另外,我最終可能會遇到兩種令人困惑的數據類型。
我想類似這樣的流動東西:
控制器(薄)→UserService(含確認)→UserRepository(只是存儲)→雄辯ORM
爲什麼雄辯而不是Doctrine2?因爲我想堅持一下Laravel框架和社區中常見的東西。因此,我可以從第三方模塊中獲益,例如根據模型生成管理界面或類似內容(繞過我的DDD規則)。除了使用第三方模塊,我會設計我的核心內容,所以切換應該總是很容易,不會影響數據結構選擇或性能。
Eloquent是主動記錄模式。所以我會試圖將這些數據轉換爲像Doctrine2實體那樣的POPO。但是不...如上所述,與教條2實際模型會使系統非常胖。所以我又回到了簡單的數組。瞭解這一點對未來的這兩種以及任何其他實施都有效。
但感覺不好總是依賴數組。特別是在創建內部業務規則時。開發人員必須猜測數組的值,在他的IDE中沒有自動完成功能,不能像Entity類那樣使用特殊的方法。但是,處理數據的兩種方式也不好。或者我太完美了;)我想要一個清晰的數據結構!
構建接口和POPO意味着很多重複的工作。我需要將Eloquent模型(只是一個表映射器,而不是實體)轉換爲實現此接口的實體對象。所有是額外的工作。最後,我的最後一層就像一個API,因此再次將它轉換爲數組。這也是額外的工作。數組似乎又成交了。
看起來很容易讀入DDD和六角形。這似乎很邏輯!但實際上,我試圖堅持面向對象原則這個簡單的問題。我想使用數組,因爲它是唯一能夠100%確定我不依賴於任何模型選擇和從我的ORM查詢關於性能等選項的唯一方法,並且在將數組轉換爲視圖或API時沒有重複的工作。但是用戶數組看起來並沒有明確的合同。我想用這些模式加快我的項目速度,而不是減慢它們:-)因此,不是有許多轉換器的選項。
現在我讀了很多話題。一個使POPO的接口符合像Doctrine2這樣的適當實體可能會返回的內容,但是所有額外的工作都可以用於Eloquent。切換到Doctrine2應該相當容易,但會影響性能如此糟糕,或者需要將Doctrine2陣列數據轉換爲這些自己的實體接口。其他人選擇返回簡單的數組。
有人說服人們使用Doctrine2而不是Eloquent,但是他們忽略了Doctrine2很重的事實,並且您確實需要將數組結果用於只讀操作。
我們設計存儲庫是可以改變的嗎?不是因爲它只是通過設計「很好」。那麼,如果它對業績或重複工作產生如此巨大的影響,我們如何依靠完整的實體?即使只使用Doctrine2(耦合),也會由於其性能而出現同樣的問題!
所有的ORM實現都能夠返回數組,因此在那裏沒有重複的工作。很好的表現。但我們錯過了明確的合同。我們沒有陣列或類屬性的接口(作爲解決方法)...呃;)
難道我只是錯過了我們的編程語言中缺少的塊嗎?簡單數據結構上的接口
是否明智的做出所有數組並且擁有先進的業務邏輯與這些數組對話?因此沒有明確界面的類。任何預先計算的數據(通常會由實體方法返回)將位於定義Service類的數組鍵中。如果不是明智的,考慮到以上所有情況,還有什麼選擇?
如果有人在這個考慮到性能,不同ORM實現等的「領域」方面有豐富經驗的人可以告訴我他/她如何處理這個問題,我真的很感激嗎?
在此先感謝!