Уменьшить количество условных выражений


у меня есть небольшая функция, которая доставляет значение с более высоким приоритетом, которое на данный момент нигде не определено, только по порядку, как я оцениваю значения:

public function obtenerValorMasImportante($datos = null) {

    if ($datos->getDato1()) {
        return 'dato1';
    }
    if ($datos->getDatoX()) {
        return 'datox';
    }
    if ($datos->getLoQueSea()) {
        return 'loquesea';
    }
    if ($datos->getOtraCosa()) {
        return 'otracosa';
    }
    return false;
}

проблема проста: код работает, но Что делать, если у меня есть 100 значений? мне нужно будет написать 100 if, и это не очень хорошая идея, у меня нет идей в это время дня.

У меня нет большего контроля над объектом $datos, поэтому это не так возможность изменить или добавить к нему информацию.

¿Как я могу уменьшить количество if? или в противном случае сделать код независимым от количества значений.

Author: Shaz, 2016-08-16

3 answers

Речь идет не о том, что eval является "плохим", другим недостатком является то, что вы не можете легко поймать ошибки, и код не переносится на PHP 7, поскольку оператор return должен быть обязательно включен или он вернет NULL.

Кроме того, не нужно использовать eval. Вы можете динамически вызывать метод с помощью call_user_func.

Хотя в примере имя метода и возвращаемое значение на один 'get' меньше в строке и возвращает strtolower($nombre_metodo), предположим, что это не так, и что мы должны сопоставить имена вызываемых методов с разрозненными значениями:

function obtenerValor($datos = null) {    
    $mapMetodoAValor = [
        'Dato1' => 'valorRetorno1',
        'DatoX' => 'valorRetornoOtro',
        /* siguen más metodos => valor ...*/
    ];
    foreach($mapMetodoAValor as $metodo => $valor) {
        if(call_user_func([$datos, 'get' . $metodo])) {
            return $valor;
        }
    }
    return false;
}

Если значения всегда равны strtolower($metodo) массив может быть проще, как пример Альваро, но опять же, нет необходимости использовать eval. Вы всегда предпочитаете call_user_func

 5
Author: Jesús Franco, 2016-08-16 23:49:03

Поскольку все условные выражения имеют одинаковую базовую структуру, это случай, когда вы можете использовать eval. Идея состояла бы в том, чтобы вы изменили функцию, чтобы сделать что-то вроде этого:

  1. создает массив со списком (отсортированным по порядку приоритета) с именами проверяемых атрибутов
  2. проходит через список от первого элемента до последнего
    1. С eval присваивает значение геттера переменной вспомогательный
    2. проверяет значение вспомогательной переменной
    3. если он имеет какое-либо значение, он возвращает имя элемента массива.

Код будет выглядеть так:

function obtenerValorMasImportante($datos = null) {    
    $aux = array("Dato1", "DatoX", "LoQueSea", "OtraCosa");
    $val = null;
    for ($x = 0; $x < count($aux); $x++) {
        eval('$val = $datos->get' . $aux[$x] . '();');
        if ($val)
            return strtolower($aux[$x]);
    }
    return false;
}

Итак, теперь единственное, что вам нужно сохранить, это список атрибутов, отсортированных по приоритету.

Да, я знаю, что будут люди, которые скажут: "но eval это дьявольски и не должно использоваться", но это не совсем правильно, особенно для этого случая, потому что вы будете контролируйте все, что должно быть оценено, поэтому вы не рискуете сделать eval с неизвестным входом.

 4
Author: Alvaro Montoro, 2016-08-16 21:47:17

Основываясь на ответах, предоставленных Альваро и Хесусом (новые ответы приветствуются), я закончил тем, что использовал этот код, используя переменные функции:

public function obtenerValorMasImportante($datos = null) {

    $valores = ['Dato1', 'DatoX', 'LoQueSea', 'OtraCosa'];

    foreach ($valores as $valor) {
        $metodo = 'get' . $valor;

        if ($datos->{$metodo}()) {
            return strtolower($valor);
        }
    }
    return false;
}
 3
Author: Shaz, 2016-08-17 01:28:25