Alura > Cursos de Programação > Cursos de .NET > Conteúdos de .NET > Primeiras aulas do curso C#: aplique boas práticas de refatoração e torne seu código mais legível

C#: aplique boas práticas de refatoração e torne seu código mais legível

Melhorando a legibilidade do código - Apresentação

André: Olá! Tudo bom? Boas-vindas ao primeiro curso da formação de boas práticas com C# da Alura. Meu nome é André Bessa e irei te acompanhar ao longo dessa jornada!

Audiodescrição: André é um homem negro de rosto arredondado, com barba curta preta, cabelo curto preto, e olhos pretos. Ele veste uma camisa preta e está em um ambiente iluminado em azul. Ao fundo, há uma prateleira branca com alguns livros e decorações.

Daniel: Eu sou o Daniel Portugal, e vou acompanhar você e o André nesse curso!

Audiodescrição: Daniel é um homem branco de cabelo preto, barba preta, e olhos pretos. Ele veste uma camisa preta, usa óculos de armação retangular preta, e está em frente a uma parede iluminada em azul-escuro.

Para quem é este curso?

André: Daniel, para quem é o conteúdo que iremos apresentar neste curso?

Daniel: Este curso é para pessoas que já possuem conhecimento em C#, orientação a objetos, e testes automatizados, e querem aplicar boas práticas para deixar seus projetos de código mais legíveis, menos repetitivos, mais concisos, e mais bonitos.

O que vamos aprender?

André, o que iremos aprender neste curso especificamente?

André: Neste curso, vamos aplicar boas práticas e refatorações. Com isso, iremos aumentar a legibilidade do nosso código, além de identificar algumas situações em que podemos aplicar as refatorações, conhecer técnicas e estratégias para deixar nosso código mais conciso, e diagnosticar códigos problemáticos onde podemos aplicar boas práticas.

Daniel: Você aprenderá tudo isso de forma prática, em um projeto específico onde trabalharemos esses conhecimentos.

Qual será o projeto?

André, qual é o projeto em que iremos trabalhar?

André: Nosso projeto é a AdoPet. Fomos contratados e montamos uma equipe para desenvolver e dar manutenção em um sistema para importação de pets a partir de um arquivo. Este será o projeto em que trabalharemos ao longo do curso!

Daniel: Bacana, André! Além dos vídeos, teremos várias atividades práticas para você aplicar os conhecimentos obtidos no decorrer dos seus estudos.

Você também poderá contar com o apoio do fórum e da comunidade no Discord.

Vamos estudar?

Melhorando a legibilidade do código - Apresentação do ambiente

André: Olá! Vamos conhecer melhor o ambiente em que trabalharemos?

Apresentando o ambiente

Eu, você e o Daniel somos pessoas desenvolvedoras do projeto AdoPet. Esse projeto é constituído por um site que permite a visualização de pets para serem adotados, e a função dele é vincular a pessoa interessada em adotar um pet e determinado pet. No site, existe um formulário padrão para realizar cadastros como pessoas interessadas na adoção de um pet.

Nosso objetivo é ler um arquivo com informações de pets e guardá-las na base de dados da AdoPet. No site, conforme mencionado anteriormente, é necessário cadastrar manualmente a pessoa interessada. Da mesma maneira, precisamos cadastrar os pets. Sendo assim, teremos um esforço para fazer o cadastro de diversos pets diferentes.

Existe uma demanda que chegou para a equipe de desenvolvimento da AdoPet: automatizar esse processo. Por isso, leremos um arquivo para cadastrar de uma só vez vários pets.

Para alcançar o objetivo, teremos um projeto que irá nos permitir digitar comandos de importação para o arquivo. Esse projeto, que será do tipo console, irá ler o arquivo e importá-lo na base de dados da AdoPet.

Porém, essa base de dados é controlada por outra aplicação, em uma API que irá manter a base de dados. Para consumir essa API, criaremos uma instância de HttpClient, que abordaremos no decorrer do curso.

