Это довольно спорная тема, и я думаю, что мнений столько же, сколько и программистов. Но ради этого я хочу знать, каковы обычные практики в бизнесе (или на ваших рабочих местах).
На моем рабочем месте у нас есть строгие правила кодирования. Один из разделов посвящен магическим строкам / числам. В нем говорится (для C #):
Не используйте буквенные значения, как числовые, так и строковые, в своем коде, кроме как для определения символических констант. Используйте следующий шаблон для определения констант:
public class Whatever { public static readonly Color PapayaWhip = new Color(0xFFEFD5); public const int MaxNumberOfWheels = 18; }
Есть исключения: значения 0, 1 и нуль почти всегда можно использовать безопасно. Очень часто значения 2 и -1 тоже в порядке. Строки, предназначенные для ведения журнала или трассировки, освобождаются от этого правила. Литералы допускаются, когда их значение ясно из контекста и не подлежит будущим изменениям.
mean = (a + b) / 2; // okay
WaitMilliseconds(waitTimeInSeconds * 1000); // clear enough
Идеальной ситуацией была бы некоторая официальная исследовательская работа, показывающая влияние на читаемость / ремонтопригодность кода, когда
- Волшебные числа / строки повсюду
- Волшебные строки / числа разумно (или с разной степенью охвата) заменяются постоянными объявлениями - и, пожалуйста, не кричите на меня за использование «разумно», я знаю, что у всех разные представления о том, что такое «разумно»
- Волшебные строки / числа заменяются в избытке и там, где их не должно быть (см. Мой пример ниже)
Я хотел бы сделать это, чтобы иметь некоторые научно обоснованные аргументы при споре с одним из моих коллег, который собирается объявить такие константы, как:
private const char SemiColon = ';';
private const char Space = ' ';
private const int NumberTen = 10;
Другой пример будет (и этот в JavaScript):
var someNumericDisplay = new NumericDisplay("#Div_ID_Here");
Вы помещаете DOM ID поверх вашего файла JavaScript, если этот идентификатор используется только в 1 месте?
Я прочитал следующие темы:
StackExchange ИТ-сообщество
StackOverflow
Bytes
Есть еще много статей, и после прочтения появляются некоторые шаблоны.
Так что мой вопрос должен использовать магические строки и цифры в нашем коде? Я специально ищу ответы экспертов, которые подкреплены ссылками, если это возможно.
источник
NumberTen = 10
Это бессмысленно, так как число 10 не будет переопределено.MaxRetryCount = 10
Это имеет точку а, мы можем захотеть изменить максимальное количество повторов.private const char SemiColon = ';';
Тупой.private const char LineTerminator = ';'
; Умная.Ответы:
Аргумент, который вы должны выдвигать со своим коллегой, заключается не в названии буквального пространства, а в
Space
его неудачном выборе имени для его констант.Допустим, задача вашего кода - анализ потока записей, которые содержат поля, разделенные точками с запятой (
a;b;c
) и сами разделенные пробелами (a;b;c d;e;f
). Если тот, кто написал вашу спецификацию, позвонит вам через месяц и скажет: «мы ошиблись, поля в записях разделены символами канала (a|b|c d|e|f
)», что вы делаете?Согласно схеме «значение как имя», которую предпочитает ваш коллега, вам придется изменить значение literal (
SemiColon = '|'
) и жить с кодом, который продолжает использоватьSemiColon
для чего-то, что больше не является точкой с запятой. Это приведет к негативным комментариям в обзорах кода . Чтобы уменьшить это, вы можете изменить имя литерала наPipeSymbol
и пройти и изменить каждое вхождениеSemiColon
наPipeSymbol
. С такой скоростью вы могли бы просто использовать буквальную точку с запятой (';'
) в первую очередь, потому что вам придется оценивать каждое его использование по отдельности, и вы будете вносить такое же количество изменений.Идентификаторы для констант должны быть описательными , что значение делает , а не то , что значение является , и где ваш коллега сделал левый поворот в сорняки. В описанном выше приложении с разделением полей целью точки с запятой является разделитель полей, и константы должны иметь соответствующие имена:
Таким образом, когда меняется разделитель полей, вы меняете ровно одну строку кода, объявление константы. Кто-то, смотрящий на изменение, увидит только эту строку и сразу поймет, что разделитель полей изменился с точки с запятой на символ канала. Остальная часть кода, которую не нужно было менять, потому что она использовала константу, осталась прежней, и читателю не нужно копаться в ней, чтобы посмотреть, что еще было с ней сделано.
источник
#define one 1 #define two 2
т. Д. (Или что-то подобное было в почтовом отделении «Корал», тогдашнем языке выбора)#define one 8 #define two 16
;
на|
.public static final String MY_KEY_NAME = "MyKeyName"
CSV_RECORD_SEPARATOR
,TSV_RECORD_SEPARATOR
и т.д.).Определение точки с запятой в качестве константы является избыточным, поскольку точка с запятой уже является константой сама по себе . Это никогда не изменится.
Не похоже, чтобы однажды кто-то объявил «изменение терминологии + теперь новая точка с запятой», и ваш коллега с радостью поспешит просто обновить константу (они смеялись надо мной - посмотрите на них сейчас).
Там также вопрос последовательности. Я гарантирую, что его
NumberTen
константа НЕ будет использоваться всеми (большинство программистов не в своем уме), поэтому она не будет служить какой-либо цели, которую она ожидала в любом случае. Когда наступит апокалипсис, и «десятка» будет глобально изменена до 9, обновление константы НЕ даст результата, потому что она все равно оставит вас с кучей литералов10
в вашем коде, так что теперь система становится совершенно непредсказуемой даже внутри области видимости. революционного предположения, что «десять» означает «9».Сохранение всех настроек как conts - это то, о чем я тоже подумаю. Не следует делать это легко.
Какие примеры использования такого типа мы уже собрали? Терминатор строки ... максимальное количество повторных попыток ... максимальное количество колес ... мы уверены, что они никогда не изменятся?
Стоимость состоит в том, что изменение настроек по умолчанию требует перекомпиляции приложения, а в некоторых случаях даже его зависимостей (поскольку числовые значения const могут быть жестко запрограммированы во время компиляции).
Есть также аспект тестирования и насмешек. Вы определили строку подключения как const, но теперь вы не можете смоделировать доступ к базе данных (установить поддельное соединение) в своем модульном тесте.
источник
’
(оставленную одинарную кавычку, Unicode 8217 ) для приложений, совместимых с отображением другого символа на скрученном знаке. Поскольку Европа использует запятые так же, как американцы используют точки в качестве десятичной точки, я немного сомневаюсь в том, чтобы объявить «не ... никогда».DecimalPoint
постоянный - но неComma
илиPeriod
постоянные. Это большая разница: первая обозначает функцию , роль или цель значения. «Точка с запятой» или «запятая» не подпадают под эту категорию.Таким образом, ваш коллега стремится к ежедневной записи WTF. Эти определения глупы и излишни. Однако, как было отмечено другими, следующие определения не будут глупыми или излишними:
«Магические» числа и строки - это константы, которые имеют значение за пределами их непосредственного, буквального значения. Если константа
10
имеет значение за пределами «десяти вещей» (скажем, как код для конкретной операции или условия ошибки), тогда она становится «магической» и должна быть заменена символической константой, которая описывает это абстрактное значение.Помимо четкого описания намерений, символические константы также избавляют вас от головной боли, когда вы неправильно пишете литерал. Простое преобразование из «CVS» в «CSV» в одной строке кода прошло весь путь через модульное тестирование и QA и превратило его в рабочий процесс, где он вызвал сбой конкретной операции. Да, очевидно, что юнит-тесты и тесты качества были неполными, и это его собственная проблема, но использование символической константы могло бы полностью избежать этой изжоги.
источник
Там не должно быть ничего спорного об этом. Суть не в том, использовать магические числа или нет, а в том, чтобы иметь читаемый код.
Рассмотрим разницу между:
if(request.StatusCode == 1)
иif(request.HasSucceeded)
. В этом случае, я бы сказал, что последний гораздо удобнее для чтения, но это не значит, что вы никогда не сможете получить подобный кодint MaxNumberOfWheels = 18
.PS: именно поэтому я абсолютно ненавижу правила кодирования. Разработчики должны быть достаточно зрелыми, чтобы иметь возможность делать такие суждения; они не должны оставлять это для текста, созданного богом, кто знает.
источник