segunda-feira, 21 de julho de 2014

Convenções de Nomenclatura

Introdução

A programação consiste em grande parte em dar nomes a coisas: classes, métodos e variáveis. Mas, conseguir criar bons nomes é bem mais difícil do que parece. Para além de respeitarem as regras da linguagem ou tecnologia em que estão a ser usados, os nomes devem ser claros para o programador que os criou, mas também para outros programadores que tenham que ler o código. É aqui que entram as Convenções de Nomenclatura (Naming Conventions).

O conceito de convenção de nomenclatura é bastante mais geral, mas, na programação, podemos dizer que consiste num conjunto de regras para a escolha da sequência de caracteres a ser usada para criar os identificadores (nomes) de classes, métodos, tipos, variáveis, ou outras entidade do código fonte e documentação. As convenções aplicam-se, normalmente, quer ao formato, quer à atribuição de significado aos nomes escolhidos.

De realçar que este é um tema controverso, pois existem variadíssimas convenções, cada uma com os seus partidários e é comum as grandes empresas criarem o seu próprio conjunto de regras, para melhor servir os seus interesses. Neste artigo vamos tentar abordar os conceitos mais importantes e analisar algumas das convenções mais populares os dias de hoje.

Conteúdo

Benefícios da utilização de Convenções de Nomenclatura

À primeira vista, as convenções de nomenclatura podem não parecer assim tão importantes. Na realidade, podemos criar código sem usar qualquer tipo de convenção e ele continuar a ser funcionalmente correcto. Então, porque devemos usar convenções de nomenclatura e porque são tão recomendadas e mesmo obrigatórias na maioria dos grandes projectos?

A utilização de convenções de nomenclatura, em oposição a deixar os programadores criar livremente os nomes e formatos dos nomes, permite que seja significativamente mais fácil a outros analistas e programadores entender entender como o sistema funciona e o que está a fazer e como corrigir ou estender o código fonte para novas necessidades de negócio.

Existem outras razões e vantagens, é claro, mas a questão da manutenção é fundamental. Quando temos que olhar para o código de outra pessoa, ou mesmo para o nosso próprio código, quando já não lhe mexemos há algum tempo, ajuda-nos ter certas expectativas sobre o que um dado identificador é e o que faz, logo à primeira vista. Se pensarmos que a maior parte do tempo de vida de uma aplicação é passado na fase de manutenção, tudo o que tornar a manutenção mais fácil, ajuda. Especialmente quando é algo tão fácil como seguir algumas convenções de nomenclatura.

Podemos enumerar mais alguns dos potenciais benefícios da utilização de convenções de nomenclatura:

  • Fornecer informação adicional (metadados) sobre a utilização de um dado identificador;
  • Promover a consistência dentro de uma equipa de desenvolvimento;
  • Permitir o uso de ferramentas automáticas de refactoring ou find-and-replace com um potencial mínimo de erro;
  • Aumentar a clareza, em casos de ambiguidade;
  • Melhorar a aparência estética e profissional do produto (p.ex., por não permitir nomes excessivamente longos, cómicos, ou abreviações obscuras);
  • Evitar "colisões de nomenclatura" que podem ocorrer quando o resultado do trabalho de diferentes organizações é combinado;

Vejamos um pequeno exemplo prático:

a = b * c;

