Guia de Estilo
Convenções de layout, nomes, escopo e eficiência para código em C.
Programas precisam ser entendidos não só por computadores, mas também (e principalmente) por seres humanos. Por isso, o layout do código-fonte de um programa, ou seja, a disposição do código, é tão importante.
O layout de um programa deve seguir os mesmos princípios que o layout de qualquer outro tipo de texto. É fácil habituar-se a produzir um bom layout. O compromisso de escrever um código organizado e bem estruturado desde o início faz com que seu código seja mais fácil de testar, tenha menos bugs e os bugs existentes serão mais isolados e mais fáceis de rastrear. Além disso, na maioria dos ambientes de trabalho profissionais, espera-se que você siga os padrões de estilo da empresa. Aprender a obedecer cuidadosamente a um guia de estilo e escrever código com um grupo de outros desenvolvedores onde o estilo é consistente entre eles são valiosas habilidades de trabalho.
As diretrizes abaixo identificam algumas das qualidades de estilo que serão usadas ao avaliar seus programas. Como em qualquer atividade complexa, não existe um layout "melhor", nem uma lista definitiva que cubra todas as situações, existem escolhas melhores e piores e o objetivo deste guia é guiá-lo em direção às melhores escolhas.
Na avaliação, é esperado que você faça um esforço para seguir essas práticas. Embora seja possível escrever um código que viole essas diretrizes e, ainda assim, exiba um bom estilo (ou um resultado correto), é fortemente recomendado que você siga essas diretrizes para fins práticos de avaliação. Não perca pontos por não seguir essas diretrizes 😉.
Layout, Indentação e Espaços em Branco
Indentação
Use espaços em branco/indentação sempre! O espaço em branco/indentação adequado "ilumina" a estrutura do seu programa e torna mais fácil seguir o código e localizar erros.
- Aumente o nível de recuo em cada chave de abertura
{e diminua em cada chave de fechamento}; - Não use tabulação (tecla TAB) no código-fonte do seu programa;
- Escolha um incremento de 2 ou 4 espaços por nível de indentação. Seja consistente;
- Não coloque mais de uma declaração na mesma linha.
while (x < y) {
if (x != 0) { funcao1(x);
}
else { funcao2(y);
y--; }}
return x;while (x < y) {
if (x != 0) {
funcao1(x);
} else {
funcao2(y);
y--;
}
}
return x;Linhas Longas
Quando qualquer linha tiver mais de 100 caracteres, divida-a em duas linhas. Recue o texto flutuante para alinhá-lo com o texto acima.
if (aluno->notaFinal >= NOTA_MINIMA_APROVACAO && aluno->frequencia >= FREQUENCIA_MINIMA_PERCENTUAL && aluno->statusFinanceiro == REGULAR) {
// ...
}if (aluno->notaFinal >= NOTA_MINIMA_APROVACAO &&
aluno->frequencia >= FREQUENCIA_MINIMA_PERCENTUAL &&
aluno->statusFinanceiro == REGULAR) {
// ...
}Linhas em Branco
Use linhas em branco para separar funções e grupos lógicos de instruções dentro de uma função.
Espaço em Branco
Adicione espaço entre os operadores e seus operandos. Adicione parênteses para mostrar o agrupamento onde a precedência pode não ser clara para o leitor.
double raiz = (-b+sqrt(b*b-4*a*c))/2*a;double raiz = (-b + sqrt((b * b) - (4 * a * c))) / (2 * a);- Use um espaço para separar cada palavra da palavra seguinte (os símbolos
=,<=,while,if,foretc. contam como palavras); - Deixe um espaço depois, mas não antes, de parêntese e colchete direito;
- Deixe um espaço antes, mas não depois, de parêntese e colchete esquerdo.
while(j < n)
else{
for (i=1;i<n;++i)while (j < n)
else {
for (i = 1; i < n; ++i)- Ponteiros/Structs:
x->prox(e nãox -> prox) - Acesso a vetores:
x[i](e nãox [i]) - Incremento/Decremento:
x++(e nãox ++)
Nomes
Escolha identificadores significativos. Isso reduz a carga cognitiva para o leitor e autodocumenta a finalidade de cada variável e função.
- Substantivos para nomes de variáveis: Para variáveis, a pergunta é "O que é?" Use um substantivo e, se necessário, adicione modificador para esclarecer (
nomeCurso,valorMaximo,valorMinimo).- Evite nomes de uma letra como
aoup(exceções para contadores de loopi,jou coordenadasxey). - Nunca nomeie uma variável de
l, muito facilmente confundida com o número1.
- Evite nomes de uma letra como
- Verbos para nomes de funções: Para funções, a pergunta é "O que isso faz?" As funções que realizam ações são melhor identificadas por verbos (
encontraMenor,removePontuacao,desenhaTriangulo). As funções usadas de acordo com o seu valor de retorno são nomeadas conforme a propriedade que está sendo retornada (ehPrimo,obtemIdade). - Use constantes nomeadas: Evite espalhar números mágicos no código. Em vez disso, declare um valor
constou#definenomeado e use onde esse valor for necessário. Isso ajuda na legibilidade e fornece um local centralizado para editar o valor quando necessário.
double area = 3.14159 * r * r;
if (idade >= 18) { ... }#define PI 3.14159
const int IDADE_MAIORIDADE = 18;
double area = PI * r * r;
if (idade >= IDADE_MAIORIDADE) { ... }- Capitalização:
- Use
camelCasepara nomes de funções e variáveis (encontraMenor); - Use
PascalCasepara nomes de structs e tipos (ListaAlunos); - Use
SNAKE_CASEem maiúsculas para constantes (TAMANHO_MAX).
- Use
Escopo de Variável
- Escopo Estreito: Declare as variáveis no escopo mais estreito possível. Por exemplo, se uma variável for usada apenas dentro de um loop, declare-a dentro do loop, em vez de no início da função ou no início do arquivo.
- Não reutilize o mesmo nome no escopo interno: Declarar uma variável no escopo interno com o mesmo nome de uma variável no escopo externo fará com que o uso do nome interno "sombreie" (shadowing) a definição externa. Isso não só é confuso, mas muitas vezes leva a bugs difíceis de rastrear.
- Evite variáveis globais: Evite variáveis de escopo global. Quando há informações a serem compartilhadas entre as funções, elas devem fluir para dentro e para fora das funções por meio de parâmetros e valores de retorno, e não através do escopo global.
Uso de Recursos da Linguagem C
for vs while
Use um loop for quando o número de repetições for conhecido (definido); use um loop while quando o número de repetições for desconhecido (indefinido).
int i = 0;
while (i < n) {
printf("%d\n", i);
i++;
}for (int i = 0; i < n; i++) {
printf("%d\n", i);
}break e continue em loops
Sempre que possível, um loop deve ser estruturado da maneira normal com início, fim e incremento claros, sem nenhuma interrupção no meio.
Dito isso, existem usos limitados de break que são aceitáveis, como while (1) com break ou a necessidade de sair do loop no meio da iteração. O uso de continue é raro e frequentemente confuso para o leitor; é melhor evitar.
Sempre inclua chaves ({}) nas instruções de controle
O código de um if/else, for, while, etc., deve sempre ser encapsulado em { } e ter quebras de linha adequadas, mesmo se o corpo for apenas uma linha. O uso de chaves evita acidentes de execução em alterações futuras.
if (statusValido)
executaAcao1();
executaAcao2(); // AVISO: Esta linha SEMPRE será executada!if (statusValido) {
executaAcao1();
executaAcao2();
}Booleanos
Expressões booleanas são propensas a construções redundantes. Prefira alternativas concisas e diretas. Um valor booleano é verdadeiro ou falso; você não precisa comparar com true/false (1/0) ou converter uma expressão booleana para true/false (1/0).
if (ehPrimo(n) == true) { ... }
if (x > 0) {
return true;
} else {
return false;
}if (ehPrimo(n)) { ... }
return (x > 0);Eficiência
Na disciplina, serão avaliadas escolhas eficientes das estruturas de dados e algoritmos.
- Melhor classe O-grande: Dada uma escolha de opções para implementar um algoritmo, a preferência é geralmente para aquele com menor O-grande. Ou seja, um algoritmo
é preferível a , e um algoritmo constante ou logarítmico é melhor que um linear . - Salve o resultado de chamadas "caras" e reutize-o: Se você estiver chamando uma função computacionalmente cara e usando seu resultado várias vezes, salve esse resultado em uma variável em vez de chamar a função repetidamente. Essa otimização é especialmente valiosa dentro de loops.
for (int i = 0; i < strlen(texto); i++) {
// strlen(texto) é executado a cada iteração -> O(n²) no total!
}int tam = strlen(texto);
for (int i = 0; i < tam; i++) {
// O(n) no total
}- Evite copiar objetos grandes: Ao passar um objeto (
struct) como parâmetro ou retornar um objeto de uma função, o objeto inteiro é copiado. Copiar objetos grandes pode ser computacionalmente caro. Passe o objeto por referência (ponteiro) e evite esse gasto.
Evite Redundância
Ao redigir um código, é comum copiar e colar blocos de código quando precisa executar repetidamente as mesmas tarefas (ou tarefas semelhantes). Unificar esse código repetido em uma função simplifica o programa, além de garantir que apenas uma parte precise ser escrita, testada, depurada, atualizada e comentada.
- Decompor em uma função auxiliar: Extraia o código comum e mova para uma função auxiliar.
- Fatoração do código comum: Fatore o código comum de diferentes casos de um
if-elseouswitchencadeado.
if (opcao == 1) {
calcularTaxa();
imprimirComprovante();
} else {
calcularDesconto();
imprimirComprovante();
}if (opcao == 1) {
calcularTaxa();
} else {
calcularDesconto();
}
imprimirComprovante();Fontes
Este guia foi desenvolvido baseado nos seguintes materiais: