Este é um tópico um tanto controverso, e acho que existem tantas opiniões quanto programadores. Mas, para o efeito, quero saber quais são as práticas comuns nos negócios (ou nos seus locais de trabalho).
No meu local de trabalho, temos diretrizes rígidas de codificação. Uma seção é dedicada a seqüências / números mágicos. Ele afirma (para C #):
Não use valores literais, numéricos ou seqüências de caracteres, em seu código, exceto para definir constantes simbólicas. Use o seguinte padrão para definir constantes:
public class Whatever { public static readonly Color PapayaWhip = new Color(0xFFEFD5); public const int MaxNumberOfWheels = 18; }
Há exceções: os valores 0, 1 e nulo quase sempre podem ser usados com segurança. Muitas vezes, os valores 2 e -1 também são bons. As seqüências destinadas ao log ou rastreio estão isentas desta regra. Literais são permitidos quando seu significado é claro a partir do contexto e não estão sujeitos a mudanças futuras.
mean = (a + b) / 2; // okay
WaitMilliseconds(waitTimeInSeconds * 1000); // clear enough
Uma situação ideal seria algum trabalho de pesquisa oficial mostrando efeitos sobre a legibilidade / manutenção do código quando:
- Números / cordas mágicos estão por todo o lado
- Cordas / números mágicos são substituídos por declarações constantes razoavelmente (ou em diferentes graus de cobertura) - e não grite comigo por usar "razoavelmente", eu sei que todo mundo tem uma idéia diferente do que "razoavelmente" é
- Cordas / números mágicos são substituídos em excesso e em lugares onde eles não precisariam estar (veja meu exemplo abaixo)
Eu gostaria de fazer isso para ter alguns argumentos científicos ao discutir com um de meus colegas, que está indo ao ponto de declarar constantes como:
private const char SemiColon = ';';
private const char Space = ' ';
private const int NumberTen = 10;
Outro exemplo seria (e este está em JavaScript):
var someNumericDisplay = new NumericDisplay("#Div_ID_Here");
Você coloca IDs de DOM em cima do seu arquivo javascript se esse ID for usado apenas em um só lugar?
Li os seguintes tópicos:
StackExchange
StackOverflow
Bytes Comunidade de TI
Há muitos mais artigos e, após a leitura desses padrões, surgem alguns padrões.
Então, minha pergunta é: devemos usar cordas e números mágicos em nosso código? Estou procurando especificamente respostas de especialistas que sejam apoiadas por referências, se possível.
fonte
NumberTen = 10
Isso é inútil, pois o número 10 não será redefinido.MaxRetryCount = 10
Isso tem um ponto a: podemos querer alterar a contagem máxima de novas tentativas.private const char SemiColon = ';';
Burro.private const char LineTerminator = ';'
; Inteligente.Respostas:
O argumento que você precisa apresentar ao seu colega não é sobre nomear um espaço literal,
Space
mas sua má escolha de nome para suas constantes.Digamos que o trabalho do seu código é analisar um fluxo de registros que contêm campos separados por ponto
a;b;c
e vírgula ( ) e são separados por espaços (a;b;c d;e;f
). Se quem escreveu suas especificações telefonar para você daqui a um mês e disser "estávamos enganados, os campos nos registros são separados por símbolos de barra vertical (a|b|c d|e|f
)", o que você faz?No esquema de valor como nome que seu colega prefere, você teria que alterar o valor do literal (
SemiColon = '|'
) e viver com o código que continua a ser usadoSemiColon
para algo que não é mais um ponto e vírgula. Isso levará a comentários negativos nas revisões de código . Para diminuir isso, você pode alterar o nome do literal paraPipeSymbol
e passar e alterar todas as ocorrências deSemiColon
paraPipeSymbol
. Nesse ritmo, você também pode ter usado um ponto-e-vírgula literal (';'
) em primeiro lugar, porque terá que avaliar cada uso individualmente e estará fazendo o mesmo número de alterações.Identificadores para constantes precisam ser descritivos do que o valor faz , não o que o valor é , e é aí que o seu colega fez uma curva à esquerda para as ervas daninhas. No aplicativo de divisão de campos descrito acima, o objetivo do ponto-e-vírgula é um separador de campos e as constantes devem ser nomeadas de acordo:
Dessa forma, quando o separador de campos é alterado, você altera exatamente uma linha de código, a declaração da constante. Alguém olhando a alteração verá apenas uma linha e imediatamente entenderá que o separador de campos mudou de um ponto e vírgula para um símbolo de tubo. O restante do código, que não precisou ser alterado porque usava uma constante, permanece o mesmo, e o leitor não precisa cavar para ver o que mais foi feito.
fonte
#define one 1 #define two 2
etc (ou qualquer que fosse o equivalente no UK Post Office Coral, o então idioma de escolha). Palavra veio do alto, que, no futuro, o campo de comprimento seria o número de bytes, não segmentos, por isso , obviamente, o código foi alterado para#define one 8 #define two 16
etc;
a|
.public static final String MY_KEY_NAME = "MyKeyName"
CSV_RECORD_SEPARATOR
,TSV_RECORD_SEPARATOR
, etc.).Definir ponto e vírgula como uma constante é redundante, porque ponto e vírgula e já é constante por si só . Isso nunca vai mudar.
Não é como se um dia alguém anunciasse "mudança de terminologia, + é o novo ponto e vírgula agora", e seu colega se apressaria feliz em atualizar a constante (eles riram de mim - olhe para eles agora).
Há também uma questão de consistência. Eu garanto que o seu
NumberTen
constante NÃO será usada por todos (a maioria dos programadores não está maluca), por isso não servirá ao propósito esperado. Quando o apocalipse chegar e "dez" for redimensionado globalmente para 9, atualizar a constante NÃO funcionará, pois ainda lhe deixará um monte de literais10
s no seu código, agora o sistema se torna totalmente imprevisível, mesmo dentro do escopo de uma suposição revolucionária de que "dez" significa "9".Armazenar todas as configurações como consts é algo que eu também teria dúvidas. Não se deve fazer isso de ânimo leve.
Que exemplos desse tipo de uso reunimos até agora? Terminador de linha ... contagem máxima de novas tentativas ... número máximo de rodas ... temos certeza de que elas nunca mudarão?
O custo é que a alteração das configurações padrão requer a recompilação de um aplicativo e, em alguns casos, até suas dependências (como os valores numéricos de const podem ser codificados durante a compilação).
Há também o aspecto de teste e zombaria. Você definiu a cadeia de conexão como uma const, mas agora opa, não é possível simular o acesso ao banco de dados (estabelecer uma conexão falsa) em seu teste de unidade.
fonte
’
(aspas simples à esquerda, Unicode 8217 ) para aplicativos compatíveis com a exibição de um glifo diferente para a marca ondulada. Como a Europa usa vírgulas da mesma forma que os americanos usam períodos como ponto decimal, eu me sinto um pouco hesitante em declarar "nunca ... nunca".DecimalPoint
constante - mas nãoComma
ouPeriod
constantes. É uma grande diferença: o primeiro denota uma função , um papel ou um propósito do valor. "Ponto e vírgula" ou "vírgula" não se enquadram nessa categoria.Portanto, seu colega está buscando uma entrada diária no WTF. Essas definições são tolas e redundantes. No entanto, como foi apontado por outros, as seguintes definições não seriam tolas ou redundantes:
Números e cordas "mágicos" são constantes que têm significado além de seu valor imediato e literal. Se a constante
10
tiver um significado além de "dez coisas" (digamos, como um código para uma operação específica ou condição de erro), é quando ela se torna "mágica" e deve ser substituída por uma constante simbólica que descreve esse significado abstrato.Além de descrever claramente a intenção, as constantes simbólicas também poupam algumas dores de cabeça quando você escreve incorretamente um literal. Uma simples transposição de "CVS" para "CSV" em uma linha de código passou por todos os testes de unidade e controle de qualidade e entrou na produção, onde causou falha de uma operação específica. Sim, obviamente, os testes de unidade e controle de qualidade estavam incompletos e esse é o seu próprio problema, mas o uso de uma constante simbólica teria evitado completamente esse azia.
fonte
Não deveria haver nada controverso sobre isso. O ponto não é se queremos usar números mágicos ou não, o ponto é ter um código legível.
Considere a diferença entre:
if(request.StatusCode == 1)
eif(request.HasSucceeded)
. Nesse caso, eu diria que o último é muito mais legível, mas isso não significa que você nunca pode ter um código como esseint MaxNumberOfWheels = 18
.PS: É por isso que eu odeio absolutamente as diretrizes de codificação. Os desenvolvedores devem ser maduros o suficiente para serem capazes de fazer julgamentos assim; eles não devem deixar para um pedaço de texto formado por Deus sabe quem.
fonte