类中的ANDING布尔表达式和单个if语句的意外输出

时间:2016-01-27 14:31:00

标签: php oop single-responsibility-principle

我编写了一个从数组中获取数据的函数。该函数的一部分是对数据的验证,它检查密钥是否为空以及数组密钥是否不存在(编辑后我的错误)。该函数如下所示:

public function getData($key = "")
{
    if (!empty($key) && !array_key_exists($key, $this->data)) {
        throw new ConfigurationException("$key does not exist");
    }
    return empty($key) ? $this->data : $this->data[$key];
}

应用SRP原则后,将'验证'放入另一个类中,它看起来像这样:

class ConfigurationVerificationHandler
{

    public function isPresent($key, array $data)
    {
        return empty($key) && array_key_exists($key, $data);
    }
}

public function getData($key = "")
{
    $verificationHandler = new ConfigurationVerificationHandler();
    if (!$verificationHandler->isPresent($key, $this->data)) {
        throw new ConfigurationException("$key does not exist");
    }
    return empty($key) ? $this->data : $this->data[$key];
}

从这两个片段中,我期望得到相同的结果,因为我将!运算符放在isPresent函数之前,使其检查条件是否为假。

这是怎么来的布尔表达式不一样,不会给出相同的结果?

4 个答案:

答案 0 :(得分:2)

您写道“该功能的一部分是对数据的验证,它检查密钥是否为空并且数组密钥是否存在。”,所以您应该这样做:

public function getData($key = "")
{
    // Throw exception if key is empty OR array-key does not exist
    if (empty($key) || !array_key_exists($key, $this->data)) {
        throw new ConfigurationException("$key does not exist");
    }
    // This won't be executed if $key is empty or does not exist
    return $this->data[$key];
}

请注意,由于您没有捕获异常,throw之后的代码将无法执行!在这里,您在!之前错过了empty()

public function isPresent($key, array $data)
{
    return !empty($key) && array_key_exists($key, $data);
}

最终应该是这样的:

public function getData($key = "")
{
    $verificationHandler = new ConfigurationVerificationHandler();
    if (!$verificationHandler->isPresent($key, $this->data)) {
        throw new ConfigurationException("$key does not exist");
    }
    // $key can't be empty here
    return $this->data[$key];
}

阅读PHP Exception handling,因为您混淆了布尔logig,De Morgan's laws

答案 1 :(得分:1)

!A && !B!(A && B)不同。人们只需看一个变量为真的情况(让我们选择A)而另一个是假的:

!true && !false --> false && true --> false

!(true && false) --> !(false) --> true

但是,!A && !B 等同于!(A || B)

!(true || false) --> !(true) --> false

答案 2 :(得分:0)

函数体isPresent()应为:

public function isPresent($key, array $data)
{
    return empty($key) || array_key_exists($key, $data);
}

您从:

开始
if (! empty($key) && ! array_key_exists($key, $this->data)) {

,这相当于:

if (! (empty($key) || array_key_exists($key, $this->data))) {

在下一步中,将条件移至isPresent()方法会导致上面显示的代码。

答案 3 :(得分:-1)

这两行不一样:

if (!empty($key) && !array_key_exists($key, $this->data)) {

    return empty($key) && array_key_exists($key, $data);

De Morgan's:

 !(P && Q) -> (!P) || (!Q)

由于你的return版本在调用点被否定,你正在有效地执行!P || !Q版本,与&&中的if不完全相同。