Я написал функцию для получения данных из массива. Часть этой функции — проверка данных, она проверяет, не является ли ключ пустым и не существует ли ключ массива (мой плохой после редактирования). Функция выглядит так:
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
функция, проверяя, является ли условие ложным.
Как это получается, что логические выражения не одинаковы и не дают одинакового результата?
!A && !B
это не то же самое, что !(A && B)
, Нужно только взглянуть на случай, когда одна переменная равна true (давайте выберем A), а другая — false:
!true && !false --> false && true --> false
!(true && false) --> !(false) --> true
Тем не мение, !A && !B
является эквивалентно !(A || B)
:
!(true || false) --> !(true) --> false
Вы написали: «Часть в этой функции — проверка данных, она проверяет, не является ли ключ пустым и существует ли ключ массива», поэтому вы должны сделать это:
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 и так как вы путаете логическую логику, Законы де Моргана.
Тело функции 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()
Метод приводит к приведенному выше коду.
Эти две строки не совпадают:
if (!empty($key) && !array_key_exists($key, $this->data)) {
return empty($key) && array_key_exists($key, $data);
Де Морган:
!(P && Q) -> (!P) || (!Q)
Так как ваш return
версия отменяется в точке вызова, вы эффективно выполняете! P || ! Q версия, которая не совсем совпадает с вашей &&
в if
,