Desenvolvimento

18 jun, 2015

Escrevendo código usando boas práticas – seu código é legível?

Publicidade

Neste artigo, eu vou dar algumas dicas de como escrever um código mais legível.

O código que você escreve é legível?  Ou você é daqueles programadores que dizem: “Enquanto eu estou escrevendo o código, eu e Deus entendemos o código. Daqui uma semana só Deus vai entender…”?

Vamos fazer um teste. Pegue um fragmento de código que você escreveu uns seis meses ou um ano atrás e tente entender o código.

E então, como você se saiu?

Foi fácil de entender ou você teve que ficar um bom tempo tentando decifrar o que o código estava fazendo? Se você gastou mais do que alguns poucos minutos para entender o seu próprio código, então há uma boa chance de que existe alguma coisa errada com ele.  Mas espera aí… o código esta funcionando, você pode dizer.

Tudo bem, mas se você, que é o autor do código não conseguiu entender o seu funcionamento apenas fazendo uma leitura e teve que gastar um tempo para entendê-lo, o que vai acontecer se outro programador for designado para alterar o seu código?

Talvez o seu código não esteja escrito de forma suficientemente clara e de acordo com as melhores práticas de codificação.

Este artigo procura dar algumas dicas para ajudá-lo a escrever um código mais legível para si mesmo e também para outros desenvolvedores que forem ler o seu código.

Dicas para escrever um código mais legível

Vamos começar analisando um trecho de código que foi escrito na linguagem VB.NET e C# de forma nada legíveis.

VB .NET

    Public Function verificar(s As List(Of DateTime)) As String
    Dim stb As String = Nothing
    For Each hchgd As DateTime In s
    If hchgd <= DateTime.Now Then stb = ( stb  & hchgd ) + vbLf _
    Else stb  = stb  & Convert.ToString("atrasado" & vbLf)
    Next
    Return stb 
    End Function

C#

        public string verificar(List<DateTime> s)
        {
        string stb  = null;
        foreach (DateTime hchgd in s)
        { if (hchgd <= DateTime.Now)
        { stb  = stb  + hchgd + "\n"; }
        else { stb  = stb  + "atrasado\n"; }}
        return stb ;}

Você saberia me dizer o que esse código faz?

À primeira vista não há como saber.

Vamos ser sinceros, esse pequeno trecho de código é um sério candidato ao Oscar do código menos legível. Agora, imagine um trecho com esse estilo de codificação com umas 30 linhas. Um caos, não é mesmo?

Então vamos melhorar o código e torná-lo legível, de forma que qualquer programador possa entendê-lo. Veja abaixo uma versão legível:

VB .NET

Public Function VerificaHoraDeChegadaDosVoosDomesticos(HorarioDeChegadaVoosDomesticos As List(Of DateTime)) As String

    Dim stringBuilder = New StringBuilder()

    For Each horaDaChegadaDoVoo As DateTime In HorarioDeChegadaVoosDomesticos
            If horaDaChegadaDoVoo <= DateTime.Now Then
                stringBuilder.AppendLine(horaDaChegadaDoVoo.ToString())
            Else
                stringBuilder.AppendLine("Atrasado")
            End If
     Next

  Return stringBuilder.ToString()

  End Function

C#

   public string VerificaHoraChegadaDosVoosDomesticos(List<DateTime> HorarioDeChegadaVoosDomesticos)
   {
            var stringBuilder = new StringBuilder();
            foreach (DateTime horaDaChegadaDoVoo in HorarioDeChegadaVoosDomesticos)
            {
                if (horaDaChegadaDoVoo <= DateTime.Now)
                {
                    stringBuilder.AppendLine(horaDaChegadaDoVoo.ToString());
                }
                else
                {
                    stringBuilder.AppendLine("Atrasado");
                }
            }
            return stringBuilder.ToString();
    }

Agora sim, melhorou muito, e olhando o código podemos compreender o motivo para o qual ele foi escrito.

Fizemos várias modificações para aumentar a legibilidade do código. Vejamos:

Começando com o nome do método, que foi alterado de um nome que não dizia muito coisa, para um nome muito mais significativo:

verificar  =>  VerificaHoraDeChegadaDosVoosDomesticos

Alteramos os nomes das variáveis:

d => foi alterada para stringBuilder
hchgd => foi alterada para horaDaChegadaDoVoo
s => foi alterada para HorarioDeChegadaVoosDomesticos

