09 diciembre 2011

Mapeos Objeto/Relacional

Llegué a la conclusión de que los frameworks de mapeo Objeto/Relacional no sirven.

- Ehh! ¿Por que? Si yo uso Hibernate y esta bueno!

Aca van mis razones...

De Objetos...
Aprendí con el tiempo que la principal ventaja de la programación orientada a objetos es la posibilidad de tratar con distintas implementaciones a traves de su interfaz. 

Si estas pensando que me refiero al polimorfismo, tenes razón, pero di esta vuelta para evitar la tipica asociación de polimorfismo con jerarquias de clases.

Veamos un ejemplo que suele darse en los cursos introductorios: la cuenta bancaria.


Supongamos que tenemos en nuestro sistema un Cajero que puede hacer depositos en estas cuentas:



La instancia cuenta se pudo haber definido mediante una sub-clase, clase anonima, proxy dinamico o usando AspectJ y manipulación de bytecode. No importa. Mientras cumpla con la interfaz CuentaBancaria nuestro Cajero va a funcionar.

... y Relacional
Ahora supongamos que definimos una Cuenta de la siguiente manera:

CuentaBancaria cuenta = new Decorator(cuentaOriginal);

Nuestro Cajero sigue funcionando pero...

motorDeMapeoOR.guardar(cuenta);

explota.

El motor de mapeo O/R necesita saber como tratar la instancia para poder mapear su clase y sus variables de instancia a la base de datos. En otras palabras: encapsulamiento y polimorfismo las pelotas.

Quizas pienses que me fui a un ejemplo extremo y que uno nunca tiene casos como estos. 

Sin embargo en todos los sistemas JEE que veo siempre hay un "modelo" que termina estando sumamente acoplado a la base de datos:
  • No es conveniente jugar con las jerarquias de clases por que no se pueden mapear de una forma buena.
  • No se puede refactorizar algo para cambiar su composición por que es engorroso modificar los mapeos.
  • No se pueden usar objetos más "dinamicos", como objetos que tengan closures (en un lenguaje que lo permita), implemetaciones de interfaces definidas inline o simplemente un decorator como el del ejemplo.
Entonces la solución es: hacemos objetos pobres casi sin comportamiento solo para transferir datos (DTOs). Luego tenemos un modelo mas "rico" que se crea a partir de estos DTOs. 

Suena simple, pero en la práctica termina siendo una engorrosa y aburridisima repetición de código que los programadores tienden a solucionar de forma sencilla: en lugar de separar estos DTOs del modelo de dominio, terminan juntandolo en un modelo de dominio que solo guarda datos y muchas "clases utilitarias". Es decir aprovechan muy poco las posibilidades de polimorfimo que brinda el lenguaje. 

Pero si iba a estar todo tan acoplado y dependiente de la base de datos, ¿Para que nos preocupamos en hacer el mapeo? ¿No era mejor usar algo tipo Active Record? Al fin de cuentas son lo mismo que los DTOs pero con menos código.

Esto es lo que hace Rails y la primera vez que lo vi me parecio una cagada. Huele mal, pero los mapeos O/R no huelen mucho mejor.

...a las conclusiones
Los frameworks de mapeo O/R no cumplen con su promesa de un modelo de dominio libre de la base de datos, y me pregunto cuales son las ventajas en usarlos. Es decir si los usamos solo para facilitar la interacción con JDBC, quizás hay otras maneras que no requieran ningún tipo de mapeo y mantenimiento de "beans" intermedios.

En el caso de Java, creo que si Sun en lugar de definir una interfaz tan fea como la de RowSet que mezcla un montón de responsabilidades, hubiese hecho algo mas sencillo que se pueda usar como un Active Record, no habria razones para utilizar mapeos O/R como JPA.

No hay comentarios.:

Publicar un comentario