significado programación programacion objetos mutables inmutables inmutable inmutabilidad funcional ejemplos dios clases design functional-programming immutability

design - programación - Objetos funcionales inmutables en dominio altamente mutable



programacion funcional inmutabilidad (8)

Para mí, parecería que habría un enjambre descomunal de nuevas instancias cada ''tic''.

De hecho, ese es el caso. Tengo una aplicación Haskell que lee un feed de datos del mercado (cerca de cinco millones de mensajes en el transcurso de un día de negociación de seis horas, para los datos que nos interesan) y mantiene el "estado actual" para varias cosas, como el los precios y cantidades más recientes de ofertas y ofertas para los instrumentos, qué tan bien encaja nuestro modelo en el mercado, etc. etc. Es bastante aterrador simular una ejecución de este programa frente a una alimentación grabada en el modo de perfilado y verlo asignar y GC cerca de 288 TB de memoria (o cerca de 50,000 veces el tamaño de la memoria RAM de mi máquina) en los primeros 500 segundos de su ejecución. (La cifra sería considerablemente mayor sin crear perfiles, ya que la creación de perfiles no solo ralentiza la aplicación, sino que también obliga a que todo se ejecute en un núcleo).

Pero tenga en cuenta que el recolector de basura en implementaciones de lenguaje puro está optimizado para este tipo de comportamiento. Estoy bastante satisfecho con la velocidad general de mi aplicación, y creo que es bastante exigente, ya que tenemos que analizar varios cientos de mensajes por segundo a partir de la información del mercado, hacer algunos cálculos bastante extensos para construir nuestro modelo y usar eso modelo para generar pedidos para ir al intercambio lo más rápido posible.

Actualmente estoy aprendiendo programación funcional en mi tiempo libre con Scala, y tengo una pregunta para principiantes ociosa.

Puedo ver la elegancia de tener objetos inmutables al hacer algo como calcular una transformada wavelet de Haar, es decir, cuando los datos que están siendo representados por los objetos no cambian.

Pero vi un blog donde alguien tenía un pequeño juego como ejemplo cuando demostraba la inmutabilidad. Si un objeto de criatura recibió daño, no cambió su estado: devolvió un nuevo objeto de criatura con los nuevos puntos de golpe y una nueva bandera de "aggro hacia X". Pero si tuviéramos que diseñar algo así como un MMORPG, World of Warcraft dice. Cien jugadores en un campo de batalla ... posiblemente miles de ataques y efectos de hechizo debilitador / debilitador que los afectan de diferentes maneras. ¿Todavía es posible diseñar el sistema con objetos completamente inmutables? Para mí, parecería que habría un enjambre descomunal de nuevas instancias cada ''tic''. Y para obtener la instancia de objetos actualmente válida, todos los clientes tendrían que pasar constantemente por algún tipo de objeto central de "mundo del juego", o?

¿Escala la programación funcional para esto, o es este un caso de "mejor herramienta para el mejor trabajo, probablemente no inmutable aquí"?


Como casi todas las herramientas de programación, los objetos inmutables son potentes, pero peligrosos en la situación incorrecta. Creo que el ejemplo del juego no es muy bueno o al menos muy artificial.

Eric Lippert tiene algunas posts interesantes sobre el tema de la inmutabilidad, y son bastante interesantes.



Es importante tener en cuenta al diseñar un programa funcional que, como usted dice, los objetos inmutables tendrán una sobrecarga. También es importante recordar que tener objetos en tu programa de MMORPG ser inmutable será intrínsecamente más escalable. Por lo tanto, la inversión inicial en equipos puede ser mayor, pero en el futuro, a medida que las cosas se expandan, podrás escalar a tu base de jugadores.

Otra cosa importante a considerar es que ahora las máquinas más robustas tienen 6 núcleos por CPU. Considere una máquina de doble CPU con 6 núcleos cada uno. Uno de estos 12 núcleos puede estar haciendo recolección de basura y, por lo tanto, la sobrecarga de derribar muchos objetos se puede compensar con la aplicación que se puede ampliar fácilmente a esos otros 11 núcleos.

