| FAQ Lite | ||||||||||||||||||||
| Padrões de Codificação | ||||||||||||||||||||
|
||||||||||||||||||||
| [ 25.1 ] Quais são os bons padrões de codificação em C++ ? |
| Obrigado por ler essa resposta, ao invés de tentar
estabelecer os seus próprios padrões de codificação. Saiba, desde já, que algumas pessoas em comp.lang.c++ são muito sensíveis a essa questão. Praticamente todos os engenheiros de software já foram, em algum momento de suas carreiras, subjugados por pessoas que usaram padrões de codificação como um instrumento de controle, de poder. Pior ainda, várias tentativas de estabelecer padrões de codificação em C++ foram feitas por pessoas que, a rigor, não sabiam muito bem do que estavam falando , de tal modo que os padrões acabavam baseados no que foi o estado da arte, quando os autores dos padrões realmente ainda escreviam código. Esse tipo de imposição acabou gerando uma atitude de descrença em relação aos padrões de codificação. É óbvio que alguém que remete uma questão como a deste FAQ deseja ser treinado, e portanto não pretende gerar padrões limitados à sua ignorância. Contudo, remeter uma questão como esta para comp.lang.c++ tende a produzir uma discussão que vai gerar mais calor do que luz. |
| [ 25.2 ] Padrões de codificação são necessários? São suficientes? |
| Padrões de codificação não tranformam programadores
não orientados a objeto em programadores orientados a objeto; isso só o treinamento e a
experiência podem fazer. Se padrões de codificação têm algum mérito, é o de
desencorajar a fragmentação que ocorre quando grandes organizações coordenam a
atividade de diferentes grupos de programadores. Mas você quer mais do que isso de um padrão de codificação. A estrutura fornecida por padrões de codificação dá aos neófitos um nível menor de liberdade, o que é bom. Entretanto orientações pragmáticas devem funcionar melhor do que um bonito manual de padrões. As organizações precisam de uma filosofia consistente de projeto e implementação. Por exemplo:
O que é necessário é um pseudo padrão para projeto detalhado. Eu recomendo a seguinte abordagem para que se atinja tal padronização:
Treinamento fornece instrução intensiva; supervisão faz com que OO seja efetivamente implementado, ou seja, faz com que OO deixe de ser apenas um discurso e se tranforme em prática; bibliotecas de classes C++ de alta qualidade fornecem treinamento de longa duração. Você encontra no mercado esses três tipos de treinamento. Espelhe-se em organizações bem sucedidas: Compre, não faça. Compre bibliotecas, compre treinamento, compre ferramentas, compre consultoria. É muito dificil o sucesso de companhias que tentam abastecer-se internamente de treinamento e de ferramentas, além de desenvolver e vender sistemas de aplicação. Ainda que poucos os considerem ideais, ou mesmo bons, os padrões são necessários às organizações que desenvolvem software. As FAQs seguintes fornecem algumas orientações básicas sobre convenções e em estilos. |
| [ 25.3 ] Nossa empresa deve estabelecer padrões de codificação com base em nossa experiência em C? |
| Não. Não importa quão vasta seja sua experiência em C. Independentemente de quão avançado seja o seu conhecimento em C, ser um bom programador C não faz de você um bom programador C++. Migrar de C para C++ é mais do que aprender a sintaxe e a semântica da parte ++ do C++. Organizações que querem os benefícios de OO, mas falham em introduzir OO em sua metodologia de programação, desperdiçam o seu tempo e não atingem os benefícios esperados. Padrões de codificação em C++ devem ser preparados por especialistas em C++. Um bom começo é informar-se com comp.lang.c++. Procure especialistas que possam ajudá-lo a não cair em armadilhas. Treine-se. Compre bibliotecas e verifique se boas bibliotecas satisfazem seus padrões de codificação. Não estabeleça seus próprios padrões de codificação até que você tenha considerável experiência em C++. Não ter padrões é melhor do que ter padrões inadequados. Procure no mercado tanto treinamento quanto bibliotecas para aprender com especialistas. Um alerta final: quando há demanda para um serviço no mercado, as oportunidades para os charlatões aumentam. Examine antes de comprar. Solicite avaliação do serviço prestado a outras empresas. Considere que o fato de conhecer C++ em profundidade não faz de alguém um bom instrutor, um bom comunicador. Selecione um profissional atualizado que possa ensinar, não um professor profissional que possa estar desatualizado. |
| [ 25.4 ] O operador ?: é nocivo, já que pode ser usado para criar código ininteligível? |
| Não. Mas, como sempre, lembre-se que legibilidade é um
dos mais importantes atributos do código. Há que diga que o operador ?: deve ser evitado porque o consideram confuso, quando comparado ao velho e bom comando if. Em alguns casos ?: tende a dificultar a leitura do seu código, e nesses casos você deve mesmo substituir o ?: por if. Mas há casos em que ?: é muito aplicável porque enfatiza o que realmente está acontecendo, melhor que o comando if. Vamos começar um exemplo simples. Suponha que você quer imprimir o resultado da chamada a uma função. Nesse caso você deve colocar o seu principal objetivo (imprimir) no início da linha, e colocar a chamada à função dentro dessa mesma linha (esse critério de relevância da esquerda para a direita é baseado na noção intuitiva de que a maioria dos desenvolvedores consideram a primeira ação na linha a ação mais importante). |
// Preferred (emphasizes the major goal — printing): cout << funct(); // Not as good (emphasizes the minor goal — a function call): functAndPrintOn(cout);
| Agora vamos estender essa idéia usando o operador ?: Suponha que seu objetivo real é imprimir alguma coisa, mas você precisa fazer algum teste lógico para determinar o que deve ser impresso. Já que a impressão é a ação conceitualmente mais importante, nós prefirimos colocá-la no início da linha, dando menos relevância ao teste lógico. No código a seguir, a variável n representa o número de remetentes da mensagem; a mensagem é impressa com cout: |
int n = /*...*/; // number of senders // Preferred (emphasizes the major goal — printing): cout << "Please get back to " << (n==1 ? "me" : "us") << " soon!\n"; // Not as good (emphasizes the minor goal — a decision): cout << "Please get back to "; if (n==1) cout << "me"; else cout << "us"; cout << " soon!\n";
| Tudo o que se disse neste FAQ você deve considerar também para não escrever código hermético e ilegível usando combinações de ?:, &&, ||, etc. Por exemplo: |
// Preferred (obvious meaning): if (f()) g(); // Not as good (harder to understand): f() && g();
| Pessoalmente eu considero que o exemplo com o if explícito
é mais claro, porque enfatiza a ação mais importante - uma decisão baseada no
resultado da chamada de f() - ao invés da ação menos importante - a chamada de f(). Em
outras palavras, o uso de if aqui é bom pelas mesmas razões que o tornaram inadequado no
exemplo anterior: queremos que as
ações principais sejam facilmente identificadas. Seja qual for o caso, não se esqueça de que legibilidade é o objetivo, ou pelo menos um dos objetivos mais importantes. Sua preocupação não deve ser evitar certas construções sintáticas como ?: ou && ou || ou if ou mesmo goto. Se você enfatiza o objetivo principal em critérios globais como - ações principais em destaque ou a ação principal no início da linha ou cerifique-se de que seu código seja óbvio e legível - você consegue bons resultados. Código deve ser escrito para ser lido, não pelo compilador, mas por outros seres humanos. |
| [ 25.5 ] Devo declarar variáveis locais no meio ou no topo da função? |
| Declare as variáveis locais o mais próximo possível da
primeira instrução em que são utilizadas. Um objeto é inicializado (construído) no momento em que é declarado. Se você não tem informações suficientes para inicializar o objeto até o meio da função, então declare-o no meio da função quando o objeto poderá ser inicializado corretamente. Não declare o objeto vazio no topo da função para atribuir-lhe um valor posteriormente, isso prejudica a performance do seu código. Construir um objeto corretamente é mais rápido do que construí-lo incorretamente e remodelá-lo mais tarde. Exemplos mostram diferença de velocidade da ordem de 350% em classes simples como String. Em casos reais, a degradação de performance pode variar, e até serem menores que 350%, mas de qualquer forma será degradação de performance. Degradação desnecessária. Uma réplica comum ao critério exposto acima é: vamos disponibilizar funções membro set() para todos os dados em nossos objetos de modo a diluir os custos de construção dos objetos. Isso é pior do que a degradação de performance, porque agora você está introduzindo no problema uma dificuldade adicional de manutenção do código. Disponibilizando funções membro set() para todos os dados é quase o mesmo que tornar todos os dados public porque assim você expõe sua técnica de implementação para todos. A única coisa que fica oculta são os nomes físicos dos membros dos objetos, mas o fato de você estar usando uma List e um String e um Float, por exemplo, fica exposto para todos verem. Em resumo: variáveis locais devem ser declaradas próximo de seu primeiro uso. Lamento que isso não seja familiar a especialistas em C, mas novo não significa necessariamente mau. |
| [ 25.6 ] Qual a melhor convenção para nomes de arquivos-fonte: foo.cpp? foo.c? foo.cc? |
|
|
| Se você já tem uma convenção, use-a. Se não tem,
consulte os manuais de seu compilador para verificar o que o compilador espera que você
use. Normalmente espera-se .C, .cc, .cpp ou .cxx (naturalmente a extensão .C presume existência de um
sistema de arquivos case-sensitive para distinguir .C de .c). Nós temos usado .cpp para códigos fonte em C++, mas também temos usado .C. Neste caso, usamos as opções do compilador para forçar que arquivos .C sejam tratados como arquivos fonte C++ (-Tdp para IBM CSet++, -cpp para Zortech C++, -P para Borland C++, etc) quando trabalhamos em ambientes com gerenciador de arquivos case-sensitive. Nenhuma dessas abordagens é tecnicamente superior a qualquer outra. Geralmente usamos a que o nosso cliente prefere porque, de novo, essa é uma questão determinada por considerações comerciais, e não por critérios técnicos. |
| [ 25.7 ] Qual a melhor convenção para nomes de arquivos-header? foo.H? foo.hh? ou foo.hpp? |
| Se você já tem uma convenção, use-a. Se não tem, e
não precisa que seu editor distinga entre arquivos-header C e C++, simplesmente use .h. Em
qualquer outro caso use o que o seu editor espera, como .hh ou .hpp. Nós usamos tanto .hpp quanto .h para nossos arquivos-header em C++ |
| [ 25.8 ] Há orientações lint-like para C++? |
Sim, há várias práticas consideradas potencialmente
perigosas. Entretanto nenhuma delas é intrinsecamente má, há situações em que se
torna necessário utilizá-las:
|
Fred operator+ (const Fred& a, const Fred& b)
{
Fred ans = a;
ans += b;
return ans;
}
| Desse modo os operadores binários não precisam sequer ser friend. Em alguns casos é possível obter melhor eficiência implementado-se operadores comuns (por exemplo, se class Fred é na realidade String, e += tem que realocar/copiar um string em memória, pode ser melhor obter o tamanho do string logo de início. |
| [ 25.9 ] O que é melhor: nomes identificadores that_look_like_this ou nomes thatLookLikeThis ? |
| Isso depende de seus antecedentes em programação. Se você tem conhecimento prévio de Pascal ou de Smalltalk, youProbablySquashNamesTogether como nessa forma. Se você tem conhecimento anterior de Ada You_Probably_Use_A_Large_Number_Of_Underscores como nessa outra forma. Se sua experiência anterior é predominante em Microsoft Windows, você provavelmente prefere o estilo húngaro onde você jkuidsPrefix vndskaIdentifiers ncqWith ksldjfTheir nmdsadType. E ainda há o pessoal com experiência prévia em Unix C que abbr evthng n use vry srt idntfr nms Portanto aqui também não há um padrão universal. Se sua organização já tem uma padronização para codificação de identificadores, use-a. Mas nada justifica criar um novo Jihad por causa disso. De um ponto de vista estritamente comercial, há apenas duas coisas que realmente importam nesse contexto: o código deve ser legível e todos na mesma organização devem usar o mesmo estilo. |
| [ 25.10 ] Há outras fontes de consulta para padrões de codificação? |
| Sim, há várias. Aqui estão algumas fontes de consulta que você pode usar como um ponto de partida no desenvolvimento dos padrões de codificação de sua organização: |
| Uma anti-orientação simplória mas divertida: |
| As orientações de Ellemtel estão disponíveis em: |
| Nota: O autor não endossa esses sites, nem o seu conteúdo. Estão listados aqui apenas como um serviço público. O autor não verificou os detalhes das recomendações desses sites. |
|
| | Home | Bookmarks | Universidades | Para Saber mais | Universidades | WEB Directory | Mapa do site | | |