2009-06-22 6 views
8

Me gusta el concepto de inmutabilidad, pero a veces me pregunto, cuando una aplicación no debe ser paralela, ¿se debe evitar que las cosas sean inmutables?¿Es la inmutabilidad útil en aplicaciones no paralelas?

Cuando una aplicación no es multiproceso, no está plagado de problemas de estado compartido, ¿verdad?

¿O es la inmutabilidad un concepto como OOP que puede usar por completo o no? Excluir los casos en que algo no debe ser inmutable en función del uso/rendimiento, etc.

Me enfrento a esta pregunta cuando escribo una aplicación para mí, que es moderadamente grande (tal vez como líneas de 1-2k).

+8

El estado inmutable es bueno para aplicaciones multiproceso porque es más fácil razonar sobre la corrección del estado inmutable en escenarios multiproceso. ¡Pero TAMBIÉN es más fácil razonar sobre la corrección del estado inmutable en escenarios de un solo hilo! Es simplemente más fácil razonar sobre cosas que no cambian que razonar sobre cosas que sí cambian. –

+0

@Eric: lol. . –

Respuesta

8

Me encanta la inmutabilidad porque significa que no tengo que confiar en el código de otras personas para no perder el tiempo con los objetos que espero seguir siendo el mismo.

Cuando pasa un objeto a otro componente como List<T>, está a merced de lo que hace ese componente. Esto es especialmente importante cuando devuelve colecciones como propiedades.

public class Foo { 
    private List<Bar> _barList; 
    public ICollection<Bar> BarList { get return _barList; } 
} 

No hay nada que impida que un consumidor de esta clase limpie la recolección. Incluso cambiar el tipo de devolución a IEnumerable<Bar> no es completamente seguro. No hay nada que impida que un fragmento de código mal escrito lo devuelva al List<T> y llamando a .Clear().

Sin embargo, si realmente quiero la colección a permanecer constante pude volver a escribir como followis

public class Foo { 
    private ImmutableCollection<Bar> _barList; 
    public ImmutableCollection<Bar> BarList { get { return _barList; } } 
} 

Ahora estoy seguro de tener que confiar en otros códigos de usar mi clase de forma incorrecta. No pueden estropearlo.

+0

¿ImmutableCollection in BCL? ¿O solo un ejemplo? –

+1

@Joan, es de una biblioteca que tengo. Está disponible en http://code.msdn.microsoft.com/BclExtras – JaredPar

+0

Gracias Jared, lo descargará. –

9

Me gusta la ventaja de la inmutabilidad que solo necesita validar una vez: al crear el objeto. Eso es una gran ventaja en realidad.

+6

Buen punto. Esta idea también tiene implicaciones de seguridad. Supongamos que pasa un objeto mutable X al método Foo. Foo comprueba X para asegurarse de que X es un argumento válido para Foo, arroja si no es así y luego realiza alguna operación sensible a la seguridad basada en X. Si un interlocutor hostil puede mutar X en otro hilo después de la comprobación del argumento, la comprobación del argumento ¡se puede evitar de manera efectiva! Esta es una de las razones por las cuales las cadenas son inmutables en .NET: desea poder decir "abrir este archivo", realizar una comprobación de seguridad en esa ruta y saber que la cadena de ruta no cambiará entre la verificación y el archivo abierto . –

+0

Para hacer esto, se debe usar un patrón de fábrica estático ... sincronizado. –

2

Un beneficio importante de la inmutabilidad es que uno no necesita rastrear la propiedad de los objetos inmutables. Simplemente existen mientras alguien los necesite y luego desaparecen en la nada cuando ya no son necesarios. Si bien utilizar un recolector de basura en muchos casos significa que no es necesario escribir ningún código expreso que trate sobre la propiedad de objetos mutables (la excepción más grande es aquellos que implementan IDisposable), en muchos casos es muy difícil escribir el código correcto en el que los objetos que tienen estado mutable no tiene un "propietario" claramente definido. La confusión acerca de quién posee el estado de los objetos mutables puede ser una fuente frecuente de errores; cuando se usan objetos inmutables (aparte de algunos que implementan IDisposable) generalmente se pueden ignorar los problemas de propiedad.

Otro punto a considerar es que es mucho más fácil razonar sobre una referencia mutable a un objeto semánticamente inmutable, o una referencia inmutable a un objeto mutable, que razonar acerca de una referencia mutable a un objeto mutable. Si uno tiene una referencia mutable a un objeto mutable, a menudo puede no estar claro si el enfoque correcto para actualizar el estado es simplemente mutar el objeto directamente, o copiar su estado a un nuevo objeto, mutar eso y actualizar la referencia. En algunos casos, habrá circunstancias que requieran cada tipo de operación (como con List<T>, que a veces reemplaza una matriz con una matriz más grande, pero por lo general realiza actualizaciones en el lugar), pero tal enfoque solo funciona si el tipo mantiene control exclusivo sobre los objetos mutables en cuestión.A menudo es más útil tener una referencia inmutable a un tipo mutable (en cuyo caso el código puede exponer la referencia, posiblemente a través de un contenedor de solo lectura, a otros objetos que desean una "visualización en vivo" de su estado) o tener un referencia mutable a un objeto que es inmutable o, como mínimo, nunca se mutará durante la vida de la referencia.