Oop 在松耦合设计中使用基础结构类

Oop 在松耦合设计中使用基础结构类,oop,domain-driven-design,loose-coupling,value-objects,Oop,Domain Driven Design,Loose Coupling,Value Objects,我有一个关于松散耦合OOP设计的问题。 考虑一下我们有一个简单的值对象,比如电子邮件 final class Email { private $_email; public function __construct($email) { self::isValid($email); $this->_email = $email; } public function getEmail() {

我有一个关于松散耦合OOP设计的问题。 考虑一下我们有一个简单的值对象,比如电子邮件

final class Email 
{
    private $_email;

    public function __construct($email)
    {
        self::isValid($email);
        $this->_email = $email;
    }

    public function getEmail()
    {
        return $this->_email;
    }

    public static function isValid($email)
    {
    // some validation logic goes here  
        return true;
    }
}

在我真正实现isValid方法之前,一切都是简单明了的。 我有两个选择:

1) 实现我自己的验证逻辑,它可能非常丑陋,比如:

public static function isValid($email)
{
    $v = preg_match(
        '/^[-a-z0-9!#$%&\'*+\/\=?^_`{|}~]+(?:\.[-a-z0-9!#$%&\'*+\/\=?^_`{|}~]+)*@(?:[a-z0-9]([-a-z0-9]{0,61}[a-z0-9])?\.)*(?:aero|arpa|asia|biz|cat|com|coop|edu|gov|info|int|jobs|mil|mobi|museum|name|net|org|pro|tel|travel|pro|[a-z][a-z])$/',
        $email
    );

   return $v > 0;
}
2) 使用一些内置框架验证器

 public static function isValid($email)
 {
        $validator = new Zend_Validate_Email(); // tight-coupling detected!
        return $validator->isValid($email);
 }
我真的不想走第一条路,因为我不想重新发明轮子,也不想重复代码,所以我坚持走第二条路

如果我遵循第二种方法,我就会遇到问题——我的类依赖于另一个框架类

我的实际问题是在简单情况下不使用依赖项注入而直接在实体/值对象中使用低级基础结构类是否可以接受


如果我“正确地”实现这个示例,那么仅仅为了松耦合的目的,代码就会变得更加复杂。我必须创建一个EmailFactory,它将为我的Value Object(Email)类提供一个预配置的EmailValidator实例,该实例将在isValid函数中使用…

只要验证函数不需要外部资源,我将直接重用依赖项并避免其注入

域对象封装域规则,并应包含确保这些规则的所有必要信息。它更多地围绕着高内聚性而不是低耦合性进行设计(聚合的概念本身就是减少相互依赖性的一种手段)

示例中的
Email
类应该是电子邮件地址验证的单点故障。如果所有域对象都通过该类验证电子邮件,那么重用现有的框架(甚至第三方)功能是一个实现细节,并且不再是松耦合的问题。如果验证规则发生更改,您将不得不重新实现该功能-使用
Zend\u Validate\u Email
或一些自定义代码

将验证逻辑注入实体或值对象会带来很多问题:

  • 属于域对象的逻辑将被移动到另一个类
  • 向实体中注入服务通常是很困难的
  • 仅为
    EmailValidator
    类引入接口违反了
  • 电子邮件上调用静态
    isValid
    方法是不可能的

只有在验证逻辑需要外部资源的罕见情况下,我才倾向于使用一个带有注入服务的工厂,该工厂在创建域对象时进行验证——但只有在重新考虑域模型的设计之后才进行验证。

如果内置框架验证器只是封装逻辑的“功能”,并且不依赖于任何状态或上下文。