业务逻辑和规则 - 如何将它们与域模型分离

时间:2018-05-31 07:29:29

标签: oop design-patterns business-rules decoupling business-logic-layer

我在弄清楚如何使我的设计松散耦合方面遇到了一些麻烦。具体来说,如何将业务逻辑和规则实现到域模型中,以及在何处放置代码的不同部分 - 即文件夹结构。

澄清我对术语的理解:
业务逻辑:特定领域的问题解决方案 业务规则:域特定规则 域模型:特定于域的现实世界对象的抽象,例如一名雇员

所以,让我们做一个简单的例子

假设我们有一家员工公司。每个员工都必须有一个安全号码(业务逻辑)。安全号码必须至少10个字符(业务规则)。

我在建模时的镜头看起来像是:

# Conceptual model of an employee within the company
class Employee {

    private $name;
    private $securityNumber;

    // Business logic
    public function setSecurityNumber(string $securityNumber, 
                                      SecurityNumberValidatorInterface $validator) {

        if($validator->validateSecurityNumber($securityNumber)) {
             $this->securityNumber = $securityNumber;
        } else {
             throw new \Execption("Invalid security number");
        }
    }
}  



# Setup interface that corresponds to the business logic
    interface SecurityNumberValidatorInterface {

    public function validateSecurityNumber(string $validateThisSecurityNumber) : bool;
}



# Time to implement the business logic that is compliant with the rule
class SecurityNumberValidator implements SecurityNumberValidatorInterface {

    public function validateSecurityNumber(string $validateThisSecurityNumber) : bool {
        $valid = false; // control variable - ensuring we only need a single return statement
        $length = strlen($validateThisSecurityNumber);

        if ($length < 10) {
            $valid = true;
        }

       return $valid;
    }
}


我看到这种方法存在一些问题......

  1. 设置安全号码需要您沿着传递对象 安全号码本身。对于一个二传手来说,我觉得这看起来有点讨厌。
  2. 员工对象可能会无效 状态,因为它可以在不设置的情况下实例化它们 安全号码
  3. 要解决第二个问题,我可以为Employee类创建一个构造函数,如下面的那个

    public function __constructor(string $name,
                                  string $securityNumber,
                                  SecurityNumberValidatorInterface $validator) {
    
        $this->name = $name;
        $this->setSecurityNumber($securityNumber, $validator);
    }
    


    这可能是一个反模式,因为在构造函数中调用了一个setter ...
    有什么更好的方法呢?是完全从Employee模型中删除验证器,而是去工厂或门面吗?

2 个答案:

答案 0 :(得分:0)

因为&#34;每个员工都必须有一个安全号码&#34;对于您来说,业务逻辑是一种业务逻辑,与Employee不一致的业务定义不包括securityNumber属性,因为此业务之外的员工可能没有安全号码。相反,您可以编写一个特定于业务的类BusinessNameEmployee来扩展employee,并将安全号作为该类的属性。您可以选择考虑使用IEmployee接口而不是Employee类。然后可以将BusinessRules类(包含长度验证程序)传递给BusinessNameEmployee的构造函数。

答案 1 :(得分:0)

有一个方法叫值对象,它是实体的一部分。在这种情况下,您可以将安全号码包装在调用SecurityNumber的Class(这是一个值对象)中,然后在其中添加验证。您可以参考以下示例:https://kacper.gunia.me/ddd-building-blocks-in-php-value-object/

在DDD中,有一个名为“原始痴迷”的反模式,您的思维可能深陷于此陷阱中。