JavaScript funcional para o mundo real!

Igor Franca
Horizon Four
Published in
9 min readSep 12, 2018

Todo mundo anda falando bastante de programação funcional, o maior problema é, “Como demônios começar a escrever um código mais alinhado com a filosofia funcional, sendo que não posso começar uma nova aplicação do zero?”.

Ou seja, como começar a escrever código com outra filosofia, sendo que as aplicações que temos que manter no dia-a-dia estão diferentes? Pensando nisso, quis compartilhar alguns exemplos de como eu mesmo mudei minha maneira de escrever código, para poder trazer pra mais perto da realidade as vantagens do JavaScript funcional!

Quando pensando em aplicações web, é MUITO comum termos que manipular coleções. O que são coleções? Todo e qualquer conjunto de informações, organizados de maneira que você consiga achar um item ou, por exemplo, organizar dados parecidos juntos; ou seja, um Array e até mesmo um Objeto podem ser uma coleção! Para ilustrar, que tal começarmos com uma coleção de Ricks?

Essa coleção é bem simples, porém, imagine que ela vem direto de um banco de dados! Eee imagina que nosso front-end quer que retornemos apenas os nomes e as dimensões dos Ricks que tenham família! (Sacanageeeem, eu sei kkkkk, mas exemplos legais são escassos, sorry :/) Beleza, caso você não saiba como fazer ainda, fica tranquilo, vamos quebrar o problema em partes!

Primeiro passo: Precisamos primeiro saber se temos um array na chave family do objeto, e então contarmos quantos itens temos nele.

Segundo passo: Precisamos pegar apenas aqueles que tem mais de 0 itens! Ou seja, todos que não tem esse Array vazio.

TTerceiro passo: Por fim, precisamos transformar os documentos que tem as três chaves (name , dimension e family) para conter apenas a chave name e a chave dimension, para que nosso front consuma apenas o que precisa, certo? 😄

A primeira coisa que passaria na cabeça de alguém que nunca teve contato com a filosofia funcional de código poderia ser: “Okay, faço um while pra percorrer a lista de Ricks, salvo em uma lista de objetos com o index e um boolean pra saber se tem ou não items no array da família e, depois, eu pego do array de Ricks só os indexes que tem coisas!”

Você deve estar pensando agora… “Quee??? Como assim mano, não entendi nada!” PERA! Não fecha o artigo e deixa pra estudar JavaScript funcional depois! Eu deixei o mais complexo que consegui imaginar só para pensarmos que, sim, apesar de uma coleção simples, essa operação pode ficar MUITO complexa e beeem confusa! Então, que tal escrevermos funções simples que conseguem fazer algumas coisas?

Pausa para o chá 😄!

Um passo importante e que conseguimos imaginar e resolver tranquilos com uma função simples é: contar se um array tem objetos e se esses objetos tem a chave family se essa chave é um array, podemos pegar a propriedade length dele! Poxa, melhor ainda! E se fizéssemos uma função que manipula só um registro, ou seja, só um Rick, e consegue fazer todo o rolê? Poderia ser algo assim:

Okay, agora sim! Temos um pouco de funcionalidade pra resolver nosso problema não? Vamos reparar em alguns detalhes que deixei de propósito nessa função! O primeiro ponto importante pra começarmos a aprender sobre programação funcional é: o nome da função diz absolutamente TUDO o que ela faz! Ou seja, mesmo que alguém não entenda o que ela faz de fato, o nome dela deve ser o mais claro possível! Outro ponto: repare que nossa função só recebe um parâmetro! Isso vai ficar cada vez mais fundamental, conforme você avançar seu nível de programação funcional. Na verdade, as técnicas mais avançadas de programação funcional só te ensinam a transformar funções complexas, com muitos parâmetros, em funções mais simples, com apenas um único parâmetro! 😃

Beleza, com esses novos conceitos de programação na cabeça, podemos pensar no próximo problema que temos para resolver, sem nos preocuparmos ainda em como vamos juntar tudo! Agora podemos transformarmos um objeto com três chaves em um objeto com apenas as chaves name e dimension! Esse passo também é fácil e já teremos matado 75% do problema! Que tal se recebermos apenas um rick, como fizemos com a última função, e retornarmos sempre um novo objeto com a chave name do objeto rickpassado como parâmetro? Bem simples e só pra deixar claro, estamos deixando o tratamento de erros de lado, por enquanto - mas prometo fazer um outro post para falar de tratamento de erros em programação funcional!

Outro detalhe importante que podemos aprender nessa função é: repare que eu poderia alterar o objeto que recebi de parâmetro, mas preferi transformá-lo em um novo objeto só com a chave que eu queria! Significa que qualquer um que usar essa função não precisa se preocupar, porque ela irá funcionar (HA HA pegou?? :D) sem alterar em nada o objeto, aplicando um outro princípio da programação funcional - o de não gerar efeitos colaterais em nada! 😄

Beleza! Temos dois dos três steps done! Mas como podemos saber se nosso código está realmente mais fácil de manter, se está mais estável? - outra importante vantagem da programação funcional - Bora escrever alguns testes?

O primeiro passo é exportar as funções, assim podemos testar tudo o que criamos até agora!

Okay, bem simples, já exportamos o que precisamos, agora vou instalar duas libs que eu AMO, a Chai.js e o Mocha! Não se preocupa se nunca ouviu falar delas, são muito fáceis de usar e podemos usar sem se preocupar com o que elas fazem por baixo dos panos, por enquanto! Se tiver dificuldade pra começar um novo projeto com o npm ou instalando essas libs, pode me chamar que eu te ajudo! Sem tretas!

