标签: domain-driven-design

持久性无知有什么好处?

我是DDD + TDD世界的新手.但我已经编程了将近9年.

有人可以解释我坚持不懈的好处吗?典型的nHibernate应用程序只是将类和数据库之间的依赖关系推送到映射文件.

如果我更改类文件或数据库,我必须更改映射文件.那么是不是只是通过添加一个抽象层来推动依赖?在我看来,到目前为止,我认为这不是革命性的.但我不确定我是否遗漏了什么.

最后,我如何测试映射文件?映射文件中可能会出现错误,我该如何测试它们?

domain-driven-design persistence-ignorance

38
推荐指数
2
解决办法
1万
查看次数

替代与CQRS的多对多关系

我们如何使用CQRS/DDD模拟经典的多对多关系?

我知道DDD和CQRS实现和解决方案都倾向于特定于域,因此可能很难对这个问题提出一般性答案.

但是,我们假设我们在BookAuthor之间有熟悉的关系.这是一种经典的多对多关系.

对我来说,Book and Author似乎是两个不同的实体,每个实体都属于它们自己的Aggregate Root.因此,明确地模拟它们之间的多对多关系并不是一种可行的方法.

我们如何建模AddBookCommand?我们希望能够在我们的图书馆中添加一本书,并以某种方式说明某位作者撰写本书.我们如何建模(并坚持)这种关系?

无论是还是作者似乎是不错的候选值对象 ...

architecture domain-driven-design cqrs dddd

37
推荐指数
1
解决办法
3417
查看次数

Command + CommandHandler和Service有什么区别?

我一直在阅读使用Command对象来表示我们的域公开的用例,以及Command Handler对象来处理这些命令.

例如:

  • RegisterUserCommand
  • RegisterUserCommandHandler

但它看起来与a具有完全相同RegisterUserService,其中命令对象将表示registerUser()方法的参数.

当然,如果方法有太多的参数,我最终会创建一个对象来包装它们,并且该对象与它相同RegisterUserCommand.

那么为什么有不同的模式来表示同样的事情呢?服务很普遍,而不是命令(根据我的经验); 我错过了什么区别?简而言之,为什么我会使用一个而不是另一个?

design-patterns domain-driven-design command-pattern cqrs

37
推荐指数
2
解决办法
9175
查看次数

实现存储库模式的最佳方式?

我一直在探索BDD/DDD,因此试图找到Repository模式的正确实现.到目前为止,很难就实现这一点的最佳方式达成共识.我试图将其归结为以下变化,但我不确定哪种方法最好.

作为参考,我正在构建一个以NHibernate作为后端的ASP.MVC应用程序.

public interface IRepository<T> {
        // 1) Thin facade over LINQ
        T GetById(int id);
        void Add(T entity);
        void Update(T entity);
        void Remove(T entity);
        IQueryable<T> Find();
        // or possibly even
        T Get(Expression<Func<T, bool>> query);
        List<T> Find(Expression<Func<T, bool>> query);
}

public interface IRepository<T> {
        // 2) Custom methods for each query
        T GetById(int id);
        void Add(T entity);
        void Update(T entity);
        void Remove(T entity);
        IList<T> FindAll();
        IList<T> FindBySku(string sku);
        IList<T> FindByName(string name);
        IList<T> FindByPrice(decimal price);
        // ... and so on
}

public …
Run Code Online (Sandbox Code Playgroud)

c# bdd domain-driven-design repository-pattern

36
推荐指数
3
解决办法
1万
查看次数

域模型中的继承vs枚举属性

我在工作中讨论过"域模型中的继承使开发人员生活变得复杂".我是OO程序员,所以我开始寻找在域模型中具有继承性的论据,这样可以简化开发人员的生活,而不是让交换机遍布整个地方.

我想看到的是:

class Animal {

}

class Cat : Animal {

}

class Dog : Animal {

}
Run Code Online (Sandbox Code Playgroud)

另一位同事说的是:

public enum AnimalType {
    Unknown,
    Cat,
    Dog
}

public class Animal {

    public AnimalType Type { get; set; }

}
Run Code Online (Sandbox Code Playgroud)

我如何说服他(链接是欢迎的)一个类层次结构比在这种情况下具有枚举属性更好?

谢谢!

oop inheritance enums domain-driven-design domain-model

36
推荐指数
4
解决办法
6446
查看次数

CQRS中的值对象 - 在哪里使用

假设我们拥有受CQRS启发的架构,其中包括命令,域模型,域事件,读取模型DTO等组件.
当然,我们可以在域模型中使用值对象.我的问题是,它们是否也应用于:

  1. 命令
  2. 活动
  3. 的DTO

我没有看到任何在上述组件中使用Value Objects(VO)的示例.相反,使用原始类型.也许这只是简单的例子.毕竟,我对DDD中使用VO的理解是它们可以作为整个应用程序的粘合剂.

我的动机:

命令.
假设用户提交包含地址字段的表单.我们有Address Value Object来表示这个概念.在客户端构造命令时,我们应该验证用户输入,当它格式正确时,我们可以在那里创建Address对象并用它初始化Command.我认为不需要将Address对象的创建委托给命令处理程序.

域事件.
域模型已经在值对象方面运行,因此通过使用VO发布事件而不是将它们转换为基本类型,我们可以避免使用某些映射代码.我很确定在这种情况下使用VO是可以的.

DTO的.
如果我们的查询端DTO可以包含值对象,则可以提供更多灵活性.例如,如果我们有Money对象,我们可以选择是以EUR还是USD显示,不需要更改Read Model.

domain-driven-design dto value-objects cqrs

36
推荐指数
2
解决办法
5423
查看次数

35
推荐指数
2
解决办法
5743
查看次数

为什么域驱动设计似乎只受C#和Java等静态语言的欢迎?

域驱动设计已成为我的首选架构.我已经能够在ASP.net框架中找到大量的书籍和教程来应用DDD原理.它似乎主要来自Java开发人员现在所做的一段时间.

对于我的个人项目,我开始更倾向于Python,即使我发现很难放弃静态类型.我希望能够找到使用动态语言应用DDD的大量帮助.关于Python和DDD似乎没有什么.这是为什么?显然DDD可以很好地应用于Python.人们不会在Python中承担大量项目吗?或者在动态类型中使用DDD简单地应用DDD因此减少了所需的学习量?

也许我的问题是由于我缺乏Python经验.您可能对我提出的任何建议将不胜感激.

python domain-driven-design

35
推荐指数
4
解决办法
9637
查看次数

具有实体框架4.1和父/子关系的存储库模式

我仍然对存储库模式有些困惑.我想要使​​用此模式的主要原因是避免从域调用EF 4.1特定数据访问操作.我宁愿从IRepository接口调用泛型CRUD操作.这将使测试更容易,如果我将来必须更改数据访问框架,我将能够这样做,而无需重构大量代码.

这是我的情况的一个例子:

我在数据库中有3个表:Group,Person,和GroupPersonMap.GroupPersonMap是一个链接表,只包含主键GroupPerson主键.我用VS 2010设计器创建了3个表的EF模型.EF很聪明,可以假设它GroupPersonMap是一个链接表,因此它不会在设计器中显示它.我想使用我现有的域对象而不是EF生成的类,所以我关闭了模型的代码生成.

我与EF模型匹配的现有类如下:

public class Group
{
   public int GroupId { get; set; }
   public string Name { get; set; }

   public virtual ICollection<Person> People { get; set; }
}

public class Person
{
   public int PersonId {get; set; }
   public string FirstName { get; set; }

   public virtual ICollection<Group> Groups { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

我有一个通用的存储库接口,如下所示:

public interface IRepository<T> where T: class …
Run Code Online (Sandbox Code Playgroud)

c# domain-driven-design aggregateroot repository-pattern entity-framework-4.1

35
推荐指数
1
解决办法
2万
查看次数

CQRS中命令处理程序,聚合,存储库和事件存储之间的关系

我想了解基于CQRS的系统中命令处理程序,聚合,存储库和事件存储之间关系的一些细节.

到目前为止我所理解的:

  • 命令处理程序从总线接收命令.他们负责从存储库加载适当的聚合并调用聚合上的域逻辑.完成后,他们从总线上删除命令.
  • 聚合提供行为和内部状态.国家永远不公开.改变状态的唯一方法是使用行为.模拟此行为的方法从命令的属性创建事件,并将这些事件应用于聚合,聚合又调用事件处理程序,相应地设置内部状态.
  • 存储库只允许在给定ID上加载聚合,并添加新聚合.基本上,存储库将域连接到事件存储.
  • 事件存储,最后但并非最不重要,负责将事件存储到数据库(或任何使用的存储),并将这些事件重新加载为所谓的事件流.

到现在为止还挺好.现在有一些我还没有得到的问题:

  • 如果命令处理程序要在现有聚合上调用行为,那么一切都很简单.命令处理程序获取对存储库的引用,调用其loadById方法并返回聚合.但是,当没有聚合时,命令处理程序会做什么,但是应该创建一个?根据我的理解,聚合应该稍后使用事件重建.这意味着聚合的创建是在回复fooCreated事件时完成的.但是为了能够存储任何事件(包括fooCreated),我需要一个聚合.所以这对我来说就像鸡蛋和鸡蛋一样:我不能在没有事件的情况下创建聚合,但是应该创建事件的唯一组件是聚合.所以基本上归结为:我如何创建新的聚合,谁做了什么?
  • 当聚合触发事件时,内部事件处理程序会响应它(通常通过应用方法调用)并更改聚合的状态.这个事件如何移交给存储库?谁发起了"请将新事件发送到存储库/事件存储"动作?聚合本身?通过观察聚合来存储库?还有谁订阅了内部活动?...?
  • 最后但并非最不重要的是,我有一个问题正确理解事件流的概念:在我的想象中,它只是一个有序的事件列表.重要的是它是"有序的".这是正确的吗?

events domain-driven-design cqrs

35
推荐指数
2
解决办法
6388
查看次数