0

I wrote a function for getting data out of a array. A part in that function is verification of the data, it checks if the key is NOT empty and if the array key does NOT exists (my bad after the edit). The function looks like this:

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];
}

After applying the SRP princple, by putting the 'verification' into another class, it looked like this:

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];
}

From both of these snippets, I expected the same result, because I put the ! operator before the isPresent function, making it check if the condition is false.

How does this come the boolean expressions are not the same and dont give the same result?

Bas
  • 2,106
  • 5
  • 21
  • 59
  • 2
    see De Morgan's law (https://en.wikipedia.org/wiki/De_Morgan%27s_laws): `!(A && B) == (!A) || (!B)` – king_nak Jan 27 '16 at 14:39

4 Answers4

2

You wrote "A part in that function is verification of the data, it checks if the key is NOT empty and if the array key exists.", so you should do this:

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];
}

Note that since you don't catch your exception, the code after throw won't get executed! Here, you're missing an ! before empty().

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

And the end should look like this:

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];
}

Read PHP Exception handling and since you're confusing boolean logig, De Morgan's laws.

steffen
  • 16,138
  • 4
  • 42
  • 81
  • @DownVoter -- care to comment? – steffen Jan 27 '16 at 14:41
  • You changed the semantic of the `getData()` function. Its original purpose was to return a value (given a non-empty valid key) or the entire array of data (when an empty string is provided as key). Your version removed the latter. – axiac Jan 27 '16 at 14:54
  • I just noticed a mistake in my own question, I ment to say that I had to check aswell if the array key didn't expect aswell. I like the explaination though. – Bas Jan 27 '16 at 14:54
  • @axiac I started my answer with a quotation which didn't match the implementation and which I chose to rely on. Since the OP apparently did confuse De Morgan, it's not a good idea to interpret the source code. I chose his description instead. – steffen Jan 27 '16 at 15:17
1

!A && !B is not the same as !(A && B). One only has to look at the case where one variable is true (let's pick A) and the other is false:

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

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

However, !A && !B is equivalent to !(A || B):

!(true || false) --> !(true) --> false
John Sensebe
  • 1,386
  • 8
  • 11
  • And if you relate this to the actual question, you may get upvotes instead of ignored or downvotes! – RiggsFolly Jan 27 '16 at 14:39
  • @RiggsFolly The actual question is "How does this come the boolean expressions are not the same and dont give the same result?" – John Sensebe Jan 27 '16 at 14:41
0

The body of function isPresent() should be:

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

You started from:

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

and that is equivalent to:

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

On the next step, moving the condition into the isPresent() method leads to the code exposed above.

axiac
  • 68,258
  • 9
  • 99
  • 134
-1

These two lines aren't the same:

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

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

By De Morgan's:

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

Since your return version is being negated at the calling point, you're effectively executing the !P || !Q version, which is not quite the same as your && in the if.

Marc B
  • 356,200
  • 43
  • 426
  • 500