Что такое магическое число и почему оно плохо?

Вам нужно сформировать теорию, почему вы считаете, что алгоритм заканчивается. В идеале доказать теорию как математическую теорему.

Вы можете искать функцию состояния проблемы, которая уменьшает каждый рекурсивный вызов. Например, см. Следующее обсуждение функции Аккермана, из Wikipedia

Не может быть сразу очевидно, что оценка A (m, n) всегда завершается. Однако рекурсия ограничена, поскольку в каждом рекурсивном приложении либо m уменьшается, либо m остается неизменным и n уменьшается. Каждый раз, когда n достигает нуля, m уменьшается, поэтому m в конечном итоге также достигает нуля. (Выражение более технически, в каждом случае пара (m, n) уменьшается в лексикографическом порядке по парам, что является упорядоченным, как и порядок одиночных неотрицательных целых чисел, что означает, что в упорядочении бесконечно много раз подряд.) Однако, когда m уменьшается, нет верхней границы того, сколько n может увеличиться - и оно часто будет сильно возрастать.

blockquote>

Это тип рассуждений, которые вы должны подумайте о применении к вашему алгоритму.

Если вы не можете найти способ доказать, что ваш алгоритм завершен, попробуйте найти вариант, окончание которого вы можете доказать. Не всегда возможно решить, завершается ли произвольная программа или нет. Трюк заключается в том, чтобы написать алгоритмы, которые вы можете подтвердить.

482
задан Adam Davis 8 January 2016 в 05:08
поделиться

12 ответов

Магическое число является прямым использованием числа в коде.

, Например, если Вы имеете (в Java):

public class Foo {
    public void setPassword(String password) {
         // don't do this
         if (password.length() > 7) {
              throw new InvalidArgumentException("password");
         }
    }
}

Это должно быть пересмотрено к:

public class Foo {
    public static final int MAX_PASSWORD_SIZE = 7;

    public void setPassword(String password) {
         if (password.length() > MAX_PASSWORD_SIZE) {
              throw new InvalidArgumentException("password");
         }
    }
}

Это улучшает удобочитаемость кода, и легче поддержать. Вообразите случай, где я установил размер поля пароля в GUI. Если я использую магическое число, каждый раз, когда макс. размер изменяется, я должен измениться в двух участках кода. Если я забуду один, это приведет к несоответствиям.

JDK полон примеров как в Integer, Character и Math классы.

пз: инструменты Статического анализа как FindBugs и PMD обнаруживают использование магических чисел в Вашем коде и предлагают рефакторинг.

541
ответ дан Lii 8 January 2016 в 05:08
поделиться

@eed3si9n: я даже предположил бы, что '1' магическое число.:-)

принцип А, это связано с магическими числами, - то, что каждый факт Ваши соглашения о коде с должен быть объявлен точно однажды. При использовании магических чисел в коде (таких как пример длины пароля, который @marcio дал, можно легко закончить тем, что копировали тот факт, и когда Ваш понимать того факта изменяется, у Вас есть проблема обслуживания.

1
ответ дан Andrew 8 January 2016 в 05:08
поделиться

Я всегда использовал термин "магическое число" по-другому как неясное значение, сохраненное в структуре данных, которая может быть проверена как быстрая проверка достоверности. Например, файлы gzip содержат 0x1f8b08 как свои первые три байта, файлы класса Java запускаются с 0xcafebabe, и т.д.

Вы часто видите магические числа, встроенные в форматы файлов, потому что файлы могут быть отправлены вокруг скорее случайно и потерять любые метаданные о том, как они были созданы. Однако магические числа также иногда используются для структур данных в оперативной памяти, как ioctl () вызовы.

быстрая проверка А магического числа прежде, чем обработать файловую структуру или структуру данных позволяет сигнализировать об ошибках рано, а не подонке полностью посредством потенциально долгой обработки, чтобы объявить, что вход был полным вздором.

3
ответ дан DGentry 8 January 2016 в 05:08
поделиться

Я предполагаю, что это - ответ на мой ответ к Вашему более раннему вопросу. В программировании магическое число является встроенной числовой константой, которая появляется без объяснения. Если это появляется в двух отличных местах, это может привести к обстоятельствам, где один экземпляр изменяется и не другой. И по этим причинам, важно изолировать и определить числовые константы вне мест, где они используются.

4
ответ дан Community 8 January 2016 в 05:08
поделиться

Магическое число может также быть числом со специальным предложением, hardcoded семантика. Например, я однажды видел систему, где рекордные идентификаторы> 0 обычно рассматривали, 0 саму была "новая запись",-1 был, "это - корень", и-99 был, "это было создано в корне". 0 и-99 заставил бы WebService предоставлять новый идентификатор.

то, Что плохо об этом, - то, что Вы снова используете пространство (то из целых чисел со знаком для рекордных идентификаторов) для специальных способностей. Возможно, Вы никогда не будете хотеть создавать запись с идентификатором 0, или с отрицательным идентификатором, но даже если не, каждый человек, который смотрит или на код или на базу данных, мог бы наткнуться на это и быть смущен сначала. Само собой разумеется, что те специальные значения не были хорошо зарегистрированы.

Возможно, 22, 7,-12 и 620 количество как магические числа, также.;-)

