Это очень расплывчатое название, но я не мог придумать лучшего способа выразить это. Но, в качестве примера, подумайте о направлении, в котором движется персонаж в игре. Просто кажется неправильным использовать строку, а затем делать что-то подобное if(character.direction == "left")
. Мне кажется , что она оставляет слишком много места для глупых ошибок, вроде случайного использования Left
или l
или что - то вместо left
. Мои подозрения верны? Если да, то каков предпочтительный способ достижения чего-то подобного?
19
bash
.Ответы:
Если используемый вами язык поддерживает использование перечислений, я бы их использовал. Это позволяет вам ограничить количество опций, доступных для данного типа. например в Java:
источник
enum
такими классными, как java. Многие языки (например, VBA) имеютenum
, но это, возможно, не лучший вариант, так как в нем отсутствует такая же перспектива на будущее. См. Мой ответ для некоторого обсуждения того, почемуenum
одно это неполное, часто хрупкое и специфичное для языка решение.Страшная практика - использовать буквенные строки (или магические числа) в коде.
Перечисления хороши или, по крайней мере, используют константы (конечно, перечисления являются просто типом-оберткой для одной или нескольких связанных констант).
У этого простого переключателя есть так много преимуществ, что я даже не знаю, с чего начать, чтобы объяснить их (по крайней мере, без кофе). Читайте о магических числах, это та же самая точная концепция, применяемая только к числовому значению вместо строкового значения.
Вот один быстрый реф, я уверен, что есть еще сотни: /programming/47882/what-is-a-magic-number-and-why-is-it-bad
источник
Короткий ответ: Да, строки не идеальны для какой-либо задачи, кроме хранения и доступа к последовательности текстовых символов, и даже если лежащие в основе биты абстракции являются строками, есть преимущество ссылаться на них как на переменные или константы .
Длинный ответ: большинство языков предлагают типы, которые ближе к области вашей проблемы, и даже если они этого не делают, у них, вероятно, есть какой-то метод, с помощью которого вы можете определить
left
как объект, отличный отright
(и т. Д. И т. Д.). Превращение в строку с помощью"left"
просто лишает языка и полезной функциональности IDE, такой как проверка ошибок. Даже если вам придется использоватьили что-то эквивалентное, у него есть преимущества использования строки, когда вы обращаетесь к ней по всему коду. Например,
будет обнаружен как ошибка во время компиляции (в лучшем случае, java и т. д.) или будет помечен любой IDE, которая стоит своих битов как неправильная (в худшем случае, базовая и т. д.).
Кроме того, наличие понятия
left
ссылочной сущности поможет вам согласовать любое направление с выбранным типом направления. Используя"left"
, направление стремится бытьString
. Если вы найдете или создадите лучшую абстракцию для этого типа, вам нужно будет изучить весь ваш код, меняя каждый экземпляр"left"
. Константа или переменная не требуют каких-либо изменений, если тип разработан.Тип, который вы действительно хотите, относится к вашему домену. Что ваш код планирует делать с вашим
left
? Возможно, вы захотите отразить ось x текстуры или спрайта, которые направлены влево или движутся вперед; если это так, вы можете создатьleft
объект со свойством или методом, отражающим это поведение, при этом вашright
объект будет иметь противоположный результат без зеркального отображения. Вы можете сделать эту логику в объекте, который представляет спрайты или текстуры, и в этом случае вы снова будете страдать за использование"left"
вместоleft
причин, указанных выше.В Java (и, возможно, в других языках, которые я пока не знаю),
enum
это хорошая альтернатива, потому что в Javaenum
она также полезнаfinal class
с конечным набором экземпляров. Вы можете определить поведения, если они вам нужны, и вы можете переключиться на открытый класс без каких-либо хлопот за пределами файла, который объявляетenum
, но многие языки рассматривают егоenum
как примитивный тип или требуют использования специального синтаксиса. Этоenum
приводит к утечке кода, который не имеет к нему никакого отношения и, возможно, потребуется исправить позже. Убедитесь, что вы понимаете концепцию вашего языка,enum
прежде чем рассматривать вариант.источник
Вы не указали свой язык, но чтобы дать общий ответ, вы должны использовать строки, когда вам действительно нужен текст, а не представлять что-то. Например, пример, который вы привели, просто не был бы приемлем в производственном программном обеспечении.
Каждый язык имеет различные базовые типы данных, и вы должны использовать тот, который наиболее подходит для задачи. Чтобы использовать ваш пример, вы можете использовать числовые константы для представления различных состояний. Таким образом, left может иметь значение ноль, а right будет единица. Помимо упомянутой причины, числовые значения занимают меньше места (памяти), и всегда быстрее сравнивать числа, чем сравнивать несколько строк символов.
Как было предложено, используйте перечисления, если ваш язык позволяет. В вашем конкретном примере это явно лучший выбор.
источник
if (uppercase(foo) == "LEFT")
Просто используйте тип данных, который имеет смысл в вашей ситуации.
Использование
string
типа в качестве базовой связи между приложениями не является проблемой. На самом деле, иногда предпочтительнее использовать строки: если у вас есть открытый API, может быть желательно, чтобы значения, входящие и выходящие из API, были удобочитаемыми. Это облегчает изучение и отладку людьми, использующими ваш API.Настоящая проблема с вашим кодом заключается в повторении значения.
Не делай этого:
Если вы произвели опечатку в одном из этих условных выражений или в других случаях использования «оставленных» где-то, возможно, вы не сможете эффективно выполнить поиск по всей базе кода, потому что вы его опечатали!
Вместо этого используйте код для перечисления или константы - в зависимости от того, какой тип данных вам нужен на языке (ах), который вы используете.
Это означает, что
LEFT
должно быть назначено один раз и только один раз в вашем приложении. И остальная часть вашего кода должна использовать эти перечисления или константы:Это также позволяет вам легче изменить тип данных, который вы используете для своих указаний позже, если вы того пожелаете.
источник
Это плохая практика?
Возможно, да, но это зависит от того , что вы делаете, а также от языка программирования, который вы используете.
В вашем примере мы можем заключить, что существует небольшой и постоянный набор значений, которые может принять направление. В этом случае нет никаких преимуществ в использовании строки и некоторые определенные недостатки. Для этого примера:
enum
Типа было бы предпочтительнее, если ваш язык программирования поддерживает это.Но ответ может быть другим, если набор значений является динамически изменяемым или должен развиваться с течением времени. В большинстве языков изменение
enum
типа (например, для добавления или удаления значения) требует полной перекомпиляции. (Например, удаление значения перечисления в Java нарушает двоичную совместимость.) И то же самое относится к именованным целочисленным константам.В подобных сценариях может потребоваться другое решение, и использование строк является одним из вариантов. (И вы можете комбинировать строковые литералы и именованные константы ... если сценарий предполагает фиксированное ядро с динамическими расширениями.)
Если вы реализуете на Java,
character.direction == "left"
это плохая практика по другой причине. Вы не должны использовать==
для сравнения строк, потому что это проверка идентичности объекта, а не равенство строк. (Это сработало бы, если бы вы могли гарантировать, что все экземпляры"left"
строки были интернированы, но это требует анализа всего приложения.)источник
String
для представления направлений приведет к практически нулевой разнице в объеме работ, необходимых для внесения изменений. Более разумный подход состоит в том, чтобы предположить, что количество направлений не изменится, и признать, что вам придется проделать большую работу в любом случае, если правила игры так кардинально изменились.Как и предполагалось, вы должны использовать Enums. Тем не менее, просто использование Enum в качестве замены для Strigns не является достаточным ИМХО. В вашем конкретном примере скорость игрока на самом деле должна быть вектором с помощью физики:
Этот вектор должен затем использоваться для обновления позиции игрока каждый тик.
Затем вы можете объединить это с перечислением для большей читабельности:
источник