Весняний РОЗПРОДАЖ

Заміна магічного числа символьною константою

Також відомий як: Replace Magic Number with Symbolic Constant

Проблема

В коді використовується число, яке несе якийсь певний сенс.

Рішення

Замініть це число константою з такою назвою, що пояснює сенс цього числа.

До
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).

Корисні факти

Не всі числа є магічними

Якщо призначення чисел очевидні, їх не потрібно замінювати константами, класичний приклад:

for (i = 0; i < сount; i++) { ... }

Альтернативи

  1. Іноді магічне число можна замінити викликом методу. Наприклад, якщо у вас є магічне число, що означає кількість елементів колекції, вам не обов’язково використовувати його для перевірок останнього елементу колекції. Замість цього можна використати вбудований метод отримання довжини колекції.

  2. Магічні числа можуть бути використані для реалізації кодування типу. Наприклад, у вас є два типи користувачів, і щоби позначити їх, у вас є числове поле в класі, в якому для адміністраторів зберігається число 1, а для простих користувачів — число 2.

    В цьому випадку має сенс використати один з рефакторингів позбавлення від кодування типу:

Порядок рефакторингу

  1. Оголосіть константу і присвойте їй значення магічного числа.

  2. Знайдіть усі згадки магічного числа.

  3. Для всіх знайдених чисел перевірте, чи узгоджується це магічне число з призначенням константи. Якщо так, замініть його вашою константою. Ця перевірка важлива, оскільки одне і теж число може означати абсолютно різні речі (в цьому випадку, вони мають бути замінені різними константами).