10
ответ дан Sören Kuklau 8 January 2016 в 05:08
поделиться
  • 1
    You' право ре... Я wasn' t думающий об этом. Можно сделать привязку От элемента к элементу в SL3, хотя, поэтому просто свяжите Ширину Сетки к ActualWidth ListBox и т.д. Если it' s немного прочь из-за дополнения или чего-либо как этот, можно использовать IValueConverter для согласовывания его. – Rich 14 April 2009 в 11:04

В программировании "магическое число" является значением, которому нужно дать символьное имя, но вместо этого подсунули в код как литерал, обычно больше чем в одном месте.

Это плохо по той же причине, ПЯТНО (Единственная Точка Истины) хорошо: Если бы Вы хотели изменить эту константу позже, необходимо было бы искать через код для нахождения каждого экземпляра. Это также плохо, потому что другим программистам не могло бы быть ясно, что это число представляет, следовательно "волшебство".

Люди иногда берут устранение магического числа далее путем перемещения этих констант в отдельные файлы для действия как конфигурация. Это иногда полезно, но может также создать больше сложности, чем это стоит.

11
ответ дан Nick Retallack 8 January 2016 в 05:08
поделиться
  • 1
    У Вас есть более пример кода для этого. Я использую WPF, и я сделал, чтобы ListBox установил с DataTemplate, настроенным с Сеткой. У меня также есть ListBox. Установка ItemContainerStyle с Шаблоном и HorizontalContentAlignment установила для Протяжения однако этого doesn' t устраняют проблему. Я надеялся, что мог поместить, RelativeBinding к ActualWidth как Вы имеют в Вашем примере кода выше. – Luke 29 June 2009 в 14:32

Вы смотрели на статью в Википедии для магическое число?

Это вдается в небольшое количество подробностей обо всех способах, которыми сделана ссылка магического числа. Вот кавычка о магическом числе как плохая практика программирования

, термин магическое число также относится к плохой практике программирования использования чисел непосредственно в исходном коде без объяснения. В большинстве случаев это делает программы тяжелее, чтобы считать, понять, и поддержать. Хотя большинство руководств делает исключение для нуля чисел и один, это - хорошая идея определить все другие числа в коде как названные константами.

33
ответ дан MarianD 8 January 2016 в 05:08
поделиться
  • 1
    Та секунда должна кодировать блок быть ModifierKeys.Alt? – paxdiablo 23 June 2010 в 08:39

Магическое число является последовательностью символов в начале формата файла или обменом протокола. Это число служит проверкой работоспособности.

Пример: Откройте любой файл GIF, Вы будете видеть в, очень запустите: GIF89. "GIF89", являющийся магическим числом.

Другие программы могут считать первые несколько символов файла и правильно определить GIFs.

опасность состоит в том, что случайные двоичные данные могут содержать эти те же символы. Но это очень маловероятно.

Что касается обмена протокола, можно использовать его, чтобы быстро определить, что текущее 'сообщение', которое передается Вам, повреждается или не допустимое.

Магические числа все еще полезны.

19
ответ дан Brian R. Bondy 8 January 2016 в 05:08
поделиться
  • 1
    Я пытался установить ширину в ListBox. ItemContainerStyle с помощью < Свойство Метода set =" Width" Значение =" {Привязка RelativeSource = {RelativeSource AncestorType = {x:Type ListBoxItem}}, Path=ActualWidth} "/> и это didn' t работа. – Luke 29 June 2009 в 15:32

