То есть каждое число в коде, которое мы отправляем методу в качестве аргумента, считается магическим числом? Для меня это не должно. Я думаю, что если какое-то число, скажем, для минимальной длины имени пользователя, и мы начинаем использовать «6» в коде ... тогда да, у нас есть проблема с обслуживанием, и здесь «6» - это магическое число .... но если мы вызываем метод, один из аргументов которого принимает целое число, например, в качестве i-го члена коллекции, а затем мы передаем «0» вызову этого метода, в этом случае я не вижу, что «0» является магией число. Как вы думаете?
21
Ответы:
Если значение числа очень ясно в контексте, я не думаю, что это проблема "магического числа".
Пример: допустим, вы пытаетесь получить подстроку строки от начала до некоторого токена, и код выглядит следующим образом (воображаемый язык и библиотека):
В этом контексте значение числа 0 достаточно ясно. Я полагаю, вы могли бы определить
START_OF_SUBSTRING
и установить его в 0, но в этом случае я думаю, что это будет излишним (хотя это был бы правильный подход, если бы вы знали, что начало вашей подстроки может быть не 0, но это зависит от специфики твоя ситуация).Другой пример может быть, если вы пытаетесь определить, является ли число четным или нечетным. Письмо:
не так странно, как:
Тестирование отрицательных чисел как
также странно для меня, я бы предпочел увидеть
источник
360
для обозначения полного поворота с пониманием, что большинство людей будут знать, что это значит (хотя это это случай, когда не помешало бы предоставить константу)0
в контексте моего примера подстроки. В этом случае это может быть наименьшее количество ущерба, которое они могут причинить. Прошло много времени с тех пор, как я делал любое кодирование, которое выполняло геометрические вычисления, но обычно значения 15, 30, 45, 60, 90, 180, 360 были константами, которые были приняты. Я никогда не видел, чтобы кто-нибудь определилFIFTEEN_DEGREES
, ...Очевидно, что ноль означает отсутствие. Я считаю, 0 легче понять, чем переменная с именем "senceValue ".
Очевидно, 0 - начальная позиция. Я был бы смущен переменной с именем "firstPosition". Такая переменная заставила бы меня задуматься, может ли измениться начальная позиция.
источник
Я бы предложил три ключевых фактора при принятии решения, должно ли что-то быть постоянным объявлением:
Нечто подобное пи, вероятно, следует записывать как именованную константу, а не как числовой литерал, поскольку числовой литерал может быть излишне многословным, излишне неточным или и тем, и другим. Что-то вроде количества слотов в кеше должно быть именованной константой (хотя см. Примечание ниже), чтобы обеспечить возможность расширения кеша без необходимости изменять весь код, который его использует. Такие вещи, как числа «4», «28» и «29» в утверждении,
if ((year % 4)==0) FebruaryDays = 29; else FebruaryDays = 28;
вероятно, не должны называться константами, поскольку выражение почти наверняка более читабельно, чемif ((year % YearsBetweenLeapYears)==0) FebruaryDays = FebruaryDaysInLeapYear; else FebruaryDays = FebruaryDaysInNonLeapYear;
. Обратите внимание, что разработчики стандартов указали, что продолжительность февраля 2100 в этом году не будет соответствовать вышеуказанной формуле, препятствие для правильной обработки таких дат (т. е. код не будет отключен из-за целочисленного переполнения или других подобных проблем).Важное предостережение с правилом № 2 заключается в том, что в некоторых случаях код может опираться на жестко запрограммированные числа таким образом, который не может быть легко представлен именованной константой. Например, метод, который вычисляет перекрестное произведение двух векторов, переданных в качестве дискретных параметров, будет иметь смысл только при использовании на трехмерных векторах. Требуемое количество измерений не является значением, которое можно было бы существенно изменить без полного переписывания процедуры. Даже если предвидеть возможную потребность в вычислении перекрестного произведения трех четырехмерных векторов, использование именованной константы для значения «3» мало что сделает для удовлетворения этой потребности.
источник
Это, как и все принципы, является вопросом степени. Вообще говоря, числовые литералы в исходном коде более подозрительны, чем они больше. Максимальная длина, например 10, или адрес памяти, такой как 0x587FB0, явно плохая практика - почти наверняка вам рано или поздно придется повторять эти значения более одного раза, что создает риск несовместимости и незначительных ошибок в местах, которые не были изменилось.
0 находится на другом конце шкалы; это все еще подозрительно, но не так сильно. Используете ли вы 0 в качестве значения дозорного? Тогда вам, вероятно, следует использовать символическую константу вместо этого, просто потому, что константа может объяснить, что это значит. Это чрезвычайно укоренившееся культурное соглашение типа «0 означает успешное завершение»? Это, наверное, хорошо. Означает ли это «первый элемент в коллекции»? Это может быть безвредно, но если есть альтернативный метод, такой как
first()
я, вероятно, предпочел бы это.источник
Каждый неназванный номер, который не сразу очевиден из контекста, является магическим числом. Немного глупо определять числа, которые имеют значение, которое сразу видно из контекста.
В django (веб-фреймворк Python) я могу определить поле базы данных с необработанным числом, например:
что яснее (и рекомендуемая практика ) чем сказать
так как мне вряд ли когда-нибудь понадобится менять длину (и всегда можно сравнить с
max_length
полем). Если мне нужно изменить длину поля после первоначального развертывания приложения, мне нужно изменить его точно в одном месте на поле в моем коде django, а затем дополнительно написать миграцию для изменения схемы БД. Если мне когда-либо понадобится ссылкаmax_length
на определенное поле типа объекта, я могу сделать это напрямую - если эти поля определялиPerson
класс, я могу использоватьPerson._meta.get_field('firstname').max_length
для полученияmax_length
используется (который определяется в одном месте). Тот факт, что те же 40 использовались для нескольких полей, не имеет значения, так как я могу захотеть изменить их независимо. Длина имени не должна зависеть от длины среднего имени или фамилии; они являются отдельными значениями и могут меняться независимо.Часто индексы массива могут использовать безымянные числа; например, если у меня есть файл данных CSV, который я хочу поместить в словарь Python, с первым элементом в строке в качестве словаря, который
key
я бы написал:Конечно, я мог бы назвать
index_column = 0
и сделать что-то вроде:или, что еще хуже, определение,
after_index_col = index_col + 1
чтобы избавиться отindex_col+1
, но это не делает код более понятным, на мой взгляд. Кроме того, если я даюindex_col
имя, я лучше заставлю код работать, даже если столбец не равен 0 (отсюда иrow[:index_col] +
часть).источник
max_lngth=40
vs.max_length=MAX_LENGTH_NAME
- это классический пример магического числа, которое кричит как символ. Придет день, когда вы захотите поддержать 45 имен персонажей, и теперь каждое использование «40» является подозрительным и должно быть тщательно изучено.40
к1
. Вы должны думать о контексте.