Compartilhar via


Boas práticas em programação .Net

Durante meu percurso na carreira de TI, uma das minhas maiores preocupações era a de criar códigos com qualidade. E para mim qualidade envolvia tudo, deste atender aos requisitos de negócios, requisitos técnicos, performance e muitos outros. Com isto eu não poderia deixar de me preocupar com as melhores práticas de programação, pois meu objetivo principal era garantir a vida útil do sistema que eu estava escrevendo e também evitar me tornar “pai do sistema”.

É realmente péssimo ser “pai do sistema”, pois isto significa que só você (ou mesmo nem você) consegue entendê-lo, pois a lógica pode estar confusa ou complexa demais. O código pode estar mal documentado, o código pode não ser intuitivo, entre diversos outros motivos.

Ao longo dos anos aprendi com muitas pessoas o que devo e também o que não devo fazer. Vi também muitas pessoas fazerem coisas que nunca deveriam, pois se tornariam “pais do sistema” e nunca mais se livrariam de dar manutenção no código-fonte.

Eu sempre digo que é preciso ter em mente que programar com qualidade é mais do que criar sistemas que executam métodos e trazem o resultado esperado. Programar com qualidade é fazer isto, e também garantindo que o sistema foi escrito da melhor forma possível, que será simples efetuar manutenções e evoluções nele, que a performance será boa e que o sistema seja facilmente expansível e escalável.

Abaixo, através de minha vivência eu elenco os pontos que considero mais críticos para um código-fonte com boa qualidade.

Nota: Neste artigo estou tratando de programação .Net, e todos os exemplos são escritos em C#.

 

Lista de Boas práticas em programação .Net

 

1.     Declare classes utilizando Pascal case

 

      public static  class Logger
      {  
                    ...      
      }  

 

2.     Declare métodos utilizando Pascal case

 

      public static  void GravarLog(string textoLog)
      {  
                    ...      
      }  

 

3.      Declare propriedades utilizando Pascal case

 

      public string  MensagemLog
      {  
                     get { return this.mensagemLog; }  
                     set { this.mensagemLog = value;}  
      }  

4.     Utiliza a cláusula this

Utilize a cláusula this para atribuir o escopo da variável ou método, mesmo que pareça óbvio a você. Amanhã pode não ser táo óbvio.

 

      return this.MensagemLog;

5.     Para declaração de atributos e variáveis utilize Camel case

 

      int valorTotal = 0;

6.     Para declaração de parâmetros utilize Camel case

 

      void PreencherIdentificacao(string proximoNome)
      {  
                    ...      
      }  

**7.     Utilize Pascal Case para nomes de arquivos. **

 

      Logger.cs ou Logger.vb  

  

8.      Não use notação Húngara para nomes de variáveis

A notação Húngara consiste em um prefixo de 1 ou 2 caracteres seguidos ou não de underscore “_”.  

Esta prática era utilizada por programadores há anos atrás para identificação do tipo ou objetivo de uma classe, método ou atributo. Porém esta convenção não é mais considerada uma boa prática após as linguagens fortemente tipadas surgirem, como o .Net e Java.

//Obsoleto:
string m_Nome;
int nIdade;
object oNovoObjeto;
  
//Atual:
string nome;
int idade;
object novoObjeto;

 
  

9.     Não utilize “_” para variáveis locais.

Esta prática não é mais considerada uma boa prática recaindo no uso de notação Húngara. Declare a variável em Pascal case.

 

      //Recomendável  
      private int  valorTotal;
   
      //Evite:  
      private int  _ValorTotal; 

10.  Utilize o prefixo apropriado para elementos de UI.

Esta prática auxiliará a você e outros programadores a identificar dentre o resto das variáveis. Segue abaixo uma lista dos prefixos recomendados para uso.

Controle 

Prefixo

Form frm

Label

lbl

TextBox

txt

DataGrid

dtg

Button

btn

ImageButton

imb

Hyperlink

hlk

DropDownList 

ddl

ListBox

lst

DataList

dtl

Repeater 

rep 

Checkbox 

chk

CheckBoxList

cbl

RadioButton

rdo

RadioButtonList

rbl

Image

img

Panel

pnl

PlaceHolder

phd

Table

tbl

Validators

val

 

11.  Namespaces devem seguir um dos seguintes padrões

