Então, meu professor estava retornando algum feedback sobre um projeto no qual eu estava trabalhando. Ele encaixou algumas marcas para este código:
if (comboVendor.SelectedIndex == 0) {
createVendor cv = new createVendor();
cv.ShowDialog();
loadVendors();
}
Isso está em um manipulador de "índice alterado" da caixa de combinação. É usado quando o usuário deseja criar um novo fornecedor, minha primeira opção (índice 0, que nunca muda) abre a caixa de diálogo "Criar um novo fornecedor". Portanto, o conteúdo da minha caixa de combinação acaba assim:
Create New Vendor...
Existing Vendor
Existing Vendor 2
Existing Vendor 3
O problema dele é com o código da primeira linha:
if (comboVendor.SelectedIndex == 0)
Ele afirma que o 0 deve ser uma constante e, na verdade, encaixou minhas marcas por causa disso. Ele afirma que eu não deveria usar literais no meu código.
O problema é que eu não entendo por que eu gostaria de tornar esse código nessa situação uma constante. Esse índice nunca mudará, nem é algo que você precisaria ajustar. Parece um desperdício de memória manter um único 0 na memória que é usado para uma situação muito específica e nunca muda.
-1
nostr.indexOf(substr) != -1
de "str
contémsubstr
" é prefectly justificada. Mas aqui, o significado do 0 não é óbvio (qual a relação com a criação de um novo fornecedor?) Nem verdadeiramente constante (e se a maneira de criar um novo fornecedor mudar?).int.Zero
em vez de fazê-lo feliz :)Respostas:
A maneira correta real de fazer isso em C # é não depender da ordem dos ComboItems .
fonte
A ordem na caixa de combinação pode mudar. E se você adicionar outra opção como "Criar fornecedor especial ..." antes de "Criar novo vendedor ..."
A vantagem de usar uma constante é que, se houver muitos métodos que dependem da ordem da caixa de combinação, você precisará alterar apenas a constante e não todos os métodos, caso isso mude.
Usar uma constante também é mais legível que um literal.
A maioria dos idiomas compilados substituirá a constante no tempo de compilação, portanto, não há penalidade no desempenho.
fonte
Essa situação que você descreve é uma decisão judicial, pessoalmente eu não usaria uma se for usada apenas uma vez e já estiver legível.
A resposta real, porém, é que ele escolheu isso para lhe ensinar uma lição.
Não esqueça que ele é professor, o trabalho dele é ensinar a você a codificação e as melhores práticas.
Eu diria que ele está fazendo um bom trabalho, na verdade.
Claro que ele pode parecer um pouco absoluto, mas tenho certeza que você pensará novamente antes de usar números mágicos.
Além disso, ele se destacou o suficiente para você ingressar em uma comunidade on-line sobre programadores apenas para descobrir o que é considerado uma prática recomendada nessa situação.
Tiremos o chapéu para o seu professor.
fonte
O fato de você ter que explicar isso prova por que você deve usar uma constante. Se você introduzisse uma constante como
NEW_VENDOR_DIALOG
, seu código seria mais auto-explicativo. Além disso, os compiladores otimizam as constantes, para que não haja uma alteração no desempenho.Escreva programas para programadores, não para compiladores. A menos que você esteja especificamente tentando otimizar, o que não parece ser o seu caso.
fonte
Eu concordo. O uso de zero aqui é "mágico". Imagine que você está lendo este código pela primeira vez. Você não sabe por que zero é especial e o literal não diz nada sobre por que zero é especial. Se, em vez disso, você disse
if(comboVendor.SelectedIndex == CreateNewVendorIndex)
, fica extremamente claro para o leitor iniciante o que o código significa.Essa é uma posição extrema; uma posição realista seria dizer que o uso de literais é uma bandeira vermelha que indica que o código pode não ser tão claro quanto poderia ser. Às vezes é apropriado.
O fato de nunca mudar é um excelente motivo para torná-lo constante . É por isso que constantes são chamadas constantes; porque eles nunca mudam.
Sério? Você não vê nenhuma situação em que alguém queira alterar a ordem das coisas em uma caixa de combinação?
O fato de você poder ver um motivo pelo qual isso pode mudar no futuro é um bom motivo para não torná-lo constante. Em vez disso, deve ser um campo inteiro estático readonly não constante. Uma constante deve ser uma quantidade garantida para permanecer a mesma para sempre . Pi e o número atômico de ouro são boas constantes. Os números de versão não são; eles mudam todas as versões. O preço do ouro é obviamente uma constante terrível; isso muda a cada segundo. Faça apenas coisas constantes que nunca mudam .
Agora chegamos ao cerne da questão.
Essa talvez seja a linha mais importante em sua pergunta, pois indica que você tem algum entendimento profundamente falho de (1) memória e (2) otimização. Você está na escola para aprender e agora seria um ótimo momento para entender corretamente os fundamentos. Você pode explicar em detalhes por que acredita que "é um desperdício de memória manter um único zero na memória"? Primeiro, por que você acredita que otimizar o uso de quatro bytes de memória em um processo com pelo menos dois bilhões de bytes de armazenamento endereçável pelo usuário é relevante? Segundo, exatamente que recurso você imagina que está sendo consumido aqui ? O que você quer dizer com "memória" sendo consumida?
Estou interessado nas respostas a essas perguntas primeiro, porque elas são uma oportunidade para você aprender como seu entendimento de otimização e gerenciamento de memória está incorreto, e segundo porque eu sempre quero saber por que os iniciantes acreditam em coisas bizarras, para que eu possa projetar melhores ferramentas para levá-los a ter crenças corretas.
fonte
Ele tem razão. Você está certo. Você está errado.
Ele está certo, conceitualmente, de que os números mágicos devem ser evitados. As constantes tornam o código mais legível, adicionando contexto ao significado do número. No futuro, quando alguém ler seu código, saberá por que um número específico foi usado. E se você precisar alterar um valor em algum lugar abaixo da linha, é muito melhor alterá-lo em um só lugar, em vez de tentar procurar em qualquer lugar onde um número específico seja usado.
Dito isto, você está certo. Nesse caso específico, eu realmente não acho que uma constante se justifique. Você está procurando o primeiro item da lista, que é sempre zero. Nunca será 23. Ou -pi. Você está procurando especificamente zero. Realmente não acho que você precise desordenar o código, tornando-o constante.
Você está errado, no entanto, ao assumir que uma constante é carregada como uma variável, 'usando memória'. Existe uma constante para o humano e o compilador. Ele diz ao compilador para colocar esse valor nesse local durante a compilação, onde você teria colocado um número literal. E mesmo que tivesse a constante na memória, para todas as aplicações, exceto as mais exigentes, a perda de eficiência nem seria mensurável. Preocupar-se com o uso da memória de um único inteiro definitivamente cai na 'otimização prematura'.
fonte
Eu teria substituído o
0
com uma constante para tornar o significado claro, comoNewVendorIndex
. Você nunca sabe se seu pedido será alterado.fonte
Essa é a preferência total do seu professor. Normalmente, você usa apenas uma constante se o literal for usado várias vezes, você deseja tornar óbvio para o leitor qual é o objetivo da linha, ou seu literal será possivelmente alterado no futuro e você só deseja alterar em um só lugar. No entanto, para este semestre, o professor é o chefe, então eu o faria a partir de agora nessa aula.
Bom treinamento para o mundo corporativo? Bem possível.
fonte
Para ser sincero, embora eu não ache o seu código uma boa prática, a sugestão dele é francamente um pouco grotesca.
Uma prática mais comum para uma caixa de combinação .NET é atribuir ao item "Selecionar .." um valor vazio, enquanto os itens reais têm valores significativos e, em seguida:
ao invés de
fonte
Ele não está errado ao enfatizar o valor do uso de constantes e você não está errado ao usar literais. A menos que ele tenha enfatizado que este é o estilo de codificação esperado, você não deve perder marcas por usar literais, pois eles não são prejudiciais. Eu já vi literais usados em todo o lugar tantas vezes no código comercial.
Seu argumento é bom. Este pode ser o seu caminho de conscientizá-lo dos benefícios das constantes:
1-Eles protegem seu código em certa medida contra violações acidentais
2-Como o @DeadMG diz em sua resposta, se o mesmo valor literal for usado em muitos lugares, ele pode aparecer com um valor diferente por engano - portanto, as constantes preservam a consistência.
3-Constantes preservam o tipo, para que você não precise usar algo como 0F para significar zero.
4-Para facilitar a leitura, COBOL usa ZERO como uma palavra reservada para o valor zero (mas também permite que você use o zero literal) - Portanto, atribuir um nome a um valor às vezes é útil, por exemplo: (Fonte: ms-Constants
ou como no seu caso (conforme mostrado na resposta de Michael Krussel)
fonte
int weeks = 52
, não há 52 semanas por ano. Há 52,142857142857146 semanas em um ano, e esse é o número em que você deve manter as frações. Claro, a única coisa que é realmente constante em todo esse conjunto de constantes é o número de meses.Você só precisaria colocá-lo em uma constante se tiver uma derivação complexa ou se repetir com frequência. Senão, um literal é bom. Colocar tudo em constante é um exagero total.
fonte
Na verdade, como mencionado, e se a posição mudar? O que você pode / deve fazer é usar um código, em vez de confiar no índice.
Então, quando você cria sua lista de seleção, ela acaba com html como
Em vez de
selectedIndex === 0
procurar, verifique se o valor estáCREATECODE
em uma constante e teria sido usado para esse teste e ao criar a lista de seleção.fonte
Eu me livraria completamente disso. Basta colocar um botão criar novo ao lado da lista da caixa de combinação. Clique duas vezes em um item da lista para editar ou clique no botão Não tenha a nova funcionalidade enterrada na caixa de combinação. Em seguida, o número mágico é removido por completo.
Em geral, qualquer número literal no código deve ser definido como uma constante, a fim de contextualizar o número. O que significa zero? Nesse caso, 0 = NEW_VENDOR. Em outros casos, pode significar algo diferente; portanto, é sempre uma boa idéia para facilitar a leitura e a manutenção colocar algum contexto em torno disso.
fonte
Como já foi dito, você deve usar algum método diferente do número do índice para identificar o item da caixa de combinação que corresponde a uma determinada ação; ou, você pode encontrar o índice com alguma lógica programática e armazená-lo em uma variável.
A razão pela qual estou escrevendo é abordar seu comentário sobre o "uso da memória". Em C #, como na maioria dos idiomas, as constantes são "dobradas" pelo compilador. Por exemplo, compile o programa a seguir e examine a IL. Você verá que todos esses números nem chegam à IL, muito menos à memória do computador:
IL resultante:
Portanto, se você usa uma constante, um literal ou um kilobyte de código usando aritmética constante, o valor é tratado literalmente na IL.
Um ponto relacionado: a dobragem constante se aplica a literais de string. Muitos acreditam que uma chamada como essa causa muita concatenação desnecessária e ineficiente de strings:
Mas confira o IL:
Conclusão: os operadores em expressões constantes resultam em expressões constantes, e o compilador faz todo o cálculo; isso não afeta o desempenho em tempo de execução.
fonte