магическое число против Символическая константа: когда заменить?
Магия: Неизвестная семантика
Символическая константа -> Предоставляет как правильный семантический, так и правильный контекст для использования
Семантика: значение или назначение вещи.
«Создайте константу, назовите ее после значения и замените ее числом». - Мартин Фаулер
Во-первых, магические числа - это не просто числа. Любое базовое значение может быть «магическим». Базовые значения - это объекты манифеста, такие как целые числа, вещественные числа, числа с плавающей запятой, числа с плавающей запятой, даты, строки, логические значения, символы и т. Д. Проблема заключается не в типе данных, а в «магическом» аспекте значения, как это показано в нашем коде.
Что мы подразумеваем под "магией"? Чтобы быть точным: «магией» мы намереваемся указать на семантику (значение или цель) значения в контексте нашего кода; что это неизвестно, непостижимо, неясно или сбивает с толку. Это понятие "магия". Базовое значение не является магическим, когда его семантическое значение или цель существования быстро и легко узнаются, ясны и понятны (не путаются) из окружающего контекста без специальных вспомогательных слов (например, символической константы).
Поэтому мы идентифицируем магические числа, измеряя способность читателя кода знать, быть ясным и понимать значение и цель базовой ценности из окружающего контекста. Чем менее известный, менее понятный и более запутанный читатель, тем более «волшебным» является базовое значение.
Полезные определения
- сбить с толку: заставить (кого-то) сбиться с толку или растерян.
- сбит с толку: привести кого-то в замешательство и замешательство.
- озадачен: полностью сбит с толку; очень озадачен.
- сбит с толку: совершенно сбит с толку или озадачен.
- озадачен: не в состоянии понять; озадачен.
- понимать: воспринимать предполагаемое значение (слова, язык или говорящий).
- значение: что означает слово, текст, понятие или действие.
- означает: намереваться передать, указать или сослаться (на конкретную вещь или понятие); означают.
- означать: указание на.
- указание: знак или часть информации, которая указывает что-либо.
- указать: указать; показать.
- знак: объект, качество или событие, наличие или происхождение которого указывает на вероятное присутствие или возникновение чего-либо еще.
Основы
У нас есть два сценария для наших основных магических ценностей. Только второе имеет первостепенное значение для программистов и кода:
- Одиночное базовое значение (например, число), значение которого неизвестно, неизвестно, неясно или сбивает с толку.
- Базовое значение (например, число) в контексте, но его значение остается неизвестным, непознаваемым, неясным или сбивающим с толку.
Общая зависимость «волшебства» заключается в том, что одиночное базовое значение (например, число) не имеет общеизвестной семантики (например, Pi), но имеет локально известную семантику (например, вашу программу), которая не совсем понятна из контекста или могут быть использованы в хорошем или плохом контексте.
Семантика большинства языков программирования не позволяет нам использовать отдельные базовые значения, за исключением (возможно) в качестве данных (то есть таблиц данных). Когда мы сталкиваемся с «магическими числами», мы обычно делаем это в контексте. Поэтому ответ на
«Заменить ли это магическое число символической константой?»
это:
"Как быстро вы можете оценить и понять семантическое значение
номер (его цель для того, чтобы быть там) в его контексте? "
Вид магии, но не совсем
Имея в виду эту мысль, мы можем быстро увидеть, что число, такое как Pi (3.14159), не является "магическим числом", если помещено в надлежащий контекст (например, 2 x 3.14159 x радиус или 2 * Pi * r). Здесь число 3.14159 мысленно распознается как Пи без символического идентификатора константы.
Тем не менее, мы обычно заменяем 3.14159 символьным постоянным идентификатором, таким как Pi, из-за длины и сложности числа. Аспекты длины и сложности числа Pi (в сочетании с необходимостью в точности) обычно означают, что символический идентификатор или константа менее подвержены ошибкам. Признание «Пи» в качестве имени - это просто удобный бонус, но не основная причина наличия постоянной.
Тем временем: обратно на ранчо
Оставляя в стороне общие константы, такие как Pi, давайте сосредоточимся в первую очередь на числах с особыми значениями, но эти значения ограничены вселенной нашей программной системы. Такое число может быть «2» (как базовое целочисленное значение).
Если я использую число 2 само по себе, мой первый вопрос может быть следующим: что означает «2»? Значение «2» само по себе неизвестно и непостижимо без контекста, что делает его использование неясным и запутанным. Даже если в нашем программном обеспечении просто «2» не произойдет из-за языковой семантики, мы хотим видеть, что «2» сама по себе не несет никакой специальной семантики или очевидной цели в одиночестве.
Давайте поместим нашу одиночную «2» в контекст: padding := 2
, где контекст - это «Контейнер GUI». В этом контексте значение 2 (в виде пикселей или другой графической единицы) предлагает нам быстрое предположение о его семантике (значение и цель). Мы могли бы остановиться здесь и сказать, что 2 в этом контексте хорошо, и нам больше ничего не нужно знать. Однако, возможно, в нашей программной вселенной это еще не все. Это еще не все, но "padding = 2" как контекст не может раскрыть его.
Давайте далее притворимся, что 2 в качестве отступа пикселей в нашей программе имеет разновидность «default_padding» во всей нашей системе. Поэтому написание инструкции padding = 2
недостаточно. Понятие «дефолт» не раскрывается. Только когда я пишу: padding = default_padding
в качестве контекста, а затем в другом месте: default_padding = 2
, я полностью осознаю лучшее и более полное значение (семантическое и целевое) значения 2 в нашей системе.
Пример выше довольно хорош, потому что «2» может быть чем угодно. Только когда мы ограничиваем диапазон и область понимания «моей программой», где 2 - это default_padding
в UX-части GUI «моей программы», мы наконец понимаем «2» в соответствующем контексте. Здесь «2» - это «магическое» число, которое переводится в символическую константу default_padding
в контексте пользовательского интерфейса GUI «моей программы», чтобы его можно было использовать как default_padding
, быстро понимаемое в более широком контексте кода вложения.
Таким образом, любое базовое значение, значение которого (семантическое и целевое) не может быть достаточно и быстро понято, является хорошим кандидатом на символическую константу вместо базового значения (например, магического числа).
Идем дальше
Числа на шкале также могут иметь семантику. Например, представьте, что мы делаем игру D & D, где у нас есть понятие монстра. Наш монстр объект имеет функцию под названием life_force
, которая является целым числом. Числа имеют значения, которые невозможно понять или понять без слов, чтобы придать смысл. Таким образом, мы начинаем с произвольной поговорки:
- full_life_force: INTEGER = 10 - очень живой (и невредимый)
- imum_life_force: INTEGER = 1 - едва жив (очень больно)
- мертв: INTEGER = 0 - мертв
- нежить: INTEGER = -1 - Мин нежити (почти мертвый)
- зомби: INTEGER = -10 - Макс нежити (очень нежить)
Исходя из символических констант, приведенных выше, мы начинаем получать мысленную картину живости, мертвости и «нежити» (и возможных последствий или последствий) для наших монстров в нашей игре D & D. Без этих слов (символических констант) у нас останутся только цифры в диапазоне от -10 .. 10
. Просто диапазон без слов оставляет нас в возможной путанице и, возможно, с ошибками в нашей игре, если разные части игры зависят от значения этого диапазона чисел для различных операций, таких как attack_elves
или seek_magic_healing_potion
.
Следовательно, при поиске и рассмотрении замены «магических чисел» мы хотим задавать очень целенаправленные вопросы о числах в контексте нашего программного обеспечения и даже о том, как числа семантически взаимодействуют друг с другом.
Заключение
Давайте рассмотрим, какие вопросы мы должны задать:
У вас может быть магическое число, если ...
- Может ли базовое значение иметь особое значение или цель в вашей вселенной программного обеспечения?
- Может ли особое значение или цель быть неизвестными, непознаваемыми, неясными или сбивающими с толку даже в собственном контексте?
- Может ли правильное базовое значение быть неправильно использовано с плохими последствиями в неправильном контексте?
- Может ли неправильное базовое значение правильно использоваться с плохими последствиями в правильном контексте?
- Имеет ли базовое значение семантические или целевые отношения с другими базовыми значениями в определенных контекстах?
- Может ли базовое значение существовать в более чем одном месте в нашем коде с различной семантикой в каждом, что вызывает у читателя путаницу?
Изучите автономные базовые значения манифеста в тексте кода. Медленно и вдумчиво задавайте каждый вопрос о каждом случае такой ценности. Подумайте о силе вашего ответа. Часто ответ не черно-белый, но имеет оттенки неправильно понятого значения и цели, скорости обучения и скорости понимания. Также необходимо посмотреть, как он подключается к программному компьютеру вокруг него.
В конце ответом на замену является ответ на меру (по вашему мнению) силы или слабости читателя, чтобы установить связь (например, «получить его»). Чем быстрее они понимают смысл и цель, тем меньше у вас «волшебства».
ЗАКЛЮЧЕНИЕ: Заменяйте базовые значения символическими константами только тогда, когда магия достаточно велика, чтобы затруднять обнаружение ошибок, возникающих в результате путаницы.