Padronizamos a formatação do código (principalmente na linguagem C#).

Usamos a tabulação, espaços e o aninhamento para tornar o código mais fácil de ler.

Usamos a classe StringBuilder para evitar a concatenação de strings com os operadores & e +.

Vamos considerar outro trecho de código muito encontrado por ai em exemplos.

Considere a classe Usuario:

C#

    public class Usuario
    {
        public bool TemEmailConfirmado { get; set; }
        public bool TemContaAtiva { get; set; }
        public bool EstaLogado { get; set; }
        public bool TemContaEspecial { get; set; }
        public bool StatusAutoGerado{ get; set; }
        public DateTime UltimoEstadoAlterado { get; set; }

        public bool SetStatus(string status)
        {
            // implementação do codigo
            return true;
        }
    }

VB .NET

Public Class Usuario
Public Property TemEmailConfirmado() As Boolean
Public Property TemContaAtiva() As Boolean
Public Property EstaLogado() As Boolean
Public Property TemContaEspecial() As Boolean
Public Property StatusAutoGerado() As Boolean
Public Property UltimoEstadoAlterado() As DateTime
Private m_UltimoEstadoAlterado As DateTime

Public Function SetStatus(status As String) As Boolean
' implementação do codigo
Return True
End Function
End Class

Agora considere um método chamado AtualizaStatus() que é responsável por atualizar o status do usuário e que tem que verificar se todas as propriedades da classe Usuario estão no estado correto.

C#

public string AtualizaStatus(string status, Usuario usuario)
        {
            if (usuario.TemContaAtiva)
            {
                if (usuario.TemEmailConfirmado)
                {
                    if (usuario.EstaLogado)
                    {
                        if (usuario.TemContaEspecial)
                        {
                            if (!usuario.StatusAutoGerado)
                            {
                                if (usuario.UltimoEstadoAlterado < DateTime.Now.AddDays(-1))
                                {
                                    if (usuario.SetStatus(status))
                                    {
                                        return "Atualizado";
                                    }
                                }
                            }
                        }
                    }
                }
            }
            return "Falhou";
        }

VB .NET

Public Function AtualizaStatus(status As String, usuario As Usuario) As String
	If usuario.TemContaAtiva Then
		If usuario.TemEmailConfirmado Then
			If usuario.EstaLogado Then
				If usuario.TemContaEspecial Then
					If Not usuario.StatusAutoGerado Then
						If usuario.UltimoEstadoAlterado < DateTime.Now.AddDays(-1) Then
							If usuario.SetStatus(status) Then
								Return "Atualizado"
							End If
						End If
					End If
				End If
			End If
		End If
	End If
	Return "Falhou"
End Function

Embora o código implementado no método AtualizaStatus() não esteja totalmente ilegível, podemos melhorar sua apresentação.

Abaixo temos a versão na qual, aplicando as boas práticas, vemos que a lógica do código fica melhor compreendida:

C#

 public class Verifica_MaisLegivel
    {
        const string OK = "Atualizado";
        const string FALHOU = "Falhou";

        public string AtualizaStatus(string status, Usuario usuario)
        {
            if (!PodeAtualizarStatus(usuario)) return FALHOU;
            if (!usuario.SetStatus(status)) return FALHOU;
            return OK;
        }

        public static bool PodeAtualizarStatus(Usuario usuario)
        {
            if (!usuario.EstaLogado) return false;
            if (!usuario.TemContaAtiva) return false;
            if (!usuario.TemEmailConfirmado) return false;
            if (!usuario.TemContaEspecial) return false;
            if (usuario.StatusAutoGerado) return false;
            if (!(usuario.UltimoEstadoAlterado < DateTime.Now.AddDays(-1))) return false;
            return true;
        }
    }

VB .NET

Public Class Verifica_MaisLegivel

    Const OK As String = "Atualizado"
    Const FALHOU As String = "Falhou"

    Public Function AtualizaStatus(status As String, usuario As Usuario) As String
        If Not PodeAtualizarStatus(usuario) Then Return FALHOU
        If Not usuario.SetStatus(status) Then Return FALHOU
        Return OK
    End Function

    Public Shared Function PodeAtualizarStatus(usuario As Usuario) As Boolean
        If Not usuario.EstaLogado Then Return False
        If Not usuario.TemContaAtiva Then Return False
        If Not usuario.TemEmailConfirmado Then Return False
        If Not usuario.TemContaEspecial Then Return False
        If usuario.StatusAutoGerado Then Return False
        If Not (usuario.UltimoEstadoAlterado < DateTime.Now.AddDays(-1)) Then
            Return False
        End If
        Return True
    End Function
End Class

Principais modificações feitas:

  • Criamos um método estático (Shared) para verificar se o status do usuário pode ser atualizado. Isso torna o método AtualizaStatus() mais fácil de entender; além disso, a lógica do método PodeAtualizarStatus() agora pode ser reutilizada em outras partes do sistema, pois ele é público e estático;
  • Todos as instruções if foram encurtadas para reduzir o aninhamento.
  • As strings que representavam mensagens forma removidas do método e foram definidas como variáveis constantes. Isso ajuda a manutenção do código, pois agora só existe um lugar para alterar o conteúdo das mensagens.

São coisas simples mas que fazem a diferença. Imagine em um código com uma extensão maior?

Recomendo que você de uma olhada nos links abaixo que dão outras orientações para escrever um código segundo as boas práticas:

Tem um ditado popular que diz: “Caldo de galinha e bom senso não fazem mal para ninguém”.

Tenha bom senso ao escrever o seu código, aplique as boas práticas, não seja preguiçoso…