Então, teremos duas aplicações: a console e a API.

Nesse curso, focaremos nossa atenção no projeto console, verificando o que podemos melhorar no processo.

Daniel: Vamos recapitular e tentar entender melhor o problema que tentaremos solucionar. Estamos entrando em uma equipe que já tem um projeto em desenvolvimento, um site, e uma base de dados. Porém, um grande problema é a questão de cadastrar diversos pets simultaneamente.

Suponha que recebemos um grupo de cachorros que precisamos cadastrar na base de dados para disponibilizar para uma região específica do Brasil. Nesse caso, teríamos que acessar o formulário e preencher os campos para registrar cada um dos pets.

A partir desse cenário, criou-se uma solução para importar pets em lote, a qual não está na web, mas sim em um programa que roda no terminal. A solução nos permitirá digitar um comando para ler o arquivo, e a partir disso, ela irá traduzir cada informação para um pet específico e consumir outra aplicação, a API da AdoPet.

Podemos acessar o Visual Studio, IDE onde iremos trabalhar durante o curso, para entender como essa solução está configurada.

André: Vamos lá, Daniel! Com o Visual Studio aberto, temos uma solução composta por dois projetos: o projeto da API, que irá manter nossa base de dados; e o projeto console, que irá consumir essa API.

É importante reforçar o seguinte: para a aplicação console se comunicar e consumir a API, primeiramente, a API precisa estar rodando. Como fazer isso?

Na aba "Gerenciador de Soluções" à direita da interface, clicamos com o botão direito sobre o projeto Alura.Adopet.API e selecionamos a penúltima opção "Abrir no Terminal".

Para rodar a API, utilizaremos o comando CLI do .NET, conforme exibido abaixo:

dotnet run 

Feito isso, a solução será compilada e a API será iniciada em uma porta específica.

Daniel: Podemos executar esse projeto de outras maneiras, por exemplo, clicando no ícone de play na barra de menu superior da interface. Você já deve ter feito ou visto isso em outros cursos da plataforma.

Optamos por fazer da forma que o André demonstrou porque, assim, a API será mantida em execução no ar. Queremos deixá-la no terminal do Visual Studio para simular que a API está disponível.

Por isso, executamos a API dessa maneira específica para este curso.

André: Perfeito, Daniel! Agora vamos testar nosso projeto console. Da mesma maneira, vamos clicar com o botão direito do mouse sobre o projeto Alura.Adopet.Console e selecionar a penúltima opção "Abrir no Terminal".

Feito isso, utilizaremos a mesma linha de comando para rodar a aplicação:

dotnet run

Daniel: Note que temos o mesmo comando (dotnet run) para ambas as execuções. Talvez você já tenha utilizado esse tipo comando para outras funções.

Por exemplo: para compilar o projeto, usamos o comando dotnet build; para executar testes automatizados, usamos o comando dotnet test.

O programa console da AdoPet foi pensado exatamente como o programa .NET, que chamamos de CLI, um programa que executa vários comandos.

André, queremos saber o seguinte: o programa console especificamente deve ter diversos comandos; existe um comando help que nos ajude a listar os comandos existentes?

André: Sim, existe! O comando é o seguinte:

dotnet run help

Ao executá-lo, será exibida uma lista com todos os comandos disponíveis no console da AdoPet.

Retorno do comando:

Adopet (1.0) - Aplicativo de linha de comando (CLI)
Realiza a importação em lote de um arquivo de pets.
Comandos possíveis:
 adopet help comando que exibe informações da ajuda.
 adopet help <NOME_COMANDO> para acessar a ajuda de um comando específico.
 adopet import <ARQUIVO> comando que realiza a importação do arquivo de pets.
 adopet show <ARQUIVO> comando que exibe no terminal o conteúdo do arquivo importado.
 adopet list comando que exibe no terminal o conteúdo cadastrado na base de dados da AdoPet.

