Es un título muy vago, pero no se me ocurre una mejor manera de expresarlo. Pero, solo como ejemplo, piense en la dirección en la que se mueve un personaje en un juego. Se siente un poco mal usar una cuerda y luego hacer cosas como if(character.direction == "left")
. Me parece que deja demasiado margen para errores tontos, como el uso accidental Left
o l
o lo que sea en lugar de left
. ¿Son correctas mis sospechas? Si es así, ¿cuál es la forma preferida de lograr algo como esto?
19
bash
.Respuestas:
Si el lenguaje que está utilizando admite el uso de enumeraciones, los usaría. Le permite limitar la cantidad de opciones disponibles para un tipo dado. Por ejemplo, en Java:
fuente
enum
como java. Muchos idiomas (por ejemplo, VBA) tienenenum
, pero puede que no sea la mejor opción ya que carece de la misma protección para el futuro. Vea mi respuesta para una discusión de por quéenum
solo es una solución incompleta, a menudo frágil y específica del idioma.Es una práctica terrible usar cadenas literales (o números mágicos) en el código.
Las enumeraciones son buenas, o al menos usan constantes (las enumeraciones, por supuesto, son solo un tipo envoltorio para una o más constantes relacionadas).
Este simple cambio tiene tantas ventajas que ni siquiera sabría por dónde empezar a explicarlas (al menos no sin un poco más de café). Lea sobre los números mágicos, es el mismo concepto exacto, solo se aplica a un valor numérico en lugar de un valor de cadena.
Aquí hay una referencia rápida, estoy seguro de que hay cientos más: /programming/47882/what-is-a-magic-number-and-why-is-it-bad
fuente
Respuesta corta: Sí, las cadenas no son ideales para ninguna otra tarea que no sea almacenar y acceder a una secuencia de caracteres textuales, e incluso si los bits subyacentes de una abstracción son cadenas, hay ventajas en hacer referencia a ellas como variables o constantes .
Respuesta larga: la mayoría de los idiomas ofrecen tipos que están más cerca del dominio de su problema, e incluso si no lo hacen, probablemente tengan algún método por el cual puede definir
left
como una entidad diferente deright
(etc., etc.). Convertirlo en una cadena mediante el uso"left"
es simplemente la pérdida del idioma y la funcionalidad útil del IDE, como la verificación de errores. Incluso si tienes que usaro algo equivalente, tiene ventajas al usar la cadena cuando se refiere a ella a través de su código. Por ejemplo,
se detectaría como un error en tiempo de compilación (el mejor de los casos, java y tal) o sería marcado por cualquier IDE que valga sus bits como incorrecto (el peor de los casos, básico y tal).
Además, tener la noción de
left
entidad referenciable lo ayudará a adaptarse a cualquier dirección que decida ir con el tipo de dirección. Al usar"left"
, la dirección se compromete a ser aString
. Si encuentra o crea una mejor abstracción para el tipo, debe buscar todo el cuerpo del código cambiando cada instancia de"left"
. Una constante o variable no requerirá ningún cambio si se elabora el tipo.El tipo que realmente desea es particular para su dominio. ¿Qué planea hacer tu código con tu
left
? Tal vez desee reflejar el eje x de una textura o sprite que se enfrenta a la izquierda o se mueve hacia adelante; si es así, es posible que desee hacerleft
un objeto con una propiedad o método que refleje ese comportamiento, con suright
objeto teniendo el resultado opuesto no reflejado. Podría hacer esa lógica en un objeto que represente los sprites o texturas, en cuyo caso nuevamente sufrirá por usar en"left"
lugar deleft
por las razones indicadas anteriormente.En Java (y probablemente en otros lenguajes que aún no conozco),
enum
es una buena alternativa porque en Javaenum
es tan útil comofinal class
con un conjunto finito de instancias. Puede definir comportamientos si los necesita, y puede cambiar a una clase abierta sin problemas fuera del archivo que declara elenum
, pero muchos idiomas ven unenum
tipo primitivo o requieren una sintaxis especial para usar. Eso filtra elenum
capó al código que no tiene nada que ver con eso y es posible que deba corregirse más adelante. Asegúrese de comprender el concepto de idioma de suenum
antes de considerar la opción.fuente
No especificó su idioma, pero para dar una respuesta genérica, debe usar cadenas cuando realmente necesita el texto, no para representar algo. El ejemplo que dio, por ejemplo, simplemente no sería aceptable en el software de producción.
Cada idioma tiene varios tipos de datos básicos y debe usar el más apropiado para la tarea. Para usar su ejemplo, podría usar constantes numéricas para representar diferentes estados. Entonces left podría tener un valor de cero y right sería uno. Además de la razón que mencionó, los valores numéricos ocupan menos espacio (memoria) y siempre es más rápido comparar números que comparar cadenas de caracteres múltiples.
Como se ha sugerido, use enumeraciones si su idioma lo permite. En su ejemplo específico, es claramente la mejor opción.
fuente
if (uppercase(foo) == "LEFT")
Simplemente use el tipo de datos que tenga sentido en su situación.
El uso del
string
tipo como comunicación subyacente entre aplicaciones / intra aplicaciones no es un problema inherente. De hecho, a veces es preferible usar cadenas: si tiene una API pública, puede ser deseable que los valores que entran y salen de la API sean legibles para los humanos. Esto facilita que las personas que usan su API puedan aprender y depurar.El verdadero problema con su código radica en repetir el valor.
No hagas esto:
Si cometió un error tipográfico en uno de estos condicionales u otros usos de "left" en alguna parte, es posible que no pueda realizar una búsqueda efectiva en todo el código base porque lo ha escrito mal.
En su lugar, codifique contra una enumeración o una constante, dependiendo de cuál sea el tipo de datos que necesita en los idiomas que está utilizando.
Eso significa que
LEFT
debe asignarse a una vez y solo una vez en su aplicación. Y, el resto de su código debería aprovechar esas enumeraciones o constantes:Esto también le permite cambiar más fácilmente el tipo de datos que usa para sus instrucciones más adelante, si así lo desea.
fuente
¿Es una mala práctica?
Probablemente sí, pero depende exactamente de lo que esté haciendo y también del lenguaje de programación que esté utilizando.
En su ejemplo, podemos inferir que existe un conjunto de valores pequeño y fijo para siempre que una dirección podría tomar. En este caso, no hay ventajas en el uso de una cadena, y algunas desventajas definitivas. Para este ejemplo:
enum
tipo sería preferible, si su lenguaje de programación lo admite.Pero la respuesta puede ser diferente si el conjunto de valores se puede modificar dinámicamente o si necesita evolucionar con el tiempo. En la mayoría de los idiomas, cambiar un
enum
tipo (por ejemplo, para agregar o eliminar un valor) requiere una compilación completa. (Por ejemplo, eliminar un valor de enumeración en Java rompe la compatibilidad binaria). Y lo mismo se aplica a las constantes de enteros con nombre.En escenarios como este, puede ser necesaria otra solución, y el uso de cadenas es una de las opciones. (Y podría combinar literales de cadena y constantes con nombre ... si el escenario implica un núcleo fijo con extensiones dinámicas).
Si está implementando en Java,
character.direction == "left"
es una mala práctica por otra razón. No debe usar==
para comparar cadenas, ya que prueba las identidades de los objetos en lugar de la igualdad de cadenas. (Funcionaría si pudiera garantizar que todas las instancias de la"left"
cadena hayan sido internados, pero eso requiere un análisis completo de la aplicación).fuente
String
para representar las direcciones supondría una diferencia cercana a cero en la cantidad de trabajo involucrado para realizar los cambios. Un enfoque más sensato es asumir que la cantidad de direcciones no cambiará y reconocer que tendría mucho trabajo por hacer de cualquier manera si las reglas del juego cambiaran tan fundamentalmente.Como se sugiere, debe usar Enums. Sin embargo, solo usar Enum como reemplazo de Strigns no es suficiente en mi humilde opinión. En su ejemplo particular, la velocidad del jugador en realidad debería ser un vector por medio de la física:
Este vector debe usarse para actualizar la posición del jugador en cada marca.
Luego puede combinar eso con una enumeración para una mayor legibilidad:
fuente