Стоит отметить иногда желание ненастраиваемых "трудно кодированных" чисел в коде. Существуют много известные включая 0x5F3759DF, который используется в оптимизированном обратном алгоритме квадратного корня.

В редких случаях, где я нахожу потребность использовать такие Магические числа, я установил их как константу в моем коде и документ, почему они используются, как они работают, и куда они произошли из.

3
ответ дан Rob Rolnick 8 January 2016 в 05:08
поделиться
  • 1
    Мне также сказали попробовать HorizontalContentAlignment =" Stretch" но к сожалению это didn' t выручают меня. НО к счастью эта ссылка выше (ищут фрагмент), помещая < ListBox. ItemContainerStyle> xaml в мой < ListBox> работа DID как очарование!Спасибо. – PHenry 3 November 2011 в 02:58

Магическое число является трудно кодированным значением, которое может измениться на более позднем этапе, но это может быть поэтому трудно обновить.

, Например, скажем, у Вас есть Страница, которая отображает последние 50 Заказов в "Вашем Заказы" Страница Обзора. 50 Магическое число здесь, потому что оно не установлено через стандарт или соглашение, это - число, что Вы восполнили причины, обрисованные в общих чертах в спецификации.

Теперь, то, что Вы делаете, является Вами, имеют 50 в различных местах - Ваш сценарий (SELECT TOP 50 * FROM orders) SQL, Ваш Веб-сайт (Ваши Последние 50 Заказов), Ваш вход в систему порядка (for (i = 0; i < 50; i++)) и возможно многих других местах.

Теперь, что происходит, когда кто-то решает измениться от 50 до 25? или 75? или 153? Теперь необходимо заменить 50 во всех местах, и Вы, очень вероятно, пропустите его. Найдите/Замените может не работать, потому что 50 может использоваться для других вещей, и вслепую замена 50 с 25 может иметь некоторые другие плохие побочные эффекты (т.е. Ваш Session.Timeout = 50 вызов, который также установлен на 25, и пользователи начинают сообщать о слишком частых тайм-аутах).

кроме того, код может быть трудно понять, т.е." if a < 50 then bla" - при обнаружении с этим посреди сложной функции другие разработчики, которые не знакомы с кодом, могут спросить себя "WTF, 50???"

Вот почему лучше иметь такие неоднозначные и произвольные числа точно в 1 месте -" const int NumOrdersToDisplay = 50", потому что это делает код более читаемым (" if a < NumOrdersToDisplay", это также означает, что только необходимо изменить его в 1 четко определенном месте.

Места, где Магические числа являются соответствующими, являются всем, что определяется через стандарт, т.е. SmtpClient.DefaultPort = 25 или TCPPacketSize = whatever (не уверенный, если это стандартизировано). Кроме того, все только определенное в 1 функции могло бы быть приемлемым, но это зависит от Контекста.

141
ответ дан Samuel 8 January 2016 в 05:08
поделиться
  • 1
    Спасибо, Луч, объяснение было добавленной премией так +1 для этого. – paxdiablo 23 June 2010 в 08:45

Проблема, которая не была упомянута с использованием магических чисел...

, Если у Вас есть очень многие из них, разногласия довольно хороши, что у Вас есть два различных цели , что Вы используете магические числа для, где значения , оказывается, то же.

И затем, конечно же, необходимо изменить значение... только для одной цели.

10
ответ дан 8 January 2016 в 15:08
поделиться
  • 1
    Превосходное объяснение! +1 для Вас Сэр – Arcturus 23 June 2010 в 20:48

А как насчет инициализации переменной в начале класса значением по умолчанию? Например:

public class SomeClass {
    private int maxRows = 15000;
    ...
    // Inside another method
    for (int i = 0; i < maxRows; i++) {
        // Do something
    }

    public void setMaxRows(int maxRows) {
        this.maxRows = maxRows;
    }

    public int getMaxRows() {
        return this.maxRows;
    }

В этом случае 15000 - это магическое число (согласно CheckStyles). Для меня установка значения по умолчанию - это нормально. Я не хочу делать это:

private static final int DEFAULT_MAX_ROWS = 15000;
private int maxRows = DEFAULT_MAX_ROWS;

Это затрудняет чтение? Я никогда не думал об этом, пока не установил CheckStyles.

3
ответ дан 22 November 2019 в 22:41
поделиться
Другие вопросы по тегам:

Похожие вопросы: