C# 开始使用TDD和DDD

C# 开始使用TDD和DDD,c#,tdd,domain-driven-design,repository-pattern,C#,Tdd,Domain Driven Design,Repository Pattern,我刚刚读完Eric Evans的《领域驱动设计:解决软件核心的复杂性》,我正在尝试编写我的第一个以领域为中心的应用程序(用C#) 我们的帮助台将使用该应用程序跟踪计算机分配给用户的情况 我已经绘制了一个简单的类图来反映这个领域的一部分。看起来像这样 我还确定了我的第一个特性(将计算机分配给用户),并为此编写了一个测试 [Test] public void AllocateToUser() { var user = new Owner("user1"); var computer

我刚刚读完Eric Evans的《领域驱动设计:解决软件核心的复杂性》,我正在尝试编写我的第一个以领域为中心的应用程序(用C#)

我们的帮助台将使用该应用程序跟踪计算机分配给用户的情况

我已经绘制了一个简单的类图来反映这个领域的一部分。看起来像这样

我还确定了我的第一个特性(将计算机分配给用户),并为此编写了一个测试

[Test]
public void AllocateToUser()
{
    var user = new Owner("user1");
    var computer = new Computer("computer1");

    computer.Allocate(user);

    Assert.AreEqual(user.Username, computer.AllocatedTo.Username);
}
最后,我编写了使测试通过的代码

public class Computer
{
    public Computer(string name)
    {
        Name = name;
    }

    public string Name
    { get; private set; }

    public Owner AllocatedTo
    { get; private set; }

    public void Allocate(Owner owner)
    {
        AllocatedTo = owner;
    }
}

public class Owner
{
    public Owner(string username)
    {
        Username = username;
    }

    public string Username
    { get; private set; }
}
到目前为止,一切都很好(我认为)

然而,很明显,这些都不能解决持久性问题。我想我需要为计算机引入一个存储库类。也许是这样的:

public class ComputerRepository
{
    public void Store(Computer computer)
    {
        //Some persistence logic here (possibly using NHibernate?)
    }
}
现在我被卡住了。如何确保对计算机分配的用户所做的更改被传递到存储库

我似乎有以下选择:

  • 修改Computer类的Allocate方法的实现,以实例化ComputerRepository的实例并调用Store方法

  • 创建接口IComputerRepository;修改计算机的构造函数以要求提供实现IComputerRepository的类的实例。在Allocate方法中,针对该注入实例调用Store

  • 创建一个服务(AllocationService),它将结束一个分配和存储调用

  • 将Responsibility传递给客户端,强制调用代码执行两个步骤:

    • 在计算机类的实例上调用分配
    • 实例化ComputerRepository的实例并调用存储
  • 这些似乎都不令人满意:

  • 很难测试,因为我将直接在计算机类中实例化存储库

  • 通过使用依赖项注入避免了这个问题。然而,它仍然是丑陋的,因为每次我想要实例化计算机时,我都需要传递IComputerRepository的一些实例

  • 过于程序化,无法在域实体类中封装行为

  • 看起来很难看


  • 我应该做什么?

    通常我会将行为和持久性视为两个不同的关注点,并分别进行测试

    域对象应该对存储库的存在保持遗忘(尽管显然不是相反)

    在这种情况下,我们所做的是创建一个控制器(或服务),负责从其存储库加载适当的对象,调用对象上的行为,然后调用存储库来持久化更新

    然后,您可以使用模拟存储库测试控制器,以检查控制器是否正在使用更新的对象调用存储库