Em um projeto recente, eu precisei converter de bytes para kilobytes kibibyte . O código era direto o suficiente:
var kBval = byteVal / 1024;
Depois de escrever isso, peguei o restante da função funcionando e segui em frente.
Mais tarde, porém, comecei a me perguntar se havia acabado de incorporar um número mágico ao meu código. Parte de mim diz que foi bom porque o número é uma constante fixa e deve ser facilmente entendido. Mas outra parte de mim pensa que seria super claro se envolto em uma constante definida como BYTES_PER_KBYTE
.
Então, os números que são constantes conhecidas são realmente tão mágicos ou não?
Perguntas relacionadas:
Quando um número é um número mágico? e Todo número no código é considerado um "número mágico"? - são semelhantes, mas são perguntas muito mais amplas do que o que estou perguntando. Minha pergunta está focada em números constantes bem conhecidos, que não são abordados nessas perguntas.
Eliminando números mágicos: quando é hora de dizer "não"? também está relacionado, mas está focado na refatoração, em vez de se um número constante é ou não um número mágico.
fonte
FOUR_HUNDRED_FOUR = 404
,. Eu trabalhei em outro projeto onde eles eram militantes sobre o uso de strings constantes em vez de literais, então eles tinham dezenas de linhas no código que pareciam:DATABASE = "database"
1024
, porque, caso contrário, sua equipe de desenvolvimento passará todo o tempo discutindo sobre se são "kilobytes" ou "kibibytes".#define
KIBI
1024,MEBI
como 1024 * 1024 ...ZERO=0, ONE=1, TWO=2
e quando os programas forem portados para outras línguas (ou os programadores não mudam de comportamento ao mudar de idioma), você também verá lá e terá que rezar para que nunca alguém mude paraONE=2
...Respostas:
Nem todos os números mágicos são iguais.
Eu acho que nesse caso, essa constante está OK. O problema com os números mágicos é quando eles são mágicos, ou seja, não está claro qual é sua origem, por que o valor é o que é ou se o valor está correto ou não.
Ocultar 1024 atrás de BYTES_PER_KBYTE também significa que você não vê instantaneamente se está correto ou não.
Eu esperaria que alguém soubesse imediatamente por que o valor é 1024. Por outro lado, se você estivesse convertendo bytes em megabytes, definiria a constante BYTES_PER_MBYTE ou semelhante, porque a constante 1.048.576 não é tão óbvia que 1024 ^ 2, ou que está correto.
O mesmo vale para valores ditados por requisitos ou padrões, que são usados apenas em um só lugar. Acho que apenas colocar a constante no lugar com um comentário para a fonte relevante é mais fácil de lidar do que defini-lo em outro lugar e ter que perseguir as duas partes, por exemplo:
Acho melhor que
Somente quando
SOME_THRESHOLD_VALUE
é usado em vários lugares é que a troca vale a pena definir uma constante, na minha opinião.fonte
e^i*pi = -1
é muito mais explícito (melhor) que2.718^i*3.142 = -1
. As variáveis são importantes e não são apenas para código comum. O código é escrito para leitura primeiro, compilação em segundo. Além disso, as especificações mudam (muito). Enquanto o 1024 provavelmente não deveria estar na configuração, o 3.5 soa como deveria.1024*1024
plz!Há duas perguntas que faço quando se trata de números mágicos.
O número tem um nome?
Os nomes são úteis porque podemos ler o nome e entender a finalidade do número por trás dele. Nomear constantes pode aumentar a legibilidade se o nome for mais fácil de entender do que o número que substitui e o nome da constante for conciso.
Claramente, constantes como pi, e, et al. tem nomes significativos. Um valor como 1024 poderia ser,
BYTES_PER_KB
mas eu também esperaria que qualquer desenvolvedor soubesse o que 1024 significa. O público-alvo do código-fonte são programadores profissionais que devem ter experiência em conhecer vários poderes de dois e por que eles são usados.É usado em vários locais?
Enquanto os nomes são uma força de constantes, outra é a reutilização. Se é provável que um valor mude, ele pode ser alterado em um local, em vez de precisar caçá-lo em vários locais.
Sua pergunta
No caso de sua pergunta, eu usaria o número como está.
Nome: existe um nome para esse número, mas não é nada realmente útil. Não representa uma constante ou valor matemático especificado em nenhum documento de requisitos.
Locais: mesmo se usado em vários locais, nunca será alterado, negando esse benefício.
fonte
Esta citação
como dito por Jörg W Mittag responde muito bem a essa pergunta.
Alguns números simplesmente não são mágicos dentro de um contexto específico. No exemplo fornecido na pergunta, as unidades de medida foram especificadas pelos nomes das variáveis e a operação que estava ocorrendo era bastante clara.
Portanto,
1024
não é mágico, porque o contexto deixa muito claro que é o valor apropriado e constante a ser usado nas conversões.Da mesma forma, um exemplo de:
é igualmente claro e não é mágico, porque é sabido que existem 24 horas no dia.
fonte
24
qualquer maneira! Como Izkata mencionou, os segundos bissextos doem. Talvez você tenha mais sorte usando a constante24
em Marte do que na Terra!Outros pôsteres mencionaram que a conversão está sendo "óbvia", mas eu discordo. A pergunta original, neste momento, inclui:
Então, eu já sei que o autor está ou estava confuso. A página da Wikipedia aumenta a confusão:
Portanto, "Kilobyte" pode ser usado para significar um fator de 1000 e 1024, com a única diferença em taquigrafia sendo a capitalização do 'k'. Além disso, 1024 pode significar kilobyte (JEDEC) ou kibibyte (IEC). Por que não destruir toda essa confusão com uma constante com um nome significativo? BTW, este segmento usou "BYTES_PER_KBYTE" com freqüência, e isso não é menos ambíguo. KBYTE: é KIBIBYTE ou KILOBYTE? Eu preferiria ignorar o JEDEC e ter
BYTES_PER_KILOBYTE = 1000
eBYTES_PER_KIBIBYTE = 1024
. Não há mais confusão.A razão pela qual pessoas como eu, e muitas outras por aí, têm opiniões 'militantes' (para citar um comentarista aqui) sobre como nomear números mágicos, é tudo sobre documentar o que você pretende fazer e remover a ambiguidade. E você realmente escolheu uma unidade que levou a muita confusão.
Se eu ver:
Então fica imediatamente óbvio o que o autor pretendia fazer, e não há ambiguidade. Posso verificar a constante em questão de segundos (mesmo que esteja em outro arquivo), portanto, mesmo que não seja 'instantâneo', ele está próximo o suficiente para ser instantâneo.
No final, pode ser óbvio quando você está escrevendo, mas será menos óbvio quando você voltar mais tarde, e pode ser ainda menos óbvio quando alguém o editar. Demora 10 segundos para fazer uma constante; pode levar meia hora ou mais para depurar um problema com as unidades (o código não vai aparecer em você e dizer que as unidades estão erradas, você terá que fazer as contas sozinho para descobrir isso, e você provavelmente procurará 10 avenidas diferentes antes de verificar as unidades).
fonte
KB
) diferentemente não ajudarão.Definir um nome como referindo-se a um valor numérico sugere que sempre que um valor diferente for necessário em um local que use esse nome, provavelmente será necessário em todos. Também tende a sugerir que alterar o valor numérico atribuído ao nome é uma maneira legítima de alterar o valor. Essa implicação pode ser útil quando é verdadeira e perigosa quando é falsa.
O fato de dois locais diferentes usarem um valor literal específico (por exemplo, 1024) sugerirá fracamente que as mudanças que levariam um programador a mudar um provavelmente inspirariam o programador a querer mudar outros, mas essa implicação é muito mais fraca do que seria aplicável. se o programador atribuiu um nome a essa constante.
Um grande perigo com algo assim
#define BYTES_PER_KBYTE 1024
é que isso pode sugerir a alguém que encontrarprintf("File size is %1.1fkB",size*(1.0/BYTES_PER_KBYTE));
que uma maneira segura de fazer o código usar milhares de bytes seria alterar a#define
declaração. Essa mudança pode ser desastrosa, no entanto, se, por exemplo, algum outro código não relacionado receber o tamanho de um objeto em Kbytes e usar essa constante ao alocar um buffer para ele.Pode ser razoável usar
#define BYTES_PER_KBYTE_FOR_USAGE_REPORT 1024
e#define BYTES_PER_KBYTE_REPORTED_BY_FNOBULATOR 1024
atribuir um nome diferente para cada finalidade diferente servida pela constante 1024, mas isso resultaria em muitos identificadores sendo definidos e usados exatamente uma vez. Além disso, em muitos casos, é mais fácil entender o que um valor significa se alguém vê o código onde é usado, e é mais fácil descobrir onde o código significa se alguém vê os valores de quaisquer constantes usadas nele. Se um literal numérico é usado apenas uma vez para uma finalidade específica, escrever o literal no local em que é usado geralmente gera um código mais compreensível do que atribuir um rótulo a ele em um local e usar seu valor em outro lugar.fonte
Eu me inclinaria a usar apenas o número, mas acho que uma questão importante não foi levantada: o mesmo número pode significar coisas diferentes em contextos diferentes, e isso pode complicar a refatoração.
1024 também é o número de KiB por MiB. Suponha que usamos 1024 para também representar esse cálculo em algum lugar ou em vários lugares, e agora precisamos mudar para calcular o GiB. Alterar a constante é mais fácil do que uma localização / substituição global, onde você pode acidentalmente alterar a incorreta em alguns lugares, ou perder em outros.
Ou pode ser uma máscara introduzida por um programador preguiçoso que precisa ser atualizado um dia.
É um exemplo um pouco artificial, mas em algumas bases de código isso pode causar problemas ao refatorar ou atualizar para novos requisitos. Para este caso em particular, porém, eu não consideraria o número simples uma forma realmente ruim, especialmente se você puder incluir o cálculo em um método de reutilização, provavelmente faria isso sozinho, mas consideraria a constante mais 'correta'.
Porém, se você usa constantes nomeadas, como o supercat diz, é importante considerar se o contexto também é importante e se você precisa de vários nomes.
fonte