Хорошая ли идея жестко закодировать значения в наших приложениях? Или это всегда правильно называть эти типы значений динамически в случае необходимости их изменения?
programming-practices
Эдвард
источник
источник
pi
может измениться ...Ответы:
Да, но сделай это очевидным .
Делать:
Не рекомендуется:
источник
diameter = 2 * radius
илиdiameter = RADIUS_TO_DIAMETER_FACTOR * radius
? В действительности, существуют угловые случаи, когда магическое число может быть лучшим решением.diameter = radius << 1
? Я полагаю, что это также может бытьdiameter = radius << RADIUS_TO_DIAMETER_BITS_TO_SHIFT
.diameter = radius.toDiameter()
Что я нахожу странным в этом вопросе и ответах, так это то, что на самом деле никто не пытался четко определить «жесткий код» или, что более важно, альтернативы.
Т.Л., д - р: Да, это иногда хорошая идея значений трудно кода, но нет простого правила, чтобы , когда ; это полностью зависит от контекста.
Вопрос сводит его к значениям , которые я принимаю как магические числа , но ответ на вопрос, являются ли они хорошей идеей, связан с тем, для чего они фактически используются!
Несколько примеров «жестко закодированных» значений:
Значения конфигурации
Я съеживаюсь всякий раз, когда вижу подобные заявления
command.Timeout = 600
. Почему 600? Кто это решил? Было ли это раньше, и кто-то поднял тайм-аут как хак, вместо того, чтобы исправить основную проблему производительности? Или это действительно известное и документированное ожидание времени обработки?Это не должны быть магические числа или константы, они должны быть перенесены в файл конфигурации или базу данных где-либо с значимым именем, поскольку их оптимальное значение в значительной степени или полностью определяется средой, в которой выполняется приложение.
Математические формулы
Формулы обычно имеют тенденцию быть довольно статичными, так что природа постоянных значений внутри не особенно важна. Объем пирамиды составляет (1/3) б * ч. Нас волнует, откуда пришли 1 или 3? На самом деле, нет. Предыдущий комментатор справедливо указал, что
diameter = radius * 2
, вероятно, лучше, чем ...diameter = radius * RADIUS_TO_DIAMETER_CONVERSION_FACTOR
но это ложная дихотомия.Что вы должны делать для этого типа сценария - это создание функции . Мне не нужно знать, как вы пришли к формуле, но мне все еще нужно знать, для чего она нужна . Если вместо какой-либо ерунды, написанной выше, я пишу,
volume = GetVolumeOfPyramid(base, height)
то вдруг все становится намного яснее, и вполне нормально иметь магические числа внутри функции (return base * height / 3
), потому что очевидно, что они являются лишь частью формулы.Ключ здесь, конечно, иметь короткие и простые функции. Это не работает для функций с 10 аргументами и 30 строками вычислений. Используйте композицию функций или константы в этом случае.
Домен / бизнес-правила
Это всегда серая область, потому что это зависит от того, какое именно значение. В большинстве случаев именно эти магические числа являются кандидатами на превращение в константы, потому что это облегчает понимание программы, не усложняя логику программы. Рассмотрим тест
if Age < 19
противif Age < LegalDrinkingAge
; Вы, вероятно, можете понять, что происходит без константы, но это проще с описательным названием.Они также могут стать кандидатами на абстракцию функции, например
function isLegalDrinkingAge(age) { return age >= 19 }
. Единственное, что ваша бизнес-логика зачастую гораздо более запутанная, и может не иметь смысла начинать писать десятки функций с 20-30 параметрами в каждой. Если нет четкой абстракции, основанной на объектах и / или функциях, тогда прибегать к константам можно.Предостережение в том, что если вы работаете в налоговом департаменте, это становится действительно, очень обременительным и честно писать
AttachForm(FORM_CODE_FOR_SINGLE_TAXPAYER_FILING_JOINTLY_FOR_DEPRECIATION_ON_ARMPIT_HAIR)
. Вы не будете этого делать, вы будете делать это,AttachForm("B-46")
потому что каждый разработчик, который когда-либо работал или будет работать там, узнает, что «B-46» - это код формы для одного налогоплательщика, подающего бла-бла-бла - коды форм являются частью самого домена, они никогда не меняются, поэтому на самом деле они не являются магическими числами.Таким образом, вы должны экономно использовать константы в бизнес-логике; в основном вы должны понимать, является ли это «магическое число» на самом деле магическим числом или это хорошо известный аспект домена. Если это домен, то вы не будете программировать его, если не будет очень вероятного изменения.
Коды ошибок и флаги состояния
Это никогда не подходит для жесткого кода, как
Previous action failed due to error code 46
может сказать любой бедный ублюдок, который когда-либо был поражен этим . Если ваш язык поддерживает это, вы должны использовать тип перечисления. В противном случае у вас обычно будет целый файл / модуль, полный констант, указывающих допустимые значения для определенного типа ошибки.Никогда не позволяй мне увидеть
return 42
в обработчике ошибок, capiche? Никаких оправданий.Я, вероятно, пропустил несколько сценариев, но я думаю, что они охватывают большинство из них.
Так что, да, иногда приемлемо практиковать сложный код. Только не ленитесь об этом; это должно быть сознательное решение, а не простой старый неаккуратный код.
источник
Существуют различные причины присвоения идентификатора номеру.
Это дает нам критерии для жесткого кодирования литералов. Они должны быть неизменными, не сложными для ввода, встречаться только в одном месте или в одном контексте и иметь узнаваемое значение. Нет смысла определять 0 как ARRAY_BEGINNING, например, или 1 как ARRAY_INCREMENT.
источник
Как дополнение к другим ответам. Используйте константы для строк, когда это возможно. Конечно, вы не хотите иметь
но вы должны иметь
(при условии, что у вас действительно есть запрос, где вы хотите получить все результаты из определенной таблицы, всегда)
Кроме этого, используйте константы для любого числа, отличного от 0 (обычно). Если вам нужна битовая маска разрешения 255, не используйте
вместо этого используйте
Конечно, наряду с константами, знать, когда использовать счетчики. Вышеупомянутый случай, вероятно, хорошо бы вписался в один.
источник
typedef enum {init_state=0, parse_state=1, evaluation_state=2, ... }
Это зависит от того, что вы считаете жестким кодированием. Если вы попытаетесь избежать любых жестко закодированных вещей, вы окажетесь на территории софткодирования и создадите систему, которой сможет управлять только создатель (и это в конечном итоге жесткий код )
Множество вещей жестко закодировано в любых разумных рамках, и они работают. то есть нет технической причины, по которой я не смогу изменить точку входа приложения C # (static void Main), но жесткое кодирование не создает никаких проблем для любого пользователя (кроме случайного вопроса SO )
Эмпирическое правило, которое я использую, заключается в том, что все, что может и будет меняться, не затрагивая состояние всей системы, должно быть настраиваемым.
Так что, ИМХО, глупо не жестко кодировать вещи, которые никогда не меняются (пи, гравитационная постоянная, постоянная в математической формуле - объем мысли в сфере).
Также глупо не жестко кодировать вещи или процессы, которые будут влиять на вашу систему, что потребует программирования в любом случае, то есть бесполезно позволять пользователю добавлять динамические поля в форму, если любое добавленное поле потребует от разработчика обслуживания иди и напиши какой-нибудь скрипт, который заставит эту штуку работать. Кроме того, глупо (и я видел это несколько раз в корпоративных средах) создавать какой-либо инструмент конфигурации, поэтому ничто не жестко закодировано, но только разработчики в ИТ-отделе могут использовать его, и использовать его лишь немного легче, чем сделать это в Visual Studio.
Итак, суть в том, должна ли вещь быть жестко закодированной, является функцией двух переменных:
источник
Я жестко кодирую значения только в том случае, если значения указаны в Спецификации (в окончательном выпуске спецификации), например, ответ HTTP OK всегда будет
200
(если он не изменяется в RFC), поэтому вы увидите (в некоторых из моих кодов) ) константы типа:В противном случае я храню константы в файле свойств.
Причина, по которой я указал спецификации, заключается в том, что изменение констант в спецификациях требует управления изменениями, при котором заинтересованные стороны будут анализировать изменения и одобрять / не одобрять. Это никогда не происходит в одночасье и требует месяцев / лет для утверждения. Не забывайте, что многие разработчики используют спецификации (например, HTTP), поэтому изменение их означает разрушение миллионов систем.
источник
источник
Я заметил, что каждый раз, когда вы можете извлечь данные из своего кода, это улучшает то, что осталось. Вы начинаете замечать новые рефакторинги и улучшать целые разделы вашего кода.
Это просто хорошая идея работать над извлечением констант, не считайте это каким-то глупым правилом, думайте об этом как о возможности лучше кодировать.
Самым большим преимуществом было бы то, как вы можете найти похожие константы, являющиеся единственным отличием в группах кода - абстрагирование их в массивы помогло мне сократить некоторые файлы на 90% их размера и исправить довольно много ошибок копирования и вставки за это время. ,
Я пока не вижу единственного преимущества в том, чтобы не извлекать данные.
источник
Недавно я закодировал функцию MySQL, чтобы правильно рассчитать расстояние между двумя парами широта / долгота. Вы не можете просто сделать пифагор; Линии долготы сближаются по мере того, как широта увеличивается к полюсам, так что возникает какой-то волосатый триг. Дело в том, что я был довольно обеспокоен, стоит ли жестко закодировать значение, представляющее радиус Земли в милях.
Я закончил тем, что делал это, хотя на самом деле линии широты и долготы гораздо ближе, скажем, на Луне. И моя функция резко занижала бы расстояния между точками на Юпитере. Я подумал, что шансы на то, что сайт, который я создаю, с инопланетным местоположением, достаточно узки.
источник
Ну, это зависит от того, скомпилирован ли ваш язык. Если он не скомпилирован, это не имеет большого значения, вы просто редактируете исходный код, даже если он будет немного деликатным для не программиста.
Если вы программируете на скомпилированном языке, это явно не очень хорошая идея, потому что если переменные меняются, вам придется перекомпилировать, что является большой тратой времени, если вы хотите настроить эту переменную.
Вам не нужно создавать какой-либо слайдер или интерфейс для динамического изменения его переменной, но самое меньшее, что вы можете сделать, это текстовый файл.
Например, в моем проекте ogre я всегда использую класс ConfigFile для загрузки переменной, которую я записал в файл конфигурации.
источник
Два случая, когда константы в порядке (на мой взгляд, по крайней мере) в порядке:
Константы, которые не имеют отношения ни к чему другому; Вы можете изменить эти константы, когда захотите, без необходимости что-либо менять. Пример. Ширина столбца сетки по умолчанию.
Абсолютно неизменные, точные, очевидные константы, такие как «количество дней в неделю».
days = weeks * 7
Замена7
на константуDAYS_PER_WEEK
вряд ли дает какую-либо ценность.источник
Я полностью согласен с Джонатаном, но из всех правил есть исключения ...
"Магическое число в спецификации: Магическое число в коде"
В основном говорится, что любые магические числа, которые остаются в спецификации после разумных попыток получить описательный контекст для них, должны быть отражены как таковые в коде. Если магические числа остаются в коде, необходимо приложить все усилия, чтобы изолировать их и сделать их четко связанными с точкой их происхождения.
Я выполнил несколько взаимодействующих контрактов, где необходимо заполнить сообщения значениями, сопоставленными с базой данных. В большинстве случаев сопоставление довольно прямое и укладывается в общие руководящие указания Джонатана, но я встречал случаи, когда целевая структура сообщения была просто ужасна. Более 80% значений, которые должны были передаваться в структуре, были константами, определяемыми спецификацией удаленной системы. это в сочетании с тем фактом, что структура сообщения была гигантской, заставляла заполнять МНОЖЕСТВО таких констант. В большинстве случаев они не предоставили смысла или причины, просто сказали «положите M здесь» или «поместите 4.10.53.10100.889450.4452 здесь». Я также не пытался поместить комментарий рядом со всеми из них, это сделало бы полученный код нечитаемым.
Тем не менее, когда вы думаете об этом ... это в значительной степени все о том, чтобы сделать это очевидным ...
источник
Если вы жестко запрограммировали значение гравитационной постоянной Земли, никто не будет обращать на это внимание. Если вы жестко закодируете IP-адрес вашего прокси-сервера, у вас возникнут проблемы.
источник
В основном нет, но я думаю, что стоит отметить, что у вас будет больше проблем, когда вы начнете дублировать жестко закодированное значение. Если вы не продублируете его (например, используйте его только один раз в реализации класса), тогда не следует использовать константу.
источник