Roberto Umbelino
23/10/2020 Roberto Umbelino

Imutabilidade

blog-feature-image

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.

toby (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 (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.

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.” 🌳

Roberto Umbelino.

comments powered by Disqus

NOS ACOMPANHE NAS REDES SOCIAIS