TypeScript: используйте полиморфизм вместо переключателя и других условий

Пишите лучший код с принципами ООП.

Вначале я максимально использовал операторы switch. Для меня это выглядело идеально, пока однажды я не наткнулся на книгу «Чистый код». Роберт К. Мартин ясно объясняет, почему операторы switch могут быть паршивой конструкцией и почему мы можем пересмотреть их и перестать использовать их повсюду.

Со временем и накопленным опытом я стал меньше использовать операторы switch, а позже вообще не видел смысла их использовать. В этой статье я хочу поделиться одним из подходов, которые я использую в проектах вместо операторов switch. Это называется полиморфизмом, одним из принципов ООП.

Почему вы можете захотеть пересмотреть использование операторов switch?

Операторы `switch` всегда приводят к очень длинным методам, десяткам условий, и каждая инструкция требует как минимум нескольких строк кода плюс разрыв. Роберт С. Мартин в своей книге Чистый код говорит, что метод должен быть как можно меньше.

Более того, оператор switch нечитаем и не расширяем.

Необходимость просеивать (Multi-case — одиночная операция) сотни условных выражений неудобна для пользователя и может сбить с толку других.

В одном операторе switch может быть намешана совершенно разная логика и это, конечно же, неправильно, потому что метод «Должен делать только одно и делать это хорошо».

Что у нас здесь, оператор switch?

Вот исходный код, который мы рефакторим в этой статье. У нас есть один оператор switch и перечисление фруктов.

Мы можем избавиться от оператора switch, так как нам нужно только перечисление.

Давайте избавимся от оператора switch

Во-первых, давайте добавим абстрактный класс с именем Fruit, представляющий базовый объект с ценой.

Класс Fruits должен быть абстрактным, потому что мы не хотим создавать экземпляр базового класса. Унаследованные классы будут предоставлять значение цены.

Здесь вы можете видеть, что мы использовали тип утилиты Record. Если вы хотите получить больше информации о типах утилит, вы можете найти ее здесь:



Теперь давайте добавим функцию, которая будет предоставлять правильный конструктор.

Мы готовы сделать первый тест-драйв:

Перегрузка фабричной функции конструктора

Иногда удобно передать строку вместо значения перечисления. Например, мы можем получить строку из шаблона HTML, для которой мы должны вернуть цену.

Но прежде чем мы обновим нашу фабричную функцию-конструктор, нам нужно добавить еще одну функцию, которая поможет нам работать с перечислениями:

Он просто берет enum и возвращает массив с кортежами. Каждый кортеж состоит из имени и значения перечисления.

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

Давайте протестируем функцию findFruitConstructor, передав строковое значение:

Предоставление поведения по умолчанию с помощью шаблона Nullable

Что произойдет в случае, если мы каким-то образом получим имя несуществующего конструктора?

Мы получим ошибку.

Чтобы предотвратить это и иметь поведение по умолчанию для несуществующего фрукта, мы можем использовать шаблон Nullable вместо ошибки.

Давайте добавим интерфейс Nullable:

Класс Fruit должен реализовать интерфейс Nullable и метод .isNull(), который должен возвращать false.

Нам также нужно добавить класс NullableFruit, который будет представлять фрукты без поведения:

Теперь нам нужно вернуть конструктор NullableFruit вместо того, чтобы выдавать ошибку.

И вот финальная демонстрация:

Кажется, он работает так, как ожидалось. Кроме того, мы добавили много полезных функций по ходу дела, и можно добавить еще много. Это один из предложенных подходов, есть и другие. Все они, которые не используют операторы switch, очень гибкие.

Заключение

Надеюсь, вам была интересна эта статья и вы познакомились с новыми техниками. Пожалуйста, не стесняйтесь обращаться, если у вас есть какие-либо вопросы.

Нажмите кнопку 👏👏👏 и подпишитесь, это будет мотивировать меня писать больше статей.