<Nome da Empresa>.<Nome do Produto>.<Macro módulo>
ou
<Nome da Empresa>.<Nome do Produto>.<Macro módulo>.<Micro módulo>

**12.  Utilize o prefixo “I” concatenado com Camel Case para interfaces **

public interface  ILogger
{
     ...
}

  

****13. Identação com Tab

Não utilize a barra de espaços para identar código e sim o TAB configurado com tamanho 4.  Comumente os TABs são configurados para tamanho 4.   

**14. ** Comentários devem ser feitos no mesmo nível de identação do código. **    **

//Recomendável:
// Concatena a variável com o texto para poder ser apresentado
string mensagemCompleta = "Olá " + nome;
  
// Apresenta o texto
MessageBox.Show(mensagemCompleta);
  
 
//Evite:
// Concatena a variável com o texto para poder ser apresentado
    string mensagemCompleta = "Olá " + nome;   
 
 // Apresenta o texto
    MessageBox.Show(mensagemCompleta);

**
15.  Utilize comentários com significados completos e claros**

Isto mantém o seu código com alta manutenalibidade.

// Recomendável
// Concatena a variável com o texto para poder ser apresentado
string mensagemCompleta = "Olá " + nome;
  
// Apresenta o texto para o usuário
MessageBox.Show(mensagemCompleta);
  
 
// Evite
// Pega o nome
string mensagemCompleta = "Olá " + nome;
  
// Mostra
MessageBox.Show(mensagemCompleta);

  

16.  Não escreva comentários para cada linha de código.

Atenha-se aos pontos do código em que você percebe que um comentário aumentará o entendimento do código. Isto facilitará que outros programadores evoluam ou efetuem manutenção no sistema.

 

17.  Utilize // ou /// para comentários, evitando /* … */

 

18.  Escreva comentários sempre que necessário

Porém atenha-se ao fato que código claro e bem formado necessita de menos comentários.

19.  Não escreva comentários onde a leitura do próprio código se explique.

Porém sempre considere que o óbvio para você que criou o código pode não ser tão óbvio assim. Então verifique imparcialmente se o comentário é ou não necessário.

20.  Verifique a ortografia e gramática de seus comentários.

Lembre-se, nosso nível de qualidade e cultura é muitas vezes medido pela qualidade da escrita.

21.  Há um equilíbrio de quantidade de comentário.

Muito comentário deixa seu código confuso e deselegante. Pouco ou nenhum comentário acarreta no mesmo.

22.  Código complexo deve ser comentado.

Se você está utilizando alguma lógica complexa ou estranha deixe muito bem documentado. Assim outros programadores entendam o motivador e não alterem ou questionem desnecessariamente.

 

23.  Não utilize apenas um caractere para definir variáveis.

Este hábito é muito comum em declaração de contadores, como: i, j, k, n, s etc.

Utilize nomes como: index, iCount, column, row

//Recomendável
int iCount;
int index;
string nomeCliente;
 
 
//Evite
int i;
string txt;

24.  Crie nomes com significado

Utilize palavras descritivas para criar variáveis e métodos. Não abrevie.

//Recomenável
string endereco;
int salario;
int iCount;
  
 
//Evite
string end;
int sal;
int i;

25.  Não crie nome de variáveis que lembre nomes de comandos ou palavras chaves.

   Esta prática irá complicar a sua vida e a de seus colegas.

bool isBool;
string myClass;

**
26.  Utilize os tipos de dados específicos do C# ou VB.Net**

É muito prático utilizar os tipos comuns em ambas as linguagens, porém este vício acarreta em problemas futuros a você mesmo. Ao invés dos tipos definidos no namespace System.

//Recomendável
int idade;
string nome;
object Pedido;
 
 
//Evite
Int32 idade;
String nome;
Object Pedido;

Reforçando o dito acima, alguns desenvolvedores preferem utilizar os tipos comuns em System para não ter de pensar em tipos de dados diferentes entre C# e VB.Net, porém isto pode trazer más interpretações ou problemas em se programando mais de uma linguagem.

27.  Variáveis Booleans são sempre verdadeiras ou falsas

Para variáveis do tipo boolean que por natureza representam uma condição verdade, sempre coloque o prefixo “is” ou outro prefixo que traga o significado do uso da variável.

Em alguns casos podemos utilizar palavras de nosso idioma para deixar claro o esperado do booleano, se true ou false é o adequado.  

