0

我应该在设置域对象属性时验证它们吗?

在这个例子中,我从我的模型层获得了一个用户域对象,目前只是在设置属性之前验证传入参数的类型和/或格式,因为我不知道应该验证什么域对象。一些例子可以帮助我理解它。

这是我应该如何验证域对象属性还是根本不应该验证它们?

在后一种情况下,我可以删除每个 setter 和 getter,并将域对象属性公开,这样我就可以直接与它们交互。

class User
{
    private $id;
    private $firstname;
    private $lastname;
    private $email;
    private $password;
    private $registerDate;

    public function setId($id)
    {
        if (is_int($id)) {
            $this->id = $id;
        } else {
            throw new Exception('Parameter must be an integer.');
        }
    }

    public function setFirstname($firstname)
    {
        if (is_string($firstname)) {
            $this->firstname = $firstname;
        } else {
            throw new Exception('Parameter must be a string.');
        }
    }

    //{ etc setters }

    public function __get($property) {
        if (property_exists($this, $property)) {
            return $this->$property;
        }
    }
}
4

2 回答 2

0

我的建议是将验证逻辑从实体移动到类,从而持久化它们,无论是数据映射器、存储库还是其他东西。或者更好的是,为每个实体类型/聚合根单独的验证器类。

为什么?关注点分离。

让我们考虑验证。我看到两种验证器。第一个 - 类型/范围检查,例如,“用户名必须是字符串并且介于 5-50 个字符之间”。第二 - 域特定验证,例如,“电子邮件必须是唯一的”。域验证可能很昂贵,并且通常需要许多支持类(服务、数据映射器、数据库适配器等)。

于 2014-06-12T09:19:53.587 回答
0

在 99% 的情况下,在动态的弱类型语言中检查原始类型对我来说似乎是一种过度杀伤力。你$firstname是否是一个正确的字符串并不重要,它会在需要时被隐式转换为一个。

但是,有时检查作为参数传递的原语的值(不是它的type,请注意)是否满足某些特定的业务逻辑约束确实有意义:

function squareRoot($number) {
    if(!is_numeric($number) || $number < 0)
        throw new \InvalidArgumentException("Positive number expected.");
    return sqrt($number);
}

也就是说,我只会在绝对必要的时候使用这种官僚主义。如果有人想将一个非数字字符串传递给一个以setNumber($number)doctype 命名的方法,说明$number是一个数字,那么如果结果中发生了不好的事情,那就是他的问题了。

对于期望特定类型的对象(或实现特定接口)作为参数的方法,请改用类型提示:

function foo(BarObject $bar) {
    // ...
}

这也适用于数组:

function doStuffWithArray(array $a) {
    // ...
}

有趣的是,没有类型提示允许数组和对象都实现\ArrayAccess接口,但这只是 PHP 的许多怪癖之一。

于 2014-06-12T09:07:38.787 回答