Veo los beneficios de hacer que los objetos en mi programa sean inmutables. Cuando realmente estoy pensando profundamente en un buen diseño para mi aplicación, a menudo llego naturalmente a que muchos de mis objetos son inmutables. A menudo llega al punto en que me gustaría tener todos mis objetos inmutables.
Esta pregunta aborda la misma idea, pero ninguna respuesta sugiere cuál es un buen enfoque para la inmutabilidad y cuándo usarla realmente. ¿Hay algunos buenos patrones de diseño inmutables? La idea general parece ser "hacer que los objetos sean inmutables a menos que sea absolutamente necesario que cambien", lo cual es inútil en la práctica.
Mi experiencia es que la inmutabilidad conduce mi código cada vez más al paradigma funcional y esta progresión siempre ocurre:
- Comienzo a necesitar estructuras de datos persistentes (en el sentido funcional) como listas, mapas, etc.
- Es extremadamente inconveniente trabajar con referencias cruzadas (por ejemplo, el nodo de árbol que hace referencia a sus hijos mientras que los niños hacen referencia a sus padres), lo que me hace no usar referencias cruzadas, lo que nuevamente hace que mis estructuras de datos y mi código sean más funcionales.
- La herencia se detiene para tener sentido y en su lugar empiezo a usar la composición.
- Todas las ideas básicas de OOP como la encapsulación comienzan a desmoronarse y mis objetos comienzan a parecerse a funciones.
En este punto, prácticamente ya no uso nada del paradigma OOP y puedo cambiar a un lenguaje puramente funcional. Por lo tanto, mi pregunta: ¿existe un enfoque coherente para un buen diseño OOP inmutable o es siempre el caso de que cuando llevas la idea inmutable a su máximo potencial, siempre terminas programando en un lenguaje funcional que ya no necesita nada del mundo OOP? ¿Hay alguna buena guía para decidir qué clases deberían ser inmutables y cuáles deberían permanecer mutables para garantizar que la POO no se desmorone?
Solo por conveniencia, daré un ejemplo. Tengamos ChessBoarduna colección inmutable de piezas de ajedrez inmutables (ampliando la clase abstractaPiece) Desde el punto de vista de OOP, una pieza es responsable de generar movimientos válidos desde su posición en el tablero. Pero para generar los movimientos, la pieza necesita una referencia a su tablero, mientras que el tablero debe tener referencia a sus piezas. Bueno, hay algunos trucos para crear estas referencias cruzadas inmutables dependiendo de su lenguaje OOP, pero son difíciles de manejar, mejor no tener una pieza para hacer referencia a su tablero. Pero entonces la pieza no puede generar sus movimientos ya que no conoce el estado del tablero. Luego, la pieza se convierte en una estructura de datos que contiene el tipo de pieza y su posición. Luego puede usar una función polimórfica para generar movimientos para todo tipo de piezas. Esto se puede lograr perfectamente en la programación funcional, pero es casi imposible en OOP sin verificaciones de tipo de tiempo de ejecución y otras malas prácticas de OOP ... Entonces,