private bool  isTerminado; 
private bool  haveRestricao; 
private bool  possuiRestricao;

     

28.  Use enum sempre que necessário.

Não utilize números ou textos para representar valores discretos.

//Recomendável
//Enumerador de tipos de emails
enum TipoEmail
{
    Html = 0,
    TextoPuro = 1
}
  
/// <summary>
void SendMail (string message, string tipoEmail)
{
    switch (tipoEmail)
    {
        case TipoEmail.Html:
        {
            // ...
            break;
        }
        case TipoEmail.TextoPuro:
        {
             // ...
             break;
        }
        default:
        {
            // Algum tratamento
            break;
        }             
    }
}
  
//Evite
/// <summary>
void SendMail (string message, string tipoEmail)
{
    switch (tipoEmail)
    {
        case "Html":
        {
             // ...
             break;
        }
        case "TextoPuro":
        {
             // ...
             break;
        }
        default:
        {
           // Algum tratamento
           break;
        }             
    }
  }

29.  Use StringBuilder ao invés de string

Quando você for manipular strings em loops ou sabe que irá concatenar a string mais de 3 vezes utilize o objeto StringBuilder para evitar fragmentação e replicação de memória.

//Recomendável
/// <summary>
public string  ComposeMessage(string[] lines)
{
    StringBuilder message = new  StringBuilder();
    for (int iCount = 0; iCount < lines.Length; iCount++)
    {
        message.Append(lines[iCount]);
    }
    return message.ToString();
 } 
  
  
 //Evite
/// <summary>
public string  ComposeMessage(string[] lines)
{
    string message = string.Empty;
    for (int iCount = 0; iCount < lines.Length; iCount++)
    {
        message += lines[iCount];
    }
    return message;
 }

30.  Declare variáveis o mais próximo possível de onde você irá utilizá-las.

Uma prática muito comum é declarar todas as variáveis no começo do método. Isto parece ser uma boa prática, mas torna confuso entender o que tantas variáveis fazem no método. Ao contrário disto, declare a variável próximo ao momento que uso, pois além de ficar claro o uso, você torna o seu escopo o mais local possível, mesmo dentro do próprio método.

31.  Nunca declare mais de uma variável em uma mesma linha

No início de aprendizado de programação muitos de nós aprendemos que é possível declarar mais de uma variável na mesma linha. Esta prática tornará seu código extremamente confuso de se ler, manter ou evoluir.

 

32.  Mantenha variáveis, propriedades e métodos privados antes de itens públicos.

Para fins organizacionais, o que é privado é apresentado na classe antes do que é public. Assim é mais fácil efetuar manutenção do sistema.

33.  Evite utilizar variáveis globais

Declare variáveis locais e sempre passe-as a outros métodos ou classes por valor ou referência, dependendo do caso.

Se você compartilhar uma variável como global será extremamente difícil rastrear qual é o valor dela entre os métodos e classes.

 

34.  Não crie variáveis public ou protected .

Crie-as privadas e exponha-as através de propriedades public ou protected.

//Exemplo
/// <summary>
private string codigoEmpresa;
 
/// <summary>
public string CodigoEmpresa
{
    get { return this.codigoEmpresa; }
    set { this.codigoEmpresa = value; }
}

                               

35.  Não use variáveis de sessão através do código.

Utilize variáveis de sessão apenas dentro das classes e exponha métodos que acessem o valor gravado através de System.Web.HttpContext.Current.Session

 

36.  Deve existir só UMA linha em branco entre cada método em uma classe.

O excesso de linhas em branco entre métodos é extremamente mal visto tanto para organização de código quanto para auditorias de produtividade por linhas de código.

 

****37. ** Utilize uma linha em branco para separar grupos de lógica de código. **

É de boa prática separar blocos de lógica de códigos para que a leitura dos métodos fiquem mais simples e de fácil entendimento.

//Certo 
private bool apresentacao (string nome) 
{ 
     string mensagem = "Olá  " + nome; 
     DateTime currentTime = DateTime.Now; 
 
    string message = mensagem + ". Esta é sua visita número “ + iCount;

     if ( ... ) 
     {  
    return false;
     }  
     return true;
}
 
 
//Errado
private bool apresentacao (string nome) 
{ 
     string mensagem = "Olá  " + nome; 
     DateTime currentTime = DateTime.Now; 
     string message = mensagem + ". Esta é sua visita número “ + iCount;
     if ( ... ) 
     {     
       return false; 
     }  
     return true;
}

