DEV Community

Cover image for O que é a pureza em funções do JavaScript e por que é importante
DEVANIL
DEVANIL

Posted on

O que é a pureza em funções do JavaScript e por que é importante

O processo de estudo do JavaScript geralmente começa de forma muito prática. Desde declarar variáveis até entender o inferno do JavaScript Assíncrono, os conceitos mais teóricos são deixados de lado. E essa lacuna começa a incomodar quando você passa a entrar em tópicos mais profundos.

Com isso em mente tive a ideia de começar a blogar sobre programação explicando alguns conceitos mais teóricos (e até mesmo filosóficos) do JavaScript Moderno, começando pela pureza.

O que é essa tal de pureza?

Imagine que você está criando um sistema complexo utilizando o paradigma da programação funcional. Isso quer dizer que o seu projeto terá uma infinidade de funções, uma chamando a outra, ao ponto de chegar um momento em que o código ganha vida própria e faz coisas que você não pediu.

Se o seu objetivo não for criar uma IA na gambiarra, isso é algo que você quer evitar a princípio. Você não quer que ao mudar alguma coisa em uma função, algo em outra função que você nem sabe onde está dê um duplo twist carpado sem ter ideia de como foi feito.

A função pura, portanto, é aquela em que não há mudança. Já a função impura é aquela que modifica variáveis, estados ou dados além do seu escopo.

O filósofo Heráclito dizia que não era possível se banhar no mesmo rio duas vezes, pois o rio de um segundo atrás não é mais o mesmo rio de agora, devido seu fluxo. As funções puras vão na direção contrária e tentam preservar o mesmo rio para que você consiga se banhar nele quantas vezes quiser, sempre sabendo que o que vai acontecer.

Funções puras

Vamos dar uma olhada nessa função em JavaScript:

function calcularDobro(numero) {
    return numero * 2
}
Enter fullscreen mode Exit fullscreen mode

Aqui nós temos uma função que vai calcular o dobro de um número. Se nós chamarmos calcularDobro(4) teremos como resultado o número 8. Não importa quantas vezes vamos chamar essa função, nós sabemos que se o argumento for 4, o resultado vai ser 8. Se o argumento for 5, o resultado vai ser 10, e assim sucessivamente.

calcularDobro(4) // => retorna 8
calcularDobro(4) // => retorna 8
calcularDobro(4) // => retorna 8
// ou seja, nunca mudou o resultado
Enter fullscreen mode Exit fullscreen mode

Uma função pura vai ter esse comportamento imutável. É uma função que sabe quem ela é. É como se fosse aquela pessoa sênior do trabalho, super disciplinada e metódica. Todo mundo da firma sabe a hora que ela vai tomar um café, como vai responder ao ser abordada, etc...

São duas as características:

  1. Dada a mesma entrada, sempre vai retornar a mesma saída.
  2. Não produzirá nenhum efeito colateral.

Funções impuras

Agora veja essa função e tente entender o que ela está fazendo:

let numero = 8

function calcularDobro() {
    return numero *= 2
}
Enter fullscreen mode Exit fullscreen mode

Esta função tem o mesmo objetivo do exemplo anterior. Mas perceba que ela está acessando uma variável fora do próprio escopo. Quando a chamamos com calcularDobro() vamos ter o resultado 16. Se chamarmos de novo, o resultado será 32, e assim sucessivamente. Nós temos aqui uma função impura.

calcularDobro() // => retorna 16
calcularDobro() // => retorna 32
calcularDobro() // => retorna 64
// ou seja, o resultado está mudando
Enter fullscreen mode Exit fullscreen mode

Um outro exemplo de função impura a seguir:

function mostrarAlerta() {
  alert('Este é um efeito colateral!');
}
Enter fullscreen mode Exit fullscreen mode

Esta também é uma função impura pois tem um efeito colateral. O resultado sempre será o mesmo dependendo do ambiente que você tem configurado, ou seja, sempre vai retornar um alerta na janela com a mesma mensagem. No entanto, para ela produzir esse alerta o DOM API é acessado. No caso do DOM temos segurança que provavelmente nunca mudará, mas se fosse outra API, quem nos garantiria a imutabilidade?

Um outro exemplo de função impura é a seguinte:

function multiplicarAleatorio(numero) {
    return numero * Math.random()
}
Enter fullscreen mode Exit fullscreen mode

Aqui estamos pegando um número e multiplicando por um valor aleatório (que é o que a função Math.random() faz. Aliás, ela também é impura). Mesmo que os seus argumentos sejam sempre os mesmos, os resultados vão ser diferentes:

multiplicarAleatorio(3) // => retorna 1.2427312565643085
multiplicarAleatorio(3) // => retorna 0.0966362658711748
multiplicarAleatorio(3) // => retorna 2.493662851387264
// uma função impura
Enter fullscreen mode Exit fullscreen mode

Está claro com esses exemplos que a função impura não sabe muito bem o que ela é. Em comparação com aquele colega de trabalho estável, esse é aquele outro que um dia chega 8h da manhã e no outro quase 12h e que a gente não sabe se vai nos responder com educação ou irritado. Mas pode ser que esse seja justamente o funcionário criativo que faz algo incrível se tiver um líder capaz de usar seu talento.

Então não condene as funções impuras. Se tiver como evitar é sempre bom, mas elas podem ser importantes se você souber onde usá-las, tendo muito cuidado em documentar o comportamento para que o código seja compreensível para outros ou mesmo para você no futuro.

Quais os benefícios de usar funções puras?

Reprodutibilidade: um dos princípios de uma experiência científica é a capacidade dela ser reproduzida e o resultado continuar sendo o mesmo. Na programação, essa habilidade permite que testes sejam executados mais facilmente, que bugs não ocorram...

Paralelização: apesar do JavaScript, em teoria, rodar com single thread, ou seja, uma coisa por vez, já é bastante comum as funções assíncronas. Com funções puras, você pode chamá-las em paralelo sem medo do resultado mudar, ganhando tempo de execução.

Memoization: esse termo significa, nesse caso, a capacidade de guardar na memória o resultado da função. Nós vimos que o resultado da função sempre vai ser o mesmo. Isso significa que podemos salvar o valor da função em uma variável e depois usá-la no lugar da função que o resultado será o mesmo.

São vários outros benefícios, especialmente quando se usa a programação funcional, mas para isso precisamos avançar em outros conceitos que serão temas para postagens futuras.

Se você achou algum erro ou quiser dar alguma sugestão para melhorar a qualidade, me chama lá no LinkedIn ou no Twitter. As postagens futuras serão avisadas por lá também.

Referências

AUTH0. Glossary of Modern JavaScript Concepts: Part 1. Auth0 - Blog. Disponível em: <https://auth0.com/blog/glossary-of-modern-javascript-concepts/>. Acesso em: 14 Mar. 2022.

‌MOTTO, Todd. Pure versus impure functions - Ultimate CoursesTM. Ultimatecourses.com. Disponível em: <https://ultimatecourses.com/blog/pure-versus-impure-functions>. Acesso em: 14 Mar. 2022.

‌ELLIOTT, Eric. Master the JavaScript Interview: What is a Pure Function? Medium. Disponível em: <https://medium.com/javascript-scene/master-the-javascript-interview-what-is-a-pure-function-d1c076bec976#.kt48h2bfa>. Acesso em: 14 Mar. 2022.

‌BRASSEUR, Arne. Functional Programming: Pure Functions - SitePoint. Sitepoint.com. Disponível em: <https://www.sitepoint.com/functional-programming-pure-functions/>. Acesso em: 14 Mar. 2022.

Discussion (0)