Todos sabemos que os números mágicos (valores codificados) podem causar estragos no seu programa, especialmente quando é hora de modificar uma seção de código que não tem comentários, mas onde você desenha a linha?
Por exemplo, se você possui uma função que calcula o número de segundos entre dois dias, substitui
seconds = num_days * 24 * 60 * 60
com
seconds = num_days * HOURS_PER_DAY * MINUTES_PER_HOUR * SECONDS_PER_MINUTE
Em que momento você decide que é completamente óbvio o que o valor codificado significa e o deixa em paz?
refactoring
coding-standards
maintainability
oosterwal
fonte
fonte
seconds = CALC_SECONDS(num_days);
TimeSpan.FromDays(numDays).Seconds;
HOURS_PER_DAY will never need to be altered
), você nunca estará codificando para o software implantado em Marte. : PRespostas:
Há duas razões para usar constantes simbólicas em vez de literais numéricos:
Simplificar a manutenção se os números mágicos mudarem. Isso não se aplica ao seu exemplo. É extremamente improvável que o número de segundos em uma hora ou o número de horas em um dia mude.
Para melhorar a legibilidade. A expressão "24 * 60 * 60" é bastante óbvia para quase todos. "SECONDS_PER_DAY" também é, mas se você estiver procurando um bug, talvez seja necessário verificar se SECONDS_PER_DAY foi definido corretamente. Há valor na brevidade.
Para números mágicos que aparecem exatamente uma vez e são independentes do resto do programa, decidir se deve criar um símbolo para esse número é uma questão de gosto. Se houver alguma dúvida, vá em frente e crie um símbolo.
Não faça isso:
fonte
publid final int FOUR = 3;
public static int THREE = 3;
... nota - nãofinal
!Eu manteria a regra de nunca ter números mágicos.
Enquanto
É perfeitamente legível na maioria das vezes, depois de ter codificado por 10 horas por dia durante três ou quatro semanas no modo de trituração
é muito mais fácil de ler.
A sugestão de FrustratedWithFormsDesigner é melhor:
ou melhor ainda
As coisas deixam de ser óbvias quando você está muito cansado. Código defensivamente .
fonte
A hora de dizer não é quase sempre. Os momentos em que acho mais fácil usar números codificados são em locais como o layout da interface do usuário - a criação de uma constante para o posicionamento de cada controle no formulário fica muito cansativa e cansativa e, se esse código geralmente é tratado por um designer de interface do usuário, não importa muito. ... a menos que a interface do usuário seja definida dinamicamente, ou use posições relativas para alguma âncora ou seja escrita à mão. Nesse caso, eu diria que é melhor definir algumas constantes significativas para o layout. E se você precisar de um fator de correção aqui ou ali para alinhar / posicionar algo "correto", isso também deve ser definido.
Mas no seu exemplo, acho que substituir
24 * 60 * 60
porDAYS_TO_SECONDS_FACTOR
é melhor.Concordo que os valores codificados também são bons quando o contexto e o uso são completamente claros. Esta, no entanto, é uma decisão judicial ...
Exemplo:
Como @rmx apontou, usar 0 ou 1 para verificar se uma lista está vazia ou talvez nos limites de um loop é um exemplo de caso em que o objetivo da constante é muito claro.
fonte
0
ou1
acho.if(someList.Count != 0) ...
é melhor queif(someList.Count != MinListCount) ...
. Nem sempre, mas geralmente.Pare quando não conseguir definir um significado ou objetivo para o número.
é muito mais fácil de ler do que apenas usar os números. (Embora possa ser mais legível por ter uma única
SECONDS_PER_DAY
constante, mas é uma questão completamente separada.)Suponha que um desenvolvedor que observe o código possa ver o que ele faz. Mas não assuma que eles também sabem o porquê. Se a sua constante ajuda a entender o porquê, vá em frente. Se não, não.
Se você acabar com muitas constantes, como sugerido por uma resposta, considere usar um arquivo de configuração externo, pois ter dezenas de constantes em um arquivo não melhora exatamente a legibilidade.
fonte
Eu provavelmente diria "não" a coisas como:
E definitivamente diria "não" para:
fonte
Um dos melhores exemplos que encontrei para promover o uso de constantes para coisas óbvias como
HOURS_PER_DAY
é:Estávamos calculando quanto tempo as coisas estavam na fila de trabalho de uma pessoa. Os requisitos foram vagamente definidos e o programador foi codificado
24
em vários locais. Eventualmente, percebemos que não era justo punir os usuários por permanecerem em um problema por 24 horas, quando realmente funcionam apenas 8 horas por dia. Quando chegou a tarefa de corrigir isso E ver quais outros relatórios poderiam ter o mesmo problema, era muito difícil fazer grep / pesquisar no código de 24 teria sido muito mais fácil fazer grep / procurarHOURS_PER_DAY
fonte
Penso que, desde que o número seja completamente constante e não tenha possibilidade de mudar, é perfeitamente aceitável. Portanto, no seu caso, tudo
seconds = num_days * 24 * 60 * 60
bem (supondo que você não faça algo bobo como fazer esse tipo de cálculo dentro de um loop) e sem dúvida melhor para facilitar a leitura do queseconds = num_days * HOURS_PER_DAY * MINUTES_PER_HOUR * SECONDS_PER_MINUTE
.É quando você faz coisas assim que é ruim:
lineOffset += 24; // 24 lines to a page
Mesmo que você não consiga encaixar mais linhas na página ou mesmo que não tenha a intenção de alterá-la, use uma variável constante, pois um dia ele voltará para assombrá-lo. Por fim, o objetivo é a legibilidade, não economizando 2 ciclos de cálculo na CPU. Já não é 1978, quando bytes preciosos foram extraídos por todo o seu valor.
fonte
Está perfeitamente bem. Esses números não são realmente mágicos, pois nunca mudarão.
Quaisquer números que possam mudar razoavelmente ou não tenham significado óbvio devem ser colocados em variáveis. O que significa praticamente todos eles.
fonte
seconds = num_days * 86400
ainda ser aceitável? Se um valor como esse fosse usado várias vezes em vários arquivos diferentes, como você verificaria se alguém não digitou acidentalmenteseconds = num_days * 84600
um ou dois lugares?Eu evitaria criar constantes (valores mágicos) para converter um valor de uma unidade para outra. Em caso de conversão, prefiro um nome de método de fala. Neste exemplo, isso seria
DayToSeconds(num_days)
interno, por exemplo, o método não precisa de valores mágicos porque o significado de "24" e "60" é claro.Nesse caso, eu nunca usaria segundos / minutos / horas. Eu usaria apenas TimeSpan / DateTime.
fonte
Use o contexto como um parâmetro para decidir
Por exemplo, você tem uma função chamada "calculaSegundosBetween: aDay e: anotherDay", não será necessário fazer muita explicação sobre o que esses números fazem, porque o nome da função é bastante representativo.
E outra pergunta é: quais são as possibilidades de calculá-lo de uma maneira diferente? Às vezes, existem muitas maneiras de fazer a mesma coisa; portanto, para orientar futuros programadores e mostrar a eles qual método você usou, definir constantes pode ajudar a descobrir isso.
fonte