DEV Community

Iago Angelim Costa Cavalcante
Iago Angelim Costa Cavalcante

Posted on • Originally published at iagoangelimc.Medium on

3 1 1 1 1

Programação Funcional com Javascript — Composição

Programação Funcional com Javascript — Composição

Vamos falar neste artigo sobre composição, o que é, como resolver um determinado problema com isso e qual problema ela pode vir a resolver.

Composição

É quando podemos reunir várias funções em uma única, onde a mesma recebe um número variado de funções por parâmetro, e dentro dela é usado o resultado de uma como entrada da outra. Vamos exemplificar com código, que talvez fique mais claro o entedimento.

O Problema

Vamos imaginar que estamos sentados em nossa mesinha, ai o gerente chega com a gente e fala que precisa que façamos um novo módulo front-end para o sistema MarombaWebApp, e que nesse módulo, nosso amiguinho do back-end vai devolver uma lista de usuários onde nela possui alguns dados, sendo um deles a quantidade de parcelas faltantes e outro o valor de cada parcela, e que na nossa tela precisamos mostrar a lista de todos os usuários e o total que falta eles pagarem. Precisamos desse controle e o prazo é pra daqui a uma hora.

Dado esse problema e o prazo, apertado, precisamos entregar aquilo funcionando logo, nós nem pensamos na qualidade, só pensamos que estamos já atrasados pra entregar. Com a descrição do problema, a solução já veio na mente, uma lista é comum de receber e pensamos logo em iterar essa lista e somar o montante. Logo, logo nosso problema está resolvido e ficaria dessa forma:

const usuarios = [
{ nome: 'Aluno 1', parcelasFaltantes: 3, valor: 89.9 },
{ nome: 'Aluno 2', parcelasFaltantes: 5, valor: 19.9 },
{ nome: 'Aluno 1', parcelasFaltantes: 7, valor: 49.9 },
{ nome: 'Aluno 1', parcelasFaltantes: 6, valor: 69.9 },
{ nome: 'Aluno 1', parcelasFaltantes: 2, valor: 99.9 }
]
let total = 0
usuarios.forEach(usuario => {
total += usuario.parcelasFaltantes * usuario.valor
})
console.log('valor total faltante =>', total)
view raw problema.js hosted with ❤ by GitHub

Onde temos uma lista fictícia, uma variável global para receber o nosso total e um laço de repetição onde vamos pegar o valor total de cada usuário. Aparentemente não temos problema algum não é mesmo, mas vamos supor que precisamos dessa mesma lógica em outro módulo do sistema, dado uma lista, eu precise da somatória do total, o que vamos fazer ?! Isso mesmo que você pensou, ctrl + c e ctrl + v. Começando assim a repetição de código em todo os nosso sistema, olha que lindeza.

A Solução

Como vocês já devem ter imaginado, pra solucionar esse nosso pequeno problema, vamos utilizar a técnica de composição e com isso aplicaremos algo conhecido pela maioria dos Dev’s, o princípio da responsabilidade única, o famoso S do SOLID.

Nosso primeiro passo, vai ser separar as responsabilidades, onde teremos uma função para realizar o cálculo do valor total por usuário (linha 9) e outra função onde será realizado a somatória total do valor faltante de todos os usuários (linha 12):

const usuarios = [
{ nome: 'Aluno 1', parcelasFaltantes: 3, valor: 89.9 },
{ nome: 'Aluno 2', parcelasFaltantes: 5, valor: 19.9 },
{ nome: 'Aluno 1', parcelasFaltantes: 7, valor: 49.9 },
{ nome: 'Aluno 1', parcelasFaltantes: 6, valor: 69.9 },
{ nome: 'Aluno 1', parcelasFaltantes: 2, valor: 99.9 }
]
const totalPorUsuario = usuario =>
usuario.parcelasFaltantes * usuario.valor;
const somatorioTotal = usuarios =>
usuarios.reduce((total, usuario) => total += totaPorUsuario(usuario), 0);
console.log('valor total faltante =>', somatorioTotal(usuarios))

Temos o mesmo resultado da nossa solução onde está tudo junto e misturado, só que dessa vez, cada coisa está no seu devido lugar, fazendo só o que precisa fazer.

Porém podemos dar uma melhorada e separar a soma que é feita dentro da função somatorioTotal e criar uma outra função de soma de forma que ela se tornará genérica o suficiente pra ser usada em qualquer outro lugar.

