C'est un titre très vague mais je ne pouvais pas penser à une meilleure façon de le formuler. Mais, juste à titre d'exemple, pensez à la direction dans laquelle un personnage dans un jeu se déplace if(character.direction == "left")
. Il me semble que cela laisse trop de place aux erreurs idiotes, comme l'utilisation accidentelle Left
ou l
ou quoi que ce soit à la place de left
. Mes soupçons sont-ils corrects? Si oui, quelle est la meilleure façon de réaliser quelque chose comme ça?
19
bash
.Réponses:
Si la langue que vous utilisez prend en charge l'utilisation des énumérations, je les utiliserais. Il vous permet de limiter le nombre d'options disponibles pour un type donné. par exemple en Java:
la source
enum
comme java. De nombreuses langues (par exemple VBA) en ontenum
, mais ce n'est peut-être pas la meilleure option car elles n'ont pas la même pérennité. Voir ma réponse pour une discussion de pourquoienum
seul est une solution incomplète, souvent fragile et spécifique à la langue.C'est une terrible pratique d'utiliser des chaînes littérales (ou des nombres magiques) dans le code.
Les énumérations sont bonnes, ou du moins utilisent des constantes (les énumérations ne sont bien sûr qu'un type d'encapsuleur pour une ou plusieurs constantes liées).
Ce simple interrupteur a tellement d'avantages que je ne saurais même pas par où commencer pour les expliquer (du moins pas sans plus de café). Lisez sur les nombres magiques, c'est le même concept exact, appliqué uniquement à une valeur numérique au lieu d'une valeur de chaîne.
Voici une référence rapide, je suis sûr qu'il y en a des centaines d'autres: /programming/47882/what-is-a-magic-number-and-why-is-it-bad
la source
Réponse courte: Oui, les chaînes ne sont idéales pour aucune tâche autre que le stockage et l'accès à une séquence de caractères textuels, et même si les bits sous-jacents d'une abstraction sont des chaînes, il y a des avantages à les référencer en tant que variables ou constantes .
Réponse longue: la plupart des langues proposent des types plus proches du domaine de votre problème, et même si ce n'est pas le cas, elles ont probablement une méthode par laquelle vous pouvez définir
left
en tant qu'entité différente deright
(etc etc). La transformer en chaîne en utilisant"left"
est simplement la perte de la langue et des fonctionnalités utiles de l'EDI telles que la vérification des erreurs. Même si vous devez utiliserou quelque chose d'équivalent, il a des avantages à utiliser la chaîne lorsque vous y faites référence dans votre code. Par exemple,
serait détecté comme une erreur au moment de la compilation (dans le meilleur des cas, java et autres) ou serait signalé par n'importe quel IDE valant ses bits comme étant mauvais (dans le pire des cas, de base et autres).
De plus, le fait d'avoir la notion d'
left
entité référençable vous aidera à s'adapter à la direction que vous décidez d'aller avec le type de direction. En utilisant"left"
, la direction s'engage à être aString
. Si vous trouvez ou créez une meilleure abstraction pour le type, vous devez parcourir tout le corps de votre code en changeant chaque instance de"left"
. Une constante ou une variable ne nécessitera aucune modification si le type est élaboré.Le type que vous voulez vraiment est particulier à votre domaine. Qu'est-ce que votre code prévoit de faire avec vous
left
? Peut-être voudrez-vous mettre en miroir l'axe x d'une texture ou d'un sprite qui fait face à gauche ou qui avance; si tel est le cas, vous souhaiterez peut-être créerleft
un objet avec une propriété ou une méthode qui reflète ce comportement, votreright
objet ayant le résultat non inversé opposé. Vous pouvez faire cette logique dans un objet qui représente les sprites ou les textures, auquel cas vous souffrirez à nouveau pour l'utilisation"left"
au lieu desleft
raisons indiquées ci-dessus.En Java (et probablement dans d'autres langages que je ne connais pas encore),
enum
c'est une bonne alternative car en Java,enum
c'est aussi utilefinal class
avec un ensemble fini d'instances. Vous pouvez définir des comportements si vous en avez besoin, et vous pouvez basculer vers une classe ouverte sans tracas en dehors du fichier qui déclare leenum
, mais de nombreuses langues voient unenum
comme un type primitif ou nécessitent une syntaxe spéciale à utiliser. Cela fuit leenum
capot vers un code qui n'a rien à voir avec cela et peut-être besoin d'être corrigé plus tard. Assurez-vous de bien comprendre le concept de votre langueenum
avant de considérer l'option.la source
Vous n'avez pas spécifié votre langue, mais pour donner une réponse générique, vous devez utiliser des chaînes lorsque vous avez réellement besoin du texte, pas pour représenter quelque chose. L'exemple que vous avez donné, par exemple, ne serait tout simplement pas acceptable dans les logiciels de production.
Chaque langue possède différents types de données de base et vous devez utiliser celle qui convient le mieux à la tâche. Pour utiliser votre exemple, vous pouvez utiliser des constantes numériques pour représenter différents états. Donc, gauche pourrait avoir une valeur de zéro et droite serait un. Outre la raison que vous avez mentionnée, les valeurs numériques occupent moins d'espace (mémoire) et il est toujours plus rapide de comparer des nombres que de comparer plusieurs chaînes de caractères.
Comme cela a été suggéré, utilisez des énumérations si votre langue le permet. Dans votre exemple spécifique, c'est clairement le meilleur choix.
la source
if (uppercase(foo) == "LEFT")
Utilisez simplement le type de données qui convient à votre situation.
L'utilisation du
string
type comme communication inter / intra-application sous-jacente n'est pas intrinsèquement un problème. En fait, il est parfois préférable d'utiliser des chaînes: si vous avez une API publique, il peut être souhaitable que les valeurs entrant et sortant de l'API soient lisibles par l'homme. Cela facilite l'apprentissage et le débogage pour les utilisateurs de votre API.Le vrai problème avec votre code réside dans la répétition de la valeur.
Ne faites pas ça:
Si vous avez fait une faute de frappe dans l'une de ces conditions ou d'autres utilisations de "left" quelque part, vous ne pourrez peut-être pas effectuer efficacement une recherche à l'échelle du code, car vous l'avez mal saisie!
Au lieu de cela, codez par rapport à une énumération ou une constante - selon la prise en charge du type de données dont vous avez besoin dans la ou les langues que vous utilisez.
Cela signifie que
LEFT
vous devez attribuer une seule et unique fois à votre demande. Et, le reste de votre code devrait exploiter ces énumérations ou constantes:Cela vous permet également de modifier plus facilement le type de données que vous utilisez pour vos directions ultérieurement, si vous le souhaitez.
la source
Est-ce une mauvaise pratique?
Probablement oui, mais cela dépend exactement de ce que vous faites, ainsi que du langage de programmation que vous utilisez.
Dans votre exemple, nous pouvons déduire qu'il existe un petit ensemble de valeurs fixes pour toujours qu'une direction pourrait prendre. Dans ce cas, il n'y a aucun avantage à utiliser une chaîne et certains inconvénients certains. Pour cet exemple:
enum
type serait préférable si votre langage de programmation le prend en charge.Mais la réponse peut être différente si l'ensemble de valeurs est modifiable dynamiquement ou doit évoluer dans le temps. Dans la plupart des langues, la modification d'un
enum
type (par exemple pour ajouter ou supprimer une valeur) nécessite une recompilation complète. (Par exemple, la suppression d'une valeur d'énumération en Java rompt la compatibilité binaire.) Et il en va de même pour les constantes entières nommées.Dans des scénarios comme celui-ci, une autre solution peut être requise et l'utilisation de chaînes est l'une des options. (Et vous pouvez combiner des littéraux de chaîne et des constantes nommées ... si le scénario implique un noyau fixe avec des extensions dynamiques.)
Si vous implémentez en Java,
character.direction == "left"
c'est une mauvaise pratique pour une autre raison. Vous ne devez pas utiliser==
pour comparer des chaînes, car il teste l'identité des objets plutôt que l'égalité des chaînes. (Cela fonctionnerait si vous pouviez garantir que toutes les instances de la"left"
chaîne ont été internées, mais cela nécessite une analyse de l'ensemble de l'application.)la source
String
pour représenter les directions ferait une différence proche de zéro à la quantité de travail nécessaire pour effectuer les changements. Une approche plus sensée consiste à supposer que le nombre de directions ne changera pas et à reconnaître que vous auriez beaucoup de travail à faire de toute façon si les règles du jeu changeaient si fondamentalement.Comme suggéré, vous devez utiliser Enums. Cependant, le simple fait d'utiliser l'Enum en remplacement des Strigns n'est pas suffisant à mon humble avis. Dans votre exemple particulier, la vitesse du joueur devrait en fait être un vecteur au moyen de la physique:
Ce vecteur doit ensuite être utilisé pour mettre à jour la position du joueur à chaque tick.
Vous pouvez ensuite combiner cela avec une énumération pour une meilleure lisibilité:
la source