Когда числа НЕ Волшебные?

У меня есть такая функция:

float_as_thousands_str_with_precision(value, precision)

Если я использую это так:

float_as_thousands_str_with_precision(volts, 1)
float_as_thousands_str_with_precision(amps, 2)
float_as_thousands_str_with_precision(watts, 2)

Это магические числа 1/2?


person theanine    schedule 24.04.2012    source источник


Ответы (3)


Да, это магические числа. Очевидно, что числа 1 и 2 указывают точность в примере кода, но не почему. Зачем вам нужны амперы и ватты, чтобы быть более точными, чем вольты в этот момент?

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

Я бы предложил что-то вроде:

HIGH_PRECISION = 3;
MED_PRECISION = 2;
LOW_PRECISION = 1;

И ваш клиентский код будет выглядеть так:

float_as_thousands_str_with_precision(volts, LOW_PRECISION )
float_as_thousands_str_with_precision(amps, MED_PRECISION )
float_as_thousands_str_with_precision(watts, MED_PRECISION )

Затем, если в будущем вы сделаете что-то вроде этого:

HIGH_PRECISION = 6;
MED_PRECISION = 4;
LOW_PRECISION = 2;

Все, что вам нужно сделать, это изменить константы...

Но чтобы попытаться ответить на вопрос в заголовке OP:

IMO единственные числа, которые действительно можно использовать и не считать «магическими», - это -1, 0 и 1 при использовании в итерации, проверке длин и размеров и многих математических операциях. Некоторые примеры, когда использование констант фактически запутывает код:

for (int i=0; i<someCollection.Length; i++) {...}

if (someCollection.Length == 0) {...}

if (someCollection.Length < 1) {...}

int MyRidiculousSignReversalFunction(int i) {return i * -1;}

Это все довольно очевидные примеры. Например. начать и первый элемент и увеличить на единицу, проверяя, пуста ли коллекция и меняет знак... нелепо, но работает в качестве примера. Теперь замените все значения -1, 0 и 1 на 2:

for (int i=2; i<50; i+=2) {...}

if (someCollection.Length == 2) {...}

if (someCollection.Length < 2) {...}

int MyRidiculousDoublinglFunction(int i) {return i * 2;}

Теперь вы начали спрашивать себя: почему я начинаю итерацию с третьего элемента и проверяю все остальные? А что такого особенного в числе 50? Что особенного в коллекции из двух элементов? пример с удвоением действительно имеет смысл, но вы можете видеть, что значения 2 и 50, отличные от -1, 0, 1, сразу же становятся магическими, потому что очевидно, что в том, что они делают, есть что-то особенное, и мы понятия не имеем, почему.

person Paul Sasik    schedule 24.04.2012

Нет, это не так.

Магическим числом в этом контексте будет число, имеющее необъяснимое значение. В вашем случае указывается точность, которая хорошо видна.

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

int calculateFoo(int input)
{
  return 0x3557 * input;
}

Вы должны знать, что фраза «магическое число» имеет несколько значений. В данном случае он указывает число в исходном коде, необъяснимое окружением. Есть и другие случаи, когда фраза используется, например, в заголовке файла, идентифицируя его как файл определенного типа.

person Femaref    schedule 24.04.2012
comment
Согласованный. Хотелось бы, чтобы у меня была ссылка на ежедневную статью WTF, которая была об этом. ONE = 1; TWO = 2;... лол - person Matt Phillips; 24.04.2012

Буквенное число НЕ ЯВЛЯЕТСЯ магическим числом, если:

  • он используется один раз, в одном месте, с очень четкой целью, основанной на его контексте
  • он используется с такой частотой и в таком ограниченном контексте, что считается не магическим (например, +1 или -1 в петлях, которые люди так часто принимают за не магические).
  • некоторые люди принимают +1 нулевого смещения как не волшебство. Я не. Когда я вижу переменную + 1, я все еще хочу знать, почему, и ZERO_OFFSET не может ошибаться.

Что касается примера сценария:

float_as_thousands_str_with_precision (вольты, 1)

И предлагаемый

float_as_thousands_str_with_precision (вольты, HIGH_PRECISION)

1 — это волшебство, если эта функция для вольт с 1 будет использоваться повторно для одной и той же цели. Тогда, конечно, это «волшебство», но не потому, что смысл неясен, а потому, что у вас просто есть несколько вхождений.

Ответ Пола был сосредоточен на части «необъяснимого смысла», думая, что HIGH_PRECISION = 3 объясняет цель. ИМО, HIGH_PRECISION предлагает не больше объяснения или ценности, чем что-то вроде PRECISION_THREE, THREE или 3. Конечно, 3 больше, чем 1, но это все равно не объясняет, ПОЧЕМУ нужна более высокая точность или почему существует разница в точности. Цифры предлагают столько же смысла и ясности, сколько и предлагаемые метки.

Почему вообще нужна разная точность? Как инженер, я могу предположить, что есть три возможных причины: (а) истинное инженерное обоснование того, что само измерение действительно только с точностью X, поэтому дисплей должен отражать это, или (б) места на дисплее достаточно только для X точность, или (c) зритель не будет заботиться о чем-либо выше, чем точность X, даже если она доступна.

Это сложные причины, которые трудно уловить в виде постоянной метки, и, возможно, их лучше обслуживать комментариями (чтобы объяснить, почему что-то было сделано).

ЕСЛИ бы использование этих функций было в одном месте и только в одном месте, я бы не считал магию цифр. Цель ясна.

Для справки:

Буквальное число ЯВЛЯЕТСЯ магией, когда

  • «Уникальные значения с необъяснимым значением или несколько вхождений, которые можно (предпочтительно) заменить именованными константами». http://en.wikipedia.org/wiki/Magic_number_%28programming%29 (3-я пуля)
person Greg Willits    schedule 25.04.2012