Além do próprio help, conseguimos executar o help com um comando específico, temos o comando import para importar um arquivo, o show que irá ler o conteúdo do arquivo, e o list que permitirá listar informações disponíveis já cadastradas na base de dados da API.

Daniel: Agora que já conhecemos os comandos que estão no projeto Alura.Adopet.Console, podemos analisar o código que implementa esses comandos e, a partir disso, entender o que podemos fazer, quais boas práticas podemos aplicar, e quais princípios podemos utilizar para evoluir o projeto e deixá-lo ainda mais interessante.

Começaremos a fazer isso no próximo vídeo!

André: Até lá, pessoal!

Melhorando a legibilidade do código - Nomes significativos

André: Vamos começar a olhar para o nosso código e entender o que podemos melhorar. A princípio, no arquivo Program.cs, já conseguimos identificar um ponto de melhoria: o código tem muitos comentários.

Temos, por exemplo, o comentário abaixo:

// args[0] é o comando a ser executado pelo programa
switch (args[0].Trim())

// código omitido

Da mesma forma, temos a explicação do args[1] da linha de código 17:

// args[1] é o caminho do arquivo a ser importado
using (StreamReader sr = new StreamReader(args[1]))

// código omitido

Esses indicativos não são muito interessantes para o nosso código.

Imagine a seguinte situação: outra pessoa desenvolvedora passará a colaborar com o projeto Alura.Adopet.Console. Será um pouco difícil para ela entender o que significa args[0] e args[1]. Nesse caso, podemos fazer algumas melhorias.

Uma das maneiras é criar nomes significativos, trabalhando com variáveis.

Nomes significativos

Com isso em mente, em vez de passar args[0] para o switch na linha 11, que tal criarmos a variável que representa esse parâmetro?

Como podemos observar no código, o switch recebe a string referente ao comando a ser executado, que entrará em cada case para executar o código. Então, vamos criar uma variável chamada comando, que irá receber o que está contido no switch logo abaixo.

Usamos o atalho "Ctrl + X" para recortar o conteúdo de uma linha e colar em outra.

Feito isso, passaremos para o switch a string comando que acabamos de criar.

string comando = args[0].Trim();
switch (comando)

Dessa forma, nosso código já fica mais legível e significativo.

Daniel: Isso mesmo, André. Praticamos nossas primeiras boas práticas, trabalhando em cima de um código que explica um código. Essa é a primeira orientação:

Não depender de comentários para explicar o código.

O comentário ficará fixo, e dificilmente iremos alterá-lo ao fazer ajustes no código. Assim, teremos comentários desatualizados em relação ao código.

A segunda orientação é criar variáveis que representam valores, então:

Usar variáveis significativas.

André: Perfeito, Daniel. Agora podemos remover o comentário da linha 10, pois já temos uma variável que representa o args[0].

Trecho a ser removido:

// args[0] é o comando a ser executado pelo programa

Na linha 18, conforme visto anteriormente, temos o args[1] que representa o caminho do arquivo a ser importado. Nesse caso, poderíamos criar uma string chamada caminhoDoArquivo. O que você acha, Daniel?

Daniel: Talvez não seja tão interessante dessa forma, André. Existe uma documentação da Microsoft que é um guia de nomenclatura. Ele indica que nomes de variáveis precisam ser o máximo possível legíveis e contextualizados.

No comentário, é dito que args[1] é o caminho do arquivo para importação, então não é um caminho de arquivo qualquer. Nesse caso, seria interessante colocar um nome de variável um pouco maior, porém, mais significativo.

André: Então, vamos declarar a variável como caminhoDoArquivoDeImportacao. Ela será igual a args[1]. Em seguida, passaremos a variável como argumento da função StreamReader().

string caminhoDoArquivoDeImportacao = args[1];
using (StreamReader sr = new StreamReader(caminhoDoArquivoDeImportacao))

Feito isso, podemos remover o comentário da linha 17.

Trecho a ser removido:

