2016-05-31 118 views
1

在Symfony 3中,您將如何根據領域驅動設計(DDD)區分以下內容?Symfony和領域驅動設計

  • 服務(即在配置服務文件中定義的一個)
  • 學說庫(\學說\ ORM \ EntityRepository)
  • 實體(在實體文件夾中的類)

I」 m意識到該學說與Symfony是分離的(即它可以被完全省略)。但是沒有Doctrine的Symfony項目中的版本庫是哪一個?或者,也許Symfony(沒有教條)實際上不是真的遵循DDD?

編輯

我嘗試下面小樣的情景,使我的問題更加清晰

控制器有一個函數返回所有可用的管理者對項目

class ManagementController 
    public function getAvailableManagers(Array $project) 
    { 
     ... 
    } 
}  

可用經理意味着他們手頭沒有項目,項目屬於他們的專業領域(例如客戶服務,業務關係,物流等)

但是由於設計不佳,專業領域不存儲在數據庫中,而是需要通過API調用調用到單獨的HR系統。稍後它將被集成到數據庫中

我會想(請隨時糾正我),管理器應該是一個存儲庫類,因爲它目前從2個不同的來源獲取其信息。問題是......我應該爲此使用Doctrine Repository嗎?或者,也許它應該只是一個普通的實體或者一個服務?

class ReplacementInstructionRepository extends \Doctrine\ORM\EntityRepository 
{ 
    private $id; 
    private $name; 
    private $speciality; 
    private $projects; 
} 

我需要一個關於如何拆分它的指南。謝謝

乾杯,

+1

是什麼讓你認爲Symfony with Doctrine遵循DDD?大多數Symfony應用程序都是粗糙應用程序。如果適用,您可以使用Symfony遵循一些DDD原則。你寫的問題對我來說毫無意義。 – Cerad

+0

感謝您的反饋意見,我用示例場景更新了問題。希望它會清除困惑:) –

回答

4

雖然我不明白很好的問題,在這裏你有應用DDD原則與Symfony的項目的一些例子。

https://github.com/PhpFriendsOfDdd/state-of-the-union/blob/master/README.md

編輯

你最後的描述後,我想我可以提供一個更好的答案:-)。

我會說Specification Pattern適合您的情況。規範模式允許您將業務規則保留在您的域圖層中。在這種情況下,你提到一個重要的業務規則:

可用的經理表示,他們對他們手頭沒有項目,該項目屬於自己的專業領域內(如客戶服務,業務關係,物流等)

在這種情況下,您提到了我們需要處理的糟糕設計。在一個新建項目中,我會將經理的專業領域保存在經理中,因此所有的事情都可以在經理的同一個總根中生活。

在你的情況,我會通過庫外部黨(人力資源系統)整合就像你可以看到下面:

nampespace xxx\infrastructure\persistence 
class ManagersRepository 
{ 
    public function __construct(HrApiClient $apiClient) 
    { 
     $this->apliClient = $apiClient; 
    } 

    public function findWithoutProjects() 
    { 
     $sqlQuery = //find all managers without project 
     $managers = $this->execute($sqlQuery); 
     foreach ($managers as $manager) { 
      $projects = $this->apliClient->findProjectsOfManagerId($manager->id()); 
      $manager->specialisedIn($projects); //This should be done with reflection 
     } 

     return $managers; 
    } 

    public function selectSatisfying(Specification $specification) 
    { 
     return $specification->satisfyingElementsFrom($this); 
    } 
} 

namespace xxx\Domain 
class ManagersAvailableSpecification implements Specification 
{ 
    public function __construct($aNewProject) 
    { 
     $this->aNewProject = $aNewProject; 
    } 

    public function isSatisfiedBy($manager) 
    { 
     // business rules here... 
     if ($manager->isSpecialisedIn($this->aNewProject)) { 
      return true; 
     } 

     return false; 
    } 

    public function satisfyingElementsFrom(ManagersRepository $managersRepository) 
    { 
     $managers = $managersRepository->findWithoutProjects(); 

     return array_filter(
      $managers, 
      function (Manager $manager) { 
       return $this->isSatisfiedBy($manager); 
      } 
     ); 
    } 
} 

注意,第一類,因爲它是一個具體實施庫(使用MySql,Postgre等)位於基礎架構層。而第二個,因爲它只取決於它的界面,以及定義可用管理器的業務規則。

現在你可以有這樣一個服務:

class FindAvailableManagersService 
{ 
    private $managersRepository; 

    public function __construct(ManagersRepository $managersRepository) 
    { 
     $this->managersRepository = $managersRepository; 
    } 

    public function execute(FindAvailableManagersRequest $request) 
    { 
     $managersAvailable = $this->managersRepository->selectSatisfying(
      new ManagersAvailableSpecification($request->project()) 
     ); 

     return $managersAvailable; 
    } 
} 

另請注意,如果將來你從第三方專業的域名遷移到自己的數據庫,你只需要修改一個類,但沒有別的得到感動:-)

+0

感謝您的鏈接,我正在閱讀:) –

+0

我更新了我的答案,更多細節。希望你覺得它有用。 – mgonzalezbaile

+0

有趣......因此您的存儲庫不使用Doctrine Repository('\ Doctrine \ ORM \ EntityRepository'),而是使用正常的類作爲存儲庫。那是因爲Doctrine Repository無法投入使用,因此無法注入?謝謝 –

1

問題是...我應該使用Doctrine知識庫爲此?

我認爲這是與DDD有關的最經典的誤解。 ORM存儲庫和實體完全不同於DDD存儲庫和實體。他們只是有同一個名字,但這一切,你不應該混淆他們。

DDD實體位於域中,並且不依賴域之外的類。 DDD存儲庫接口在域中定義,實現位於基礎結構中,可以依賴於基礎結構的其他部分。因此,要實現DDD存儲庫接口,可以根據需要使用ORM存儲庫,但可以使用與關係數據庫完全不同的數據存儲解決方案,例如noSQL數據庫。