Как опытный разработчик программного обеспечения, я научился избегать волшебных струн.
Моя проблема в том, что с тех пор, как я их использовал, прошло так много времени, что я забыл большинство причин. В результате у меня возникают проблемы с объяснением, почему они являются проблемой для моих менее опытных коллег.
Какие объективные причины существуют, чтобы их избегать? Какие проблемы они вызывают?
anti-patterns
Kramii
источник
источник
Ответы:
В языке, который компилируется, значение магической строки не проверяется во время компиляции . Если строка должна соответствовать определенному шаблону, вы должны запустить программу, чтобы гарантировать, что она соответствует этому шаблону. Если вы использовали что-то, например, перечисление, значение по крайней мере допустимо во время компиляции, даже если это может быть неправильное значение.
Если волшебная строка пишется в нескольких местах, вы должны изменить их все без какой-либо безопасности (например, ошибка времени компиляции). Этому можно противостоять, только объявив его в одном месте и повторно использовав переменную.
Опечатки могут стать серьезными ошибками. Если у вас есть функция:
а кто-то случайно набирает:
Это тем хуже, чем реже или сложнее строка, особенно если у вас есть программисты, незнакомые с родным языком проекта.
Волшебные струны редко самодокументируются. Если вы видите одну строку, это ничего не говорит вам о том, что еще строка может / должна быть. Возможно, вам придется изучить реализацию, чтобы убедиться, что вы выбрали правильную строку.
Реализация такого рода является утечкой , требующей либо внешней документации, либо доступа к коду, чтобы понять, что должно быть написано, тем более что она должна быть идеальной (как в пункте 3).
Если не считать функции «найти строку» в IDE, существует небольшое количество инструментов, поддерживающих шаблон.
Вы можете по совпадению использовать одну и ту же магическую строку в двух местах, когда на самом деле это разные вещи, поэтому, если вы выполнили поиск и замену и изменили оба, один из них может сломаться, пока другой работает.
источник
Вершина того, за что ухватились другие ответы, состоит не в том, что «магические ценности» плохие, а в том, что они должны быть:
Что обычно отличает приемлемые «константы» от «магических ценностей», так это некоторое нарушение одного или нескольких из этих правил.
При правильном использовании константы просто позволяют нам выражать определенные аксиомы нашего кода.
Что подводит меня к окончательному выводу, что чрезмерное использование констант (и, следовательно, чрезмерное количество допущений или ограничений, выраженных в терминах значений), даже если оно иным образом соответствует вышеуказанным критериям (но особенно, если оно отклоняется от них), Это может означать, что разрабатываемое решение не является достаточно общим или хорошо структурированным (и поэтому мы больше не говорим о плюсах и минусах констант, а о плюсах и минусах хорошо структурированного кода).
Языки высокого уровня имеют конструкции для шаблонов на языках низкого уровня, которые должны использовать константы. Те же шаблоны можно использовать и в языке более высокого уровня, но этого не следует делать.
Но это может быть экспертное суждение, основанное на впечатлении всех обстоятельств и того, как должно выглядеть решение, и то, как именно это суждение будет оправдано, будет сильно зависеть от контекста. В самом деле, это может быть неоправданным с точки зрения какого-либо общего принципа, кроме как утверждать: «Я достаточно взрослый, чтобы уже видеть такую работу, с которой я знаком, лучше»!
РЕДАКТИРОВАТЬ: приняв одно редактирование, отклонив другое и теперь выполнив свое собственное редактирование, могу ли я теперь считать, что стиль форматирования и пунктуации в моем списке правил должен быть установлен раз и навсегда, ха-ха!
источник
value / 2
, чемvalue / VALUE_DIVISOR
с последним, определенным как в2
другом месте. Если вы намереваетесь обобщить метод, обрабатывающий CSV, вы, вероятно, захотите, чтобы разделитель передавался как параметр, а не определялся как константа вообще. Но это все вопрос суждения в контексте - пример @ WGroleau -SPEED_OF_LIGHT
это то, что вы хотели бы явно назвать, но не каждому буквальному требованию это нужно.источник
Пример из реальной жизни: я работаю со сторонней системой, в которой «сущности» хранятся с «полями». В основном система EAV . Поскольку добавить другое поле довольно просто, вы получите доступ к нему, используя имя поля в виде строки:
(обратите внимание на волшебную строку «ProductName»)
Это может привести к нескольким проблемам:
Таким образом, мое решение для этого состояло в том, чтобы генерировать константы для этих имен, организованных по типу сущности. Так что теперь я могу использовать:
Это все еще строковая константа, которая компилируется в один и тот же двоичный файл, но имеет несколько преимуществ:
Далее в моем списке: спрятать эти константы за сгенерированными строго типизированными классами - тогда и тип данных будет защищен.
источник
nameField = myEntity.ProductName;
.Волшебные струны не всегда плохи , поэтому это может быть причиной, по которой вы не можете придумать общую причину, чтобы избегать их. (Под «волшебной строкой» я предполагаю, что вы подразумеваете строковый литерал как часть выражения, а не как константу.)
В некоторых особых случаях следует избегать волшебных строк:
Но в некоторых случаях «волшебные струны» хороши. Скажем, у вас есть простой парсер:
Здесь действительно нет волшебства, и ни одна из вышеописанных проблем не применима. ИМХО не было бы никакой пользы, чтобы определить
string Plus="+"
и т. Д. Держите это просто.источник
if (dx != 0) { grad = dy/dx; }
."+"
и"-"
наTOKEN_PLUS
иTOKEN_MINUS
. Каждый раз, когда я читал это, я чувствовал, что из-за этого было труднее читать и отлаживать! Определенно место, где я согласен, что использование простых строк лучше.Чтобы добавить к существующим ответам:
Интернационализация (i18n)
Если текст, отображаемый на экране, жестко запрограммирован и скрыт внутри слоев функций, вам будет очень сложно обеспечить перевод этого текста на другие языки.
Некоторые среды разработки (например, Qt) обрабатывают переводы путем поиска из текстовой строки базового языка в переведенный язык. Волшебные струны, как правило, могут пережить это - пока вы не решите, что хотите использовать тот же текст в другом месте и получить опечатку. Даже тогда очень сложно найти, какие магические строки нужно перевести, если вы хотите добавить поддержку другого языка.
Некоторые среды разработки (например, MS Visual Studio) используют другой подход и требуют, чтобы все переведенные строки содержались в базе данных ресурсов и считывались обратно для текущей локали по уникальному идентификатору этой строки. В этом случае ваше приложение с волшебными строками просто не может быть переведено на другой язык без серьезной переделки. Эффективная разработка требует ввода всех текстовых строк в базу данных ресурсов и получения уникального идентификатора при первом написании кода, а после этого i18n относительно прост. Попытка заполнить это после факта, как правило, потребует очень больших усилий (и да, я был там!), Так что гораздо лучше сделать все правильно с самого начала.
источник
Это не является приоритетом для всех, но если вы когда-нибудь захотите иметь возможность автоматически вычислять метрики связности / сцепления в вашем коде, магические строки делают это практически невозможным. Строка в одном месте будет ссылаться на класс, метод или функцию в другом месте, и не существует простого, автоматического способа определить, что строка связана с классом / методом / функцией, просто анализируя код. Только базовый фреймворк (например, Angular) может определить наличие связи - и он может сделать это только во время выполнения. Чтобы получить информацию о сопряжении самостоятельно, вашему анализатору необходимо знать все об используемой вами среде, помимо базового языка, на котором вы кодируете.
Но опять же, это не то, что заботит многих разработчиков.
источник