Imutabilidade

Recentemente tive que realizar uma apresentação sobre o tema de Imutabilidade na programação. Nessa apresentação eu tinha como objetivo fazer uma explicação de forma que fosse rápida, simples e efetiva para servir como um start para o uso da imutabilidade na programação. Então sem mais delongas bora para explicação. 😉
O que é?
Se pegarmos a própria definição da palavra a imutabilidade é uma característica ou qualidade de algo que não que não pode ser alterado. Isso significa que durante todo o “ciclo de vida” de algo irá permanecer imutável, sem a alteração de estado.
Vamos a exemplo para entender melhor o conceito.
(Ciclo de vida do cachorro Toby.)
Nesse exemplo temos o cãozinho chamado Toby, e ao nascer ele veio ao mundo como um belo cachorro, porém os dias e mesês foram passando e cada vez mais o Toby crescia até a hora em que se tornou o Adulto Toby, todavia, mesmo havendo essa mudança no cãozinho ele permaneceu sendo um cachorro. Os dias não param e quando menos esperava o Toby já havia se tornado o Velhinho Toby e PASMEM, ele ainda assim continuo sendo um cachorro 😱, e foi assim até o final de sua vida. 😢
Com essa linda história do cãozinho mostra que durante todo o ciclo de vida do Toby ele permaneceu sendo um cachorro, ele não teve uma alteração de estado, sempre se manteve imutável quanto a isso.
O ponto conclusivo dessa história é dizer que o Toby nunca vai poder virar a Frederica(A galinha pistola). Uma vez que o Toby foi “criado” como cachorro irá permanecer cachorro até o final da sua vida.
(Toby nunca será a galinha Frederica.)
E na programação?
A definição do conceito na programação continua tendo o mesmo propósito. Por exemplo tudo aquilo que for criado/instanciado não deve sofrer alteração no seu estado até o final da sua vida.
❌ Mutável
var cachorro = 'Toby'
cachorro = 'Frederica'
✔️ Imutável
const cachorro = 'Toby'
// Não irá permitir alterar o valor.
“🤔 Okay... mas como que eu faço para alterar um valor então?
”
Certo, aqui vem uma parte muito importante da imutabilidade na programação, apesar de não poder ser possível alterar o valor de algo que é imutável, é possível usá lo para criação de um novo valor, uma nova variável.
Vamos a um exemplo.
✔️ Imutável
const bebeToby = {
idade: '8 semanas',
peso: '5,2 kg',
raca: 'Golden Retriever',
nome: 'Toby'
}
// Agora o Toby cresceu e preciso alterar a idade e o peso dele.
const adultoToby = {
...bebeToby, // Uma cópia da variável bebeToby com todos os atributos.
idade: '1 ano', // Sobrescrevendo a idade inicial.
peso: '32,2 kg' // Sobreescrevendo o peso inicial.
}
Agora simmm, dessa forma você está trabalhando com imutabilidade, a variável bebeToby
se manteve imutável, porém, foi utilizada para criação da variável adultoToby
que a partir de agora deverá ser utilizada como a variável “atualizada”.
“🤔 Humm entendi, mas afinal de contas porque utilizar imutabilidade?
”
Aháá, eu já estava esperando por essa pergunta, a grande razão do uso da imutabilidade é devido ao Grande Vilão Side Effect.
(Vilão Side Effect.)
Em um código mutável não há garantia de que quando ser executado irá realizar sempre a mesma operação, pois a operação utiliza de um valor que é variável e isso pode ocasionar os “efeitos colaterais” mais conhecido como side effects.
❌ Exemplo de Side Effect.
var total = 80
var desconto = 2
function exibirTotalComDesconto() {
total = total - desconto
console.log(`O total com desconto é: ${total}`)
}
// Na primeira chamada tudo irá ocorer de forma correta.
exibirTotalComDesconto() // R$ 78
// Na segunda chamada vamos ter o valor total errado.
exibirTotalComDesconto() // R$ 76
Isso é apenas um pequeno exemplo, mas pode acabar acontecendo com muitos, principalmente programadores iniciantes.
Prós Vs Contras
Há muitos prós e contras para o uso da imutabilidade, mas não é o intuíto citar todas aqui nesse post, então vou por algumas interessantes.
Prós
- ✔️ Clean code.
(Não cometendo mutabilidade o código fica mais legível e melhor de dar manutenção.)
- ✔️ Pensamento funcional.
(Imutabilidade e programação funcional andam lado a lado, então ao fazer uso de imutabilidade já irá aprender alguns conceitos de programação funcional.)
- ✔️ Evitar side effects.
(Código imutável não irá gerar efeitos colaterais.)
Contras
- ❌ Complexidade inicial.
(Inicialmente é pouco complexo aplicar o conceito da imutabilidade, mas os esforços valem a pena.)
- ❌ “Caro para memória do computador”
(O poder computacional já evoluiu muito, mas é interessante saber que ao fazer uso da imutabilidade é mais caro para memória, pois, um espaço na memória nunca é reaproveitado.)
Alguns exemplos
Bom vou finalizar esse post adicionando alguns exemplos de transformação de códigos mutáveis para imutáveis.
Push no Array
❌ Mutável.
let nomes = ['Anderson', 'Antonio', 'Pablo', 'William']
nomes.push('Roberto')
✔️ Imutável.
const nomes = ['Anderson', 'Antonio', 'Pablo', 'William']
const nomesAtualizados = [...nomes, 'Roberto']
Concatenando valores na String
❌ Mutável.
let nomes = ['Anderson', 'Antonio', 'Pablo', 'Roberto', 'William']
let tabelaHTML = `
<table>
<thead>
<tr>
<th>Nomes</th>
</tr>
</thead>
<tbody>
`
for (let i = 0; i < nomes.length; i++) {
tabelaHTML += `
<tr>
<td>${nomes[i]}</td>
</tr>
`
}
tabelaHTML += `
</tbody>
</table>
`
✔️ Imutável.
const nomes = ['Anderson', 'Antonio', 'Pablo', 'Roberto', 'William']
const gerarLinhaHTML = nome => `
<tr>
<td>${nome}</td>
</tr>
`
const linhasHTML = nomes.map(gerarLinhaHTML).join('')
const tabelaHTML = `
<table>
<thead>
<tr>
<th>Nomes</th>
</tr>
</thead>
<tbody>
${linhasHTML}
</tbody>
</table>
`
Somando valores do Array
❌ Mutável.
let items = [5, 10, 15, 50]
let totalItems = 0
for (let i = 0; i < items.length; i++) {
totalItems += items[i]
}
❌ Mutável, usando reduce.
const items = [5, 10, 15, 50]
const totalItems = items.reduce((total, item) => {
total += item
return total
}, 0)
✔️ Imutável.
const items = [5, 10, 15, 50]
const totalItems = items.reduce((total, item) => total + item, 0)
Agrupando valores
❌ Mutável.
let produtos = [
{ codigoPai: 1, nome: 'Camisa Vermelha' },
{ codigoPai: 1, nome: 'Camisa Verde' },
{ codigoPai: 2, nome: 'Camisa Preta' }
]
let produtosAgrupados = produtos.reduce((acumulador, produto) => {
let chave = acumulador.hasOwnProperty(produto.codigoPai)
if (chave) {
acumulador[produto.codigoPai].push(produto)
return acumulador
} else {
acumulador[produto.codigoPai] = [produto]
return acumulador
}
}, {})
✔️ Imutável.
const produtos = [
{ codigoPai: 1, nome: 'Camisa Vermelha' },
{ codigoPai: 1, nome: 'Camisa Verde' },
{ codigoPai: 2, nome: 'Camisa Preta' }
]
const produtosAgrupados = produtos.reduce(
(acumulador, produto) => ({
...acumulador,
[produto.codigoPai]: [...(acumulador[produto.codigoPai] || []), produto]
}),
{}
)
Considerações finais
A imutabilidade apesar de complexa no começo é muito válida de ser aplicada, os ganhos de legibilidade de código e principalmente a diminuição de bugs no código fazem o eforço valer a pena.
Vou deixar anexado aqui minha Apresentação em Slides, dá uma olhada lá, ficou bem maneira.
Espero que esse post tenha agregado algo ao seu conhecimento, até a próxima. ✌
“Programar é uma arte de transformar complexidade em simplicidade.” 🌳
comments powered by DisqusRoberto Umbelino.