Domain driven design 域驱动设计有界上下文域对象

Domain driven design 域驱动设计有界上下文域对象,domain-driven-design,bounded-contexts,Domain Driven Design,Bounded Contexts,我试图弄清楚我是如何处理DDD和使用有界上下文的 我试着举个例子来说明我的问题。(我使用贫血课程来提高速度) 我试图找出如何在不同的有界上下文中分离域对象 我考虑了可能是雇员的域对象 假设我有两个有限的环境,人力资源部和财务部 public class Employee { public int Id { get; set; } public Title Title { get; set; } public string Forename

我试图弄清楚我是如何处理DDD和使用有界上下文的

我试着举个例子来说明我的问题。(我使用贫血课程来提高速度)

我试图找出如何在不同的有界上下文中分离域对象

我考虑了可能是雇员的域对象

假设我有两个有限的环境,人力资源部和财务部

public class Employee
    {
        public int Id { get; set; }
        public Title Title { get; set; }
        public string Forename { get; set; }
        public string Surname { get; set; }
        public Address Address { get; set; }
        public DateTime DateOfBrith { get; set; }
        public DateTime EmploymentStartDate { get; set; }

    }
public class Employee
    {
        public int Id { get; set; }
        public Title Title { get; set; }
        public string Forename { get; set; }
        public string Surname { get; set; }
        public Address Address { get; set; }
        public DateTime DateOfBrith { get; set; }
        public string NationalInsuranceNumber { get; set; }
        public BankAccount BankAccountDetails { get; set; }
        public double ContractedHours { get; set; }
}
一般来说,财务部门比人力资源部门需要更多关于员工的信息。人力资源部不需要任何有关员工银行详细信息、国民保险号码或合同工时的信息。(也许在某些企业中这并不完全正确,但让我们在示例中假设一下)

因此,在两种不同的情况下,与员工的行为/互动是不同的

人力资源部

public class Employee
    {
        public int Id { get; set; }
        public Title Title { get; set; }
        public string Forename { get; set; }
        public string Surname { get; set; }
        public Address Address { get; set; }
        public DateTime DateOfBrith { get; set; }
        public DateTime EmploymentStartDate { get; set; }

    }
public class Employee
    {
        public int Id { get; set; }
        public Title Title { get; set; }
        public string Forename { get; set; }
        public string Surname { get; set; }
        public Address Address { get; set; }
        public DateTime DateOfBrith { get; set; }
        public string NationalInsuranceNumber { get; set; }
        public BankAccount BankAccountDetails { get; set; }
        public double ContractedHours { get; set; }
}
财务部

public class Employee
    {
        public int Id { get; set; }
        public Title Title { get; set; }
        public string Forename { get; set; }
        public string Surname { get; set; }
        public Address Address { get; set; }
        public DateTime DateOfBrith { get; set; }
        public DateTime EmploymentStartDate { get; set; }

    }
public class Employee
    {
        public int Id { get; set; }
        public Title Title { get; set; }
        public string Forename { get; set; }
        public string Surname { get; set; }
        public Address Address { get; set; }
        public DateTime DateOfBrith { get; set; }
        public string NationalInsuranceNumber { get; set; }
        public BankAccount BankAccountDetails { get; set; }
        public double ContractedHours { get; set; }
}
在这个示例中,我如何限制HR上下文中的Employee对象,使其仅具有所需的行为,并且财务上下文具有扩展的行为

如果一个应用程序被分解成多个上下文,所有这些上下文都具有与员工相关联的自定义行为,那么我将如何对员工对象建模

我研究了构建上下文映射的不同方法,共享内核似乎很有希望,但这意味着所有上下文都将共享与Employee域对象相关的所有行为

我希望每种情况都是有限的


救命啊

我对您所在领域的了解有限,但我可能会在每个有限的上下文中分别对员工进行建模,也就是说,有两个独立的实体,以便它们可以单独发展以满足每个上下文的需要


人力资源部将负责雇佣新员工,修改他们的细节(姓名变更等),以及解雇和裁员等不太有趣的任务。因此,我很想将主员工记录保存在人力资源系统中,当财务部需要了解更新时,我会通过web服务或消息总线等将这些更改推送到另一个系统中。创建诸如
Title
Forename
姓氏
,之类的属性,
地址
出生日期
在财务上下文中为只读。

每个BC定义自己的模型。通常,员工仅在一个BC中定义为完整的概念。其他BC对它有自己的定义,大多数情况下它将是一个id(使其成为GUID)。在您的示例中,员工作为一个完整的实体存在于HR中是有意义的。对于财务,您将拥有一个id和从财务角度来看有意义的字段。这里没有重复,因为模型有不同的用途(将其视为构成单词的重复字母,每个单词都是这些重复字母的组合,但它代表不同的概念)

将BC视为独立组件(项目、应用程序)。仅仅因为您在一个应用程序中有一些字段,并不意味着您应该在可能使用这些字段的每个应用程序中重复使用该对象。保持您的模型相互有界和独立。随着时间的推移,它们可能会以不同的方式演变


另外,问问自己财务部是否真的需要员工的地址或头衔或姓/名。您的用例将告诉您真正需要的数据。从概念名称和用例模型开始,这就是您如何找到相关属性和行为的方法。记住,YAGNI,如果没有它的用例,那么就没有对象/字段:D

我想我有一个问题,就是如果你有4个上下文,并且所有4个都以某种方式共享一些域模型对象(雇员)行为,你最终会重复代码,如果一个更改需要在行为上匹配,则需要执行4次,如果有道理的话!是的,这是有道理的。DDD方法倾向于生成大量代码,但复杂度不变。在这种情况下,BC上的更改不会影响其他BC。对我来说有道理。PS:更严格的setter属性,也有意义;)是的,我刚刚使用了一个肮脏的贫血类,因为我只是想得到一个基本的模型对象进行演示。这也应该对你有所帮助