0

我目前正在爲一個新的Zend Framework 2項目使用DDD(域驅動設計)。一切正常,但我確實有關於應用程序服務的問題。在DDD內使用ZF2控制器插件進行應用程序服務?

我知道應用程序服務位於應用程序層,並且是域邏輯的入口點。例如,他們可以訪問域服務或存儲庫。

現在我想知道是否應該將應用程序服務作爲控制器插件來實現。在經典的MVC應用程序中,這個控制器插件可以處理來自被叫域服務或存儲庫的結果。根據這些結果,他們可以生成重定向響應或將數據/表單傳遞給ViewModel。如果這個邏輯封裝在一個插件中,我的控制器只需調用插件並返回插件的結果。

我完全錯了嗎?或者你寧願保留邏輯如何對控制器中的域服務或存儲庫的結果作出反應?

最好的問候,

拉爾夫

+0

我不確定您在域和應用程序服務之間做出的實際區別。我想你可以爲你的服務類製作插件,但目前我看不到優勢。我有控制器工廠,並注入控制器所需的服務。有時候我的服務本質上就像存儲庫一樣,但我仍然一直定義一個服務,因爲應用程序定義了一個基本服務,它處理所有的域安全。 – dualmon 2015-03-02 15:50:04

+0

那麼域服務只處理屬於域的東西,而應用服務則是作爲應用程序和域之間的網關處理。這些應用程序服務將注入存儲庫或域服務,並且控制器獲取注入的應用程序服務。 – Frille2012 2015-03-04 12:46:26

回答

2

當然它是一種主觀的,人們對這樣的事情強烈的意見......所以這裏是我的:

  1. 控制器插件包含的代碼的通用到任何MVC/REST 行爲和業務邏輯不是通用的。插件應該促進 「控制」請求/響應,而不是在模型層面上減少 的業務邏輯。將它鏈接在一起會使它更少可重複使用,例如 。控制檯操作。此外,它會使其不太可能 與其他框架一起使用業務邏輯。
  2. 測試很尷尬。將控制器插件作爲控制器注入類構造函數參數會有點多餘,因爲它們已經可以從注入到AbstractActionControllerAbstractRestfulController中的插件管理器中獲得 。沒有以明顯/可見的方式注入依賴關係(如槽構造方法)使得難以弄清楚控制器類實際上取決於 。此外,由於所有插件(相關的AbstractPlugin)都依賴於控制器實例,因此將http上的上下文從 切換到控制檯(如用於phpunit測試)可能會出現問題。另外測試邏輯 作爲控制器插件被寫入/提供將遲早會升級到在測試中包括請求/響應對象,並且這是不必要的複雜性。
  3. 這並不直觀。當我聽到插件時,我想到了一些小事。 不是一個完整的業務邏輯代碼掩埋在這樣不起眼的 名稱。所以,當我沒有時間調試某人編碼最後的 的東西時,我需要它的東西是不合適的。

我再次想重申一下,那只是我的看法。我瞭解到,有很多模式可能會在一個足夠奇怪的用例下崩潰,但上述觀點對我和我的團隊而言至今仍有意義。

+0

經過進一步閱讀,我得出了同樣的結論。我創建了應用程序服務作爲單獨的命令對象。這些命令在錯誤情況下拋出異常,或者在成功時返回一個小的結果對象。控制器操作現在只處理這些異常或結果對象。 感謝您的想法。 – Frille2012 2015-03-04 12:42:58

0

至於這裏我的解決方案的例子中,你可以看到一個控制器動作:

public function showAction() 
 
    { 
 
     $service = $this->readProductEntityCommand; 
 
     $service->setId($this->params()->fromRoute('id')); 
 

 
     try { 
 
      $result = $service->execute(); 
 
     } catch (ProductException $e) { 
 
      $this->flashMessenger()->addMessage($e->getMessage()); 
 

 
      return $this->redirect()->toRoute('part3/product'); 
 
     } 
 

 
     return new ViewModel(
 
      array(
 
       'productEntity' => $result->getData(), 
 
      ) 
 
     ); 
 
    }

這裏是作爲一個命令對象

class ReadProductEntityCommand implements CommandInterface 
 
{ 
 
    protected $productRepository; 
 

 
    protected $id; 
 

 
    public function __construct(ProductRepositoryInterface $productRepository) 
 
    { 
 
     $this->productRepository = $productRepository; 
 
    } 
 

 
    public function setId($id) 
 
    { 
 
     $this->id = $id; 
 
    } 
 

 
    public function execute() 
 
    { 
 
     if (is_null($this->id)) { 
 
      throw new ProductIdInvalidException(
 
       'Produkt ID wurde nicht angegeben.' 
 
      ); 
 
     } 
 

 
     try { 
 
      $product = $this->productRepository->getProduct(
 
       new ProductIdCriterion(
 
        new ProductId($this->id) 
 
       ) 
 
      ); 
 
     } catch (\Exception $e) { 
 
      throw new ProductNotFoundException(
 
       'Es konnten kein Produkt gelesen werden.' 
 
      ); 
 
     } 
 

 
     if ($product === false) { 
 
      throw new ProductNotFoundException('Produkt wurde nicht gefunden.'); 
 
     } 
 

 
     $result = new Result(); 
 
     $result->setValid(true); 
 
     $result->setData($product); 
 
     $result->setMessage('Produkt wurde gelesen.'); 
 

 
     return $result; 
 
    } 
 
}
應用服務構建的一個例子

也許這有助於未來的人。

相關問題