Несколько слов в защиту switch

1
620
views

Перевод статьи «Switch is ok».

Photo by Dave Phillips on Unsplash

Конструкция switch в последнее время пользуется дурной славой. Одни разработчики всеми силами пытаются ее избегать, другие считают, что ее вообще следует отнести к устаревшим. То есть, эту конструкцию практически воспринимают как какой-то анти-паттерн. Чтобы проиллюстрировать примеры такого отношения, приведу несколько ссылок на статьи:

В своей статье я попытаюсь опровергнуть распространенные доводы против switch.

Switch — старая и неуклюжая конструкция

Да, конструкция switch — старая. Но if-выражение тоже старое, да и цикл for немолод, и что с того? Это реально очень странный аргумент. Новые и блестящие штуки не обязательно лучше старых.

Нам приходится вручную добавлять break

Это интересный довод, поскольку во всех приводимых при этом примерах switch показан с ключевым словом break. Так что, в качестве контраргумента, приведу свой пример. На самом деле break в конструкции switch не обязателен, мы можем ограничиться одним лишь return.

switch (x) {
  case "DC":
    return "Batman";
  case "Marvel":
    return "Wolverine";
  default:
    return "Spiderman"
}

Ну, и где тут break?

Это не выражение

Да, не выражение. Но оберните switch в функцию, и получите выражение:

function hero(x) {
  switch (x) {
    case "DC":
      return "Batman";
    case "Marvel":
      return "Wolverine";
    default:
      return "Spiderman"
  }
}
const myHero = hero("DC");

Это признак нечистого и процедурного программирования

Вы работаете с мультипарадигменным языком, где можете изменять все, что угодно, можете сделать любой побочный эффект по своему желанию, и при этом приводите подобные аргументы? Чистота в таких языках, как JS, это лишь практика кодинга. Если вы хотите писать чистый код, switch не будет препятствием, поверьте мне.

Конструкция switch располагает к ошибкам

Прекратите пользоваться Notepad. Пожалуйста.

И обновите свою Windows 8.

Вместо switch следует использовать объектные литералы

Да, это можно. Я не буду утверждать, что использование литералов это плохая идея. Но говорить, что использование switch намного хуже, тоже преувеличение. Посмотрите на эти два примера:

// switch
function hero(x) {
  switch (x) {
    case "DC":
      return "Batman";
    case "Marvel":
      return "Wolverine";
    default:
      return "Spiderman"
  }
}
// literal
function hero(x = "default") {
  const herosMap = {
    "DC": "Batman",
    "Marvel" : "Wolverine",
    "default": "Spiderman"
  }
  return herosMap[x];
}

Да-да, я знаю: вы заметили, что второй пример меньше, а еще там хороший прием с дефолтным значением, а это секси. Но код не должен быть «секси», за этим обращайтесь к своей девушке/парню. Да и меньше — не всегда лучше. Когда вы читаете эти два куска кода, на втором вы наверняка задерживаетесь чуть дольше. Признайте это!

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

switch не подходит для ООП-кода

Ну да, а ваш StrategyFactoryProducerPattern, конечно, лучше. Но если серьезно, switch и вправду может не сочетаться с принципами объектно-ориентированного программирования насчет полиморфизма.

А вы вообще пишете объектно-ориентированный код? Если нет, то этот аргумент пролетает мимо.

Мы можем сделать какой-то FP-wrapper, чтобы больше никогда не видеть switch

Зачем использовать switch, если можно использовать функцию? Ниже приведен пример из статьи «Eliminate the switch statement for better code». Вы можете сделать так:

const switchcase = cases => defaultCase => key =>
  cases.hasOwnProperty(key) ? cases[key] : defaultCase

const counter = (state = 0, action) =>
  switchcaseF({
    'INCREMENT': () => state + 1,
    'DECREMENT': () => state -1
  })(state)(action.type)

а можете проще:

const counter = (state = 0, action) => {
  switch (action.type) {
    case 'INCREMENT':
      return state + 1
    case 'DECREMENT':
      return state - 1
    default:
      return state
  }
}

Да, но в первом варианте нет {, нет явного return, зато есть частичное применение, и обратите внимание, как в конце эта функция вызывается дважды (state)(action.type) — это секси!

Если для вас это аргумент, идите поспите, а затем перечитайте код снова. И — да, я уже говорил, кто именно должен быть секси.

Конструкция switch вполне нормальна

В конструкции switch нет ничего плохого. Мы можем использовать ее без break, она наглядна, в ней четко видны все возможные ветки. Если вы думаете, что использование switch и функциональное программирование несовместимы, посмотрите на чистые функциональные языки, в которых есть совпадение с шаблоном. Взгляните на пример кода на Elm:

hero x = case x of
  DC -> "Batman"
  Marvel -> "Wolverine"
  _ -> "Spiderman"

Да, это функциональное программирование, и — да, case of это выражение, но это не значит, что нужно непременно отказаться от switch. Используйте эту конструкцию, сделайте так, чтобы она что-то возвращала в любом случае. Не нужно усложнять то, что должно быть простым.

1 КОММЕНТАРИЙ

  1. Хорошая статья, полезная. Правда, если честно, я недолюбливал всегда switch, даже до становления ООП.

ОСТАВЬТЕ ОТВЕТ

Please enter your comment!
Please enter your name here