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

时间:2014-02-20 15:06:33

标签: 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()
    {
        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函数中使用...

1 个答案:

答案 0 :(得分:0)

只要验证函数不需要外部资源,我就会直接重用依赖项并避免它的注入。

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

示例中的Email类应该是电子邮件地址验证的单点故障。如果所有域对象都通过该类验证电子邮件,那么重用现有框架(甚至第三方)功能是一个实现细节,而不是松散耦合的问题。如果验证规则发生变化,您无论如何都必须重新实现该功能 - 使用Zend_Validate_Email或一些自定义代码。

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

  • 属于域对象的逻辑将被移动到另一个类
  • 将服务注入实体通常是not advised
  • 仅为EmailValidator类引入界面违反了Reused Abstractions Principle
  • isValid上调用静态EMail方法是不可能的

只有在验证逻辑需要外部资源的极少数情况下,我倾向于使用具有注入服务的工厂,该服务在创建域对象时进行验证 - 但仅在重新考虑域模型的设计之后。