38.  Não utilize acentuação em nenhuma parte do programa

Exceto comentários, caso seja inerente ao idioma em que está programando

// Errado:
void PreencherIdentificação(string próximoNome)
{
     ...
}
 
// Certo:
void PreencherIdentificacao(string proximoNome)
{
     ...
}

39.  Sempre coloque um espaço antes e depois de qualquer tipo de operador.

//Certo
if (isExistente == true)
{ 
     ...                                    
} 
 
 
//Errado 
if(isExistente==true) 
{ 
     ...
}

 

40.  Use #region para agrupar partes relacionadas de um código

O uso de #region torna seu código muito mais fácil de ser programado, evoluído ou corrigido. Porém EVITE o uso excessivo de regions, exemplo, uma region para cada método ou evento. 

Se necessário crie #region específicas para lógicas complexas ou para um contexto específico

41.  Nomes de métodos devem dizer o que vão fazer

//Certo
private void GravarPedido (Pedido pedido)
{
     // Lógica para gravar os pedidos.
}
 
  
//Errado
// Este método irá gravar o pedido.
private void Gravar(Pedido ped)
{
     // Lógica para gravar os pedidos.
}

   

42.  Evite escrever métodos muito longos.

Um método possui em média entre 20 e 50 linhas. Se o método possuir mais de 50 linhas considere refatorá-lo para que possua maior reaproveitamento de código e para que fique legível.

 

43.  Um método deve efetuar apenas uma tarefa.

Não combine mais de um objetivo em um método, mesmo que as tarefas sejam pequenas.

//Certo
...
//Obtém o endereço de email de acordo com o usuário AD
email.Address = ObterDadosEmail(usuario);
 
//Obtém os dados do email
email = PreencheDadosEmail(tipoEmail);
 
//Envia o email
EnviarEmail(Email);       
 
/// <summary>
private string ObterDadosEmail(string usuario)
{
  // Lógica para retornar o endereço do e-mail
}
 
/// <summary>
private Email PreencheDadosEmail(TipoEmail tipoEmail)
{
 // Lógica para retornar os dados do Email (Subject, Body, etc)
}
 
/// <summary>
private void EnviarEmail(Email email)
{
 // Lógica para enviar email
}
 
//Errado
// Aqui obtemos os dados do e-mail, montamos o texto e enviamos ao servidor SMTP
ObterEmail(string usuario);
 
public void ObterEmail(string usuario)
{
     // Primeira tarefa
     // Obter os dados do email
 
     // Segunda tarefa
     // Montar o texto do email
 
     // Terceira tarefa
     // Enviar o email
}

    

44.  Sempre declare a visibilidade de classes e métodos

public class SecurityInfo
{ 
    ...  
}

   

****45.  Chaves “{ }” sempre devem ser colocadas em uma linha separada e não na mesma linha como ocorre muito em if, for etc. ** **



      Certo:  
      if ( ... )
      {  
                      // Tomar uma ação      
      }  
   
      Errado:   
      if ( ... ) {
                      // Tomar uma ação      
      }  

**46. ** O nome do arquivo deve ser o mesmo do nome da classe.

public static class Logger 
{
    ...  
} 
 
Nome do arquivo: Logger.cs ou Logger.vb

47.  Sempre verifique por valores inesperados.

Se você estiver esperando um parâmetro com somente dois possíveis tipos de resultados, nunca assuma que sempre virão apenas estes dois, coloque uma validação para resultados inesperados. Importante: Vale para qualquer quantidade de parâmetros, o objetivo é fechar o escopo do que é esperado.



      //Certo  
      if    (tipoPessoa == Enumerators.TipoCliente.PessoaFisica)  
      {  
                   // Lógica para pessoa física      
      }  
      else if  (tipoPessoa == Enumerators.TipoCliente.PessoaJuridica)
      {  
                   // Lógica para pessoa jurídica      
      }  
      else  
      {  
                    // Qualquer outro resultado não é válido e uma exceção deve ser disparada      
                    throw new  Exception('Valor não esperado'  + tipoPessoa + '.');  
      }  
              
      //Errado  
      if    (tipoPessoa == Enumerators.TipoCliente.PessoaFisica)  
      {  
                   // Lógica para pessoa física      
      }  
      else if  (tipoPessoa == Enumerators.TipoCliente.PessoaJuridica)
      {  
                   // Lógica para pessoa jurídica      
      }  
      //Desta forma a lógica acima será validada e qualquer valor diferente do  
      // esperado irá sair da lógica sem o conhecimento do programador  

48.  Não coloque hardcode, utilize constantes ou propriedades.

O uso de código hardcoded é extremamente condenável. O uso de constante é uma possibilidade de facilitar a manutenção, mas ainda pode ser visto como harcoded dependendo do nível de maturidade esperado.

Se possível trabalhe com propriedades provindas de um arquivo de configuração ou de xml. Assim um valor poderá ser alterado sem a necessidade de recompilação de código.

 

49.  Nunca escreva paths, nomes de arquivos, urls, uri, etc hardcoded.

Sempre obtenha um path programaticamente ou de um arquivo de configuração, pois do contrário serão também considerados hardcoded com o agravante de ser a respeito de caminhos para alcançar arquivos ou servidores.

 

50.  Nunca assuma que seu código irá rodar no drive C

Nada impede que o código rode em uma máquina no drive F. Use caminhos lógicos e não físicos.

 

51.  Converta strings para caixa-baixa (ou alta) antes de efetuar uma comparação.

Isto irá garantir que o que você está comparando não está sujeito a erro de digitação entre maiúsculas e minúsculas.

Nota: Esta regra não se aplica aos poucos e raros sistemas em que uma mesma palavra escrita com casing diferente pode ser utilizada.

 



      //Exemplo:  
      if    (nome.ToLower() ==     'José'    )  
      {  
                      // ...      
      }  

**
52.  O event handler não deve conter código para executar uma ação**

Eventos servem para disparar chamadas a objetivos e não para deixar todo o objetivo, ou seja, a lógica no evento. Isto acabará com o reaproveitamento de código, pois mais de um evento pode chamar o mesmo método.

Considere invocar um método que execute o que você deseja no evento.

 

53.  Execução de eventos pré-programados

Não execute programaticamente a ação de click de um botão que já esteja disponível no evento click. Ao invés disto invoque o mesmo método que seria invocado pelo evento do clique.

 

54.  Evite arquivos muito grandes.

Se um arquivo possuir mais de 1000 linhas de código este com certeza é um grande candidato a refatoramento e com isto pode ser dividido em mais de um arquivo, o que geralmente significa mais de uma classe.

  

55.  Evite linhas de código com muitas funções.

Esta prática não denota conhecimento de código complexo e ainda torna o código difícil de ler, atualizar, efetuar manutenção ou mesmo de detectar erros.



      //Ex:  
      return int  resultado = Convert.toInt32(GetResult(variavel), fatorPonderacao);     

Aqui vemos um retorno de uma variável que será inicializada e populada pelo retorno de um método o qual ainda precisa de dois parâmetros, e por fim precisa ser convertido para o tipo de dados. Um erro ocorrendo nesta linha pode ser provocado por diversos motivos. Considere separar a lógica para se tornar mais clara.

 

56.  Não escreva mais de uma classe por arquivo

Salvo os raros momentos em que este uso é justificado evite criar mais de uma classe por arquivo. Na dúvida separe uma classe por arquivo.

 

57.  Evite métodos e propriedades públicas

A não ser que seja estritamente necessário expô-las. Utilize internal caso o método ou propriedade deve ser acessível, porém apenas dentro do mesmo namespace.

 

58.  Evite passar muitos parâmetros para um método.

Se você possui um método que recebe mais de 4 parâmetros, tais parâmetros são fortes candidatos a se tornarem uma classe ou uma struct.

 

59.  Organize logicamente seus arquivos/classes na Solution dentro de pastas.

Normalmente em grandes projetos podemos chegar a 10 pastas principais com até 10 pastas secundárias, e até 5 pastas terciárias. Se for necessário criar mais folders, considere criar outro namespace para isto.

 

60.  Crie classes organizadas que possam exibir logs de acordo com configurações.

Sua classe idealmente deve ser capaz de obedecer a configuração do log. Por exemplo, se a configuração de log está marcada para error, você  logará apenas mensagens de erro. Já se estiver marcada para trace, você logará todas as mensagens errors, warning ou  traces.

 

