sexta-feira, 24 de janeiro de 2020

Side effect: um conceito fundamental em programação funcional


Em programação funcional, é preciso entender o que é "side effect" (efeito colateral) e por que ele é ruim.  #programming #functionallrogramming #software #softwareengineer

Side effect

É qualquer alteração no estado da aplicação, resultante da chamada de uma função, além do seu retorno esperado.

 O que é "estado da aplicação"? É o valor (perene ou transiente) de alguma variável do contexto atual, seja ele global ou local.

Meilir Page-Jones, autor do livro "Structured Design", já havia levantado e classificado este problema como Acoplamento por imagem, no qual dois módulos compartilham uma estrutura de dados comuns e ambos a modificam.

O Side effect é ruim porque ele adiciona mais vetores de mudança ao Estado, ou seja, mais razões para que ele seja alterado, dificultando a manutenção e teste do software, e tornando acabando com a idempotência das funções. Em outras palavras, se a função for invocada várias vezes, provocará várias mudanças no Estado.

Esta é uma das causas mais frequentes de brittleness no software. 

Um exemplo simples de Side Effect seria:

class xpto {
    int contador = 0;
    ...
    void atualizar() {
        contador++;
    }
} 
Você enxerga o problema? Ao invocar o método "atualizar()" o estado será alterado. E se houver outros métodos que utilizam e/ou alteram o estado?

Uma solução melhor seria transformar o método "atualizar()" em uma função pura (pure function), cujas características são:

  1. O valor de retorno é o mesmo, se forem fornecidos os mesmos argumentos;
  2. Não provoca efeitos colaterais (side effects) no estado;

Uma função pura não deve variar seu retorno, a não ser que os argumentos recebidos tenham variado. Por exemplo, ela não pode retornar algo diferente devido à leitura de arquivos. Tudo deve ser em função dos argumentos.

Vejamos agora outra versão para nosso exemplo, deste vez sem side effects:


class xpto {
    int contador = 0;
    ...
    int atualizar(int c) {
        return c + 1;
    }
} 

Então? Notou a diferença? Se você efetivamente desejar alterar o estado da aplicação, poderá fazer algo assim:

contador = atualizar(contador);

Graaaaaannnndeeeeee diferença, dirá você, com ar de desdém! 

Mas sim, é uma grande diferença. O método "atualizar()" não produz mais efeitos colaterais e você pode controlar quando e se deseja mudar o estado da aplicação.

Nenhum comentário:

Postar um comentário