1

從這些爭論在繼續:域Enties訪問庫

DDD - the rule that Entities can't access Repositories directly

Is it ok for entities to access repositories?

還有一些在那裏感覺更好的爲域名來訪問存儲庫的情況。就拿這個例子中,它假定我需要一個TaskStatus表,其中包含一個用於報告的說明數據庫:

public class TaskStatus 
{ 
    public long Id {get;set;} 
    public string Description {get;set;} 
} 

public class Task 
{ 
    public long Id {get;set;} 
    public string Description {get;set;} 
    public TaskStatus Status {get;set;} 

    public void CompleteTask() 
    { 
     ITaskStatusReposity repository = ObjectFactory.GetInstace<ITaskStatusReposity>(); //Or whatever DI you do. 
     Status = repository.LoadById(Constants.CompletedTaskStatusId); 
    } 
} 

我知道我可以有CompletedTaskStatus和OpenTaskStatus對象,但在有些情況下,這將是unnessacery,並可能導致到一個類爆炸。

無論如何,爲什麼存儲庫接口存儲在域中,如果不是這樣的東西?

回答

3

實體訪問存儲庫可以嗎?

不,請不要這樣做。

首先,領域模型的想法是將業務邏輯從應用程序中分離出來。將它從數據庫,存儲庫和應用程序中分離出來。這使您可以將業務邏輯分開,並允許將其與應用程序分開進行測試和更改。

該域應完全不知道數據持久性,並應假設它自動發生。

ddd-the-repository-pattern.aspx

其次還有其他更實際的理由不注入你的資料庫到您的enties。

  1. 通過將您的存儲庫注入到您創建的存儲庫依賴項的實體中,您的應用程序應該是單元可測試的。

  2. 使用GetInstance()方法打破了Demeter法則,您正在創建ITaskStatusRepository與實體的緊密耦合。這意味着當創建一個新的任務並編寫單元測試時,任務需要一個ITaskStatusRepository並不是明顯的opon構造。這使得單元測試業務邏輯變得更加困難。

  3. 從DDD的角度來看,存儲庫不僅關心與數據庫的接口,還可能從內存存儲中檢索。或一個列表。

  4. 您的存儲庫不必與表格建立1對1的關係。如果您需要任務存儲庫執行與其他表的內部聯接以執行復雜查詢,並返回任務項列表,那麼您將從存儲庫公開一個執行該查詢的方法。 (我認爲這是存儲庫模式的常見誤解)。

  5. 您的實體不應該關注在db上執行操作。

參見此處發佈的圖像:

DDD: how the layers should be organized?

public class TaskStatus 
{ 
    public long Id { get; set; } 
    public string Description { get; set; } 

    public TaskStatus() { 
     Description = "Incomplete"; 
    } 
} 

public class Task 
{ 
    public long Id {get;set;} 
    public string Description {get;set;} 
    public TaskStatus Status {get;set;} 

    public void CompleteTask() 
    {   
     Status.Description = "Complete"; 
    } 
} 

應用層裏面,你的資料庫負責持久性(或沒有)。存儲庫是聚合根的列表<>。它在聚合根級別工作。

在TaskService中使用您的任務的示例。服務作用於來自應用層的實體。

public class TaskService 
{ 
    private readonly ITaskRepository _taskRepository; 

    public TaskService(ItaskRepository taskRepository){ 
     _taskRepository = taskRepository; 
    } 

    public List<Task> CompleteAllTasks() 
    { 
     List<Tasks> getTasks = _taskRepository.GetTasks(); 
     getTasks.ForEach(CompleteTask); 
     return _taskRepository.Save(getTasks); 
    }  
} 
+0

1 + 2:通過訪問ITaskStatusRepository,域沒有意識到持久性的性質,儘管我接受它意識到持久性存在。當然,它仍然是單元測試,因爲存儲庫可以被嘲笑?我仍然不確定你是如何暗示我會實現我在上面做的事情? –

+0

3:我不確定除了訪問數據庫之外,我的Repository還在做什麼? 4:好吧,所以TaskStatus可以是一個枚舉,你可以有'public void Complete(){Status = TaskStatus.Complete; }'和StatusDescription應該是任務的屬性? –

+0

除非我弄錯了,否則我並不認爲'CompleteTask'是屬於資源庫的東西。我的例子非常簡單,唯一的商業邏輯是當任務完成時,它的狀態變爲「已完成」。這個邏輯可能會更復雜,而且當然不應該在存儲庫中完成? –