Como fazer uso de tipos de dados mais expressivos

0 18

Tipos de dados usados de forma mais expressiva, potencialmente melhoram o entendimento e a manutenção do código fonte de uma aplicação.

Certamente que a experiência traz mudanças na forma como pensamos e escrevemos nossos códigos.

Hoje quero compartilhar minha vivência em relação a algo pouco discutido mas bastante importante: tipos de dados.

Tipos de Dados Primitivos

Nas linguagens de programação, são os tipos básicos (nativos) utilizados para armazenar em memória os dados das variáveis. Como exemplo, no C# temos: int, short, bool, char, string etc.

Com eles, é possível construir estruturas de dados robustas, que nos permitem abstrações mais complexas.

Veja a classe Conta abaixo, formada somente por tipos nativos. Ela é bem simples, contendo apenas informações essenciais sobre uma conta qualquer.

public class Conta
{
    public string Fornecedor { get; set; }
    public string Numero { get; set; }
    public decimal Valor { get; set; }
    public DateTime Vencimento { get; set; }
    public DateTime Pagamento { get; private set; }
    public string Situacao { get; private set; }

    public Conta()
    {
        Situacao = "EmAberto";
    }
}

Inicialmente, essa implementação parece atender as necessidades, mas no decorrer da evolução do sistema alguns problemas podem surgir.

Observe a propriedade Numero, nós podemos atribuir qualquer dado texto a ela, o que nos levaria a coisas como: “12345”, “12 3 45”, “1234-5”. Ou seja, a representação da informação fica dúbia e custosa de se manter.

Por que então não colocamos o tipo como inteiro, assim, unicamente números podem ser alocados? Bem, Numero é o identificador da conta, entretanto, não necessariamente é de fato um número.

Como então, poderíamos resolver casos como esse? Veremos isso a seguir.

Tipos de Dados Expressivos

Algumas linguagens nos permitem compor tipos mais adequados ao domínio da aplicação. Sendo assim, vamos nos utilizar disso na nossa classe Conta.

public class Conta
{
    public Fornecedor Fornecedor { get; }
    public IdentificadorDeConta Numero { get; }
    public decimal Valor { get; set; }
    public DateTime Vencimento { get; set; }
    public DateTime Pagamento { get; private set; }
    public SituacaoConta Situacao { get; private set; }

    public Conta(Fornecedor fornecedor, string identificador)
    {
        Situacao = SituacaoConta.EmAberto;
        Fornecedor = fornecedor;
        Numero = fornecedor.ObterIdentificador(identificador);
    }
}

public enum SituacaoConta : byte
{
    EmAberto,
    Paga
}

public class Fornecedor
{
    public string RazaoSocial { get; set; }
    public string NomeFantasia { get; set; }

    public IdentificadorDeConta ObterIdentificador(string identificador)
    {
        var valido = ValidarIdentificador(identificador);

        if (!valido)
            throw new ArgumentOutOfRangeException($"Identificador '{identificador}' não é válido.");

        return new IdentificadorDeConta(identificador);
    }

    private bool ValidarIdentificador(string identificador)
    {
        throw new NotImplementedException();
    }
}

public struct IdentificadorDeConta
{
    public string Identificador { get; }

    public IdentificadorDeConta(string identificador)
    {
        Identificador = identificador;
    }
}

Veja como pequenas alterações já nos permitem sermos mais expressivos.

Substituímos o string da Situação pelo enum SituacaoConta, onde está mais claro quais opções temos para o dado que queremos guardar. E, ainda, evitamos que seja informado um dado não condizente.

Também, alteramos o tipo do Fornecedor que, além de ser mais representativo, nos permite atribuir mais informações do que apenas o nome, como anteriormente.

Demos, adicionalmente, ao tipo Fornecedor a responsabilidade de gerar o IdentificadorDeConta, impedindo que esse seja construído de forma errada.

Complexidade Aparente

Pode ser contraintuitivo, em muitos casos, o aumento da complexidade para ganhos tão pequenos na expressividade. Mas, não se engane, tipos primitivos “escondem” muita informação.

Acredito, o tipo string ser o pior deles, visto que podemos guardar virtualmente qualquer valor nele. Portanto, saber abstrair tipos mais concisos com o domínio é fundamental para o desenvolvimento.

De outra forma, manter tipos primitivos em excesso, pode causar o “vazamento do domínio”, um tema crucial, mas para outra discussão.

Espero que tenha conseguido elucidar um pouco o tema. Deixe seus comentários abaixo, ficarei feliz em responder. Até a próxima.

Deixe uma resposta

Seu endereço de email não será publicado.