Ainda lendo o livro “Programação Funcional para Desenvolvedores Java” do Ph.D Dean Wampler, esbarrei com um conceito interessante desse paradigma de programação e que poderia ser pensado no orientação a objetos.
O que são funções sem efeitos colaterais?
Segundo o livro, funções que possuem efeitos colaterais são aquelas que não importa quantas vezes nós a chamemos, ela sempre retornará o mesmo valor. Isso acontece porque essa funções não alteram o estado em que elas estão, como por exemplo na orientação a objeto, gravar valores em um campo do objeto em que estão ou, na programação procedural, gravar valores em variáveis globais. Sendo assim, funções sem efeitos colaterais são obviamente o oposto disso. Buscando um pouco mais sobre esse tema, encontrei o blog do Maurízio Szabo, e ele da o seguinte significado a funções sem efeitos colaterais:
Uma função não tem efeitos colaterais quando não importa quantas vezes ela é chamada, ela sempre traz os mesmos resultados – Maurício Szabo
Então, um função sem efeito colateral é aquela que retorna sempre o mesmo resultado se sempre usarmos os mesmos parâmetros de entrada e também é aquela que não depende do contexto. Reparem que essas duas partes da definição se relacionam. Se uma função não depende do contexto, isto é, não altera o contexto nem depende de algum dado dele, o resultado dela só dependerá dos parâmetros de entrada e, por isso, se informarmos sempre os mesmos parâmetros ela sempre retornará o mesmo resultado.
Diante de tais definições cheguei a conclusão de que é improvável que sob o paradigma orientado a objetos seja possível criar uma função que não cause efeitos colaterais ao ser invocada, pois é dificil uma função não alterar variáveis do objeto apesar de ser fácil encontrar funções que sempre retornam os mesmo valor não importando o número de vezes que são chamadas. Isso porque as funções são extremamente coesas ao escopo ou contexto empregado pela classe em que ele está e, por isso, acabam alterando informações daquele contexto, como os atributos da classe.
(…) não é possível escrever um código completamente isento de efeitos colaterais (na verdade, até é possível, mas provavelmente ninguém vai querer usar um programa no qual você roda-o e ele imprime na tela um resultado baseado em valores hard-coded no código…). Então, a ideia é evitar ao máximo efeitos colaterais em seu código (ao contrário do que você aprendeu a programar na faculdade, se sua faculdade for igual à minha…) – Maurício Szabo
Então, mesmo que seja impossível eliminar todos os efeitos colaterais, porque devo tentar ao máximo evitá-los em meu código? Pelas vantagens que isso traz.
Vantagens – Porque deveria pensar nisso?
Dentre as vantagens podemos citar, facilitar testes unitários, diminuir complexidade do código e facilitar reuso, entendimento e manutenção do código. Seguem abaixo as citações dos autores que afirmam o mesmo:
Por fim, sem efeitos colaterais, é mais fácil de testar o código. E embora seja impossível fazer um sistema completo sem nenhum efeito colateral, nos testes isso é imprescindível (teardown, ou o “after” do rspec, são funções que obrigatoriamente devem limpar qualquer “sujeira” que seu teste tenha feito: criar arquivos, criar registros no banco de dados, etc). – Maurício Szabo
Outra fonte de complexidade, de que leva a falhas, são funções que mudam o estado, e.g., gravar valores no campo de um objeto ou de variáveis globais. – Dean Wampler
Funções sem efeitos colaterais são ótimas para implementar reuso, já que não dependem do contexto no qual são executadas. Comparadas com funções com efeitos colaterais, também são mais fáceis de projetar, entender, otimizar e testar. Assim, têm menor probabilidade de ter erros. – Dean Wampler
Como tornar minha função sem efeitos colaterais?
Há algumas dicas dadas pelo Maurício em seu post para tornar as funções com menos efeitos colaterais possível. A primeira é implementar a ideia das funções realizarem poucas ações e terem um único objetivo unida com a ideia de evitar funções que possuam o mesmo objetivo.
Enfim, a ideia principal é fazer os métodos fazerem poucas coisas. Se você precisa criar um método que vai identificar se aquele registro é válido, certifique-se de que ele APENAS faz isso. – Maurício Szabo
E a segunda dica é evitar retornos baseados em número randômicos e data para que seja possível o retorno ser sempre o mesmo e evitar IO para que o estado se mantenha sempre o mesmo.
Outra dica interessante é que para uma função não ter efeitos colaterais, ela não pode envolver-se com E/S (IO) (ou seja, não pode imprimir na tela, salvar num arquivo, ler um caractere, etc), nem gerar ou consumir número randômicos, acessar a data e hora atual, etc… isso porque qualquer E/S modifica o estado do sistema, gerar número randomicos é, por definição, algo que gera um resultado diferente sempre que é chamado, e acessar a data e hora é basicamente ter um resultado diferente a cada milisegundo (por isso que fazemos “stub” desse tipo de operação em testes). – Maurício Szabo
Referências
[1] – WAMPLER, Dean. Functional Programming for Java Developers: Tools for Better Concurrency, Abstraction, and Agility. ” O’Reilly Media, Inc.”, 2011.
[2] – Em: <https://mauricioszabo.wordpress.com/2012/03/16/efeitos-colaterais-e-codigos/>. Acesso em: 24 janeiro 2015
Olá Bom dia,
Mesmo com Orientação a objetos você pode ter funções sem efeito colateral, ela tem que receber as informações e tudo que ela precisa alterar ela devolve como resposta, se for um objeto uma copia dele alterado. Quando se trabalha com linguagens que permite a passagem de parametro por valor, como C++ você já facilita a vida nesse sentido.
Agora se pensarmos em java e quisermos garantir que o que passamos não seja alterado devemos pensar em sempre usar valueobjects para garantir imutabilidade.
O conceito de “efeito colateral” na minha visão é a intenção da função (conceito de interface com inteções reveladas) aonde quem usa não precisa saber como é a implementação dela para saber se dependendo do que passar como entrada a entrada vai alterar todo o fluxo do programa, ela faz algo e esse algo ela ti responde na resposta como ela faz não importa.
Abs.
CurtirCurtir
Alô, Renato! Perdão a demora em responder! Muito obrigado pelo acréscimo de informação altamente relevante! Perfeito sua colocação quanto a possibilidade de ter funções sem efeitos colaterais na orientação a objeto, apesar das “dificuldades naturais” que o paradigma vai trazer, algo diferente na programação funcional. Excelente sua colocação quanto aos Value Objects como uma forma de contornar as tais “dificuldades naturais” e fica como dica pra quem está interessado no assunto e desejando aplicar no OOP. Outro ponto muito bom abordado pelo seu comentário é a ideia de que funções sem efeitos colaterais de fato auxiliam em manter quem usa a função longe da preocupação de saber COMO ela funciona, pois, se há efeitos colaterais, obviamente vai haver uma preocupação de quais efeitos serão esses e em que eles poderão afetar demais partes da aplicação. Se eu invoco uma função que pode gerar efeitos colaterais, vou me preocupar em saber COMO ela funciona para não afetar onde não desejo, mas, se ela não tiver efeito colateral, me preocuparei apenas em saber o que ela faz. Muito obrigado! Abraços!
CurtirCurtir