Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Oop 业务规则分为两类_Oop_Design Patterns_Domain Driven Design_Ooad_Grasp - Fatal编程技术网

Oop 业务规则分为两类

Oop 业务规则分为两类,oop,design-patterns,domain-driven-design,ooad,grasp,Oop,Design Patterns,Domain Driven Design,Ooad,Grasp,我有一个具有以下业务规则的项目分配域 当一名新员工被分配到一个项目时,总支出不得超过预算金额。 对于员工,总分配百分比不得超过100% 我已经创建了如下所示的实体,这些实体是用C创建的 问题: 分配逻辑分为两个类–Project和Employee..列表 有什么行为要求客户拥有订单列表?当您更多地考虑域的行为时,即在什么时候需要什么数据时,您可以基于用例对聚合进行建模,事情变得更加清晰和容易,因为您只需要对聚合边界中的一小部分对象进行更改跟踪 我怀疑Customer应该是一个没有订单列表的单独聚

我有一个具有以下业务规则的项目分配域

当一名新员工被分配到一个项目时,总支出不得超过预算金额。 对于员工,总分配百分比不得超过100% 我已经创建了如下所示的实体,这些实体是用C创建的

问题:

分配逻辑分为两个类–Project和Employee..列表

有什么行为要求客户拥有订单列表?当您更多地考虑域的行为时,即在什么时候需要什么数据时,您可以基于用例对聚合进行建模,事情变得更加清晰和容易,因为您只需要对聚合边界中的一小部分对象进行更改跟踪

我怀疑Customer应该是一个没有订单列表的单独聚合,而Order应该是一个有订单行列表的聚合。如果需要对客户的每个订单执行操作,请使用orderRepository.GetOrdersForcustomerId;进行更改,然后使用orderRespository.Saveorder


业务规则也与现有分配相关。让分配成为工厂中的聚合和包装业务规则怎么样?比如:

public Allocation Allocate(Project project, Role newRole, int newPercentage, Employee newEmployee)
{
     List<Allocation> existingAllocationsInProject = allocationRepository.findBy(project);
     //validate project rule
     List<Allocation> existingAllocationsInEmployee = allocationRepository.findBy(newEmployee);
     //validate employee rule
}

因此,在这种情况下,我们不必担心如何找到现有的分配。并且可以使用规范模式进一步重构规则有效性。

业务规则也与现有分配相关。让分配成为工厂中的聚合和包装业务规则怎么样?比如:

public Allocation Allocate(Project project, Role newRole, int newPercentage, Employee newEmployee)
{
     List<Allocation> existingAllocationsInProject = allocationRepository.findBy(project);
     //validate project rule
     List<Allocation> existingAllocationsInEmployee = allocationRepository.findBy(newEmployee);
     //validate employee rule
}
因此,在这种情况下,我们不必担心如何找到现有的分配。规则有效性可以使用规范模式进行进一步重构。

我有几点意见:

分离分配逻辑是正确的做法

考虑将分配逻辑移动到服务类,例如ProjectService和EmployeeService,以便域模型可以是无逻辑的

考虑添加一个新的AllocationService类来操作分配

public void Allocate(Project project, Role role, Employee employee, int percentage)
{
      // Fetch allocation from allocation repository
      var allocations = _allocationRepository.GetAllocations(project.Id);

      // project allocation logic
      if (!_projectService.Allocate(Project, Role, int percentage))
      {
          // throw exception
      }

      // allocate to employee
      if(!_employeeService.Allocate(employee, role, percentage))
      {
          // throw exception
      }

      // create new allocation
      _allocationRepository.Add(new Allocation
            {
                ......
            });
}
分配存储库和服务可以通过构造函数注入,例如

public interface IAllocationRepository
{
       IEnumerable<Allocation> GetAllocationsByProject(Project project);

       IEnumerable<Allocation> GetAllocationsByEmployee(Employee employee);

       void Add(Allocation);
}
IAllocationRepository也可以注入到EmployeeService和ProjectService中,因此您不需要传递分配列表

我有几点意见:

分离分配逻辑是正确的做法

考虑将分配逻辑移动到服务类,例如ProjectService和EmployeeService,以便域模型可以是无逻辑的

考虑添加一个新的AllocationService类来操作分配

public void Allocate(Project project, Role role, Employee employee, int percentage)
{
      // Fetch allocation from allocation repository
      var allocations = _allocationRepository.GetAllocations(project.Id);

      // project allocation logic
      if (!_projectService.Allocate(Project, Role, int percentage))
      {
          // throw exception
      }

      // allocate to employee
      if(!_employeeService.Allocate(employee, role, percentage))
      {
          // throw exception
      }

      // create new allocation
      _allocationRepository.Add(new Allocation
            {
                ......
            });
}
分配存储库和服务可以通过构造函数注入,例如

