CRUD = Create, Read, Update, Delete, para que nos entendamos.
Pocas características útiles son sólo CRUD. Si parece CRUD puede que no hayamos pensado lo suficiente en el punto del vista del usuario final o en las decisiones de arquitectura. Puede ser CRUD, pero en principio lo consideraría un mal olor.
En nuestro proyecto actual estamos implementando la posibilidad de hacer comentarios sobre un usuario. Es decir, unos usuarios hacen comentarios de otros. En un primer momento pensé…
“esto es un CRUD, sólo hay que crear comentarios, borrarlos, publicarlos y despublicarlos… una entidad Comment con unos cuantos campos bastará y el ORM hará todo por mí”.
Antes de lanzarme a tirar código a saco, sin embargo, dediqué unos minutos a analizar la situación.
La postura de “queremos la funcionalidad de los comentarios” expresada tal que así es la típica del product owner que sólo quiere meter más y más funcionalidad pero sin ponerse en la piel del usuario de verdad.
Cuando me puse a pensar como usuario me vinieron estas ideas:
Me gustaría que cuando alguien me hace un comentario, me llegase un email por si quiero poder ocultar el comentario, o simplemente para enterarme el primero. En caso que quiera ocultar el comentario quiero que haya un link directo en el email para que sea rápido y cómodo.
Me gustaría que sólo se mostrasen los últimos N comentarios y que
no me llegasen miles de avisos si algun sistema de spam intenta hacerlo.
En realidad, me gustaría poder configurar cúando me llegan notificaciones por email y cúando no.
Si me hubiese lanzado a hacer CRUD, cuando hubiese querido implementar estas características, que como usuario si me aportan mucho más sentido, probablemente hubiese comenzado el spaguetti code. Total, para hacer CRUD no uso TDD, uso el ORM y a correr. Así que de haberlo hecho, ahora tendría que seguir tirando líneas o borrar y rehacer.
De aquí la importancia de preguntarse realmente qué valor aportan para el usuario, las decisiones que tomamos sobre el producto.
Si lo planteamos ahora desde el punto de vista de la arquitectura, debemos considerar cuestiones como rendimiento, escalabilidad, interfaz de usuario y unas cuantas cosas más.
Me gustaría que los comentarios se almacenasen en caché para que el acceso fuese rápido y pudiese escalar con frontales memcache. Esto implica que antes cambios como el borrado de comentarios la caché se debería actualizar.
Además me gustaría que a la hora de mostrar el comentario, me diese opciones de borrarlo si soy el autor, o de hacerlo invisible o visible si soy el usuario al que va dirigido el comentario. En fin, empieza a no ser trivial la forma en que voy a mostrar la información.
Además quiero que cuando alguien responda a un comentario, la conversación se vea reflejada en forma de comentarios anidados de alguna manera.
Teniendo en cuenta estas consideraciones básicas, si hubiese tirado por el CRUD, de nuevo vendría el spaguetti code.
Como siempre, lo que hemos hecho ha sido pensar primero en los casos que más nos interesan, definir los escenarios y hacer TDD de arriba a abajo sin importar del todo qué campos tendra la entidad Comment. Hemos diseñado la estrategia de caché (como ya teniamos arquitectura de caché, ha sido muy fácil) y con algún mock aquí y allá hemos podido especificar los comportamientos que van a aportar el valor que queremos.
Muchas veces el spaguetti code se produce por no detenerse 2 minutos a pensar como un usuario final o no ponerse el sombrero de arquitecto 😉