Замена магического числа символьной константой
Проблема
В коде используется число, которое несёт какой-то определённый смысл.
Решение
Замените это число константой с человеко-читаемым названием, объясняющим смысл этого числа.
double potentialEnergy(double mass, double height) {
return mass * height * 9.81;
}
static final double GRAVITATIONAL_CONSTANT = 9.81;
double potentialEnergy(double mass, double height) {
return mass * height * GRAVITATIONAL_CONSTANT;
}
double PotentialEnergy(double mass, double height)
{
return mass * height * 9.81;
}
const double GRAVITATIONAL_CONSTANT = 9.81;
double PotentialEnergy(double mass, double height)
{
return mass * height * GRAVITATIONAL_CONSTANT;
}
function potentialEnergy($mass, $height) {
return $mass * $height * 9.81;
}
define("GRAVITATIONAL_CONSTANT", 9.81);
function potentialEnergy($mass, $height) {
return $mass * $height * GRAVITATIONAL_CONSTANT;
}
def potentialEnergy(mass, height):
return mass * height * 9.81
GRAVITATIONAL_CONSTANT = 9.81
def potentialEnergy(mass, height):
return mass * height * GRAVITATIONAL_CONSTANT
potentialEnergy(mass: number, height: number): number {
return mass * height * 9.81;
}
static const GRAVITATIONAL_CONSTANT = 9.81;
potentialEnergy(mass: number, height: number): number {
return mass * height * GRAVITATIONAL_CONSTANT;
}
Причины рефакторинга
Магические числа — это числовые значения, встречающиеся в коде, но при этом неочевидно, что они означают. Данный антипаттерн затрудняет понимание программы и усложняет её рефакторинг.
Дополнительные сложности возникают, когда нужно поменять определённое магическое число. Это нельзя сделать автозаменой, так как одно и то же число может использоваться для разных целей, а значит, вам нужно будет проверять каждый участок кода, где используется это число.
Достоинства
-
Символьная константа может служить живой документацией смысла значения, которое в ней хранится.
-
Значение константы намного проще заменить, чем искать нужное число по всему коду, при этом рискуя заменить такое же число, которое в данном конкретном случае использовалось для других целей.
-
Убирает дублирование использования числа или строки по всему коду. Это особенно актуально, если значение является сложным и длинным (например,
-14159
,0xCAFEBABE
).
Полезные факты
Не все числа являются магическими.
Если предназначения чисел очевидны, их не надо заменять константами, классический пример:
Альтернативы
-
Иногда, магическое число можно заменить вызовом метода. Например, если у вас есть магическое число, обозначающее количество элементов коллекции, вам не обязательно использовать его для проверок последнего элемента коллекции. Вместо этого можно использовать встроенный метод получения длины коллекции.
-
Магические числа могут быть использованы для реализации кодирования типа. Например, у вас есть два типа пользователей, и чтобы обозначить их, у вас есть числовое поле в классе, в котором для администраторов хранится число
1
, а для простых пользователей — число2
.В этом случае имеет смысл использовать один из рефакторингов избавления от кодирования типа:
Порядок рефакторинга
-
Объявите константу и присвойте ей значение магического числа.
-
Найдите все упоминания магического числа.
-
Для всех найденных чисел проверьте, согласуется ли это магическое число с предназначением константы. Если да, замените его вашей константой. Эта проверка важна, так как одно и тоже число может означать совершенно разные вещи (в этом случае, они должны быть заменены разными константами).