Sou a favor de prefixos bem feitos .
Eu acho que a notação húngara (do sistema) é responsável pela maior parte do "mau rap" que os prefixos recebem.
Essa notação é inútil em linguagens fortemente tipadas, por exemplo, em C ++ "lpsz" para dizer que sua string é um ponteiro longo para uma string terminada em nulo, quando: arquitetura segmentada é história antiga, as strings C ++ são por ponteiros de convenção comuns para terminação nula matrizes de caracteres e não é tão difícil saber que "customerName" é uma string!
No entanto, eu uso prefixos para especificar o uso de uma variável (essencialmente "Aplicativos Húngaro", embora prefira evitar o termo Húngaro por ter uma associação ruim e injusta com o Sistema Húngaro), e esse é um método muito útil para economizar tempo e abordagem de redução de erros .
Eu uso:
- m para membros
- c para constantes / readonlys
- p para ponteiro (e pp para ponteiro para ponteiro)
- v para volátil
- s para estática
- i para índices e iteradores
- e para eventos
Onde desejo esclarecer o tipo , uso sufixos padrão (por exemplo, List, ComboBox, etc).
Isso torna o programador ciente do uso da variável sempre que a vê / usa. Provavelmente, o caso mais importante é "p" para ponteiro (porque o uso muda de var. Para var-> e você precisa ter muito mais cuidado com ponteiros - NULLs, aritmética de ponteiros etc.), mas todos os outros são muito úteis.
Por exemplo, você pode usar o mesmo nome de variável de várias maneiras em uma única função: (aqui um exemplo de C ++, mas se aplica igualmente a muitos idiomas)
MyClass::MyClass(int numItems)
{
mNumItems = numItems;
for (int iItem = 0; iItem < mNumItems; iItem++)
{
Item *pItem = new Item();
itemList[iItem] = pItem;
}
}
Você pode ver aqui:
- Nenhuma confusão entre membro e parâmetro
- Nenhuma confusão entre índice / iterador e itens
- Uso de um conjunto de variáveis claramente relacionadas (lista de itens, ponteiro e índice) que evitam as muitas armadilhas de nomes genéricos (vagos) como "count", "index".
- Prefixos reduzem a digitação (mais curta e funcionam melhor com o preenchimento automático) do que alternativas como "itemIndex" e "itemPtr"
Outro ponto importante dos iteradores "iName" é que nunca indexo uma matriz com o índice errado e, se eu copiar um loop dentro de outro loop, não preciso refatorar uma das variáveis de índice do loop.
Compare este exemplo irrealisticamente simples:
for (int i = 0; i < 100; i++)
for (int j = 0; j < 5; j++)
list[i].score += other[j].score;
(difícil de ler e geralmente leva ao uso de "i" onde "j" foi planejado)
com:
for (int iCompany = 0; iCompany < numCompanies; iCompany++)
for (int iUser = 0; iUser < numUsers; iUser++)
companyList[iCompany].score += userList[iUser].score;
(que é muito mais legível e elimina toda a confusão sobre a indexação. Com o preenchimento automático nos IDEs modernos, isso também é rápido e fácil de digitar)
O próximo benefício é que os trechos de código não exigem que nenhum contexto seja entendido. Posso copiar duas linhas de código em um e-mail ou documento, e qualquer pessoa que esteja lendo esse trecho pode dizer a diferença entre todos os membros, constantes, ponteiros, índices etc. Não preciso adicionar "ah, e tenha cuidado porque 'data' é um ponteiro para um ponteiro ", porque é chamado 'ppData'.
E pelo mesmo motivo, não preciso desviar os olhos de uma linha de código para entender. Não preciso pesquisar o código para descobrir se 'data' é um local, parâmetro, membro ou constante. Não preciso mover minha mão para o mouse para poder passar o ponteiro do mouse sobre 'dados' e esperar uma dica (que às vezes nunca aparece) aparecer. Assim, os programadores podem ler e entender o código significativamente mais rápido, porque não perdem tempo pesquisando para cima e para baixo ou esperando.
(Se você não acha que está perdendo tempo pesquisando de cima para baixo para descobrir coisas, encontre um código que você escreveu há um ano e que não o examinou desde então. Abra o arquivo e pule pela metade do caminho sem lê-lo. Veja como até agora você pode ler a partir deste ponto antes de não saber se algo é um membro, parâmetro ou local.Agora pule para outro local aleatório ... É isso que todos nós fazemos o dia inteiro quando estamos percorrendo o código de outra pessoa ou tentando entender como chamar sua função)
O prefixo 'm' também evita a notação feia e prolixo "this->", e a inconsistência que ela garante (mesmo se você for cuidadoso, geralmente acabará com uma mistura de "this-> data" e 'data' na mesma classe, porque nada impõe uma ortografia consistente do nome).
A notação 'this' tem como objetivo resolver a ambiguidade - mas por que alguém escreveria deliberadamente um código que pode ser ambíguo? Ambigüidade vai levar a um bug, mais cedo ou mais tarde. E em alguns idiomas 'this' não pode ser usado para membros estáticos, então você deve introduzir 'casos especiais' no seu estilo de codificação. Prefiro ter uma única regra de codificação simples que se aplique a todos os lugares - explícita, inequívoca e consistente.
O último grande benefício é com o Intellisense e o preenchimento automático. Tente usar o Intellisense em um Windows Form para encontrar um evento - você precisa percorrer centenas de métodos misteriosos de classe base que você nunca precisará chamar para encontrar os eventos. Mas se cada evento tivesse um prefixo "e", eles seriam listados automaticamente em um grupo em "e". Assim, a prefixação trabalha para agrupar os membros, consts, eventos etc. na lista do intellisense, tornando muito mais rápido e fácil encontrar os nomes que você deseja. (Geralmente, um método pode ter entre 20 e 50 valores (locais, parâmetros, membros, consts, eventos) acessíveis em seu escopo. Mas, depois de digitar o prefixo (eu quero usar um índice agora, digito 'i. .. '), são apresentadas apenas 2-5 opções de preenchimento automático. A' digitação extra '
Sou um programador preguiçoso, e a convenção acima me poupa muito trabalho. Posso codificar mais rapidamente e cometo muito menos erros, porque sei como todas as variáveis devem ser usadas.
Argumentos contra
Então, quais são os contras? Os argumentos típicos contra prefixos são:
"Esquemas de prefixo são ruins / maus" . Concordo que "m_lpsz" e seu tipo são mal pensados e totalmente inúteis. É por isso que aconselho usar uma notação bem projetada, projetada para suportar seus requisitos, em vez de copiar algo inapropriado para o seu contexto. (Use a ferramenta certa para o trabalho).
"Se eu mudar o uso de algo, tenho que renomeá-lo" . Sim, é claro que sim, é disso que trata a refatoração e por que os IDEs têm ferramentas de refatoração para fazer esse trabalho de maneira rápida e indolor. Mesmo sem prefixos, alterar o uso de uma variável quase certamente significa que seu nome deve ser alterado.
"Prefixos me confundem" . Como todas as ferramentas até você aprender a usá-lo. Quando seu cérebro se acostumar com os padrões de nomeação, ele filtrará as informações automaticamente e você não se importará mais com os prefixos. Mas você tem que usar um esquema como esse solidamente por uma semana ou duas antes de se tornar realmente "fluente". E é aí que muitas pessoas olham para o código antigo e começam a se perguntar como conseguiram sem um bom esquema de prefixo.
"Eu posso apenas olhar o código para resolver essas coisas" . Sim, mas você não precisa perder tempo procurando em outro lugar no código ou lembrando-se de cada pequeno detalhe quando a resposta é certa no local em que seu olho já está focado.
(Algumas) informações podem ser encontradas apenas aguardando uma dica de ferramenta aparecer na minha variável . Sim. Onde houver suporte, para alguns tipos de prefixo, quando o código for compilado corretamente, após uma espera, você poderá ler uma descrição e encontrar as informações que o prefixo teria transmitido instantaneamente. Eu sinto que o prefixo é uma abordagem mais simples, mais confiável e mais eficiente.
"É mais digitado" . Realmente? Mais um personagem inteiro? Ou é: com as ferramentas de preenchimento automático do IDE, muitas vezes reduz a digitação, porque cada caractere de prefixo reduz significativamente o espaço de pesquisa. Pressione "e" e os três eventos de sua classe aparecerão no intellisense. Pressione "c" e as cinco constantes serão listadas.
"Eu posso usar em this->
vez de m
" . Bem, sim, você pode. Mas esse é apenas um prefixo muito mais feio e mais detalhado! Somente ele apresenta um risco muito maior (especialmente em equipes) porque, para o compilador, é opcional e, portanto, seu uso é frequentemente inconsistente. m
por outro lado, é breve, claro, explícito e não opcional, por isso é muito mais difícil cometer erros ao usá-lo.