public interface IAllocationRepository
{
       IEnumerable<Allocation> GetAllocationsByProject(Project project);

       IEnumerable<Allocation> GetAllocationsByEmployee(Employee employee);

       void Add(Allocation);
}
IAllocationRepository也可以注入到EmployeeService和ProjectService中,因此您不需要传递分配列表

分配逻辑分为两类-项目和员工

我不会这样做,因为这会分割分配责任,从而打破单一责任原则。如果您发现它既不属于项目也不属于员工,则a可以执行此项工作。通常,涉及不构成同一聚合一部分的多个实体的操作是位于此类服务中的候选操作

列表,因此,它甚至可能是一个值对象。确保第一项限制(分配时不超过预算)得到满足的责任属于项目实体,并可在员工分配时执行

第二个棘手的约束是:员工在几个项目中的分配不超过100%。在这种情况下,您可能有兴趣提供方法来获取分配给特定员工的那些项目,可能是通过您的项目存储库。您还可以提供一个用于检查的操作,以提供给定员工的总分配,可能是通过域服务

请注意,您实际上是在项目类的Allocate方法中执行所有这些逻辑:首先通过GetAllocationsForEmployee获得所有分配,然后将检索到的列表传递给Employee.Allocate,它实际上可以命名为CanBeAllocated。您可能会觉得确保这一业务逻辑是员工的责任,但我认为这与员工的属性和行为没有多大关系,因此,它应该是项目的一部分。如果您一直觉得职责混杂,请分配方法或域服务

最后一点要注意的是,如果在前面的评论中出现了一些混乱,那么将逻辑放入模型类中并没有错,它实际上是整个领域建模的一个基本部分!本文对此提供了一些很好的见解

分配逻辑分为两类-项目和员工

我不会 这样做是因为它分割了分配责任,从而打破了单一责任原则。如果您发现它既不属于项目也不属于员工,则a可以执行此项工作。通常,涉及不构成同一聚合一部分的多个实体的操作是位于此类服务中的候选操作

列表,因此,它甚至可能是一个值对象。确保第一项限制(分配时不超过预算)得到满足的责任属于项目实体,并可在员工分配时执行

第二个棘手的约束是:员工在几个项目中的分配不超过100%。在这种情况下,您可能有兴趣提供方法来获取分配给特定员工的那些项目,可能是通过您的项目存储库。您还可以提供一个用于检查的操作,以提供给定员工的总分配,可能是通过域服务

请注意,您实际上是在项目类的Allocate方法中执行所有这些逻辑:首先通过GetAllocationsForEmployee获得所有分配,然后将检索到的列表传递给Employee.Allocate,它实际上可以命名为CanBeAllocated。您可能会觉得确保这一业务逻辑是员工的责任,但我认为这与员工的属性和行为没有多大关系,因此,它应该是项目的一部分。如果您一直觉得职责混杂,请分配方法或域服务


最后一点要注意的是,如果在前面的评论中出现了一些混乱,那么将逻辑放入模型类中并没有错,它实际上是整个领域建模的一个基本部分!提供了一些很好的见解。

无逻辑域模型的优势是什么?域逻辑不应该驻留在doamin实体中吗?有什么好的参考来证明这一点吗?好吧,这些模型将是数据库表的1-2-1映射。然后,您可以创建一个“实体”,用业务逻辑来包装模型。在这种情况下,服务充当您的域实体。域模型没有逻辑的优势是什么?域逻辑不应该驻留在doamin实体中吗?有什么好的参考来证明这一点吗?好吧,这些模型将是数据库表的1-2-1映射。然后,您可以创建一个“实体”,用业务逻辑来包装模型。在这种情况下,服务充当您的域实体。它不会成为一个贫血的域模型吗?OOP的信息专家方面在这里丢失了,不是吗?Reference@eulerfx我在这里引用了你的帖子?你有不同的建议吗?@Lijo这是决定代码归属的责任。我个人更喜欢引入一个特定的概念对象,如果它不属于任何一个对象或者似乎属于多个对象。它不会成为一个贫乏的领域模型吗?OOP的信息专家方面在这里丢失了,不是吗?Reference@eulerfx我在这里引用了你的帖子?你有不同的建议吗?@Lijo这是决定代码归属的责任。我个人更喜欢引入一个特定的概念对象,如果它不属于任何一个对象或者似乎属于多个对象。2.3.参考文献1。2.3.