2017-01-24 18 views
2

爲了讓我的應用程序正常工作,我需要定期同步來自外部服務的數據(可能是API或簡單的文本文件,但現在它是一個API)。ddd - 應該在哪裏與遠程API同步?

因爲這需要一次創建/更新許多實體,所以我需要創建一個域服務。但是,我還需要創建一些將包含遠程API響應的DTO?

這個邏輯應該去哪裏?如果我有以下目錄結構:

Domain - 
    Model - // my set of entities and repository interfaces are here 
     .... 
    Synchronization - 
     RunSynchronizationService.php // domain service 
Application 
    Synchronization - 
     SynchronizeData.php // application service 
     SynchronizationDataSourceInterface.php // used by application service 
     MySpecificRemoteApiDataSource.php // this implements the interface above 
     SynchronizationDataSourceResponse.php // this would be returned by each call of SynchronizationDataSourceInterface method, and would contain data normalized, but not validated. 
Infrastructure - 
    MyConcreteImplementationOfModelEntityRepository.php 

而當我想以同步數據,我smply調用應用程序\同步\ SynchronizeData的同步方法,至極將採取的具體實現SynchronizationDataSourceInterface的,調用它的方法,並驗證在將它們傳輸到Domain \ Model \ Synchronization \ RunSynchronizationService之前返回的SynchronizationDataSourceResponse對象?

或者我應該刪除RunSynchronizationService(域服務)並讓應用程序服務(SynchronizeData.php)在同步過程的每個步驟創建/更新域實體?

+0

我可能是錯的,但我在這裏聞到一些過度工程。我的第一個建議是在一個(子)包中隔離同步。我的第二個建議是,爲什麼不從一個小型服務開始,讓它在以後更好地理解其作用時讓它發展。 –

+0

@IhorBurlachenko問題在於同步過程相對較大。我必須從API獲取並驗證每個實體5到10個響應,並且至少有700個 – Lucio

+0

然後我會隱藏Synchronization(子)包中的所有細節。我不會把任何東西放在領域層。如果我理解正確,同步與域沒有關係,但只是您的應用程序如何處理數據。 –

回答

2

通常,當提出有關外部服務接口應該在哪裏生存的問題時,我試圖將其視爲另一個存儲庫。我選擇的抽象級別將取決於誰將使用該服務(只是該項目的域/應用程序層?其他項目?),如果該服務有不同版本/供應商,以及如何使用該服務決心。

對於您的示例,我將假定此應用程序是唯一直接使用同步服務的應用程序。共享服務需要進一步隔離公共端點(如接口和輸出對象),以避免不必要的對象溢出到其他項目中。

但是在這種情況下,爲了將服務視爲另一個存儲庫,我將它的接口和標準輸出放在域中預期並使用的域中。

什麼意思是「驗證」在您的描述中有點模糊,所以我會嘗試攻擊這裏的不同觀點。一個或全部可能適用。

如果驗證需要您與域數據進行比較,則它應該位於RunSynchronizationService.php模塊中。該模塊似乎負責獲取同步數據並將其應用到您的域。

如果對來自同步服務調用的數據進行驗證,並且不需要直接訪問域對象圖,那麼我會將驗證放在接口的服務實現上,並將驗證調用公開服務接口。爲了處理在多個版本的同步服務(例如VersionA,VersionB等)中相同驗證的情況,您可以對同步服務使用繼承和覆蓋或常用幫助函數等。在下面的示例中,我用繼承。

它可能是你需要做兩種驗證。首先檢查與域(在實施的類上)無關的同步數據問題,然後根據域中的業務規則(在RunSynchronizationService中)檢查。但可能這兩個調用都會發生在RunSynchronizationService中,因爲您會在界面上公開同步數據驗證調用。

應用層應負責創建服務實例(MySpecificRemoteApiDataSource),並將其作爲SynchronizationDataSourceInterface傳遞到RunSynchronizationService.php模塊。如果有多個版本,應用層可能會負責選擇哪一個(可能來自配置)和使用工廠。

但是,這又高度依賴於該同步服務的範圍。如果你有依賴它的外部項目,你可能希望該工廠是服務層本身的一部分,這樣每個其他項目都使用相同的選擇方法進行操作。

Domain - 
    Model - // my set of entities and repository interfaces are here 
     .... 
    Synchronization - 
     RunSynchronizationService.php // domain service 
     SynchronizationDataSourceInterface.php // used to define the contract associated with a sync service 
     SynchronizationDataSourceResponse.php // this would be returned by each call of SynchronizationDataSourceInterface method, and would contain data normalized, but not validated. 
Application - 
    Synchronization - 
     SynchronizeData.php // application service - Uses a factory or some means of determining which version to use and introduce the domain to the data point. 

Infrastructure - 
    MyConcreteImplementationOfModelEntityRepository.php 

Synchornization - 
    VersionA - 
     MySpecificRemoteApiDataSource.php // Implements SynchronizationDataSourceInterface.php, inherits from SyncApiDataSourceBase.php 
    SyncApiDataSourceBase.php // Common logic for sync goes here, such as validation. 
+0

我差不多也一樣!除了我在'Infrastructure/Synchronization'中放置''SynchronizationDatasourceInterface''的具體實現外。儘管如此,這是一個非常有效的答案,謝謝! – Lucio