Я довольно новичок в разработке программного обеспечения, поэтому в качестве учебного упражнения я написал игру в шахматы. Мой друг посмотрел на него и указал, что мой код выглядит
for (int i = 0; i < 8; i++){
for (int j = 0; j < 8; j++){
в то время как он настоял, что это должно быть вместо
for (int i = 0; i < CHESS_CONST; i++){
for (int j = 0; j < CHESS_CONST; j++){
с каким-то лучшим именем символа, о котором я не могу думать прямо сейчас.
Теперь, конечно, я знаю, как правило, избегать использования магических чисел, но я чувствую, что с
- это число никогда не изменится;
- в любом случае имя не может быть таким описательным, поскольку число используется во многих местах кода; а также
- любой, кто просматривает исходный код шахматной программы, должен знать о шахматах достаточно, чтобы понять, для чего нужна восьмерка,
действительно нет необходимости в символической константе.
Так что вы думаете, ребята? Это излишне, или я должен просто согласиться и использовать символ?
coding-style
coding-standards
chocolatedevil
источник
источник
i
иj
переменные цикла. Я не могу на всю жизнь выяснить, какой из них должен представлять ранг, а какой - файл. Ранги варьируются от 1..8, а файлы - от a..h, но в вашем случае, обаi
иj
от 0..7, так что это не помогает мне понять, что есть что. Есть ли какой-то международный кризис нехватки писем, о котором я не знаю, или что не так с переименованием их вrank
иfile
?foreach(var rank in Ranks)
. Я также рассмотрел бы объединение обоих циклов в один, где каждый элемент представляет собой кортеж (rank, file).Ответы:
ИМХО, твой друг прав в использовании символического имени, хотя я думаю, что имя определенно должно быть более наглядным (например,
BOARD_WIDTH
вместоCHESS_CONST
).Даже если число никогда не изменится в течение жизни программы, в вашей программе могут быть другие места, где число 8 будет иметь другое значение. Замена "8" на то,
BOARD_WIDTH
где подразумевается ширина доски, и использование другого символического имени, когда подразумевается другое, делает эти различные значения явными, очевидными, и ваша программа в целом становится более читаемой и поддерживаемой. Это также позволяет вам выполнять глобальный поиск по вашей программе (или поиск по обратному символу, если ваша среда это обеспечивает) в случае, если вам нужно быстро определить все места в коде, которые зависят от ширины платы.Смотрите также этот предыдущий пост SE.SE для обсуждения, как (или как не) выбирать имена для чисел.
В качестве примечания: поскольку это обсуждалось здесь в комментариях : если в коде вашей реальной программы имеет значение,
i
относится ли переменная к строкам иj
столбцам доски, или наоборот, то рекомендуется выбирать имена переменных, которые сделать различие четким, какrow
иcol
. Преимущество таких имен в том, что они делают неправильный код неправильным.источник
Хорошо, вот несколько комментариев, которые у меня есть:
Избавиться от магических чисел - отличная идея. Существует концепция, известная как СУХОЙ, которая часто искажается, но идея заключается в том, что вы не дублируете знания концепций в своем проекте. Поэтому, если у вас есть класс с именем ChessBoard, вы можете сохранить константу с именем BOARD_SIZE или ChessBoard.SIZE. Таким образом, существует один единственный источник этой информации. Кроме того, это помогает удобочитаемости позже:
Даже если число никогда не меняется, ваша программа, возможно, лучше. Любой человек, читающий его, знает больше информации о том, что делает код.
Плохое имя хуже, чем отсутствие имени, но это не значит, что что-то не должно быть названо. Просто измените имя. Не выбрасывайте ребенка с водой из ванны. : p Имя может быть описательным, если вы хорошо понимаете, что оно описывает. Затем эта концепция может быть использована для нескольких разных вещей.
источник
Что вам действительно нужно, так это исключить ссылки на тошноту до констант, независимо от того, названы они или нет:
Если вы на самом деле собираетесь распространять константу, повторяя такие циклы и еще много чего, лучше придерживаться
8
.8
самоописывает; это не макрос, который обозначает что-то еще.Ты никогда не собираешься превратить это в шахматную программу 9x9, и если ты когда-либо сделаешь, распространение 8 не будет главной трудностью.
Мы можем выполнить поиск по токену 8 в базе кода на 150 000 строк и определить, какие случаи означают то, что в секундах.
Гораздо важнее модульный код, чтобы знание шахмат концентрировалось как можно меньше. Лучше иметь один, два, может быть, три шахматно-специфических модуля, в которых встречается буквальное число 8, чем тридцать семь модулей, на которые возложена ответственность за шахматы, ссылаясь на 8 через символическое имя.
Когда или если эта 8 константа становится источником напряжения в вашей программе, вы можете легко это исправить в это время. Исправьте реальные проблемы, которые происходят сейчас. Если вы не чувствуете, что вам мешает именно эта восьмерка, следуйте этому инстинкту.
Предположим, что в будущем вы хотите поддерживать альтернативные размеры платы. В этом случае эти циклы должны измениться, независимо от того, используют ли они именованную константу или
8
, потому что измерения будут получены с помощью некоторого выражения, подобногоboard.width
иboard.height
. Если у вас естьBOARD_SIZE
вместо того8
, эти места будет легче найти. Так что это меньше усилий. Тем не менее, вы не должны забывать о усилии замены8
сBOARD_SIZE
в первую очередь. Общее усилие не ниже. Создание одного прохода по коду для изменения8
кBOARD_SIZE
, а затем другой , чтобы поддерживать альтернативные размеры, не дешевле , чем просто переход от8
альтернативной поддержки измерения.Мы также можем взглянуть на это из чисто холодного, объективного анализа рисков / выгод. В программе есть голые константы. Если они заменены константой, то никакой пользы нет; Программа идентична. С любым изменением существует ненулевой риск. В этом случае он маленький. Тем не менее, ни один риск не должен быть взят без выгоды. Чтобы «продать» изменения в свете этих рассуждений, мы должны предположить выгоду: будущую выгоду, которая поможет с другой программой: будущую версию программы, которой сейчас не существует. Если такая программа планируется, эта гипотеза и связанные с ней рассуждения являются добросовестными и должны приниматься всерьез.
Например, если у вас есть дни, чтобы добавить больше кода, который будет способствовать дальнейшему распространению этих констант, вы можете покончить с ними. Если эти экземпляры констант - это примерно все экземпляры, которые когда-либо будут существовать, тогда зачем?
Если вы когда-либо работаете с коммерческим программным обеспечением, аргументы ROI также будут применяться. Если программа не продается, а изменение некоторых жестко закодированных чисел на постоянные не улучшит продажи, вы не получите компенсацию за эти усилия. Изменение имеет нулевую отдачу от затрат времени. Аргументы ROI обобщают за деньги. Вы написали программу, вложив время и усилия, и получили из этого что-то: это ваше возвращение, ваше «R». Если, сделав это изменение в одиночку, вы получите больше этого «R», что бы это ни было, тогда непременно. Если у вас есть какой-то план дальнейшего развития, и это изменение улучшает ваш «R», то же самое. Если изменение не имеет немедленного или прогнозируемого «R» для вас, забудьте об этом.
источник
8
это не самоописание, это число, которое может означать что угодно. А может, они хотят сыграть в шахматы 9х9, почему бы и нет? Если у вас есть 150 000 строк кода, вы никак не сможете запомнить, что каждый из них8
означает в коде, и даже если бы вы могли, с чего бы это? Это просто много лишних хлопот. Что касается модульности, замена8
на что-то подобноеNUM_RANKS
не вредит модульности, на самом деле, это помогает, потому что облегчает работу с кодом.8
сBOARD_SIZE
в первую очередь» - время , которое вы потратили разглядывая над кодом , пытаясь понять , что каждый8
делает в вашей программе месяцев теперь, скорее всего , больше времени , затрачиваемого на смену8
с значимая константа уровня модуля.