Entendiendo la inmutabilidad: Qué es, para qué sirve y cómo usarla

En estos años en los que los lenguajes funcionales están comenzando a transformarse en opciones alternativas reales en prácticamente todos los campos, uno de los conceptos que acostumbra a venir asociado a ellos es el de la imperturbabilidad.

Aunque es verdad que la imperturbabilidad es una idea que no es exclusiva de la programación funcional, sí que cobra una relevancia vital en este género de lenguajes.

La programación funcional se asienta sobre muchos conceptos matemáticos que precisan de la imperturbabilidad para proseguir siendo válidos.

Todavía de esta manera, creo que es un término que es interesante de comprender con independencia del tipo del paradigma de programación que emplees.

La imperturbabilidad hace nuestro código considerablemente más predecible, pues somos más siendo conscientes de dónde se generan los cambios de estado.

¿Qué es la imperturbabilidad?

La idea es sencillísima de entender: algo es inalterable cuando no se puede alterar.

En el contexto de la programación, una variable es inalterable cuando su valor no se puede alterar. Y un objeto lo es cuando su estado no puede ser actualizado tras la creación del objeto.

Es en consecuencia una forma de asegurarnos que nuestro objeto no se altera en lugares inopinados, afectando con esto la ejecución de nuestro programa.

¿Dónde aplica la imperturbabilidad?

La imperturbabilidad facilita mucho el tratamiento de la concurrencia

Fuera de la programación puramente funcional, donde ya comentaba que su necesidad es más rigurosa, la imperturbabilidad nos puede ahorrar muchos quebraderos de cabeza.

Imaginemos por poner un ejemplo que trabajamos en Java, y tenemos una clase con esta forma:

public class Person undefined

Si bien en Java se utilizarían getters y setters en general, lo podemos dejar de esta forma por facilitar.

Si ahora en cualquier punto de la aplicación tenemos una función que usa un objeto de tipo Person, este puede ser cambiado desde dentro de ella sin problema:

public void doSomething(Person person) undefined

En un caso tan simple puede no tener sentido, e inclusive hay formas de disminuir al mínimo los inconvenientes con reglas estrictas sobre en qué momento se puede alterar un objeto y en qué momento no.

Mas al final la opción está ahí, y cuando los programas se vuelven grandes y aparecen las prisas, se terminan cometiendo violaciones de esas reglas.

En un punto donde produce muchas ventajas es en las aplicaciones multihilo, donde la imperturbabilidad facilita mucho el tratamiento de la concurrencia. Si algo no se puede alterar, da lo mismo que se acceda a ello desde diferentes hilos al unísono, como el orden en que se haga.

La imperturbabilidad, por norma general, hace nuestro código considerablemente más predecible, pues somos más siendo conscientes de dónde se generan los cambios de estado.

¿De qué manera se logra la imperturbabilidad?

Como la API de Java no es inalterable, cualquier empleo que hagamos de ella es susceptible de violar la imperturbabilidad

En los lenguajes dispuestos para ello, es bastante fácil, puesto que la propia sintaxis nos facilita mucho la labor. En lenguajes como Scala podemos hacer una variable inalterable sencillamente utilizando val en vez de var para declararla:

val p = new Person(name, surname)

En Java tampoco es mucho más difícil. Es sencillamente incorporar la palabra final a cuanto queramos hacer inalterable. Si por servirnos de un ejemplo, deseamos hacer la clase Person inalterable, solo deberíamos hacer lo siguiente:

public final class Person undefined

De este modo, ya podemos estar seguros de que el estado de este objeto no se alterará. Un tanto más verboso, mas fácil ¿verdad?

Los inconvenientes brotan en el momento en que nos hallamos con situaciones más complejas. Como la API de Java no es inalterable, cualquier empleo que hagamos de ella es susceptible de violar la imperturbabilidad.

Pongamos por poner un ejemplo que la persona guarda un listado de personas que son sus hijos:

public final class Person undefined

Por más que hagamos la lista inalterable, su estado es alterable, con lo que podemos hacer:

person.children.add(new Person(n1, s1));

