Como desenvolvedor de software experiente, aprendi a evitar seqüências de caracteres mágicas.
Meu problema é que já faz muito tempo desde que eu os uso, esqueci a maioria das razões. Como resultado, estou tendo problemas para explicar por que eles são um problema para meus colegas menos experientes.
Que razões objetivas existem para evitá-las? Que problemas eles causam?
anti-patterns
Kramii
fonte
fonte
Respostas:
Em um idioma que compila, o valor de uma string mágica não é verificado no momento da compilação . Se a sequência precisar corresponder a um padrão específico, você deverá executar o programa para garantir que ele se encaixe nesse padrão. Se você usou algo como uma enumeração, o valor é pelo menos válido no tempo de compilação, mesmo que possa ser o valor errado.
Se uma string mágica estiver sendo escrita em vários lugares, você precisará alterá-las sem nenhuma segurança (como erro em tempo de compilação). Isso pode ser combatido declarando-o apenas em um lugar e reutilizando a variável.
Erros de digitação podem se tornar erros graves. Se você tem uma função:
e alguém digita acidentalmente:
Isso é pior, quanto mais rara ou complexa for a string, especialmente se você tiver programadores que não estão familiarizados com o idioma nativo do projeto.
Cordas mágicas raramente são auto-documentadas. Se você vir uma string, isso não informa nada sobre o que mais poderia / deveria ser. Você provavelmente terá que examinar a implementação para ter certeza de que escolheu a string certa.
Esse tipo de implementação está com vazamento , necessitando de documentação externa ou acesso ao código para entender o que deve ser escrito, especialmente porque precisa ser perfeito para caracteres (como no ponto 3).
Com exceção das funções "encontrar cadeia" nos IDEs, há um pequeno número de ferramentas que suportam o padrão.
Por coincidência, você pode usar a mesma seqüência mágica em dois lugares, quando realmente são coisas diferentes; portanto, se você fez um Find & Replace e mudou os dois, um deles pode quebrar enquanto o outro trabalha.
fonte
O cume do que as outras respostas entenderam não é que "valores mágicos" sejam ruins, mas que deveriam ser:
O que normalmente distingue "constantes" aceitáveis de "valores mágicos" é alguma violação de uma ou mais dessas regras.
Bem usadas, as constantes simplesmente nos permitem expressar certos axiomas do nosso código.
O que me leva a um ponto final, que o uso excessivo de constantes (e, portanto, um número excessivo de suposições ou restrições expressas em termos de valores), mesmo que de outra forma atenda aos critérios acima (mas principalmente se desviar deles), pode implicar que a solução que está sendo planejada não seja suficientemente geral ou bem estruturada (e, portanto, não estamos mais falando sobre os prós e contras das constantes, mas sobre os prós e contras do código bem estruturado).
Linguagens de alto nível têm construções para padrões em linguagens de nível inferior que teriam que empregar constantes. Os mesmos padrões também podem ser usados na linguagem de nível superior, mas não deveriam.
Mas isso pode ser um julgamento especializado, baseado na impressão de todas as circunstâncias e como deve ser uma solução, e exatamente como esse julgamento será justificado dependerá muito do contexto. De fato, pode não ser justificável em termos de qualquer princípio geral, exceto afirmar "Tenho idade suficiente para já ter visto esse tipo de trabalho, com o qual estou familiarizado, feito melhor"!
EDIT: depois de aceitar uma edição, rejeitar outra e agora ter realizado minha própria edição, agora posso considerar que o estilo de formatação e pontuação da minha lista de regras será resolvido de uma vez por todas haha!
fonte
value / 2
, em vez devalue / VALUE_DIVISOR
com o último definido como em2
outro lugar. Se você pretendia generalizar um método manipulando CSVs, provavelmente desejaria que o separador fosse passado como um parâmetro e não definido como uma constante. Mas é tudo uma questão de julgamento no contexto - o exemplo de WGroleauSPEED_OF_LIGHT
é algo que você gostaria de nomear explicitamente, mas nem todo literal precisa disso.fonte
Exemplo da vida real: estou trabalhando com um sistema de terceiros em que "entidades" são armazenadas com "campos". Basicamente, um sistema EAV . Como é bastante fácil adicionar outro campo, você obtém acesso a um usando o nome do campo como string:
(observe a sequência mágica "NomeDoProduto")
Isso pode levar a vários problemas:
Portanto, minha solução para isso foi gerar constantes para esses nomes, organizadas por tipo de entidade. Então agora eu posso usar:
Ainda é uma constante de seqüência de caracteres e compila exatamente o mesmo binário, mas tem várias vantagens:
A seguir, na minha lista: oculte essas constantes atrás das classes fortemente tipadas geradas - e também o tipo de dados é protegido.
fonte
nameField = myEntity.ProductName;
.Cordas mágicas nem sempre são ruins , então esse pode ser o motivo pelo qual você não consegue encontrar uma razão geral para evitá-las. (Por "string mágica", presumo que você queira dizer literal de string como parte de uma expressão e não definida como uma constante.)
Em alguns casos particulares, as cordas mágicas devem ser evitadas:
Mas em alguns casos, "cordas mágicas" são boas. Digamos que você tenha um analisador simples:
Realmente não há mágica aqui, e nenhum dos problemas descritos acima se aplica. Não haveria benefício em definir o IMHO,
string Plus="+"
etc. Mantenha-o simples.fonte
if (dx != 0) { grad = dy/dx; }
."+"
e"-"
porTOKEN_PLUS
eTOKEN_MINUS
. Toda vez que eu li, parecia que era mais difícil ler e depurar por causa disso! Definitivamente, um lugar em que concordo que usar cordas simples é melhor.Para adicionar às respostas existentes:
Internacionalização (i18n)
Se o texto a ser exibido na tela estiver codificado e oculto em camadas de funções, será muito difícil fornecer traduções desse texto para outros idiomas.
Alguns ambientes de desenvolvimento (por exemplo, Qt) manipulam traduções pesquisando de uma sequência de texto do idioma base para o idioma traduzido. Geralmente, as cordas mágicas podem sobreviver a isso - até você decidir que deseja usar o mesmo texto em outro lugar e obter um erro de digitação. Mesmo assim, é muito difícil encontrar quais seqüências mágicas precisam ser traduzidas quando você deseja adicionar suporte para outro idioma.
Alguns ambientes de desenvolvimento (por exemplo, MS Visual Studio) adotam outra abordagem e exigem que todas as seqüências traduzidas sejam mantidas em um banco de dados de recursos e lidas novamente para a localidade atual pelo ID exclusivo dessa sequência. Nesse caso, seu aplicativo com seqüências de caracteres mágicas simplesmente não pode ser traduzido para outro idioma sem grandes retrabalhos. O desenvolvimento eficiente exige que todas as seqüências de texto sejam inseridas no banco de dados de recursos e receba um ID exclusivo quando o código for escrito pela primeira vez, e o i18n a partir de então é relativamente fácil. Tentar preencher isso após o fato normalmente exige um esforço muito grande (e sim, eu já estive lá!), Portanto é muito melhor fazer as coisas corretamente em primeiro lugar.
fonte
Isso não é uma prioridade para todos, mas se você quiser calcular métricas de acoplamento / coesão no seu código de maneira automatizada, as seqüências mágicas tornam isso quase impossível. Uma string em um local se refere a uma classe, método ou função em outro local, e não há uma maneira fácil e automática de determinar que a string seja acoplada à classe / método / função apenas analisando o código. Somente a estrutura subjacente (Angular, por exemplo) pode determinar que há uma ligação - e só pode fazê-lo em tempo de execução. Para obter as informações de acoplamento, seu analisador precisaria saber tudo sobre a estrutura que estava usando, acima e além do idioma base em que está codificando.
Mas, novamente, isso não é algo com o qual muitos desenvolvedores se preocupam.
fonte