viernes, 8 de mayo de 2015

La concurrencia y el estancamiento de datos no es lo mismo.

Hablando con un compañero de trabajo me he percatado que todavía hay quien no entiende la diferencia entre los problemas con el estancamiento de datos y los problemas con la concurrencia cuando se trabaja con persistencia. De hecho el problema no es sólo entender la diferencia de estos 2 conceptos; si no comprender también el proceso que debe seguir la aplicación para aplicar correctamente los cambios en una entidad persistida y con acceso concurrente.

Para ilustrar esto voy a poner un sencillo ejemplo y lo iremos comentando: Supongamos una app web (que debido a su estado desconectado es perfecta para ilustrar el problema) que gestiona una lista de clientes.

El proceso de actualizar los datos de un cliente debe ser el siguiente con un modelo de concurrencia optimista:
  1. - Leemos de persistencia los datos del cliente y lo enviamos al navegador del usuario. 
  2. - El usuario modifica la dirección de facturación y envía esa información de vuelta a nuestra aplicación en el servidor.
  3. - Nuestro servidor debe de leer de nuevo de persistencia la entidad Cliente.
  4. - Ejecutamos la función de cambiar la dirección que debe tener la entidad Cliente pasándole por parámetro la nueva dirección.
  5. Una vez ejecutada con éxito la acción de cambiar la dirección se modificará esa entidad en persistencia.
A partir del punto 3 está la chicha de la cuestión y surgen preguntas que me voy a autoresponder.

¿Por qué una entidad cliente?
Diseño OO básico. Encapsulamos los datos y reglas e invariantes del dominio que deban trabajar con esos datos.

¿Por qué leer de persistencia de nuevo la entidad para modificarla en vez de regenerarla en memoria?
Porque, incluso aunque tengamos todos los datos para regenerarla enviada por el usuario al servidor, la aplicación de las reglas e invariantes del dominio por parte de la entidad puede depender de otros datos que han cambiado en persistencia mientras nuestro usuario escribía la nueva dirección y la enviaba al servidor. Esto es el problema de estancamiento de datos.

¿Entonces cuál es el problema de concurrencia?
El problema de concurrencia es cuando la entidad cambia entre los milisegundos que pasan entre que hemos leído la entidad de nuevo en el punto 3, le aplicamos los cambios en memoria en el punto 4 y la volvemos a persistir. El haber aplicado ya las reglas de dominio con datos desactualizados es el problema de concurrencia.

¿Cómo soluciono los problemas de concurrencia?
En el caso de concurrencia optimista cada tupla tendrá un sello de tiempo de su última modificación o algo por el estilo. Si, al persistir la entidad, el sello de tiempo no es igual al que se encuentra en persistencia en ese momento debemos lanzar un error indicando la situación y actuar en consecuencia. También tenemos a nuestra disposición transacciones y bloqueos para otros modelos de solución.

¿Y cómo soluciono el problema de estancamiento de datos?
Pues, aunque te sorprenda lo que te voy a decir, de ninguna manera. Los problemas de estancamiento no tienen técnicas concretas para ser solucionados. Los problemas de estancamiento de datos desaparecen con un buen diseño de la aplicación. Simplemente hay que tenerlos en cuenta cuando se diseña.

Una buena interfaz de usuario orientada a tareas y no a CRUD,  una correcta segregación de comandos y acciones, una buena encapsulación de responsabilidades, etc; todo esto es lo que nos ayuda a evitar los problemas de estancamiento de datos.

Ateniéndonos al caso que nos ocupa; si algún dato de la entidad Cliente ha cambiado sin el conocimiento del usuario pueden pasar varias cosas:
  1. - Que ese nuevo dato no importe para asignar la nueva dirección según las reglas del dominio. Por lo tanto, la entidad Cliente, incluso después de ser leída en el paso 3, aceptaría la nueva dirección sin ningún error y todos contentos. 
  2. - Que ese nuevo dato evite que la entidad Cliente acepte la nueva dirección. Esto provocaría un error de las reglas del dominio al intentar ejecutar la acción de cambiar dirección en el paso 4. Simplemente notificar al usuario que no se ha podido actualizar la dirección del cliente por la restricción de turno y refrescar su vista. El usuario verá el nuevo estado de la entidad y actuará en consecuencia. 
  3. - Que ese nuevo dato modificado sea la dirección de facturación del cliente. Pues en este caso la última en llegar gana :-D Si dos usuarios de la aplicación tienen sendas solicitudes de cambio de dirección de facturación en el sistema, probablemente sea la misma dirección, así que poco nos importa que se cambie 2 veces con el mismo valor; y en el caso de que sean direcciones diferentes el problema no es de nuestra aplicación.
¿Por qué no es problema de nuestra aplicación?
Una solicitud de cambio de dirección tiene que ser anterior en fecha y/u hora a la otra forzosamente. Si los usuarios de la aplicación no actualizan el sistema por orden de llegada y no se organizan el trabajo decentemente no es un problema de estancamiento de datos puesto que esto mismo puede ocurrir si al día siguiente otro usuario gestiona una petición de cambio de dirección de hace una semana cuando ya se había almacenado una de hace un día por otro usuario.

No hay comentarios:

Publicar un comentario