Con lo que de nuevo tenemos exactamente el mismo inconveniente. Existen muchas formas de solventar esto, como hacer children privado y permitir el acceso a sus hijos a través de un procedimiento, emplear las unmodifiable collections del SDK o bien alguna librería que ofrezca compilaciones inalterables como Guava. O bien sencillamente utilizar un array.

Resumiendo, si deseas cerciorarte de que algo es inalterable, debes estar seguro de que los estados de los objetos que emplea esa clase para su estado asimismo lo son.

¿De qué forma se altera el estado en un ambiente inalterable?

Es posible que te estés haciendo esta pregunta. Si todo es inalterable, no hay cambios de estado, y por lo tanto el programa no va a hacer nada.

La manera de alterar un objeto inalterable es sencillamente copiarlo alterando los valores precisos. De nuevo, los lenguajes que prestan atención a la imperturbabilidad tienen mecanismos para hacer esto fácil. Por poner un ejemplo si tenemos una data class en Kotlin:

data class Person(val name: String, val surname: String)

El lenguaje ya nos provee de una función copy que va a hacer el trabajo duro por nosotros:

val p1 = Person(p1, s1)
val p2 = p1.copy(surname = s2)

En Java sería un tanto más complejo, mas tampoco tiene mucha historia:

Person p1 = new Person(p1, s1);
Person p2 = new Person(p1.name, s2);

Las listas inalterables marchan igual. Si agregamos un factor a una lista, realmente se nos devuelve otra lista que tiene todos y cada uno de los objetos de la precedente más el nuevo.

¿Vale la pena emplear imperturbabilidad siempre y en todo momento?

Si estás desarrollando con el paradigma de orientación a objetos, hay ocasiones en las que probablemente no valga la pena. La imperturbabilidad tiene el sobrecoste de la generación de objetos nuevos toda vez que cambia el estado, con lo que esto puede penalizar bastante en el desempeño.

Como guía muy general, es conveniente emplear objetos alterables en los próximos casos:

En objetos con estados muy grandes, cuando la copia de un objeto pueda suponer un tiempo de ejecución notable.
Objetos que precisan ser construidos poquito a poco, por el hecho de que no podamos conseguir todo el estado de cuajo.
Sostener el estado de ejecución

Y por norma general, cualquier situación que requiera de un estado que se altera frecuentemente y/o la duplicación de ese estado sea costosa.

La imperturbabilidad, por contra, presenta ventajas en las próximas situaciones:

En objetos que no vayan a requerir modificaciones de estado
Objetos que sean simples de duplicar, aun si bien se alteren de forma ocasional
En situaciones de concurrencia

Como comentaba ya antes, la imperturbabilidad hace que el código sea considerablemente más predecible y más simple de probar, pues delimitamos considerablemente más los lugares donde se generan modificaciones de estado.

Conque una regla simple puede ser la de hacer inalterable todo el código que resulte posible.

Conclusiones

La imperturbabilidad es un término muy potente que nos puede asistir a facilitar la dificultad de entendimiento de nuestro código y, por consiguiente, a reducir las posibilidades de que se generen fallos inopinados.

Si bien en programación orientada a objetos no sea tan indispensable como en funcional, es interesante conocer esta idea para aplicarla donde más útil nos pueda parecer.

¿Conocías este término? ¿Lo empleas frecuentemente? Y si no, ¿te semeja interesante para aplicarlo en tu cada día?

hljs.initHighlightingOnLoad();

code.hljs undefined
@media only screen and (min-width: 768px) undefined
@media only screen and (min-width: 1024px) undefined

Asimismo te invitamos a

Ciertas ideas para desarrollar para Galaxy Aplicaciones y llevarse unos gadgets de Samsung en el proceso

El gobierno de USA se pone del lado de Oracle en la guerra de las APIs

BDD, Cucumber y Gherkin. Desarrollo dirigido por comportamiento

– La nueva

Entendiendo la inmutabilidad: Qué es, para qué vale y de qué forma emplearla

fue publicada originalmente en

turincon.net

por
Antonio Leiva

.