В большинстве случаев наличие нескольких условных выражений внутри функции и множества уровней вложенных отступов делает исходный код таким утомительным в обслуживании, трудным для чтения и быстро непонятным — пирамида гибели.
В предыдущем эпизоде мы рассмотрели, как выйти из цикла, не нарушая правило объектной гимнастики: Только один уровень отступа на метод! В этой статье мы обсудим два примера вложенных ЕСЛИ и попытаемся шаг за шагом объяснить, как избавиться от всех этих условных структур.
Пример 1: Введение функции утверждения
Давайте погрузимся в первый пример и посмотрим, как изменить структуру кода, чтобы удалить все вложенные IF:
Для простоты я выбрал простой пример с тремя вложенными ЕСЛИ.
В нашем случае условные предложения очень простые, но мы можем представить и более сложные. Тем не менее, извлечение условий в переменные не может быть подходящим решением и может потребовать больше тестов, чем необходимо:
Поэтому, чтобы избежать дублирования или перемещения условий в константы, я нашел лучший подход, добавив функцию утверждения:
Это утверждение простое и, кроме того, возвращает результат isTrue.
Если бы функция run() вернула логическое значение, чего здесь нет, мы могли бы сжать код, чтобы он уместился в одну строку.
«когда» может быть статическим и не связанным напрямую с соответствующим классом или файлом.
Как только мы вводим функцию утверждения, мы заменяем все вложенные условия следующим образом:
Если нам все еще нужно сохранять константы, когда условия слишком сложны, мы можем сделать следующее:
Конечно, я предпочитаю первый рефакторинг, где вызов функции утверждения является немедленным и более чистым.
Пример 2 — Замена IF на Math.max
Другой элегантный способ замены условных выражений может быть реализован путем проверки и возврата максимум нескольких результатов. Например, рассмотрим следующий код:
Кроме того, список может расширяться за счет добавления других позиций или диапазонов коэффициентов, что приводит к более сложному и нечитаемому коду.
Итак, как мы можем устранить все эти ЕСЛИ?
В этом случае мы можем начать извлекать условия в константы, чтобы позже использовать Typescript Accessors:
SonarQube выдаст предупреждение, если мы используем более трех операторов return. По этой причине я исключил это решение.
Теперь у нас есть константы, мы перемещаем их в аксессоры следующим образом:
Одновременно я добавил позицию и коэффициент как свойства класса:
Однако я хотел бы изменить все геттеры, чтобы вместо логического значения возвращалось количество выходных:
Очевидно, имя функции было изменено, чтобы отразить нашу цель.
Теперь, когда у нас есть количество выходных для всех геттеров, замена условных выражений на Math.max становится простой:
Резюме
Как мы видим, в обоих примерах наш исходный код стал более читабельным и чистым. Ведь наша главная цель — написать красивый код — который работает 😉— .
Я не упоминал модульные тесты во время рефакторинга, потому что это выходит за рамки этой статьи, однако модульные тесты необходимы и должны сопровождать весь процесс рефакторинга.
Полный исходный код примера 2 можно найти здесь: https://github.com/elie29/if-elseif.
Каждый шаг имеет свою выделенную ветку.
Не стесняйтесь оставлять мне свои отзывы или писать мне в Твиттере @elie_nehme