61.  Feche conexões abertas antes de sair do método.

Salvo alguma lógica que necessite manter a conexão aberta, se você está abrindo conexões com bancos de dados, sockets, file streams, etc sempre as feche no bloco finally.

 

62.  Sempre utilize arquitetura multi-camandas

Trabalhe sempre com arquitetura de 3 ou mais camadas para garantir o devido isolamento de acessos e responsabilidade.

63.  Nunca acesse uma base de dados a partir de páginas UI.

Esta prática vai de oposto a programação em multi-camadas e é extremamente condenável.

64.  Preencha o aquivo AssemblyInfo

O Arquivo AssemblyInfo é importante para sistemas de longa média ou longa vida útil, além de ser uma boa prática manter as informações como versão, nome da empresa, descrição, copyright, etc.

 

65.  Apresente uma mensagem de erro amigável

Usuários não gostam e nem estão preparados para mensagens de erros complexas. Porém é recomendado que a tela de erro apresente também a mensagem de erro técnica, ou que esta esteja disponível em arquivos de Log.

O recomendado é que as duas ações sejam efetuadas.

 

66.  Utilize try-catch em sua camada de dados

Em exceções de banco de dados o handler desta exceção deve gravar todas as exceções de base de dados, e o nível de detalhes deve incluir qual comando ou procedure foi executado, com quais parâmetros, conexão utilizada e etc.

 

67.  Não grave objetos muito grandes em sessão.

Isto pode comprometer a memória do servidor.

 

68.  Sempre utilize uma folha de estilos para controlar a aparência de suas páginas.

Nunca especifique tamanho de fonte, cor, etc diretamente em uma página web. A manutenção de um sistema desta forma é muito complexa e fadada a erros.

 

69.  Ao inicializar uma variável com um número especial deixe muito claro as razões.

Magic Numbers são na maioria das vezes evitáveis. Desta forma, caso você precise criar um magic number e este não possa ser configurável, deixe muito claro quais foram as razões de ter utilizado esta prática pouco ortodoxa.

 

70.  Nunca crie um “Catch pelado”, ou seja, um catch que não faça nada.

Se você esconder a exceção você nunca vai sabe quando ou se algo errado ocorreu. Você estará indo contra si mesmo.

 

71.  Antes de capturar exceções genéricas tenha certeza que cobriu as exceções específicas.

E se necessário crie exceções específicas para sua necessidade. Mas verifique se há a necessidade de haver uma exceção específica criada ou se é mais uma vontade. Exceções criadas geram maior atenção na criação e na manutenção.

    

**72.  Não capture e trate as exceções em todos os seus métodos. **

Deixe a responsabilidade com a camada mais alta que chamou o método. Exceto para casos específicos como exceções de banco de dados.

 

73.  Quando você for disparar uma exceção para a camada ou método chamador, utilize throw sem nenhuma variável inclusa

Desta forma o call stack original será preservado para o devido tratamento.

 

74.  Não crie try-catch para 100% de seus métodos.

Coloque try-catch apenas onde há a possibilidade de ocorrer um erro.

 

75.  Não crie blocos try-catch muito grandes.

Se necessário crie blocos separados de try-catch de acordo com o grupo de funcionalidade que está trabalhando. Assim o tratamento do erro será mais assertivo e a manutenção mais simples.

 

76.  Se for criar exceções próprias herde de ApplicationException.

Muitos programadores quando criam exceções próprias herdam de SystemException. Mantenha o escopo mais próximo herdando de ApplicationException.

 

77.  Mensagens de erro existem para ajudar a resolver um problema;

Tendo este pensamento em mente não retorne mensagens como: "Erro na aplicação", "Ocorreu um erro", etc.

Forneça dados específicos e tratados do erro para que o mesmo possa ser resolvido mais rapidamente. Ex.: "Falha de autenticação ao se comunicar com o Banco de dados, por favor, forneça o usuário e senha corretos".

 

78.  Na inicialização de uma aplicação faça um auto-diagnóstico.

Para garantir que todas as dependências requeridas estão disponíveis, sejam arquivos, acessos, bancos de dados etc. Esta é uma excelente prática, pois mesmo quando o sistema estiver em produção será mais fácil identificar algum problema de dependência sistêmica.