Qualquer um pode escrever código. Com poucos meses de experiência em programação, você pode escrever aplicações úteis. Fazê-las funcionar é fácil, mas escrever código da maneira correta requer mais trabalho do que fazer o código funcionar. |
A maioria dos programadores escrevem um 'código que funciona', mas não um 'bom código'. Escrever um 'bom código' é uma arte e você deve aprender e praticar sempre para escrever um 'bom código'.
Todo mundo pode ter diferentes definições para o termo 'bom código'. Na minha definição, as características de um bom código são:
A maioria dos desenvolvedores estão inclinados a escrever código para obter um melhor desempenho comprometendo a confiabilidade e facilidade de manutenção. Considerando o retorno do investimento a longo prazo (Return On Investment-ROI), eficiência e desempenho vem abaixo da confiabilidade e da facilidade de manutenção. Se o seu código não é confiável e de fácil manutenção, você (e sua empresa) estarão gastando muito tempo para identificar problemas, tentando entender o código ao longo da vida de sua aplicação.
Existem vários fatores que contribuem para 'escrever um bom código' e assim desenvolver aplicativos confiáveis e de fácil manutenção. Neste artigo vamos abordar alguns deles. Vamos começar com a padronização...
Por que padronizar a escrita do código ?
As convenções de nomenclatura, padrões de codificação e as melhores práticas descritas neste documento são compilados a partir de minha própria experiência e de diversos materiais e orientações da Microsoft e de outras fontes.
Não existe uma norma padrão que deve ser obrigatoriamente usada na padronização de código. Na verdade existem várias normas e nenhuma delas esta totalmente errada ou totalmente certa. Seguir alguma regra é melhor do que não seguir nenhuma, assim o importante é você adotar uma abordagem e segui-la.
Se individualmente a padronização já é difícil imagem em uma equipe de desenvolvedores trabalhando no mesmo projeto ?
Quando se tem uma equipe com diferentes habilidades e gostos é mais difícil obter uma padronização pois tem que se gastar um tempo para convencer todos a seguir os mesmos padrões.
Neste caso uma abordagem adequada seria definir um documento padrão a partir de um consenso comum e usar este documento como um modelo a ser seguido pela equipe. Após o início dos trabalhos o código seria revisado para verificar que todos estão seguindo as regras definidas.
Convenções de nomenclatura
Veremos a seguir algumas convenções de nomenclaturas usadas. O objetivo não é definir uma delas mas mostrar o que já foi e esta sendo usado e indicar a mais adequada.
Notação Húngara
A Notação húngara, criada por Charles Simonyi, visa a facilitar o reconhecimento do tipo de variável num programa. O nome foi dado a partir de uma brincadeira comum entre os primeiros a conhecer a notação que a achavam estranha, fazendo o seguinte comentário: "É tão estranho que até parece húngaro".(wikipéida : http://pt.wikipedia.org/wiki/Nota%C3%A7%C3%A3o_h%C3%BAngara )
Tipos de indicadores usados pela notação húngara:
Nome | Descrição | Exemplo:
|
||||||||
---|---|---|---|---|---|---|---|---|---|---|
s | String | |||||||||
sz | Aponta o primeiro caracter da terminação zero da string | |||||||||
st | Ponteiro da string, o primeiro byte é contado dos caracteres | |||||||||
h | handle (título) | |||||||||
msg | Message | |||||||||
fn | function (usada com pointer) | |||||||||
c | char (8 bits) | |||||||||
by | unsigned char (byte or uchar - 8 bits) | |||||||||
n | Int | |||||||||
b | Boolean (verdadeiro ou falso) | |||||||||
f | Flag (boolean, logical) | |||||||||
u | integer | |||||||||
w | Word | |||||||||
ch | Char, com texto ASCII | |||||||||
l | long int (32 bits) | |||||||||
dw | unsigned long int (dword - 32 bits) |
A notação húngara era muito usada na linguagem Visual Basic mas atualmente não se recomenda usar este padrão.
CamelCase
CamelCase é a denominação em inglês para a prática de escrever palavras compostas ou frases, onde a primeira letra da primeira palavra é iniciada com minúscula e unidas sem espaços. É um padrão largamente utilizado em diversas linguagens de programação, como Java, Ruby, PHP e Python, principalmente nas definições de Classes e Objetos. ( http://pt.wikipedia.org/wiki/CamelCase)
Ex: valorDoDesconto , nomeCompleto, valorDoImpostoSobreServico
PascalCase
Escreve palavras compostas ou frases montadas com palavras onde a primeira letra de cada palavra é iniciada com maiúscula. O padrão PascalCase é mais utilizado para nomear métodos e classes.
Ex: CalculaImpostoDeRenda(), ValorDoDesconto
Usando CamelCase e PascalCase
Poderiamos dizer que atualmente a grande maioria dos desenvolvedores das linguagens C# e VB .NET usa uma mistura de CamelCase com PascalCase.
Estrutura | Nomenclatura | Exemplo |
Classe | Pascal | PessoaJuridica |
Interface | I + Pascal | ICliente |
Método Público , Propriedades | Pascal | NomeCompleto() |
Método Privado | Camel Case | calculaDesconto() |
Variável Pública | Pascal | SobreNome |
Variável Privada | Camel Case | impostoPredial |
Constantes | Maiúsculas com sublinhado | VALOR_DESCONTO |
Sugestões para escrever um bom código
A seguir temos algumas sugestões para escrever um bom código começando com a padronização:
Padronização
1. Usar PascalCase para nomes de classes
2. Usar PascalCase para nomes de métodos
3. Usar CamelCase para variáveis e parâmetros de métodos
int
totalContador = 0;
void ExibirMensagem(string nome)
{
string mensagemCompleta = "Ola " +
nome;
}
4. Usar o prefixo 'I' com CamelCase para nomear interfaces : IEntidade
5. Não usar a notação húngara para nomear variáveis.
6. Utilize nomes significativos para nomear variáveis. Não use abreviações.
Ruim | Bom |
string nom | string nome |
int valSal | int valorSalario |
Dim ende as String | Dim endereco as String |
7. Não use nome de variáveis com um único caractere como i, n, c, s, t. Prefira usar nomes como : indice, temp, contador, etc. A exceção seria a utilização de i para os contadores em laços for/next.
8. Não utilize sublinhado para variáveis locais.Ex: _email (ruim)
9. Não utilize nomes de variáveis que são usadas como palavras chaves.
10. Utilize o prefixo apropriado para cada elemento de interface usado.
Ex: Principais controles e abreviações sugeridas:
Controle | Prefixo |
Label | lbl |
TextBox | txt |
DataGrid | dtg |
Button | btn |
Hyperlink | hlk |
DropDownlist | ddl |
ListBox | lst |
DataList | dtl |
CheckBox | chk |
RadioButton | rdo |
Image | img |
Panel | pnl |
Table | tbl |
Indentação e espaçamento
1. Use TAB para indentação. Não use espaços. Defina o tamanho do Tab como igual 4.
2. Comentários devem estar no mesmo nível que o código (usa o mesmo nível de recuo).
Bom | Ruim |
//Formato de uma mensagem e exibição string mensagemCompleta = "Olá" + nome; DateTime dataAtual = DateTime.Now; |
//Formato de uma mensagem e
exibição string mensagemCompleta = "Olá" + nome; DateTime dataAtual = DateTime.Now; |
3. Chaves { } devem estar no mesmo nível que o código fora as chaves. (Para linguagem C#)
Bom | Ruim |
if(string.IsNullOrEmpty(nome)) { Console.Write("Mensagem"); Console.WriteLine("\n"); Console.ReadLine(); } |
if(string.IsNullOrEmpty(nome))
{ Console.Write("Mensagem"); Console.WriteLine("\n"); Console.ReadLine(); } |
4. Use uma linha em branco para separar grupos lógicos de códigos:
Bom | Ruim |
bool Aviso ( string nome ) { string mensagemCompleta = "Ola " + nome; DateTime dataAtual = DateTime.Now; string mensagem = mensagemCompleta + ", a hora é : " + dataAtual.ToShortTimeString(); MessageBox.Show ( mensagem); if ( ... ) { // faça algo // ... return false; } return true; } |
bool Aviso ( string nome ) { string mensagemCompleta = "Ola " + nome; DateTime dataAtual = DateTime.Now; string mensagem = mensagemCompleta + ", a hora é : " + dataAtual.ToShortTimeString(); MessageBox.Show ( mensagem); if ( ... ) { // faça algo // ... return false; } return true; } |
5. Use um único espaço antes e depois de cada operador e colchetes.
Bom | Ruim |
if ( exibeValor == true ) { for ( int i = 0; i < 10; i++ ) { // } } |
if (exibeValor==true ) { for (int i=0;i<10;i++ ) { // } } |
6. Use o recurso #region para agrupar partes relacionadas de código.
Boas práticas de programação
1. Evite escrever métodos muito longos. Um método normalmente não deve ter mais 30 linhas de código. Se um método tem muitas linhas de código você deve considerar fazer uma refatoração.
2. Nome do método deve dizer o que ele faz. Se o nome do método é evidente, não há nenhuma necessidade de documentação que explique o que o método faz.
Bom | Ruim |
void CalculaValorImposto( int salario ) { // calcula imposto } |
//Este método calcula o valor do imposto void Calcular( int salario ) { // calcula imposto } |
3. Um método deve fazer apenas "uma única tarefa". Não combine mais de uma tarefa em um único método, mesmo que elas sejam simples. Um método deve ter uma única responsabilidade. (Princípio SRP)
Bom | Ruim |
void CalculaValorImposto ( int salario ) { // calcula imposto double imposto = salario * 0.25; } |
void Calcular ( int salario ) { // calcula imposto double imposto = salario * 0.25; // envia um email informando o cliente EnviaEmail(); } |
4. Sempre preste atenção para valores inesperados. Por exemplo, se você estiver usando um parâmetro com dois valores possíveis, nunca assuma que se um valor não for escolhido então a única possibilidade é o outro valor.
Bom | Ruim |
If ( tipoMembro == Registrado ) { //Registrado } else if ( tipoMembro == Convidado ) { //Convidado } else { // Tipo inesperado lança uma exceção // (Se um novo tipo for introduzido podemos // encontrar o problema com facilidade) throw new Exception (Tipo de membro inesperado + tipoMembro.ToString() + .) } |
If ( tipoMembro == Registrado ) { //Registrado } else { //Convidado } Se um novo tipo for incluido vai ocorrer o codigo esta tratando apenas dois tipos e não ocorre erro algum dificultando sua localização. |
5. Não defina números fixos no seu código. Use constantes em seu lugar. Declare constantes no início do arquivo e as utilize em seu código:
Bom | Ruim |
const int meses = 12; const int semanas = 52; const int dias = 365; const double diasPorSemana = (double) dias / (double) semanas; const double diasPorMes = (double) dias / (double) meses; |
const double diasPorSemana = (double) 365 / 52; const double diasPorMes = (double) 365 / 12; |
6. Converta strings para minúsculas ou maiúsculas antes de fazer comparações. Isto irá assegurar que a string sendo comparada irá corresponder, mesmo se ela for escrita de forma diferente. Ex: macoratti e Macoratti:
Bom | Ruim |
if (nome.ToLower () == "macoratti") { // ... } |
if (nome == "macoratti") { // ... } |
7. Use String.Empty ao invés de ""
Bom | Ruim |
if (nome == String.Empty { // ... } |
if (nome == "") { // ... } |
8. Evite usar de variáveis membros. Declare variáveis locais sempre que necessário e passe-as a outros métodos em vez de compartilhar uma variável de membro entre os métodos. Se você compartilhar uma variável de membro entre os métodos, será difícil rastrear quando e qual método foi alterado.
9. Use o recurso enum sempre que necessário. Não use números ou strings para indicar valores discretos.
Bom | Ruim |
enum TipoEmail { Html, PlainText, Attachment } void EnviaEmail(string mensagem, TipoEmail tipoDeEmail) { switch (tipoDeEmail) { case TipoEmail.Html: // manda email break; case TipoEmail.PlainText: // manda email break; case TipoEmail.Attachment: // manda email break; default: // manda email break; } } |
void EnviaEmail(string mensagem, TipoEmail tipoDeEmail) { switch (tipoDeEmail) { case "Html": // manda email break; case "PlainText": // manda email break; case "Attachment": // manda email break; default: // manda email break; } } |
10. Não crie variáveis membro como públicas ou protegidas. Mantenha-as como privadas e exponha as propriedades public/protected.
11. Não use código para acionar um evento de um botão para executar a mesma ação que você escreveu no evento click do botão. Em vez disso, chamar o mesmo método que é o evento clique do botão chama.
12. Nunca defina um caminho ou nome da unidade fixo no código. Obtenha o caminho do aplicativo via código e use o caminho relativo.
13. Nunca assuma que o seu código será executado a partir da unidade "C:". Alguns usuários podem executá-lo a partir da rede ou a partir de um "Z:".
14. No inicio da aplicação, faça algum tipo de "verificação" e garanta que todos os arquivos e dependências necessárias estão disponíveis nos locais previstos. Verifique se há conexão com o banco de dados. Envie uma mensagem amigável para o usuário em caso de problemas.
15. Se o arquivo de configuração necessário não for encontrado, a aplicação deve ser capaz de criar um arquivo com valores padrão.
16. Se um valor errado for encontrado no arquivo de configuração, a aplicação deve lançar um erro ou dar uma mensagem e também deve informar ao usuário quais são os valores corretos.
17. Mensagens de erro devem ajudar o usuário a resolver o problema. Nunca envie mensagens de erro como "Erro na aplicação", "Há um erro", etc. Prefira usar mensagens específicas como "Falha ao atualizar o banco de dados. Verifique se o ID de usuário e senha estão corretos."
18. Mostre mensagens curtas e amigáveis ao usuário. Mas registre o erro real (log de auditoria) com todas as informações possíveis. Isso vai ajudar muito no diagnóstico de problemas.
19. Não tenha mais de uma classe em um único arquivo. (Você pode criar diversas classes em um mesmo arquivo, mas isso dificulta a localização de erros.)
20. Evitar criar arquivos muito grandes. Se um único arquivo tem mais que 1000 linhas de código ele é um bom candidato a refatoração.
21. Sempre capture somente a exceção específica e não a genérica.
22. Quando você relançar uma exceção use a instrução throw sem especificar a exceção original. Dessa forma a pilha original é preservada.
catch { // trate a exceção throw; } |
23. Não escreva muito blocos try-catch muito grandes. Se necessário, escreva um try-catch separado para cada tarefa que você executa e coloque apenas a parte específica do código dentro do try-catch. Isso irá ajudá-lo a descobrir qual parte do código gera a exceção e você pode dar a mensagem de erro específica para o usuário.
24. Escreva suas próprias classes de exceção personalizada se necessário na sua aplicação. Não derive as suas exceções personalizadas da classe base SystemException, prefira herdar de de ApplicationException.
Arquitetura
1. Sempre use arquitetura em camadas.
2. Nunca acessar banco de dados a partir das páginas da interface do usuário. Sempre tenha uma camada de acesso a dados que executa todas as tarefas relacionadas com banco de dados. Isso irá ajudá-lo a apoiar ou migrar para outro banco de dados com mais facilidade.
3. Use try-catch em sua camada de dados para capturar todas as exceções de banco de dados. Este manipulador de exceção deve registrar todas as exceções do banco de dados. Os dados gravados devem incluir o nome do comando que está sendo executado, nome do procedimento armazenado, parâmetros, string de conexão usada, etc. Depois de gravar a exceção, ela pode ser lançada para que uma outra camada da aplicação possa tomar as medidas adequadas.
4. Separe sua aplicação em várias assemblies. Agrupe todas as classes de utilitários independentes em uma biblioteca de classe separada. Todos os seus arquivos relacionados com banco de dados podem estar em uma outra biblioteca de classes.
ASP .NET
1. Não use as variáveis ??de sessão em todo o código. Use variáveis ??de sessão apenas dentro das classes e exponha os métodos para acessar o valor armazenado nas variáveis ??de sessão. Uma classe pode acessar a sessão usando System.Web.HttpContext.Current.Session
2. Não guarde objetos grandes em sessão. Armazenar objetos grandes em sessão pode consumir muita memória do servidor, dependendo do número de usuários.
3. Sempre use folhas de estilo para controlar a aparência das páginas. Nunca especifique o nome e tamanho da fonte, em qualquer uma das páginas. Use a classe de estilo apropriada. Isso irá ajudá-lo a mudar a interface do usuário do seu aplicativo facilmente no futuro. Além disso, se você quiser apoiar a personalização da interface do usuário para cada cliente, é apenas uma questão de desenvolver uma outra folha de estilo para eles.
Comentários
1. Não escreva comentários para cada linha de código e cada variável declarada.
2. Use // ou /// para comentários. Evite usar / * ... * /
3. Escrever comentários sempre que necessário. Mas um bom código legível vai exigir muito menos comentários. Se todas as variáveis e nomes de métodos forem significativos, isso torna o código muito legível e não precisa de muitos comentários.
4. Não escreva comentários se o código for fácil de entender sem comentário. A desvantagem de ter muitos comentários é que, se você alterar o código e se esqueça de alterar o comentário, isso vai causar a mais confusão.
5. Se você tem que usar um pouco de lógica complexa ou pouco usual, por qualquer motivo, trate de documentá-lo muito bem com os comentários suficientes.
6. Se você inicializar uma variável numérica com um número especial diferente de 0, -1 etc., documento a razão para a escolha desse valor.
7. Realize a verificação ortográfica nos comentários e também certifique-se de que gramática e pontuação correta estão sendo usados.
Espero que as sugestões e dicas o ajudem a escrever um código mais robusto, confiável e sustentável.
Joã 3:16
Porque Deus amou o mundo de tal maneira que deu o seu Filho unigênito, para que todo aquele que nele crê não pereça, mas tenha a vida eterna.Joã 3:17
Porque Deus enviou o seu Filho ao mundo, não para que julgasse o mundo, mas para que o mundo fosse salvo por ele.Joã 3:18
Quem crê nele não é julgado; mas quem não crê, já está julgado; porquanto não crê no nome do unigênito Filho de Deus.Referências:
Padrões de Projeto - O modelo MVC - Model View ... - Macoratti.net
VB .NET - Usando Padrões de Projetos na prática - Macoratti.net
Os 7 Principios do desenvolvimento de software - Macoratti.net