O benefício é que funções puras facilitam o raciocínio do seu código. Ou, em outras palavras, os efeitos colaterais aumentam a complexidade do seu código.
Veja um exemplo de computeProductPrice
método.
Um método puro solicitaria uma quantidade de produto, uma moeda etc. Você sabe que sempre que o método é chamado com os mesmos argumentos, sempre produz o mesmo resultado.
- Você pode até armazená-lo em cache e usar a versão em cache.
- Você pode torná-lo preguiçoso e adiar sua chamada para quando realmente precisar, sabendo que o valor não mudará enquanto isso.
- Você pode chamar o método várias vezes, sabendo que ele não terá efeitos colaterais.
- Você pode raciocinar sobre o próprio método isoladamente do mundo, sabendo que tudo o que precisa são os argumentos.
Um método não puro será mais complexo para usar e depurar. Uma vez que depende do estado das variáveis que não sejam os argumentos e possivelmente alterá-las, significa que poderia produzir resultados diferentes quando chamados várias vezes, ou não ter o mesmo comportamento quando não chamado ou chamado muito cedo ou muito tarde.
Exemplo
Imagine que existe um método na estrutura que analisa um número:
decimal math.parse(string t)
Não possui transparência referencial, porque depende de:
A variável de ambiente que especifica o sistema de numeração, que é a Base 10 ou outra coisa.
A variável na math
biblioteca que especifica a precisão dos números a serem analisados. Portanto, com o valor de 1
, a análise da string "12.3456"
dará 12.3
.
A cultura, que define a formatação esperada. Por exemplo, com fr-FR
, a análise "12.345"
dará 12345
, porque o caractere de separação deve ser ,
, não.
Imagine como seria fácil ou difícil trabalhar com esse método. Com a mesma entrada, é possível obter resultados radicalmente diferentes, dependendo do momento em que você chama o método, porque algo em algum lugar mudou a variável de ambiente ou mudou a cultura ou definiu uma precisão diferente. O caráter não determinístico do método levaria a mais erros e a mais pesadelos de depuração. Ligar math.parse("12345")
e obter 5349
como resposta, já que algum código paralelo estava analisando números octais não é bom.
Como consertar esse método obviamente quebrado? Introduzindo transparência referencial. Em outras palavras, se livrando do estado global e movendo tudo para os parâmetros do método:
decimal math.parse(string t, base=10, precision=20, culture=cultures.en_us)
Agora que o método é puro, você sabe que não importa quando você chama o método, ele sempre produzirá o mesmo resultado para os mesmos argumentos.