我正在尝试实现一个简单的验证器类系统,它遵循SOLID原则和单元测试目的。
假设我有一些简单的验证器(强制,整数,更大......),现在我想实现一个更复杂的验证器,它调用几个简单的验证器(例如Form Validator使用一些验证器)
这非常受Zend和其他框架的启发。
问题是,这里如何应用或违反SOLID原则以及如何对此模型进行单元测试?
我认为我可以轻松地对每个简单的验证器进行单元测试,但不能复杂的FormValidator
interface ICheckable
{
public function check($data);
}
class MandatoryValidator implements ICheckable
{
private $_property;
public function __construct($property)
{
$this->_property = $property;
}
public function check($data)
{
return isset($data[$property]);
}
}
class IntegerValidator implements ICheckable
{
...
}
class FormValidator implements ICheckable
{
public function check($data)
{
$mandatoryValidator = new MandatoryValidator(array('LOGIN'));
if ($mandatoryValidator->check($data) == false)
{
return false;
}
$integerValidator = new IntegerValidator();
if ($integerValidator->check($data['AMOUNT']) == false)
{
return false;
}
...
return true;
}
}
答案 0 :(得分:3)
首先 - 使用ICheckable接口做得很好。这是一个好的开始。
让我们解决S.单一责任原则:
这就是说“一个班级应该只有一个改变的理由”的原则 S.在所有课程中都受到尊重吗? (简单的责任。)
目前有两个验证人员对此表示尊重。
FormValidator只有一个责任吗?我可以看到它有三件事:
这种设计的问题在于,每次有新的Validator时,都必须创建它,调用它并检查其返回值。这违反了SOLID原则中的O. (打开/关闭)
表单Validator应该收到ICheckable的“自定义”列表。这个“自定义”列表也应该强制ICheckable,所以你可以调用它。这个“自定义”列表将遍历其ICheckable列表。那将是唯一的责任。
然后,必须评估结果。当函数返回值时,您必须处理它。一般来说,这意味着更多的代码,一个额外的IF语句。这两个应该给你一个提示:责任太多了。
因此,为了实现此SOLID,您应该向验证器传递一个回调接口,该接口将用于处理验证器输出。您的示例非常简单,验证器返回true为false。哪个可以用两个“输出”方法表示 - Validated()或ValidationFailed()。 O_o,这看起来像验证器的一个非常好的“输出”接口,可以由FormValidator实现。该设计符合S. O. L. I. D.的原则。
请记住,当您第一次创建FormValidator时,您必须创建两个验证器,自定义列表并将所有内容连接在一起。
然后,您可以非常快速地对所有非常简单的类进行单元测试。 (尝试先开始编写测试)
注意:一般来说,如果你正确处理S.其他原则很容易实现。
希望这会有所帮助。如果您需要更多信息,请与我们联系。