También recuerde que no todos los objetos (y sus sub objetos) deben reconstruirse por completo en una copia. Cualquier tipo de referencia que no haya cambiado solo tomará una única asignación de referencia cuando se "copie" un objeto.


No piense en la creación de objetos en el nivel del cable. Por ejemplo, un tiempo de ejecución optimizado para un lenguaje funcional probablemente podrá "engañar" cuando se trata de reemplazar un objeto y una mutación real de la estructura existente, si no sabe nada hará referencia al original y el nuevo lo reemplazará por completo. Piense en Optimización de la Recursión de la Cola, pero aplicado al estado del objeto.


Normalmente, en la programación funcional no tendrá constructores de estilo C ++. Entonces, aunque conceptualmente está creando objetos todo el tiempo, eso no significa que el compilador tenga que crear un código para asignar un nuevo objeto, porque no puede afectar el comportamiento del programa. Como los datos son inmutables, el compilador puede ver qué valores acaba de especificar y qué ha pasado a sus funciones.

Entonces, el compilador puede crear un código compilado muy ajustado que simplemente calcula los campos en los objetos específicos cuando son necesarios. Qué tan bien funcione esto depende de la calidad del compilador que use. Sin embargo, el código de programación funcional limpio le dice al compilador mucho más acerca de su código que lo que podría suponer un compilador de C para un programa similar, por lo que un buen compilador puede generar un código mejor de lo que cabría esperar.

Entonces, al menos en teoría, no hay razón para preocuparse; las implementaciones de programación funcional pueden escalar al igual que las implementaciones de asignación de montón orientadas a objetos. En la práctica, debe comprender la calidad de la implementación del idioma con la que está trabajando.


Un MMORPG ya es un ejemplo de inmutabilidad. Dado que el juego se distribuye entre los servidores y los sistemas de los jugadores, no existe absolutamente ningún objeto central de "mundo del juego". Por lo tanto, cualquier objeto que se envíe por el cable es inmutable, ya que el receptor no lo cambia. En cambio, se envía un nuevo objeto o mensaje como respuesta, si es que hay uno.

Nunca he escrito un juego distribuido, así que no sé exactamente cómo se implementan, pero sospecho que las actualizaciones de los objetos se calculan localmente o se envían como diffs a través del cable.

Por ejemplo, estás jugando a Command & Conquer. Tu mamut tank está sentado en el modo listo protegiendo tu base. Tu oponente se acerca con un tanque ligero para explorar tu base. Tu tanque de mamut dispara y golpea el tanque de tu oponente, causando daño.

Este juego es bastante simple, así que sospecho que se calcula mucho localmente siempre que sea posible. Supongamos que las computadoras de los dos jugadores están inicialmente sincronizadas en términos de estado del juego. Luego, tu oponente hace clic para mover su tanque ligero a tu base. Se le envía un mensaje (inmutable) por el cable. Dado que el algoritmo para mover un tanque es (probablemente) determinista, tu copia de Command & Conquer puede mover el tanque de tu oponente en la pantalla, actualizando el estado de tu juego (podría ser inmutable o mutable). Cuando el tanque ligero se encuentra dentro del alcance de tu enorme tanque, tu tanque se dispara. Se genera un valor aleatorio en el servidor (en este caso, una computadora se elige arbitrariamente como el servidor) para determinar si el disparo golpea a su oponente o no. Suponiendo que se golpeó el tanque y se debe hacer una actualización del tanque de su oponente, solo se difunde el hecho de que el nuevo nivel de armadura del tanque se ha reducido al 22% para sincronizar los juegos de los dos jugadores. Este mensaje es inmutable.

Si el objeto en la computadora de cualquiera de los jugadores es mutable o inmutable es irrelevante; se puede implementar de cualquier manera. Cada jugador no cambia directamente el estado del juego de otros jugadores.


Un punto a tener en cuenta sobre la inmutabilidad es que (si se implementa correctamente) hace que la creación de objetos sea relativamente liviana. Si un campo es inmutable, se puede compartir entre instancias.