简体   繁体   English

在实际项目中确定领域驱动设计中的实体和值对象

[英]Determining Entities and Value Objects in Domain Driven Design in a real project

This is for the first time I am implementing the concept of Domain Driven Design in a real project. 这是我第一次在实际项目中实现域驱动设计的概念。 The project is about generating a permit for employees which would enable them to enter company premises. 该项目是关于为员工签发许可证,使他们能够进入公司场所。 Through an Intranet site, an employee who already possesses an Employee ID, will be able to apply for a permit or apply for replacement of a permit, in case the permit is damaged or lost. 通过Intranet网站,已经拥有员工ID的员工将能够申请许可证或在许可证被损坏或丢失的情况下申请更换许可证。 And an administrator will process the applications and hand over a physical permit in the end. 管理员将处理申请并最终交出实际许可。

I have a couple of entities - User , Permit and one Value Object - Employee . 我有几个实体- UserPermit和一个价值对象- Employee

  • A User can be entirely identified by an Employee . User可以完全由Employee标识。 Should I create a UserId as well? 我也应该创建一个UserId吗? How do I handle the case in which the administrator may not only approve, but raise an application on behalf of an employee as well? 我该如何处理管理员不仅可以批准,还可以代表员工提出申请的情况?
  • The Value Object Employee has an Id property EmployeeId which I know goes against the principle of a Value Object. 值对象Employee有一个Id属性EmployeeId ,我知道这违反了值对象的原理。 However, in my case, Employee is read-only. 但是,就我而言, Employee是只读的。 It doesn't matter to me if I get only the EmployeeId or the Employee as a whole. 对于我来说,仅获得EmployeeId还是整个Employee都无关紧要。 Am I doing this right? 我这样做对吗?
  • The Permit entity contains a lot of properties. Permit实体包含许多属性。 How do I break down the properties of Permit into Value Objects? 如何将“ Permit的属性分解为“价值对象”?
public class User : Entity
{
    public Employee Employee { get; set; }
    public bool IsAdmin { get; set; }
}
public class Permit: Entity
{
    public int ApplicationId { get; set; }
    public string EmployeeId { get; set; }
    public string Type { get; set; }
    public string Status { get; set; }
    public DateTime RequestDate { get; set; }
    public DateTime IssuanceDate { get; set; }
    public string IssuanceReason { get; set; }
    public string SurrenderReason { get; set; }
}
public sealed class Employee : ValueObject<Employee>
{
    public string EmployeeId { get; private set; }
    public string Name { get; private set; }
    public string Department { get; private set; }
    public string Division { get; private set; }
    public string BirthDate { get; private set; }
    public string Designation { get; private set; }
    public string BloodGroup { get; private set; }
    public string SecurityLevel { get; private set; }
    public string EmploymentDate { get; private set; }
}

Apart from the concerns, I'd be grateful if someone could guide me to go about it in the most appropriate manner possible. 除了担心之外,如果有人可以引导我以最合适的方式进行处理,我将不胜感激。 Thanks. 谢谢。

You should create 3 entities 您应该创建3个实体

  • Employee 雇员
  • Permit 允许
  • User 用户

Give it all an UniqueId --> because they are entity's so they are unique When there is a relation , for example between User and Employee, You can use a value object Employee (so 2 VO's) 全部赋予一个UniqueId->,因为它们是实体的,所以它们是唯一的当在用户和Employee之间存在关系时,例如,您可以使用值对象Employee(所以2个VO)

From my point of perspective it would be better to discard the User class, as it closely resembles the Employee class. 从我的角度来看,最好丢弃User类,因为它与Employee类非常相似。

The property IsAdmin is a very hard constraint, from a broader perspective you could create an Enum that represents security groups. IsAdmin属性是一个非常严格的约束,从更广泛的角度来看,您可以创建一个代表安全组的Enum This enables you to implement security for certain areas where given group X has access and group Y does not. 这使您可以为给定组X可以访问而组Y没有访问的某些区域实施安全性。 This could replace the string SecurityLevel in the Employee class. 这可以替换Employee类中的string SecurityLevel You could also implement these security groups in the Permit class. 您也可以在Permit类中实现这些安全组。

The Permit class should be used by the Employee class. Permit类应由Employee类使用。 A user can have multiple permits, active and non-active. 一个用户可以有多个许可,包括活动许可和非活动许可。 A boolean value defining that logic should be implemented into the Permit class. 定义应该在Permit类中实现的逻辑的布尔值。 By implementing the active/non-active boolean in the Permit class, you could revoke access by simply switching the value of the boolean. 通过在Permit类中实现活动/非活动布尔值,您可以通过简单地切换布尔值来撤消访问。

In modeling business processes, it will often help to think about the paperwork , rather than the things in the real world. 在对业务流程进行建模时,通常会考虑到文书工作 ,而不是现实世界中的事情。 The process begins when somebody files a request document, it ends when the adminstrator files an approval or a rejection, and so on. 当有人提交请求文档时,该过程开始;当管理员提交批准或拒绝等时,该过程结束。 The domain model's job is to do the bookkeeping, and to perform some of the logic on behalf of the business. 领域模型的工作是进行簿记,并代表业务执行一些逻辑。

See 看到

Should I create a UserId as well? 我也应该创建一个UserId吗?

If you need to handle the case where the person submitting the request is different from the person the permit is assigned to, then you should absolutely treat those as different values. 如果您需要处理提交请求的人与被分配许可的人不同的情况,那么您绝对应该将这些人视为不同的值。

It doesn't matter to me if I get only the EmployeeId or the Employee as a whole. 对于我来说,仅获得EmployeeId还是整个Employee都无关紧要。 Am I doing this right? 我这样做对吗?

Yes - there is nothing wrong with an immutable value having an identifier. 是的-具有标识符的不可变值没有错。

In more sophisticated models, value objects will often be composed from other value objects. 在更复杂的模型中,价值对象通常将由其他价值对象组成。 For example, event though EmployeeId and BloodGroup are opaque character sequences, it's probably not OK to pass a blood group to a method that is expecting an employee id, or vice versa. 例如,尽管EmployeeIdBloodGroup是不透明的字符序列,但如果将血型传递给需要雇员ID的方法,则可能BloodGroup ,反之亦然。 So rather than leaving things "stringly typed", we might invest more work in the model to make those concepts explicit. 因此,我们可能不做任何“字符串类型化”的事情,而是可能在模型中投入更多的工作来使这些概念明确。

How do I break down the properties of Permit into Value Objects? 如何将“许可证”的属性分解为“价值对象”?

Again, values can be composed from other values. 同样,值可以由其他值组成。 If there is a subset of cohesive properties, group them together. 如果存在内聚性的子集,请将它们组合在一起。

Scott Wlaschin's Domain Modeling Made Functional is a great reference here. Scott Wlaschin的功能性领域建模是一个很好的参考。

Part of the point of "objects" is that we should be able to change the in memory data structures and still have everything "work". “物”的的部分原因是,我们应该能够改变内存中的数据结构,仍然拥有一切“工作”。 So you shouldn't feel like you are committed to a particular in memory layout. 因此,您不应感到自己致力于内存布局中的特定事项。

(Note: it's really easily to couple your in memory layout to your persistent storage -- that will make things harder to change later; so try not to fall into that trap more than once.) (注意:将您的内存布局与持久性存储耦合起来真的很容易-这会使事情在以后很难更改;因此,请避免多次陷入该陷阱。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM