我在弄清楚如何使我的设计松散耦合方面遇到了一些麻烦。具体来说,如何将业务逻辑和规则实现到域模型中,以及在何处放置代码的不同部分 - 即文件夹结构。
澄清我对术语的理解:
业务逻辑:特定领域的问题解决方案
业务规则:域特定规则
域模型:特定于域的现实世界对象的抽象,例如一名雇员
假设我们有一家员工公司。每个员工都必须有一个安全号码(业务逻辑)。安全号码必须至少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;
}
}
我看到这种方法存在一些问题......
要解决第二个问题,我可以为Employee
类创建一个构造函数,如下面的那个
public function __constructor(string $name,
string $securityNumber,
SecurityNumberValidatorInterface $validator) {
$this->name = $name;
$this->setSecurityNumber($securityNumber, $validator);
}
这可能是一个反模式,因为在构造函数中调用了一个setter ...
有什么更好的方法呢?是完全从Employee
模型中删除验证器,而是去工厂或门面吗?
答案 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中,有一个名为“原始痴迷”的反模式,您的思维可能深陷于此陷阱中。