Agora com essas libs instaladinhas, podemos criar um arquivo de testes e escrever uns testes legais pra todas as funcionalidades que queremos!

Talk is cheap, show me the code né?

Esse código é bem simples e ele basicamente testa nossa função toCountIfRickHaveAFamilypra sabermos que fizemos tudo certo sempre! Justamente porque pudemos fazer funções simples, é fácil testá-las também! Sem aquelas coisas complicadas que o pessoal faz pra testar com mocks, stubs e mais um monte de nome bizarro hahahaha 😅

Então, lembra que eu disse que podemos testar? Acabei pegando um erro no código! Eu deixei >= ao invés de só > , então ele ia retornar true em todos os casos. 😅

Corrigindo,

Uhuu! Agora temos nossa função funcionando lindona! Vamos escrever outros testes? É bem tranquilo!

Quando rodamos o npm test :

Se você ficou meio perdido na parte do Mocha e do Chai.js, fica tranquilo, a ideia é só te mostrar o poder dos testes, logo logo solto um artigo sobre como testar funcionalidades em JavaScript para o Node.js.

Okay, já que escrevemos pra nossas funções atuais, que tal já escrever o teste pra nossa função principal, que deve retornar só o que o front quer consumir?

Certo! Agora podemos finalmente compor nossas funções para que elas executem a operação que a gente queria!

Para que nós consigamos fazer isso, vamos precisar de duas funções que já existem em uma coleção do JavaScript! Uma delas é o filter e a outra é o map! Você deve estar se perguntando, “Porque demônios você fez tantas funções, sendo que vamos usar duas que já existem em um array??” Simples!

Pela simplicidade de aplicarmos essa mesma função que transforma um Rick, a uma coleção e ela transformar toda a coleção pra gente! Assim, a função que seleciona apenas um Rick ganha o poder de selecionar todos os Ricks que queremos. Repare que não estamos declarando mais a função na hora que vamos usar o map, como geralmente fazemos, pois agora, já é uma funcionalidade que testamos e validamos e que também é extremamente reaproveitável!

Talvez ainda esteja meio confuso, até porque não amarramos o final, mas olha que legal, será que nosso teste para a função principal vai passar de primeira?

Beleza! O que eu fiz aqui foram duas coisas pra ficar mais lindão e garantir que nossos testes passaram 100%. Primeiro, eu trouxe aquele array de Ricks do primeiro exemplo para o nosso arquivo de testes, para que a função rode realmente com algo “real”. Também usei algo muito legal do Mocha (por essa e outras que gosto tanto dele), um outro método, o forEach do array, pra criar testes dinâmicos. Então, se por um acaso quisermos criar mais Ricks naquele array, o teste vai rodar mais vezes pra garantir que retornarmos direitinho!

E a função principal? Como fica? É incrível o fato da simplicidade dela, porque na verdade ela só junta nossas duas outras funções!

Então, como já testamos as outras duas, significa que nosso teste da função maior é redundante? Exatamente, afinal, como já dizia o Benjamin,

Esperança não é uma estratégia.

Uhuuu! Passou de primeira! Primeiro ponto, temos 7 testes o que é impressionante julgando que só temos 3 funções! Sim, isso é normal quando você escreve testes, vão haver mais testes do que quase qualquer outra coisa! E outra coisa legal é: por que passou de primeira? Simplesmente porque os outros testes que temos já testavam essa funcionalidade, então, basicamente, esse último teste só assegura que elas funcionam bem juntas.

Só pra vermos o efeito final… O que acontece se eu comentar a linha do map na função retriveOnlyTheRicksWithFamily?

Nós sabemos exatamente onde está o problema! Sabemos de cara que o problema não é na função de mapear só essas chaves, porque nossos testes dizem que ela funcionou, então, o problema só pode estar na função que junta as funcionalidades! Testes extensivos pra suas funcionalidades, que agora são simples de testar, tornam seu software mais fácil de debugar também

Claro que o foco do aprendizado hoje era em programação funcional, então o que foi que vimos que ajuda muito a começarmos a mudar as coisas devagar?

Primeiro: Só de escrevermos pequenas funções para compor funcionalidades, mesmo que em todo o lado ainda tenhamos funções gigantes, já começamos a deixar nosso software mais funcional!

Se acha que isso pode gerar um problema ou até não ser uma boa prática, coloca nos comentários desse post o que acha sobre isso! :D Vamos trocar ideias para deixar nossa comunidade mais forte!

Segundo: Testar pequenas funções é beeem mais simples, principalmente quando fazemos a função pensando em transformar em algo novo, não alterar o que já existe, podemos criar funções ainda mais fáceis de serem testadas!

Terceiro: Os nomes das funções sendo tão claros, fazem com que a função final seja extremamente legível mesmo pra quem não consegue entender direito código, já que parece quase inglês! Olha que animal:

“Filter to count if Rick have a family, then, map to pick only the Rick’s name and dimension”

Reparou que existe uma outra palavra beeem conhecida e odiada por muitos programadores JavaScript ali no meio? 😄 Talvez podemos falar de coisas assíncronas no próximo post… O que acha? Só me diz ai nos comentários!

Pra encerrar, seguem alguns links pra dar uma clarificada nas operações do array de Ricks:

E, claro, o repositório no meu GitHub, para que você possa rodar os exemplos prontos de cara :D (Mas eu recomendo fortemente tentar fazer eles você!)

--

--

Igor Franca
Horizon Four

Node.js Witch Doctor and at the free time playing with security stuff :D