Y
Y
Yevhenii K2021-09-18 16:49:26
OOP
Yevhenii K, 2021-09-18 16:49:26

Code refactoring. How to optimize the number of if?

Есть код, который принимает json данные и в зависимости от типа выполнить определённые действия.
Весь код обработки находится в if'ах, добавление новых типов оказалось неудобным.
Сейчас планирую вынести обработку в отдельные сервисы под каждый тип, а информацию передавать с помощью DTO. Но, это все равно не избавляет от сложности и количество if. Рассматривал возможность заменить на switch/match, но, такой вариант кажется не совсем верным. С похожей проблемой столкнулся и в другой части кода, где нужно обрабатывать по-разному в зависимости от состояния.

if ('text' === $message->getType()) {
    // code
}
if ('poll' === $message->getType()) {
    // code
}
if ('image' === $message->getType()) {
    // code
}

С ООП немного знаком в теории, на практике, осмысленно, применять получается редко.
Насколько я знаю в решении проблемы должен помочь полиморфизм, но, как правильно его применить не пойму.

Answer the question

In order to leave comments, you need to log in

5 answer(s)
D
Developer, 2021-09-18
amsamodum

Reflection
Pattern Strategy

R
rPman, 2021-09-18
@rPman

Instead of if in such cases, switch case is used.
An alternative is to define a map with a key of your compared values ​​and a value of a Func delegate or an instance of a class with a virtual method. But whatever you do, syntactically it will not add simplicity to you, but simply move the definition of the code and the compared value to another place. There is also a #if
preprocessor or even a custom code generator, sometimes it is justified. It is necessary to fence something more difficult than switch, when the logic inside the code near each of the value options can be folded into a common single code or vice versa, it all comes down to short instructions that look beautiful in the form of anonymous functions that look good in the form of initializer constants map

A
Alexey Hog, 2021-09-18
@Skiphog

There are many implementation options, but if it's simple, you can do this:
Create methods of the same name depending on the expected types that $message->getType() can return;
And actually call them))
So you get rid of the if heap and place the code of each implementation in your methods.
Pseudocode:

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
}

According to approximately the same scheme, you can use separate classes, services, etc.

M
Max QNEI, 2021-09-19
@MaxAlexQNEI

The answers above have useful information for you, as does the answer to the question.
However, here's another opinion to optimize your (maybe) code example:

$type = $message->getType();

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

You can also use else if or return so that further checks do not matter ...
$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;
}

A
Anton Shamanov, 2021-09-19
@SilenceOfWinter

you make checks by separate classes, bypass the array of checks - it's trite ..

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question