На недавнем проекте, мне нужно , чтобы преобразовать из байтов в килобайты kibibyte . Код был достаточно прост:
var kBval = byteVal / 1024;
После того, как я написал это, я заставил остальную часть функции работать и двигаться дальше.
Но позже я начал задаваться вопросом, вставил ли я в магический номер свой код. Часть меня говорит, что это было хорошо, потому что число является фиксированной константой и должно быть легко понято. Но другая часть меня думает, что было бы очень ясно, если бы он был обернут в определенную константу, как BYTES_PER_KBYTE
.
Так действительно ли числа, которые являются известными константами, действительно магические или нет?
Смежные вопросы:
Когда число магическое число? и считается ли каждое число в коде "магическим числом"? - похожи, но гораздо более широкие вопросы, чем то, что я задаю. Мой вопрос сосредоточен на общеизвестных постоянных числах, которые не рассматриваются в этих вопросах.
Устранение магических чисел: когда пора сказать «нет»? также связан, но сосредоточен на рефакторинге в противоположность тому, является ли постоянное число магическим числом.
источник
FOUR_HUNDRED_FOUR = 404
. Я работал над другим проектом, в котором они боролись за использование константных строк вместо литералов, поэтому они имели десятки строк в коде, который выглядел примерно такDATABASE = "database"
1024
, потому что в противном случае ваша команда разработчиков будет тратить все свое время на споры о том, являются ли они «килобайтами» или «кибибайтами».#define
KIBI
а 1024 -MEBI
как 1024 * 1024…ZERO=0, ONE=1, TWO=2
и когда программы перенесены на другие языки (или программисты не меняют поведение при переключении своего языка), вы также увидите это там, и вы должны молиться, чтобы никто не изменил их наONE=2
...Ответы:
Не все магические числа одинаковы.
Я думаю, что в этом случае эта константа в порядке. Проблема с магическими числами заключается в том, что когда они магические, то есть неясно, каково их происхождение, почему оно является тем, чем оно является, или является ли оно правильным или нет.
Скрытие 1024 за BYTES_PER_KBYTE также означает, что вы не сразу видите, правильно это или нет.
Я ожидаю, что кто-нибудь сразу поймет, почему значение равно 1024. С другой стороны, если бы вы конвертировали байты в мегабайты, я бы определил константу BYTES_PER_MBYTE или аналогичную, потому что константа 1 048 576 не настолько очевидна, что ее 1024 ^ 2, или что это даже правильно.
То же самое касается значений, которые диктуются требованиями или стандартами, которые используются только в одном месте. Я считаю, что легче просто установить константу с комментарием к соответствующему источнику, чем определять ее в другом месте, и мне приходится гнать обе части, например:
Я нахожу лучше чем
По
SOME_THRESHOLD_VALUE
моему мнению, компромисс становится выгодным только при использовании в нескольких местах.источник
e^i*pi = -1
гораздо более явно (лучше), чем2.718^i*3.142 = -1
. Переменные имеют значение, и они не только для общего кода. Код написан для чтения первым, компиляция вторым. Кроме того, характеристики меняются (много). Хотя 1024, вероятно, не должно быть в конфигурации, 3.5 звучит так, как должно быть.1024*1024
плз!Есть два вопроса, которые я задаю, когда дело доходит до магических чисел.
У номера есть имя?
Имена полезны, потому что мы можем прочитать имя и понять назначение числа, стоящего за ним. Константы именования могут улучшить читаемость, если имя легче понять, чем число, которое оно заменяет, а имя константы сжато.
Очевидно, что константы, такие как pi, e, et al. иметь значимые имена. Значение, такое как 1024, может быть,
BYTES_PER_KB
но я также ожидаю, что любой разработчик будет знать, что означает 1024. Целевая аудитория для исходного кода - профессиональные программисты, которые должны иметь опыт, чтобы знать различные степени двух и почему они используются.Используется ли он в нескольких местах?
В то время как имена являются одной сильной стороной констант, другая является возможностью повторного использования. Если значение может измениться, его можно изменить в одном месте, вместо того, чтобы искать его в нескольких местах.
Ваш вопрос
В случае вашего вопроса я бы использовал номер как есть.
Имя: есть имя для этого числа, но оно не является действительно полезным. Он не представляет математическую константу или значение, указанное в каком-либо документе с требованиями.
Местоположение: даже если оно используется в нескольких местах, оно никогда не изменится, сводя на нет это преимущество.
источник
Эта цитата
как сказал по Йорг W Миттаг отвечает на этот вопрос достаточно хорошо.
Некоторые числа просто не волшебны в определенном контексте. В примере, представленном в вопросе, единицы измерения указывались именами переменных, и выполняемая операция была достаточно ясной.
Так что
1024
это не волшебство, потому что из контекста становится ясно, что это подходящее постоянное значение для конверсий.Аналогично, пример:
одинаково ясен и не волшебен, потому что хорошо известно, что есть 24 часа в день.
источник
24
равно не сможете их использовать ! Как упомянул Изката, високосные секунды больно Может быть, вам больше повезло бы использовать константу24
на Марсе, чем на Земле!Другие авторы упоминали, что процесс конверсии «очевиден», но я не согласен. Первоначальный вопрос на данный момент включает в себя:
Так что уже я знаю, что автор или был смущен. Страница Википедии добавляет путаницы:
Таким образом, «Килобайт» может использоваться как коэффициент 1000 и 1024, с единственной разницей в сокращении, являющейся капитализацией «k». Кроме того, 1024 может означать килобайт (JEDEC) или кибибайт (IEC). Почему бы не разрушить всю эту путаницу с помощью константы со значимым именем? Кстати, этот поток часто использовал «BYTES_PER_KBYTE», и это не менее неоднозначно. KBYTE: это KIBIBYTE или KILOBYTE? Я предпочел бы игнорировать JEDEC и иметь
BYTES_PER_KILOBYTE = 1000
иBYTES_PER_KIBIBYTE = 1024
. Нет больше путаницы.Причина, по которой такие люди, как я и многие другие, имеют «воинствующее» (цитируя здесь комментарий) мнение о присвоении магических чисел, заключается в документировании того, что вы собираетесь делать, и устранении двусмысленности. И вы на самом деле выбрали подразделение, которое привело к большой путанице.
Если я вижу:
Тогда сразу становится очевидно, что автор намеревался сделать, и нет никакой двусмысленности. Я могу проверить константу за считанные секунды (даже если она находится в другом файле), поэтому, даже если она не «мгновенная», она достаточно близка к мгновенной.
В конце концов, это может быть очевидно, когда вы пишете это, но это будет менее очевидно, когда вы вернетесь к нему позже, и это может быть еще менее очевидно, когда кто-то еще его редактирует. Требуется 10 секунд, чтобы сделать константу; может потребоваться полчаса или больше, чтобы отладить проблему с модулями (код не собирается выскочить на вас и сказать, что блоки неверны, вам придется самостоятельно вычислить это, чтобы выяснить это, и вы, вероятно, выследите 10 различных путей, прежде чем проверять юниты).
источник
KB
) по-разному, не помогут.Определение имени как ссылки на числовое значение предполагает, что всякий раз, когда в одном месте, где используется это имя, требуется другое значение, оно, вероятно, потребуется во всех. Он также предполагает, что изменение числового значения, присвоенного имени, является законным способом изменения значения. Такое предположение может быть полезно, когда оно истинно, и опасно, когда оно ложно.
Тот факт, что в двух разных местах используется определенное буквальное значение (например, 1024), будет слабо свидетельствовать о том, что изменения, которые побудят программиста изменить одно, скорее всего, побудят программиста захотеть изменить другие, но это значение гораздо слабее, чем применимо если программист присвоил имя такой константе.
Основная опасность, связанная с чем-то подобным,
#define BYTES_PER_KBYTE 1024
заключается в том, что кому-то, кто сталкивается с этим, может быть предложено,printf("File size is %1.1fkB",size*(1.0/BYTES_PER_KBYTE));
что безопасный способ заставить код использовать тысячи байтов - это изменить#define
выражение. Однако такое изменение может привести к катастрофическим последствиям, если, например, какой-то другой не связанный код получит размер объекта в килобайтах и использует эту константу при выделении для него буфера.Возможно, было бы разумно использовать
#define BYTES_PER_KBYTE_FOR_USAGE_REPORT 1024
и#define BYTES_PER_KBYTE_REPORTED_BY_FNOBULATOR 1024
, назначая разные имена для каждой другой цели, обслуживаемой константой 1024, но это привело бы к тому, что многие идентификаторы были бы определены и использованы ровно один раз. Кроме того, во многих случаях проще всего понять, что означает значение, если увидеть код, в котором он используется, и проще всего выяснить, где находится код, если он видит значения любых констант, используемых в нем. Если числовой литерал используется только один раз для определенной цели, написание литерала в том месте, где он используется, часто дает более понятный код, чем присвоение ему метки в одном месте и использование его значения в другом месте.источник
Я бы склонялся к использованию только числа, однако думаю, что одна важная проблема не была затронута: одно и то же число может означать разные вещи в разных контекстах, и это может усложнить рефакторинг.
1024 также число КиБ на МиБ. Предположим, что мы используем 1024, чтобы также представить это вычисление где-то или в нескольких местах, и теперь нам нужно перейти на него, чтобы вместо этого вычислить GiB. Изменить константу проще, чем глобальный поиск / замена, где вы можете случайно изменить неправильный в некоторых местах или пропустить его в других.
Или это может быть даже небольшая маска, введенная ленивым программистом, которую нужно обновить однажды.
Это немного надуманный пример, но в некоторых основах кода это может вызвать проблемы при рефакторинге или обновлении для новых требований. Однако в этом конкретном случае я бы не счел простое число действительно плохой формой, особенно если вы можете заключить вычисление в метод для повторного использования, я бы, вероятно, сделал это сам, но посчитал бы константу более «правильной».
Однако, если вы используете именованные константы, как говорит суперкат, важно подумать, имеет ли значение и контекст, и нужно ли вам несколько имен.
источник