Как рефакторинг тупого значения может сделать наш код чище и понятнее.

Что такое на самом деле магическое число? По сути, магическое число — это код, шифр или число, которое имеет некоторое «магическое», неясное, но важное значение. Однако просто из чтения исходного кода неясно, в чем смысл.

Это как найти Ответ на Главный Вопрос Жизни, Вселенной и Всего. Ответ: 42. Почему 42? ¯\_(ツ)_/¯

Вернемся к компьютерному программированию и представим, что мы получаем code обратно:

const response = await API.request();
if (response.code === 5) {
    // DO SOMETHING
}

Здесь мы видим магическое число. 5 что-то значит, но глядя на исходный код, мы не можем сказать, в чем секрет этого конкретного значения.

Это можно легко реорганизовать, чтобы использовать константы, которые дадут нам лучшее понимание того, что происходит и как работает логика:

const ALL_OK = 5;
const response = await API.request();
if (response.code === ALL_OK) {
    // DO SOMETHING
}

Внезапно код стал намного понятнее!

Другой пример может быть:

const total = price * 1.22;

Опять же, 1.22 имеет какое-то значение, и часто мы можем угадать значение, но вместо того, чтобы гадать, мы должны знать точное значение. Кроме того, одно и то же значение может находиться в нескольких местах. Если нам нужно его изменить, то мы меняем только одну строку вместо многих:

const BASE_TAX = 1.22;
const total = price * BASE_TAX;
...
const itemPriceWithTax = itemPrice * BASE_TAX;

Если мы знаем, что такое магические числа, мы можем реорганизовать весь код, чтобы сделать его намного чище. Однако не следует слепо следовать правилу запретить магическое число!

Мы можем возразить, что не все числа являются магическими. Например, коды состояния HTTP хорошо определены, и если предположить, что все специалисты по сопровождению кода имеют одинаковое понимание, мы могли бы просто использовать эти коды напрямую:

throw new HttpError(400, 'Something went wrong! Check your request');

В этом случае 400 можно преобразовать в константу, но действительно ли мы находим это неясным и трудным для понимания?

Другое полуготовое решение состоит в том, чтобы заменить идентификаторы константами. Плохой:

const stations = [{id: 123}, {id: 456}];
const openStation = stations.filter(station => station.id !== 456);

Здесь мы видим, что хотим исключить определенную станцию ​​с id: 456, но почему эта станция была исключена? Исходный код не даст нам нужного ответа.

Чуть лучше:

const EXCLUDED_STATIONS = [456];
const openStation = stations.filter(station => !EXCLUDED_STATIONS.includes(station.id));

Мы правильно избавились от магического номера, но мы все еще можем утверждать, что через год или два, если кто-то еще придет и будет отвечать за обслуживание кода, ему будет трудно понять, почему именно эта станция была исключена?

В этом случае может помочь простой комментарий. Очевидно, что если бы мы могли использовать другое свойство, это значительно помогло бы:

const stations = [{id: 123, isOpen: true}, {id: 456, isOpen: false}];
const openStation = stations.filter(station => station.isOpen);

Однако это пример проблемы с качеством данных. Если программист не может полагаться на поступающие данные и нет возможности исправить данные в первую очередь (например, нет свойства isOpen), то, к сожалению, нам нужно ввести какой-то хак, который решит проблему.

Вывод

В общем, код должен быть чистым (легко сказать!) и не требующим пояснений. Опускание магических чисел и замена их удобочитаемыми константами — это легкая победа.

Вы всегда запрещаете магические числа в коде или видите исключения из этого правила? Позвольте мне знать в комментариях ниже!