Codding standards Alfredo Goldman Baseado no padrão da Sun Motivação • Quem escreveu não deve ser o único a poder ler o código – Ainda mais em um sistema OO • Regras simples (muito simples) ajudam – Algumas são bem óbvias... • Criar um padrão (consensual) – Em parte independente da linguagem Mais razões • 80% do tempo de desenvolvimento é para manutenção; • Quase nenhum software é mantido apenas pelo primeiro desenvolvedor; • Convenções de código melhoram a legibilidade do código; • Se o código fonte é fornecido com o sistema, ele deve estar bem apresentado. Porém.... • Para que codding standards funcionem todos os desenvolvedores devem estar de acordo com a convenção, TODOS. Resumo (baseado no padrão da sun) • • • • • • • • • Nome dos arquivos; Estrutura dos arquivos; Indentação; Comentários; Declarações; Comandos; Espaços em branco; Convenção para nomes; Práticas (simples e saudáveis) de programação. Nome dos Arquivos • Mesmo que a linguagem não exija, use sufixos claros – ex. .java, .c, .cpp, .txt • Use makefiles com nomes padrão: – ex: Folhamakefile • Sempre tenha no diretório um README – este arquivo deve conter um resumo do conteúdo do diretório Estrutura dos Arquivos • Arquivos contém seções que devem ser separadas por linhas em branco e por comentários antes de cada seção; • Deve se evitar arquivos com mais de 2000 linhas. Classes/Interfaces • • • • • • • Começam com um comentário do tipo /**...*/ O comando class, ou interface Comentários sobre a implementação /*...*/ Variáveis estáticas (em ordem de acesso) Variáveis da classe (public, protected, friendly,private) Construtores Métodos (agrupados por funcionalidade e não por escopo) Indentação (é bem importante) • Use apenas espaços (tabs = 4 espaços) • Evite linhas com mais de 80 caracteres • Regras para quebra de linha: – – – – quebra após vírgula; quebra antes de operador; quebra no maior nível possível; alinhar a quebra com o começo da expressão do mesmo nível; – Se ficar feio, indentar com 8 espaços. Exemplos someMethod(longExpression1, longExpression2, longExpression3, longExpression4, longExpression5); var = someMethod1(longExpression1, someMethod2(longExpression2, longExpression3)); longName1 = longName2 * (longName3 + longName4 + 4 *longName6; longName5) // melhor longName1 = longName2 * (longName3 + longName4 -longName5) + 4 *longName6; // pior Exemplos // indentação tradicional someMethod(int anArg, Object anotherArg, String yetAnotherArg, Object andStillAnother) { ... } //Indentação com 8 espaços em certos casos private static synchronized horkingLongMethodName(int anArg, Object anotherArg, String yetAnotherArg, Object andStillAnother) { ... } Exemplos Em ifs use geralmente a regra de indentar com 8 espaços // indentação tradicional if ((condition1 && condition2) || (condition3 && condition4) ||!(condition5 && condition6)) { //BAD WRAPS doSomethingAboutIt(); //difícil de achar } // indentação proposta if ((condition1 && condition2) || (condition3 && condition4) ||!(condition5 && condition6)) { doSomethingAboutIt(); } Exemplos (cont.) //Ou esta if ((condition1 && condition2) || (condition3 && condition4) ||!(condition5 && condition6)) { doSomethingAboutIt(); } // expressões ternárias alpha = (aLongBooleanExpression) ? beta : gamma; //ou alpha = (aLongBooleanExpression) ? beta : gamma; //ou alpha = (aLongBooleanExpression) ? beta : gamma; Comentários linhas gerais • Dois tipos de comentários (da implementação e da documentação) • Linguagens modernas tem formas específicas – use-as ! • Não adicione comentários redundantes – O excesso de comentários reflete código mal escrito – pense em rescrever o trecho... Comentários Iniciar sempre o bloco comentário com uma linha em branco: /* * Here is a block comment. */ Comentários de uma única linha devem ser precedidos por uma linha em branco: if (condicao) { /* Comentário da condição */ ... } Comentários Comentários muito curtos podem estar na mesma linha. Se existem vários os mesmo devem estar alinhados. if (a==2) { return TRUE; /* um caso especial */ } else { return isPrime(a); /* funciona para a ímpar */ } Comentários com // também podem ser usados: if (foo>2) { // comentário de linha ... } else { return false; // comentário de fim de linha } //if (outracond==1) { // return true; // trecho de codigo comentado //} Comentários (em java usar javadoc) Um exemplo: /** * Class description goes here. * * @version 1.82 18 Mar 1999 * @author Firstname Lastname */ public class Blah extends SomeClass { /* A class implementation comment can go here. */ /** classVar1 documentation comment */ public static int classVar1; /** * classVar2 documentation comment that happens to be * more than one line long */ private static Object classVar2; Comentários (em java usar javadoc) cont. /** instanceVar1 documentation comment */ public Object instanceVar1; /** instanceVar2 documentation comment */ protected int instanceVar2; /** instanceVar3 documentation comment */ private Object[] instanceVar3; /** * ...constructor Blah documentation comment... */ public Blah() { // ...implementation goes here... } Comentários (em java usar javadoc) cont. /** * ...method doSomething documentation comment... */ public void doSomething() { // ...implementation goes here... } /** * ...method doSomethingElse documentation comment... * @param someParam description */ public void doSomethingElse(Object someParam) { // ...implementation goes here... } } Declarações • Quantas por linha? – De preferência um por linha (help comments) int level; int size; // nivel de ruído // tamanho do buraco – é melhor que: int level, size; – Nunca deve se declarar dois tipos na mesma linha int elemento, vetor[]; // errado! – Pode-se alinhar declarações int level; int size; Object currentEntry; // indentation level // size of table // currently selected table entry Declarações • Inicialização – Inicialize sempre as variáveis na hora da declaração; • Exceção: variáveis que dependem de algum cálculo Declarações • Localização – Sempre no início de blocos; • mas podem ser declaradas no início do método. void myMethod() { int int1 = 0; if (condition) { int int2 = 0; ... } // beginning of method block // beginning of "if" block } // o for é um caso especial for (int i=0; i< max; i++) { ... } • Não use o mesmo nome de variável em blocos internos Declarações (classes e interfaces) • • • • Não dê espaço entre antes do “)”; O “{” deve ficar no final da linha O “}” deve estar alinhado com o comando; Métodos devem estar separados por uma linha em branco; • Comandos vazios podem ser dados por {}. Declarações (classes e interfaces) Exemplo: class Sample extends Object { int ivar1; int ivar2; Sample(int i, int j) { ivar1 = i; ivar2 = j; } int emptyMethod() {} ... } Comandos • Colocar um comando por linha; • Em um bloco indentar sempre; • Colocar { no final da linha onde começa o bloco e } alinhado com o início desta.; • Use {} mesmo quando os blocos tiverem apenas um comando. Exemplos (if) if (condition) { if (condition) { statements; } statements; } else if (condition) { if (condition) { statements; } else { statements; } statements; } else { statements; } Exemplos (for) for (initialization; condition; update) { statements; } for (initialization; condition; update); // ao invés de for (init1, init2; condition; up1, up2){ statements; } // fazer init1; for(init2; condition; up1){ statements; up2; } Exemplos (while, do while) while (condition) { statements; } while (condition); do { statement; } while (condition); Exemplos (switch) switch (condition) { case ABC: statements; /* se não houver break, coloque comentário */ case DEF: statements; break; case XYZ: statements; break; default: statements; break; // é redundante mas pode evitar erros futuros } Espaços em Branco • Use linhas em branco para a separação lógica – duas para • separar seções do mesmo arquivo; • entre definições de classes e interfaces. – uma para • • • • entre métodos; dentro de um método entre as variáveis e o 1º comando; antes de comentários (de bloco, ou linha); entre as seções lógicas de um método. Espaços em branco • Entre keywords e parênteses; while (true) { ... } // assim fica fácil visualizar métodos (sem espaço) • Após vírgulas em listas de argumentos; • Antes e depois de operadores binários a += c + d; a = (a + b) / (c * d); while (d++ = s++) { n++; // mas não para operadores unários } printSize("size is " + foo + "\n"); Espaços em branco • Entre os comandos de um for; for (expr1; expr2; expr3){ ... } • Após operações de cast myMethod((byte) aNum, (Object) x); myMethod((int) (cp+5), ((int) (i + 3)) + 1); Nomenclatura • Packages – pode-se usar domínio + subdiretórios; • Classes e Interfaces – Primeira letra de cada palavra maiúscula; • Métodos – verbos, com 1ª letra minúscula e letras de cada palavra maiúsculas; • Variáveis – 1ª letra minúscula, pequenos, se temp. ok i, j, k. • Constantes – Tudo maiúsculo separado por “_” Dicas de programação • Evite usar um objeto para acessar algo estático classMethod(); //ok Aclass.classMethod(); //ok anObject.classMethod(); //evitar • Atribuições: uma em cada linha x = y = 0; // evitar x = 0; y = 0; // ok d = (a = b + c) + r; //evitar a = b + c; d = a + r; //ok Dicas de programação • Use parênteses if (a == b && c == d) //evitar if ((a == b) && (c == d)) //ok • Use operadores ternários (em certas situações) if (cond) { return x; } return y; return (cond ? X : y); • Coloque o comentário XXX se há algo com problema e FIXME onde existem bugs Dicas de Programação • Faça o projeto primeiro em OO, depois implemente-o; • Se você tem métodos com mais de 80 linhas, provavelmente o código não está bem organizado; • Se seus arquivos tem mais de 500 linhas veja o item anterior; • Não use variáveis globais. Padronizar o cabeçalho /* * Nome do Arquivo: Teste.java * * Descrição: Este é um arquivo que serve para testar a * classe Cliente.Java * * Projeto: PDAs de venda; * Autor: Eu, tu e eles */ Dicas gerais • Sempre terminar o arquivo com uma linha em branco; • Antes de colocar um comentário para alguém no código, envie-lhe um e-mail; • Sempre faça uma mensagem de “uso”; • Sempre termine os #endif com um comentário correspondente ao #if; • Coloque /* */ entre o #include e o nome do arquivo (visual C++); • Defina constantes com um prefixo ligado ao projeto: ex: IT_MAX_CLIENTE; • Proteja headers de inclusões múltiplas: • Nunca faça o cast de um ponteiro para um inteiro (use long); • Sempre que usar arquivos, verifique se não ocorreram erros de abertura, escrita, etc. Caso particular • Quais padrões de código seriam úteis no seu caso ? • Os programas atuais respeitam estes padrões ? • Na prática, verificar que respeitar os padrões não é tão difícil.