Mutable versus inmutable describe si los sistemas, la infraestructura o los datos se pueden cambiar después de la creación. Los recursos mutables se pueden modificar in situ. Los recursos inmutables no se pueden cambiar; cualquier modificación crea una nueva instancia.
Mutable frente a inmutable es un principio que impulsa los enfoques modernos tanto para el desarrollo de software como para la gestión de infraestructura.
La distinción se puede comparar con escribir texto en una pizarra. Si puede agregar palabras, borrar partes o cambiar lo que está escrito, es como un recurso mutable. Pero si la pizarra está sellada bajo un vidrio en el momento en que termina y debe usar una nueva pizarra para escribir otra cosa, ese es un recurso inmutable.
Si bien este concepto se aplica ampliamente en la informática, se encuentra más comúnmente en la programación. En programación, comprender qué tipos de datos se pueden modificar directamente y cuándo se debe crear una nueva copia es esencial para las tareas comunes. Estas tareas incluyen escribir algoritmos, crear interfaces de programación de aplicaciones (API) y diseñar clases en programación orientada a objetos (OOP).
La elección de usar objetos mutables o inmutables afecta la forma en que se gestionan los datos en la memoria, la seguridad con la que se pueden compartir o cambiar y si pueden producirse efectos secundarios no deseados. Esta es la razón por la cual mutable versus inmutable es un concepto fundamental tanto para programadores principiantes como experimentados.
Por ejemplo, en el lenguaje de programación Python, las listas y los diccionarios son tipos mutables. Los elementos se pueden agregar, eliminar o modificar dentro de esos objetos. Por el contrario, los objetos como los booleanos (valores verdaderos o falsos) o las tuplas (colecciones ordenadas como (1,2,3)) son tipos inmutables. Sus contenidos no se pueden cambiar ni mutar sin crear un objeto completamente nuevo.
Boletín de la industria
Manténgase al día sobre las tendencias más importantes e intrigantes de la industria sobre IA, automatización, datos y más con el boletín Think. Consulte la Declaración de privacidad de IBM.
Su suscripción se entregará en inglés. En cada boletín, encontrará un enlace para darse de baja. Puede gestionar sus suscripciones o darse de baja aquí. Consulte nuestra Declaración de privacidad de IBM para obtener más información.
Elegir entre datos mutables e inmutables generalmente depende de tres factores clave: si los datos necesitan actualizaciones frecuentes, si se comparten entre subprocesos o si requieren un historial de versiones.
Los tipos mutables generalmente funcionan mejor cuando los datos necesitan actualizaciones frecuentes y varias partes de un programa modifican el mismo objeto.
Los objetos mutables modifican los datos en su lugar, lo que reduce el uso de memoria al evitar la necesidad de crear nuevos objetos. Puede reducir el uso del procesador de la recolección de elementos no utilizados (el proceso de eliminar datos no utilizados para liberar memoria) porque es posible que sea necesario crear y recopilar menos objetos temporales.
Por ejemplo, los carritos de compras en las aplicaciones usan listas mutables para agregar o eliminar artículos directamente sin crear nuevos objetos para cada cambio.
Los tipos mutables funcionan mejor con datos que cambian con frecuencia, como listas crecientes o contadores en tiempo real, porque actualizan los objetos existentes en lugar de crear otros nuevos. Esta eficiencia acelera las operaciones en estructuras de datos que dependen de modificaciones rápidas.
Por ejemplo, la lista de reproducción de una aplicación de música puede usar una lista mutable para realizar actualizaciones rápidas. Puede hacerlo en microsegundos cuando se agrega o elimina una canción, en comparación con volver a crear una lista de reproducción de 1000 canciones para cada cambio.
Los objetos mutables permiten que varias partes de un programa accedan y cambien el mismo objeto. Este proceso les permite trabajar con un estado compartido: los datos que varios componentes leen y escriben para coordinar sus acciones. Es útil cuando los componentes necesitan coordinarse o comunicarse a través de datos comunes.
Por ejemplo, una aplicación de gestión de proyectos utiliza objetos mutables para compartir listas de tareas, calendarios y notificaciones. Cuando un miembro del equipo actualiza una tarea, todos ven el cambio de inmediato.
Los tipos inmutables suelen funcionar mejor cuando los datos no deben cambiar después de su creación. Es especialmente importante en aplicaciones con concurrencia, donde varias partes de un programa acceden a los mismos datos.
Debido a que el estado de un objeto inmutable es fijo, no se verá alterado por otro código. Esta característica hace que los programas sean más predecibles y fáciles de entender porque elimina errores relacionados con mutaciones inesperadas.
Por ejemplo, las aplicaciones bancarias suelen almacenar registros de transacciones como objetos inmutables para que Sin código pueda alterarlos más adelante. Es crítico para ayudar a garantizar el cumplimiento normativo y mantener registros de auditoría que demuestren que las transacciones no han sido manipuladas.
Los objetos inmutables generalmente son seguros para subprocesos porque su estado no puede cambiar después de la creación. Varios subprocesos pueden leerlos de forma segura y simultánea sin conflictos, aunque los desarrolladores aún deben administrar las referencias con cuidado en sistemas concurrentes. Los hace ideales para programas de subprocesos múltiples, donde varios subprocesos deben acceder a los mismos datos sin causar conflictos.
Por ejemplo, una aplicación puede ejecutar hilos simultáneos para las condiciones actuales, pronósticos y alertas. Almacenar datos meteorológicos como objetos inmutables significa que cada hilo puede leer la misma información sin el riesgo de que cambie inesperadamente.
Los objetos inmutables pueden simplificar la depuración porque los valores no cambian inesperadamente durante la ejecución del programa. Esta característica puede reducir los errores causados por efectos secundarios y ayudar a los equipos a resolver problemas más rápido.
Por ejemplo, los videojuegos suelen almacenar el estado y las estadísticas de los jugadores como objetos inmutables. Debido a que estos valores no pueden cambiar inesperadamente, los desarrolladores pueden rastrear fácilmente los errores sabiendo que el código no relacionado no alterará las estadísticas.
Dos de los estilos de programación más utilizados, la programación orientada a objetos (POO) y la programación funcional, abordan la mutabilidad de manera diferente.
La programación orientada a objetos a menudo adopta la mutabilidad, creando programas en torno a objetos que contienen tanto datos como comportamientos. Estos objetos pueden cambiar con el tiempo mediante el uso de funciones especiales llamadas setters, que pueden actualizar el valor de una propiedad (por ejemplo, cambiar la edad de una persona o el precio de un producto).
Por el contrario, la programación funcional se inclina hacia la inmutabilidad. Crea y devuelve nuevos valores cada vez que algo necesita cambiar, lo que hace que los programas sean más predecibles y fáciles de probar.
Los lenguajes de programación también varían en su enfoque de los tipos mutables frente a los inmutables.
En Python, tanto los tipos mutables como los inmutables son comunes.
Un ejemplo son las cadenas, secuencias de caracteres, como nombres o oraciones. Las cadenas en Python son inmutables. Al agregar texto nuevo, se crea un nuevo objeto de cadena. Por el contrario, las listas son mutables. Estas colecciones ordenadas son iterables: puede agregar, eliminar o modificar elementos dentro del objeto de lista.
En lugar de usar un compilador (un programa que convierte el código en lenguaje de máquina antes de la ejecución) para verificar el código antes de que se ejecute, Python verifica los tipos en tiempo de ejecución. Significa que los errores se detectan solo mientras el programa se está ejecutando. Los errores relacionados con la mutabilidad, como intentar modificar una cadena inmutable, desencadenan un TypeError.
Si no se maneja el error, detiene el programa inmediatamente, evitando que se ejecute más código. Este procedimiento permite un desarrollo más rápido, pero requiere una cuidadosa atención al manejo de tipos.
Comprender la mutabilidad en Python ayuda a prevenir errores al compartir datos entre funciones o trabajar dentro de un módulo compartido. Los tutoriales y ejemplos de código en GitHub proporcionan las mejores prácticas para usar los tipos integrados de Python.
JavaScript utiliza tipos mutables e inmutables. Al igual que Python, las cadenas también son inmutables. Sin embargo, a diferencia de Python, todos los objetos son mutables de forma predeterminada.
La sintaxis flexible de JavaScript admite estilos orientados a objetos y funcionales, lo que permite a los desarrolladores gestionar la mutabilidad según sea necesario.
Al igual que Python, las cadenas de Java son inmutables. Una vez creada, el valor de una cadena no puede cambiar. Esta característica puede ser ineficaz para los programas que crean o modifican texto con frecuencia.
Para dar dirección a este problema, Java proporciona StringBuilder, una clase de cadena mutable que permite modificar el texto directamente sin crear nuevos objetos. Puede mejorar el rendimiento y reducir el uso de memoria, equilibrando la seguridad de la inmutabilidad con los beneficios de rendimiento de la mutabilidad.
C++ utiliza la palabra clave const para marcar variables, funciones e incluso objetos completos como de solo lectura. Puede dar a los desarrolladores un control detallado sobre la mutabilidad, convirtiendo eficazmente un objeto mutable en uno inmutable al evitar cambios.
Al igual que Java, las cadenas de C++ pueden ser mutables o inmutables, según su implementación.
C++ admite estilos de programación orientados a objetos y funcionales. En el estilo OOP, los desarrolladores modifican los objetos existentes a lo largo del tiempo, mientras que la programación funcional crea nuevos valores en lugar de cambiar los datos existentes.
Los principios de mutabilidad frente a inmutabilidad se extienden más allá de la programación a la infraestructura y los sistemas. Los ingenieros de software modernos aplican estos mismos conceptos al diseñar arquitecturas en la nube y canalizaciones de despliegue.
La infraestructura mutable se refiere a servidores u otros recursos de TI que se pueden cambiar después del despliegue. Por ejemplo, puede iniciar sesión en un servidor y actualizar manualmente el software, cambiar configuraciones o instalar parches. Si bien este enfoque ofrece flexibilidad, puede conducir a una desviación de la configuración en la que los servidores se convierten en "copos de nieve" únicos y los cambios se vuelven imposibles de rastrear o reproducir.
La infraestructura inmutable significa que los servidores o los recursos de TI no se pueden cambiar después del despliegue. En lugar de actualizar los sistemas en ejecución, los equipos despliegan nuevas instancias con cambios incorporados y luego retiran las antiguas. Este enfoque reduce la desviación de la configuración, simplifica la reversión y ayuda a garantizar despliegues coherentes.
Los principios de mutabilidad e inmutabilidad también pueden aplicarse a otras áreas del diseño de software y sistemas.
Algunas bases de datos utilizan registros de solo anexar, lo que significa que cada cambio se registra de forma permanente y no se puede modificar. Otros son mutables, lo que permite actualizaciones o eliminación de datos directamente, como editar un documento.
Ciertos sistemas de almacenamiento en la nube se pueden configurar como almacenamiento inmutable para mantener las versiones anteriores y bloquearlas contra cambios. Esto ayuda a proteger los datos para que no se modifiquen o eliminen accidentalmente. El almacenamiento mutable permite editar o reemplazar archivos en cualquier momento.
Muchas herramientas de control de versiones, como Git, siguen un modelo inmutable, en el que cada confirmación se guarda como una instantánea independiente e inmutable. Ayuda a garantizar un historial confiable de versiones, incluso cuando se agregan nuevos cambios.