@AFI19

Рефакторинг кода. Как оптимизировать количество if?

Есть код, который принимает json данные и в зависимости от типа выполнить определённые действия.
Весь код обработки находится в if'ах, добавление новых типов оказалось неудобным.
Сейчас планирую вынести обработку в отдельные сервисы под каждый тип, а информацию передавать с помощью DTO. Но, это все равно не избавляет от сложности и количество if. Рассматривал возможность заменить на switch/match, но, такой вариант кажется не совсем верным. С похожей проблемой столкнулся и в другой части кода, где нужно обрабатывать по-разному в зависимости от состояния.
if ('text' === $message->getType()) {
    // code
}
if ('poll' === $message->getType()) {
    // code
}
if ('image' === $message->getType()) {
    // code
}

С ООП немного знаком в теории, на практике, осмысленно, применять получается редко.
Насколько я знаю в решении проблемы должен помочь полиморфизм, но, как правильно его применить не пойму.
  • Вопрос задан
  • 313 просмотров
Пригласить эксперта
Ответы на вопрос 5
samodum
@samodum
Какой вопрос - такой и ответ
Reflection
Паттерн Стратегия
Ответ написан
Комментировать
@rPman
Вместо if в таких случаях используют switch case.

Альтернатива - определи map с ключом твои сравниваемые значения и значением делегат Func или экземпляр класса с виртуальным методом. Но что бы ты не делал, синтаксически это не добавит тебе простоты, а просто переместит в другое место определение кода и сравниваемое значение.

Есть еще препроцессор #if или даже собственный кодогенератор, иногда оно оправдано.

Городить что то сложнее switch нужно, когда логика, стоящая внутри кода около каждого из вариантов значения, может быть свернута в общий единый код или наоборот, он весь сводится к коротким инструкциям,красиво смотрящимся в виде анонимных функций, которые неплохо смотрятся в виде констант иннициализатора map
Ответ написан
Комментировать
Skiphog
@Skiphog
Crutch developer. Looking for a job.
Вариантов реализации множество, но если по простому, что можно поступить так:
Создать одноименные методы в зависимости от ожидаемых типов, которые может вернуть $message->getType();
И собственно их и вызывать ))
Так вы избавитесь от кучи if и код каждой реализации разместите в свои методы.

Псевдокод:
public function resolve()
{
    // ....

    $type = $message->getType();
    
    // Если такого метода не существует, то можно бросить Исключение или еще как-то обработать ошибку
    // А можно вообще ничего не проверять, а сделать обработку в __call(). Вариантов тоже много
    if (!method_exists($this, $type)) {
        throw new Exception(...);
    }
    
    // Вызвать подходящий метод
    return $this->$type(); //либо call_user_func...()
}

protected function text()
{
    //code
}

protected function poll()
{
    //code
}

protected function image()
{
    //code
}

По примерно такой же схеме можно использовать отдельные классы, сервисы и т.п.
Ответ написан
Комментировать
MaxAlexQNEI
@MaxAlexQNEI
Web-Developer
Ответы выше имеют для вас полезную информацию как и ответ на вопрос.
Однако вот еще мнение, что бы оптимизировать ваш (возможно) пример кода:

$type = $message->getType();

if ('text' === $type) {
    // code
}
if ('poll' === $type) {
    // code
}
if ('image' === $type) {
    // code
}


Можно использовать еще else if или return что бы проверки дальше не имели значения...

$type = $message->getType();

if ('text' === $type) {
    // code
} else if ('poll' === $type) {
    // code
} else if ('image' === $type) {
    // code
}


or

$type = $message->getType();

if ('text' === $type) {
    // code
    return;
}
if ('poll' === $type) {
    // code
    return;
}
if ('image' === $type) {
    // code
    return;
}
Ответ написан
Комментировать
SilenceOfWinter
@SilenceOfWinter
та еще зажигалка...
делаешь проверки отдельными классами, обходишь циклом массив проверок - банально..
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы