C# - Funções Puras (Escrevendo um código melhor)


 Hoje vou abordar o conceito de funções puras usando a linguagem C#.

As funções puras se assemelham às funções matemáticas. Elas não fazem nada além de calcular um resultado com base em sua entrada. Uma função pura tem duas características importantes:
  1. Não tem efeitos colaterais. Assim como a função matemática, a função pura só retorna valor.
  2. É consistente. Seu resultado é determinado apenas pelos argumentos de entrada. Dados os mesmos dados de entrada, sempre retornará a mesma saída.

Vejamos um exemplo de função pura para clarear o entendimento.

Uma função que retorna o dobro do valor informado na entrada pode ser expressa em matemática assim: f(x) = 2x

Na linguagem C# podemos expressar essa função (em uma aplicação Console) :

        private static double Dobrar(double n)
        {
            return 2 * n;
        }

Neste código o método Dobrar(double n) usa para calcular o resultado o argumento n do tipo double que não tem efeitos colaterais e não sofre alteração de estado. Logo este método é uma função pura.

Mas o que seriam esses efeitos colaterais ?

Seria qualquer interação com o mundo exterior a partir de uma função, onde, essa iteração pode estar alterando uma variável que existe fora da função ou chamando outra função.

Alguns exemplos de efeitos colaterais são:

- Alterar o estado global - por exemplo, campo de instância;
- Mudar argumentos ou variável externa;
- Executar uma operação de E/S ou requisição HTTP;
- Obter a hora atual;

Em contraste, funções impuras podem causar efeitos colaterais ou usar outras coisas além de argumentos de entrada para calcular o valor da saída.

Vejamos um exemplo de uma função impura.

A seguir temos um método(função) Concatenar(string texto) que recebe um texto como argumento e concatena o texto com a variável valor1 :

        private static string valor1 = "Macoratti .net";
        public static void Concatenar(string texto)
        {
              valor1 += ' - ' + texto;
        }

Essa função é impura porque ela modifica o membro valor1 produzindo um valor diferente.

Para tornar essa função uma função pura poderíamos fazer assim:

        public static void Concatenar(string valor1, string texto)       
        {
              return ( valor1 + ' - ' + texto ) ;
        }

Creio que o conceito agora ficou mais claro, mas aonde estamos querendo chegar apresentando o conceito de funções puras ?

Nosso objetivo é escrever um código melhor e mais robusto.

Vantagens das Funções Puras

Quando criamos classes, ao adicionar métodos às nossas classes, gastamos pouco tempo decidindo se o método deve ser uma função pura.

Ao utilizar as propriedades da classe estamos fazendo com que o método seja uma função impura. Vamos ilustrar com um exemplo prático.

Vamos supor que temos uma classe Crediario que usa o método CalculaIdadeEmDias():

    class Crediario
    {
        public DateTime DataNascimento { get; set; }
        public DateTime DataCompra { get; set; }

        public bool ClienteAprovado()
        {
            if (CalculaIdadeEmDias(DataCompra) > 12000)
            {
                return true;
            }
            return false;
        }
        private double CalculaIdadeEmDias(DateTime dataCompra)
        {
            return (dataCompra - DataNascimento).TotalDays;
        }
    }

O método CalculaIdadeEmDias(DateTime dataCompra) é uma função impura pois esta usando a propriedade DataNascimento da classe.

Para tornar esta função pura podemos fazer assim:

    class Crediario
    {
        public DateTime DataNascimento { get; set; }
        public DateTime DataCompra { get; set; }

        public bool ClienteAprovado()
        {
            if (CalculaIdadeEmDias(DataCompra, DataNascimento) > 12000)
            {
                return true;
            }
            return false;
        }
        private double CalculaIdadeEmDias(DateTime dataCompra, DateTime dataNascimento)
        {
            return (dataCompra - dataNascimento).TotalDays;
        }
    }

Observe que agora a função CalculaIdadeEmDias() não usa nenhuma propriedade da classe.

Para concluir vejamos algumas da vantagens em usar métodos que são funções puras:

1- Os métodos são mais fáceis de manter.

Eles são mais fáceis de manter porque um desenvolvedor precisa gastar menos tempo analisando os impactos das alterações no método. O desenvolvedor não precisa considerar o estado de outras entradas usadas no método. Ao considerar uma alteração em um método que não é uma função pura, o desenvolvedor deve pensar no impacto nas propriedades usadas no método que não foram transmitidas.

2- Os métodos são mais fáceis de testar.

Ao escrever um teste de unidade, é fácil passar valores para o método e escrever o teste para verificar a saída correta. Mas escrever testes em métodos que não são funções puras demora mais e é mais complicado porque é necessário mais configuração ou injeção de valores para o teste.

3- Os métodos são mais fáceis de reutilizar.

Você pode chamar o método de outros locais no módulo ou chamar o método de vários módulos diferentes facilmente quando o método é uma função pura.

4- Os métodos são mais fáceis de mover para outras classes.

Se você tem uma função pura em uma classe e deseja movê-la para uma classe utilitária a ser usada por outros módulos, é bem fácil fazê-lo.

5 - Os métodos são mais propensos a ser thread-safe.

As funções puras não fazem referência a variáveis ​​na memória compartilhada que estão sendo referenciadas por outros segmentos.

E estamos conversados...

Pegue o projeto completo aqui :  PureFunctions.zip

"Não sejais vagarosos no cuidado; sede fervorosos no espírito, servindo ao Senhor;
Alegrai-vos na esperança, sede pacientes na tribulação, perseverai na oração;"
Romanos 12:11,12

Veja os Destaques e novidades do SUPER DVD Visual Basic (sempre atualizado) : clique e confira !

Quer migrar para o VB .NET ?

Quer aprender C# ??

Quer aprender os conceitos da Programação Orientada a objetos ?

Quer aprender o gerar relatórios com o ReportViewer no VS 2013 ?

Quer aprender a criar aplicações Web Dinâmicas usando a ASP .NET MVC 5 ?

 

  Gostou ?   Compartilhe no Facebook   Compartilhe no Twitter

 

Referências:


José Carlos Macoratti