// args[1] é o caminho do arquivo a ser importado

Nas linhas 21 e 23, também temos comentários:

// separa linha usando ponto e vírgula
string[] propriedades = sr.ReadLine().Split(';');
// cria objeto Pet a partir da separação
Pet pet = new Pet(Guid.Parse(propriedades[0]),
  propriedades[1],
  TipoPet.Cachorro
);

Vamos mantê-los por enquanto, e depois trabalharemos isso melhor no decorrer do curso.

Mais adiante no código, na linha 62, temos novamente o args[1], mas o contexto é diferente do que vimos anteriormente, pois agora ele se refere a um comando.

Daniel: Exatamente. Isso mostra o que estamos reforçando ao longo do vídeo, sobre ter variáveis que representem valores que dependem do contexto. args[1] é um valor que tem um contexto específico na linha 18, no comando import, e outro valor diferente na linha 62.

Então, a pessoa que chega no projeto e vê args[1], pode não entender exatamente o que ele significa, se é o caminho do arquivo a ser importado ou o comando a ser documentado.

Sendo assim, vale a pena criar uma variável também para esse caso.

André: Criaremos uma variável chamada comandoASerExibido, um nome bastante significativo. Ela será igual a args[1], que nesse contexto é um parâmetro lido de forma diferente.

Na sequência, vamos substituir args[1] na linha 63 pela variável criada.

string comandoASerExibido = args[1];
if (comandoASerExibido.Equals("import"))

Também faremos essa substituição de args[1] pela variável comandoASerExibido nas linhas de código 68 e 73, conforme exibido abaixo:

if (comandoASerExibido.Equals("show"))
if (comandoASerExibido.Equals("list"))

Abaixo, a partir da linha 79, temos um case "show" contendo o args[1] em um novo contexto.

case "show":
    // args[1] é o caminho do arquivo a ser exibido
    using (StreamReader sr = new StreamReader(args[1]))

// código omitido

Conforme indicado no próprio comentário, ele também representa o caminho do arquivo, porém o arquivo a ser exibido. Então, precisamos criar uma nova variável. O nome novamente será bastante significativo (caminhoDoArquivoASerExibido), e a variável será igual a args[1].

Feito isso, vamos passar como parâmetro na linha 82 a variável criada.

string caminhoDoArquivoASerExibido = args[1];
using (StreamReader sr = new StreamReader(args[1]))

Agora podemos remover o comentário.

Trecho a ser removido:

// args[1] é o caminho do arquivo a ser exibido

Resolvemos o case "show", tornando-o mais legível. O case "list" abaixo já está legível, então não iremos fazer ajustes nesse bloco.

Daniel: Isso mesmo, André. Vamos recapitular o que fizemos?

Em qualquer projeto que estivermos trabalhando, primeiro precisamos ler o código e entendê-lo. Para isso, encontraremos comentários, mas é uma boa prática não depender deles. Então, substituímos os comentários por variáveis com nomes bastante significativos, com importância para cada contexto.

Para encerrar essa questão, vamos analisar a documentação da Microsoft.

André: Nessa documentação oficial, temos as convenções gerais para nomenclatura de variáveis. Percorrendo o documento, temos a seção de escolha das palavras, listando as seguintes boas práticas:

Como práticas a serem evitadas, temos o seguinte:

Conclusão

Na sequência, daremos continuidade às melhorias de legibilidade do código!

Sobre o curso C#: aplique boas práticas de refatoração e torne seu código mais legível

O curso C#: aplique boas práticas de refatoração e torne seu código mais legível possui 173 minutos de vídeos, em um total de 59 atividades. Gostou? Conheça nossos outros cursos de .NET em Programação, ou leia nossos artigos de Programação.

Matricule-se e comece a estudar com a gente hoje! Conheça outros tópicos abordados durante o curso:

Aprenda .NET acessando integralmente esse e outros cursos, comece hoje!

Conheça os Planos para Empresas