embora o código acima esteja sintaticamente correcto (em Java ou C#), não é claro qual o seu objectivo ou funcionalidade.

juros = capital * taxa;

Agora tornou-se muito mais claro qual o objectivo desta linha de código.

Conceitos e elementos mais comuns

Comprimento dos identificadores
Este é um elemento sujeito a muita discussão e controvérsia, na prática, mas é fundamental em qualquer convenção de nomenclatura. Algumas regras impõem um número limite fixo de caracteres individuais permitidos para cada identificador enquanto outras especificam apenas orientações.

Algumas considerações:

  • os identificadores mais curtos, podem ser tidos como mais convenientes, porque são mais fáceis de digitar;
  • identificadores extremamente curtos (como o 'i' ou 'j') são muito difíceis de distinguir, ao usar ferramentas de find-and-replace;
  • identificadores mais longos podem ser preferidos porque os curtos podem não codificar informação suficiente ou parecer demasiado críptica.

A preferência por identificadores mais curtos ou mais longos é uma questão ainda aberta à pesquisa. A utilização de brevidade na programação pode ser atribuída, em parte, ao seguinte:

  • Os primeiros compiladores e linkers só permitiam nomes de variáveis com 6 caracteres. Mais tarde foram permitidos nomes mais longos, para permitir uma melhor compreensão humana, mas apenas os primeiros caracteres eram significativos;
  • Os primeiros editores de código não possuíam autocomplete;
  • Os primeiros monitores eram de baixa resolução e tinham um número limitado de caracteres por linha (p.ex. apenas 80 caracteres);
  • Grande parte da ciência da computação teve origem na matemática, onde, tradicionalmente, os nomes das variáveis ​​têm apenas uma única letra.

Caixa Alta, Caixa Baixa e Números
Algumas convenções de nomenclatura definem se as letras podem aparecer em maiúsculas ou minúsculas. Outras não restringem a caixa das letras (letter casing), mas anexam uma interpretação bem definida com base em casa caso. Outras convenções especificam ainda se podem ser usados identificadores alfabéticos, numéricos ou alfanuméricos, e em caso afirmativo, em que sequência.

Identificadores multi-palavra
Uma recomendação comum, na programação, é "usar identificadores significativos". Uma única palavra pode não ser tão significativa, ou específica, como várias palavras. Consequentemente, algumas convenções de nomenclatura especificam regras para a criação de identificadores que contenham mais que uma palavra.

Como a maioria das linguagens de programação não permite a utilização de espaços em branco nos identificadores, é necessário um método de delimitação de cada palavra, que torne mais fácil de interpretar que caracteres pertencem a cada uma.

  • Palavras separadas por delimitadores
    Uma abordagem possível é delimitar as palavras através de um carácter não alfanumérico. Os dois caracteres mais utilizados nesta técnica são o hífen “-“ e o sublinhado “_”. Por exemplo, o identificador “duas palavras” seria representado como "duas-palavras" ou "duas_palavras". O hífen é usado por quase todos os programadores de Cobol, Forth e Lisp e também é comum como seletor em Cascading Style Sheets. Na maioria das outras linguagens (p.ex., famílias C e Pascal) usa-se o hífen como operador de subtração, não estando, por isso, disponível para uso em identificadores, usando-se o sublinhado no seu lugar. Esta prática chama-se Snake Case.
  • Palavras separadas por caixa de letras
    Outra abordagem é delimitar as palavras através do uso de letras maiúsculas. Neste caso o identificador “duas palavras” seria representado como "duasPalavras" ou "DuasPalavras". Esta técnica é chamada de Camel Case. Esta técnica tem duas variantes principais, uma que diz que a primeira palavra deve ter letra minúscula (“duasPalavras”) e outra que deve ter letra maiúscula (“DuasPalavras”). Existe alguma discussão sobre a correcta utilização destas variantes, mas hoje é mais comum aceitar-se que Camel Case designa a primeira variante (minúsculas) e que Pascal Case designa a segunda variante.

Metadados
Algumas convenções ultrapassam as meras regras de formato e grafia para a criação de nomes. Impõem também algumas regras para o seu significado. Alguma das técnicas usadas nessas convenções (especialmente nas mais antigas), são:

  • Notação Húngara
    A Notação Húngara é talvez a mais conhecida destas convenções, que codifica o tipo de uma variável no seu nome, através de um prefixo. Por exemplo sNome indica que a variável é uma string ou nIdade, indica que a variável é um número inteiro.
  • Notação posicional
    Uma técnica muito usada em notações curtas. P.ex. FTMARM01, onde FT é a aplicação – Facturação, M significa Menu, ARM é o módulo de Armazéns e 01 um número de sequência. Este tipo de convenção ainda é usada em mainframes dependentes de JCL e é vista também no formato MS-DOS 8.3 (máximo 8 caracteres, ponto separador e três caracteres para o tipo de ficheiro).
  • Esquema de palavras compostas
    Um dos primeiros sistemas de convenções foi desenvolvido pela IBM e consiste no esquema de palavras PRIME-MODIFIER-CLASS. Um exemplo será IT_SEQ_NO, para significar “Item Sequence Number” ou “Número de Sequência do Item”. As palavras PRIME designavam as principais entidades do sistema, enquanto as palavras MODIFIER eram utilizadas como refinamento adicional, qualificação e legibilidade. Finalmente as palavras CLASSE deveriam ser apenas uma pequena lista de tipos de dados relevantes para uma determinada aplicação. As palavras CLASSE, colocadas como sufixo teve muitas vezes a mesma finalidade que os prefixos da Notação Húngara.

Namespces
O conceito de namespace (espaço de nomes) é bastante abrangente na ciência da computação. Genericamente, pode-se definir como um container que fornece um contexto para os elementos que armazena. P.ex., a nível do sistema operativo, um directório é um namespace. Muitas linguagens de programação disponibilizam namespaces como contextos para guardar identificadores. Algumas regras para estes espaços de nomes são as seguintes:

  • Não podem existir dois identificadores iguais dentro do mesmo namespace;
  • Podem existir namespaces dentro de outro namespace, formando uma árvore de espaços de nomes;
  • Na mesma aplicação, podem existir classes ou funções com o mesmo nome, desde que estejam definidas em namespaces diferentes.

Os namespaces também necessitam de um identificador e, como tal, existem convenções de nomenclatura para a sua criação. Uma das convenções mais comuns, quer no Java, quer no .NET consiste em identificar os namespaces através de grupos de palavras em Camel Case ou Pascal Case, separadas por “.”. Cada um destes grupos tem um significado, conforme passamos a indicar:

  • Nome da empresa ou organização
  • Nome do produto ou tecnologia
  • Nome do módulo
  • Nome do sub-módulo e assim sucessivamente

Vejamos alguns exemplos:

Microsoft.Excel.Math.Random
java.util.stream
pt.governo.ministerio.financas

Convenções de Nomenclatura específicas

Java
Na linguagem Java, as convenções de nomenclatura para identificadores foram sugeridas e estabelecidas ao longo do tempo por várias comunidades, como a Sun Microsystems, ou a Netscape. Seguem-se alguns exemplos de convenções de nomenclatura da Sun:

  • Classes
    Os nomes das classes devem ser substantivos, em Pascal Case. Devemos tentar manter os nomes das classes simples e descritivos. Usamos palavras inteiras, evitando siglas e abreviaturas, a não ser quando a sigla é muito mais usada do que a forma longa, como em URL ou HTML. Alguns exemplos:
    class ImageSprite
    class TextFileParser
  • Métodos
    Os nomes de métodos devem ser verbos, em Camel Case. Alguns exemplos:
    run();
    runFast();
  • Variáveis
    Os nomes das variáveis devem ser formatados em Pascal Case. Apesar de permitido em termos de sintaxe da linguagem, os nomes de variáveis não devem começar por “_” ou “$”. Os nomes das variáveis devem ser curtos, mas significativos. Não se devem usar nomes de apenas um carácter, excepto para variáveis ​​temporárias "descartáveis". Os nomes comuns para variáveis ​​temporárias são i, j, k, m, e n para inteiros; c, d, e e para caracteres ou strings. Alguns exemplos:
    int    i;
    char   c;
    float  myWidth;
  • Constantes
    Os nomes de variáveis declaradas como constantes, devem ter todas as palavras em maiúsculas, separadas pelo carácter “_”. Alguns exemplos:
    static final int MIN_WIDTH = 4;
    static final int MAX_WIDTH = 999;

Microsoft .NET
As convenções de nomenclatura da Framework Microsoft .NET são muito semelhantes às da linguagem Java, em que a diferença mais evidente é a utilização do Pascal Case para o nome de métodos, em vez de Camel Case. Também existem pequenas diferenças entre as várias linguagens .NET, mas não muito significativas.

Recomendações

Finalizo com algumas recomendações baseadas na minha experiência pessoal:

  • A primeira recomendação é que usem convenções de nomenclatura. Para além das convenções das linguagens e das que são usadas nos locais onde trabalham, criem as vossas próprias convenções e tenham a disciplina de as usar sempre que possível;
  • Reforço a recomendação anterior para todos aqueles que estejam a liderar uma equipa de desenvolvimento, um projecto ou mesmo um departamento;
  • Criem convenções para os componentes de framework, serviços, componentes de front-end, áreas de negócio, etc. Não são só os nomes das variáveis que são importantes;
  • Utilizem a convenção dos namespaces (organização.aplicação.módulo) para evitar ambiguidades e colisões de nomes.

Sem comentários:

Enviar um comentário