const usuarios = [
{ nome: 'Aluno 1', parcelasFaltantes: 3, valor: 89.9 },
{ nome: 'Aluno 2', parcelasFaltantes: 5, valor: 19.9 },
{ nome: 'Aluno 1', parcelasFaltantes: 7, valor: 49.9 },
{ nome: 'Aluno 1', parcelasFaltantes: 6, valor: 69.9 },
{ nome: 'Aluno 1', parcelasFaltantes: 2, valor: 99.9 }
]
const totalPorUsuario = usuario =>
usuario.parcelasFaltantes * usuario.valor;
const soma = (a, b) => a + b;
const somatorioTotal = usuarios =>
usuarios.map(totalPorUsuario).reduce(soma, 0);
console.log('valor total faltante =>', somatorioTotal(usuarios))

No Javascript não existe funções que aceitem composição de forma nativa, por esse motivo, iremos implementar as funções de map e reduce de forma onde aceitem a composição.

Elas terão a seguinte estrutura:

const map = fn => xs => xs.map(fn);
const reduce = (fn, ini) => xs => xs.reduce(fn, ini)
view raw compose.js hosted with ❤ by GitHub

A função map recebe apenas uma função por parâmetro e retorna uma nova função que exige um parâmetro apenas e o parâmetro é o dado que será processado.

E temos na terceira linha a reatribuição da função reduce, onde nela temos dois parâmetrod, sendo o primeiro a função que será usada para realizar o processamento dos dados e a segunda é o valor inicial. Com isso temos algo padronizado onde a saída de uma função é a entrada da próxima.

Assim podemos organizar de forma mais eficiente o nosso código e torná-lo mais legível, as coisas vão se encaixando e fazendo sentido e fica claro o fluxo dos dados.

// Dados obtidos de algum lugar
const usuarios = [
{ nome: 'Aluno 1', parcelasFaltantes: 3, valor: 89.9 },
{ nome: 'Aluno 2', parcelasFaltantes: 5, valor: 19.9 },
{ nome: 'Aluno 1', parcelasFaltantes: 7, valor: 49.9 },
{ nome: 'Aluno 1', parcelasFaltantes: 6, valor: 69.9 },
{ nome: 'Aluno 1', parcelasFaltantes: 2, valor: 99.9 }
]
// Reatribuicao das funcoes map e reduce para suportar composicao
const map = fn => xs => xs.map(fn);
const reduce = (fn, ini) => xs => xs.reduce(fn, ini)
//Regra de negocio
const totalPorUsuario = usuario =>
usuario.parcelasFaltantes * usuario.valor;
//Separacao de responsabilidade, usando a composicao do map
const calculoTotalUsuarios = map(totalPorUsuario);
// Funcao generica
const soma = (a, b) => a + b;
// Reducao de todos os usuarios, somando todos e comecando a partir de 0
const somaTodosUsuarios = reduce(soma,0)
// Composicao das funcoes calculoTotalUsuarios e somaTodosUsuarios
const somatorioTotal = usuarios =>
somaTodosUsuarios(calculoTotalUsuarios(usuarios))
console.log('valor total faltante =>', somatorioTotal(usuarios))
view raw composicao.js hosted with ❤ by GitHub

Essa série de programação funcional com javascript foi feita de forma rápida e direta. Esse post, exclusivamente, tive que estudar bastante e ler muitos outros sobre o assunto. Se você quer se aprofundar, recomendo ler os artigos e vídeo de referência.

Aqui vão as principais referências:

Refatorando para javascript funcional

Compondo funções javascript

Let’s code with function composition — Fun Fun Function

SurveyJS custom survey software

Build Your Own Forms without Manual Coding

SurveyJS UI libraries let you build a JSON-based form management system that integrates with any backend, giving you full control over your data with no user limits. Includes support for custom question types, skip logic, an integrated CSS editor, PDF export, real-time analytics, and more.

Learn more

Top comments (1)

Collapse
 
kauefraga profile image
Kauê Fraga Rodrigues

Gostei bastante, Iago! Foi direto e claro. Estou começando a estudar programação funcional e foi de grande ajuda.

Billboard image

Create up to 10 Postgres Databases on Neon's free plan.

If you're starting a new project, Neon has got your databases covered. No credit cards. No trials. No getting in your way.

Try Neon for Free →

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay