A lo largo de mi carrera he estado en incontables discusiones sobre la inmutabilidad de los datos. Últimamente estas conversaciones giran al rededor de los modificadores disponibles en javascript: var, let y const.

La posición de las mayorías siempre es, por alguna u otra razón, a que “somos mas libres” si nuestros objetos son mutables. Yo opino que las buenas practicas de programación no se tratan de que “tan libres” somos si no de que tan disciplinados somos con el tratamiento de nuestra data, y que tanto nos importa el estado consistente de nuestra aplicación.

En programación orientada a objetos y programación funcional un «objeto inmutable» es un objeto cuyo estado no puede ser modificado una vez creado.? Es el opuesto a los «objetos mutables», que pueden ser modificados tras su creación. Wikipedia

Veamos un ejemplo de mutabilidad:

var vehiculo = 'automovil'
// el código hace algunas cosas
vehiculo = 'bicicleta'

Obtendríamos el mismo resultado si en lugar de var pusiéramos let. Todo bien hasta ahí, la mutabilidad no siempre es mala y existe por una buena razón. Pero entonces cuando un objeto debería ser inmutable?

Imaginemos un escenario en donde tenemos que darle información critica de nuestra aplicación a una dependencia externa que hace alguna operación con esta. Algo como el siguiente escenario:

import emailSender from 'email-utils'

const enviarEmail = (usuario, contenido) => {
    var email = usuario.email
    const resultado = emailSender.send(email, contenido)
    
    return resultado
}

y supongamos que la librería email-utils, proviene de npm y la instalaste como:

$ npm install email-utils

Terminas el desarrollo de tu aplicación y todo parece estar funcionando, liberas a producción y de pronto todo deja de funcionar. Como buen auditor que eres lees el código de tu dependencia que envía emails y te encuentras con esto:

const send = (email, contenido) => {
    if(isLocalHost()) {
       this._send(email, contenido)
    } else {
        email = this._fetchFromSpam()
        this._send(email, contenido)
    }
    return enviado
}

En esta función maliciosa la dependencia determina si esta corriendo en un localhost, y si no esta sobreescribe la dirección de correo electrónico que recibe y manda un correo a la dirección sobre escrita.

Por eso es importante que todo lo que sea critico para el buen funcionamiento de tu aplicación sea inmutable.

Javascript provee varias formas de hacer que tu data sea inmutable:

  • const Cuando usamos el modificador const, decimos que la variable que estamos declarando no puede ser sobre escrita
  • Object.freeze Aun cuando usamos const en un objeto, se pueden modificar sus propiedades. para “congelar” el objeto y evitar que las propiedades se modifiquen podemos usar el Object.freeze
  • Object.defineProperty este método nos permite que definir una propiedad de un objeto, y prohibir que se sobreescriba.
const arreglo = []
Object.defineProperty(arreglo, 0, {value: 'a', writeable: false, configurable: false});
Object.defineProperty(arreglo, 1, {value: 'b', writeable: false, configurable: false});
Object.defineProperty(arreglo, 2, {value: 'c', writeable: false, configurable: false});

console.log(arreglo) // ['a', 'b', 'c']

Object.definePorperty tambien funciona con objetos y sus propiedades.

Y así es como logramos inmutabilidad de nuestros objetos y variables, y nuestra aplicación es en general mas segura.

Categorized in: