Hace unos meses planificaba como desarrollar un árbol un poco especial, donde cada entidad (representada como nodo) puede tener N padres, N hijos y repetirse; a continuación muestro algunos de los problemas que tuve:
El plan
Lo primero que se me ocurrió al escuchar que en la estructura siempre debe repetirse el nodo, fue aprovechar la copia de referencias de los objetos de javascript. Este comportamiento es llamado call by sharing.
Le agregué pruebas unitarias y todo funcionó como estaba previsto; pero algo salió catastróficamente mal:
Dependencias Circulares
Explicaré este concepto con un ejemplo:
Digamos que tengo un objeto A con una llave donde guardo todos sus hijos, en este caso D y E. De igual forma el objeto D tiene una llave donde guardo todos sus padres, en este caso A y B.
Si revisas los hijos de A verás a D; si revisas los padres de esta D verás a A; si revisas a esta A encontrarás a D nuevamente y así hasta el infinito.
Al representar esto en la pantalla, el modelo se volvía incoherente y se recalculaban solas las dependencias, justo por esto se prefiere objetos inmutables.
En otras palabras, si consultaba cuales eran los padres del nodo aparecían 2 padres iguales; y no solo eso, cuando volvía a consultarlos se ajustaba; era totalmente impredecible.
Solución
Debí reestructurar toda la solución, ahora los nodos solo contienen un padre y N hijos. Cada entidad repetida en el árbol lo represento como un objeto diferente, un objeto inmutable.
Por suerte separé el código lo suficiente para poder ajustar solo las operaciones de CRUD en el código, nada que no se pueda atender dentro del tiempo de desarrollo.
D3.js
Si necesitas representar una estructura compleja, considera utilizar D3.js. Esta es una librería super poderosa que permite representar desde árboles, hasta grafos muy complejos.
La conocí tarde, pero si la hubiera utilizado me hubiera sentido mucho más libre; ya que, provee muchas funciones que tuve que desarrollar a mano.
Igual el lado positivo es que ahora no dependo de D3 y tengo mayor claridad de todo lo que conlleva realizar una estructura como esta.
Por investigar
- Cómo armar árboles con referencias circulares, Angular si lo logra en sus formularios.
- Cómo trabajar con D3.js y controlar todo tipo de errores a partir de validaciones complejas.