从CRUD迁移到DDD

时间:2014-06-04 13:18:29

标签: c# domain-driven-design crud data-modeling

现在我想根据DDD指令尝试从模型的对象开始,但是我在理解如何迁移我的思维模式时遇到了一些困难,因为我无法将我发现的示例放在我的具体案例中

我的主要概念是活动,每个活动都有一个指示性代码,一个描述,一个随时间变化的状态以及每个结果的四分之一。

用户希望能够查看从活动中雇用的所有州的历史记录,以及进行更改的日期。此外,他们还希望能够创建新状态,更改现有状态的描述,并可能在保持以前活动的价值的同时阻止其中某些状态的使用。

每个季度,用户希望能够插入包含结果和建议的结果,评级和结果的制定日期。

评级必须是用户可自由维护的列表。

按照我以前的方式思考,我会创建这样的类:

public class Activity
{
    public int ID;
    public string Desc;
    public IList<ActivityStatus> ActivityStatusList;
    public IList<Result> ResultList;
}

public class ActivityStatus
{
    public Activity Activity;
    public Status Status;
    public DateTime StartDate;
    public DateTime EndDate;
}

public class Status
{
    public int ID;
    public string Desc;
    public bool Valid;
}

public class Result
{
    public Activity Activity;
    public int Quarter;
    public string Outcome;
    public string Recommendations;
    public Rating Rating;
}

public class Rating
{
    public int ID;
    public string Desc;
    public bool Valid;
}

我将实现一个DataAccessLayer将此类映射到一个新的db(使用此类创建)和NHibernate,并添加存储库以授予用户对所有此对象的CRUD操作

根据DDD有更好的方法吗?

3 个答案:

答案 0 :(得分:2)

我建议您阅读book或至少Wikipedia article

DDD主要关注领域逻辑并首先对其进行建模 - 以面向对象的方式。持久性是一个技术问题,它不应该是您设计的起点,并且(通常)不确定您将如何设计域类。

答案 1 :(得分:2)

如果您渴望编码并相信您对该域有所了解,我建议采用BDD测试优先方法。使用SpecFlow等工具以简单的英语描述您的业务流程,然后逐步填写步骤和功能,使用模拟,设计模式,控制反转等。

如果您不熟悉DDD,背景阅读是必须。阅读EagleBeak建议的书,了解SOLID原则并亲自体验。

答案 2 :(得分:1)

我不知道是否有更好的方法,但你所说的将是以DDD方式解决这个问题的一种方法。

在我的数据访问层中,我通常使用存储库的抽象工厂。这样我就可以插入一个特定的数据访问实现,比如NHibernate。

public interface IRepositoryFactory {
  T Repository<T>();
};

public class NHibernateRepositoryFactory {
  T Repository<T>() {
    ..... // find class that implements T in Assemblies with reflection
    return repository;
  }
};

public static class Persistence {
  IRepositoryFactory Factory { get; set; }
};

通过这种方式,您可以在不引用任何特定实现的情况下调用存储库:

User user = Persistence.Factory.Get<IUserRepository>().FindByEmail("john@tt.com");
user.name = "James";
Persistence.Factory.Get<IUserRepository>().save(user);

如上所述将抽象工厂用于存储库的另一个优点是,您可以通过为存储库插入虚假实现来测试代码。

public class FakeRepositoryFactory {
  T Repository<T>() {
    ..... // find class that implements T in Assemblies of fake repositories
    return repository;
  }
};

public class FakeUserRepository : public IUserRepository {
    User FindByEmail(string email) {
      // create mocked user for testing purposes ....
      return userMock;
    }
};

您的代码不会也不应该知道用户数据来自抽象工厂的持久性。这种方式可以通过透明的方式从一种方式切换到另一种方式。