Mapeo de Objetos y Tablas Relacionales (O/R-M). Lo Que a Mí me Sirvió

 Hace  unos diez meses atrás había posteado sobre el Desajuste por Impedancia entre Objetos y Tablas Relacionales, mencionando como una de las estrategias para corregir ese desajuste a los Mapeadores entre (Propiedades de) Objetos y (Columnas de) Tablas Relacionales. Los conocidos O/R-M u Object/Relational Mappers

Esta es una alternativa de la cual yo conozco (de veras, no bromeo) innumerables casos de proyectos donde sus responsables entran con la guardia baja pensando que están adoptando una solución políticamente correcta que les va a allanar el camino, acortar tiempos de desarrollo y lograr un producto más robusto y mantenible

Pues bien, voy a ser concreto: Ted Neward, una distinguida voz para los mundos modernos tanto de Java Enterprise Edition (Java EE) como de Microsoft .NET, se refiere a esta solución como "El Vietnam de las Ciencias de la Computación". Para ello, escribió un post muy polémico donde comienza relatando su visión sobre las expectativas que Estados Unidos tenía en el momento de embarcarse en la guerra de Vietnam, y lo que la guerra en sí misma terminó significandole (desafortunadamente, el hombre es el único animal que tropieza dos veces con la misma piedra)

De ese relato hace luego una analogía con lo que los arquitectos de software comienzan creyendo que van a lograr al emplear mapeadores O/R en sus aplicaciones, y lo que viene luego aparejado. Como tocó un tema sensible para sus propios compatriotas (Ted es estadounidense), y para colmo de males hizo esa comparación en un momento igualmente sensible, recibió un sinnumero de críticas que lo obligaron, 24 horas más tarde, a publicar una aclaración en las razones que lo motivaron a usar esa guerra como ejemplo de lo que suele pasar en los proyectos donde se usa esta técnica

También un tal Diego Dagum, Diegum para los íntimos, charlatán de aquellos si los hay, publicó allá por Agosto del año pasado un post en el que se refería al antipatrón, a la mala costumbre, de sobrecargar las arquitecturas con chirimbolos pensados ante eventualidades de dudosa probabilidad de ocurrencia (probabilidad, al menos, discutible). Esa sobrecarga hace luego que al montar la aplicación sobre dicha arquitectura, todo el sistema colapse (o peor, que colapse el arquitecto -me he enterado de algún que otro casillo de arquitectos que terminaron cableados posando para el electrocardiograma –respire hondo… retenga… … largue el aire-). En este post mencionaba varios ejemplos típicos de ese comportamiento cuestionable de algunos arquitectos, ilustrando uno de ellos con un caso aparecido en los Foros de Arquitectura de Microsoft. En realidad uno de los tantos que han aparecido relacionados con O/R-M en dicho Foro de Arquitectura

En este case, mi contraparte en la discusión terminaba admitiendo que había llegado al pantano en que estaba porque la idea detrás de todo ello sonaba bien. A eso lo llamamos "pisar el palito" o "quedarse a escuchar cantos de sirena", en mis pagos

A continuación te quiero enlistar una serie de recomendaciones de mi propio folklore, después de haber fracasado con el enfoque O/R-M y atenuado un poco la magnitud de los daños. La lista es tan completa como la puedo escribir hoy en base a mis memorias (a la mie…). Creo que te va a servir mucho conocer mis conclusiones al respecto

  1. Primer Mandamiento: si todavía no te metiste con O/R-M, no te metas entonces. A cambio tratá de modelar primero procesos, a nivel de negocio, y allá donde necesites entidades de negocio, usa lo que la plataforma en la que estás desarrollando te deja más a mano. Lo crucial acá es no forzar abstracciones innecesarias: conozco casos en que alguien, no voy a dar nombres, me decía "hay que usar colecciones (tales como el "Collection Framework" de Java o las APIs de colecciones de .NET) ya que así no te condicionás a que por detrás pueda haber una base de datos, un conjunto de servicios web o archivos XML para el entorno de desarrollo"
    Suena políticamente correcto, no? Bueno. Si sos de los que piensan así te sugiero releas el post de "Demasiada Arquitectura". Normalmente cuando el proyecto comienza, hay varios datos que ya existen -a no ser que me cuentes que la compañía recién se está abriendo-, en tanto que otros datos sí van a comenzar a persistirse una vez que la aplicación esté en producción. En cualquiera de estos casos, la decisión de sí bases de datos, servicios web, integrador Tuxedo, etc, se toma de antemano y esa decisión incluso no la toma el arquitecto de la aplicación. Esa decisión normalmente será parte de una estrategia corporativa y la puede llegar a tomar el arquitecto empresarial (o Gerente de Arquitectura, es decir, un arquitecto que no está en ninguna aplicación específica de la organización sino en el portfolio completo de estas), como el Jefe de Tecnología, el director de Sistemas, etc
    Ejemplos: si la organización compró un motor de bases de datos relacional (RDBMS), no sólo vas a tener que leer y escribir los datos de la aplicación en una base de datos: lo vas a tener que hacer en esa base de datos. Si la organización firmó un convenio con algún tercero para que le provea ciertos servicios que involucran datos (por ejemplo, una empresa externa que administra la contabilidad de tu organización), es probable que un conjunto de servicios (no necesariamente web) sustituya a la base de datos corporativa. Pero en este caso el enfoque sería híbrido, de modo que ciertos datos se almacenen en una base de datos de tu organización en tanto que otros "viajen" al proveedor del servicio
    La probabilidad de que se decida cambiar en el corto plazo normalmente es baja (sí, lo es, no me des vueltas, pls que tengo que seguir con el post), con lo cual siendo que la organización está esperando ansiosa que termines la aplicación, agarrate del hecho que la decisión de dónde van a ir los datos ya fue tomada, y encolumnate detrás de esa decisión y sacale el jugo a full a esa decisión
    Tratar de construir abstracciones por si algún día decidieran cambiar no sólo te van a comer un tiempo precioso de desarrollo y time-to-market: en ejecución te van a comer un tiempo precioso… de ejecución justamente, cuando malgastes ciclos de CPU convirtiendo a listas u otras representaciones agnósticas de la implementación los datos que te llegan del mecanismo de persistencia (o los que envías al mismo). Considerá acá que el tiempo que perdés en desarrollo es tiempo acotado al período de desarrollo del proyecto, a lo sumo demora el lanzamiento, pero es tiempo que se pierde una vez. En cambio el tiempo que se disipa en ejecución es tiempo que vas a perder durante todo el período que ese código malogrado esté en producción
    Yo sé que lo que planteo a más de un romántico anti vendor lock-in no le va a caer simpático y probablemente crea que lo que pretendo en el fondo es hacer lobby por el software comercial, para que te metas con patas y todo en una plataforma específica y luego sea tanto lo que lleves hecho en la misma que nunca más se justifique cambiarla (o de lo contrario, todo el tiempo invertido se perdería)
    Pero eso no es verdad. Mi motivación es otra: si la decisión de ir por un IBM DB/2, por un Oracle o por lo que sea está ya tomada, en mérito al rendimiento y a la escalabilidad, sacale el máximo provecho que la infraestructura ponga a tu disposición -dado que seguramente eso es lo que la Dirección esperaba cuando pagó la licencia de dicha infraestructura-. Irse por el mínimo común múltiplo de todas las posibles bases de datos es desaprovechar justamente lo que tu base de datos ofrece y que hace la diferencia. Como comprarse una 4×4 y no querer meterte nunca en caminos de tierra, poceados y embarrados, por la eventualidad de que mañana te toque bajarte a un Corsa
    Estoy esperando a que me preguntes "y si finalmente unos años después se decide cambiar, qué?". Si se decide cambiar, se presupuesta el costo de reescribir la lógica de persistencia (acá no des por asumido que vas a tener que escribir toda esa lógica de vuelta, sólo las equivalencias), y pasa a ser costo de la migración. Está claro que cuando desarrollamos software quisieramos que dure tanto como sea posible. Pero todo el software tiene una vida útil y a la larga hay que alinearlo a las nuevas plataformas tecnológicas. Pensar que es tirar una inversión ya hecha es falaz: cuánto creés que te saldría hoy mantener sistemas de décadas atrás en COBOL o incluso en Assembler? Es como los autos muy viejos: empieza a salir caro mantenerlos porque los repuestos ya no se consiguen. Claro, el secreto está en que no tengas que tirarlo tan rápido, pero la expiración de la vida útil le llega a todos
    Existe un caso que no estoy mencionando, que es el de los desarrolladores que no tienen una BD disponible y quieren usar a cambio archivos XML para simular datos que se crean y se graban. Si tal es el caso, te propongo a cambio que metas tus datos mock en una planilla Excel, una pestaña por tabla, y al string de conexión lo hagas apuntar a una fuente de datos ODBC (detalles acá mismo). La aplicación siempre lo va a ver como una conexión JDBC o ADO.NET de acuerdo a la plataforma en la que estés corriendo. Es decir, elegí alternativas que te ahorren escribir demasiado código si lo que pretendías era ahorrar costos
  2. Sea que te hayas embarcado en O/R-M o no, privilegiá el modelado de tus objetos de negocio en forma local al módulo o caso de uso por sobre global el global a la aplicación. Lo que me sirve a mí es dividir las aguas de la siguiente manera: los datos los modelo según como los quiero guardar (o quizás ni tengo que molestarme en pensar cómo los voy a guardar si los datos son legacy de aplicaciones existentes con lo cual sólo debo pedir por ellos). En la lógica de aplicación, más bien me focalizo en modelar el proceso (cuya unidad visible a nivel de negocio es el caso de uso, aunque éste a su vez se puede descomponer en subcasos de funcionalidad ad hoc)
    Sería muy dificil que un caso de uso no deba acceder a datos mas, cuando deba hacerlo, mi propuesta es que el caso de uso tenga asociadas entidades de negocio que le vengan a la medida, que esté garantizado que esas entidades contengan los datos que le son necesarios sin que ello implique que deban contener todos los restantes datos asociados a la entidad
    Caso práctico: si el caso de uso de aprobación de crédito necesita conocer que la edad de quien pide el crédito sea mayor o igual que 21 años, la fecha de nacimiento la necesitás sí o sí. En cambio, la dirección del cliente, al menos para esta funcionalidad, que esté o no es accesorio (seguramente sí va a hacer falta cuando el crédito sea aprobado y se proceda a ingresar entonces el préstamo asociado
    Normalmente no es malo que casos de uso de un mismo módulo tengan un modelo de entidades compartido y quizás también reusen varios mecanismos de persistencia (Objetos de Acceso a Datos -llamados DAO por su sigla en inglés-, procedimientos almacenados, etc). Es lo deseable, y se justifica cuando obtener esa información es sencilla (digamos, uno o dos round-trips a la base de datos por entidad de negocio). Deja de serlo cuando tenemos que realizar varios accesos por una misma entidad, para traer datos que en realidad en el caso de uso no van a ser utilizados
    Caso práctico otra vez: necesito recuperar las cuotas impagas de un cliente para calcular sus días de mora, aplicar multas y mostrarle así al cliente la deuda actualizada. Es realmente necesario traer además el detalle de los bienes y servicios incluídos en cada una de las cuotas? Estoy hablando puntualmente de este caso de uso, eh? Si en uno o pocos round-trips a la base de datos me traigo todo, quizás no es tan malo (ojo, acá juega también cuántas cuotas son: si -supongamos que el caso pudiera darse-, el cliente debe 40 cuotas, así en un round-trip me trajese la cabecera y en otro el detalle… es deseable evitar este último si realmente no se va a hacer nada con el detalle
    Atención a esto que te estoy contando acá, porque los O/R-M suelen decepcionar a quienes optaron por ellos en esta parte: o hidratan (así se llama a la acción de recuperar uno o más registros en un objeto) demasiados objetos innecesarios -con los consecuentes posibles problemas de escalabilidad en lo que esto puede derivar-, o por evitar sobrehidratación terminan viajando reiteradamente a la base de datos para buscar información relacionada con una misma entidad de negocio (por ejemplo la Cabecera de un movimiento, después sus items, despues los productos asociados con estos items, y así sucesivamente), derivando esto en problemas de rendimiento
    Mi consejo, estés o no con O/R-M, es que no te mates en pensar objetos reusables a lo largo de toda la aplicación sino quizás acotados a los módulos en que son protagonistas (aquellos donde se crean, se modifican, se listan, etc; no donde se consultan por propiedades específicas que contengan). En los puntos que siguen te voy a sugerir ciertas reglas del pulgar para lidiar con el peligro de la sobrehidratación
  3. Usá carga perezoza (lazy loading) en asociaciones de agregación y carga proactiva (eager loading) en asociaciones de composición. Vamos por el principio: en los diagramas de clases de UML se conciben dos tipos de asociaciones entre objetos. Las asociaciones de composición, que establecen que si un objeto de la clase A se compone de objetos de la clase B, el ciclo de vida del objeto A determina la vida de los objetos asociados de clase B. En otras palabras, cuando el objeto A muere, sus objetos B lo acompañan a ese "Más Allá" hasta que el Garbage Collector barra sus cenizas. Y del mismo modo, el objeto A nace antes que sus objetos B. Un típico caso es cuando A representa Factura y B DetalleFactura. A este tipo de asociación se la grafica con un diamante negro, como se ve en la figura 1 a la izquierda


    Figura 1 – Asociaciones en UML:
    Composición (diamante negro)
    y Agregación (diamante blanco)

    En cambio en la misma figura, pero a la derecha, podemos ver una asociación con el diamante de color blanco. Estas son las llamadas asociaciones de agregación. En estas asociaciones, el ciclo de vida de A no condiciona a los de sus B asociados. Un típico caso es A representando un Curso (una materia de la facu, un seminario, etc) y B representado por los Alumnos inscriptos al mismo. Si por alguna razón el Curso se cancela, la asociación con los Alumnos se pierde pero estos no desaparecen
    Entonces, la regla del pulgar que te estoy contando acá no es infalible pero, ante la duda, aplicarla te va a sacar de un apuro hasta que la termines de afinar. Los mapeadores O/R te permiten, al definir cómo se mapean objetos en tablas, sus propiedades en columnas y sus asociaciones en tablas relacionadas, si vas a querer cargar las asociaciones al recuperar objetos de la clase A en la figura 1 o no. Si vas a querer recuperar los B asociados, al toque que recuperás un objeto A, se dice que es carga proactiva o eager loading. Si, en cambio, te vas a aguantar de cargar los B hasta el momento de necesitarlos realmente, se dice que es carga perezoza o lazy loading
    Como te decía en el punto anterior, acá está el dolor de cabeza de O/R-M: si elegís carga proactiva siempre, podés terminar hidratando objetos innecesariamente porque no los vas a necesitar. Esto, como te decía, podría conducir a problemas de escalabilidad: qué pasaría sí por pedir un Cliente para saber su edad, terminás cargando todas sus Cuentas, que a su vez cargan todos los Bienes y Servicios que llevan contratados, y estos últimos hacen que se recuperen todos los Productos que llevan asociados, Mecanismos de Facturación, etc? Cuánta memoria consumirías nada más en ese requerimiento? Cuánto tiempo aguantaría el servidor si la carga de usuarios que está ejecutando ese caso de uso es elevada?
    Lógico, tal vez con esto que te digo te agarra cuiqui y no vas a querer ni plantearte la carga proactiva. Entonces juguémonosla por la carga perezoza siempre. En el ejemplo de la edad del Cliente va a andar bien. Pero ahora te paso al caso de uso de la baja del Cliente. Dar de baja al Cliente implica dar de baja a cada una de sus cuentas, para que no sigan facturando servicios o bienes, o eventualmente devengando intereses. Si dar de baja cada Cuenta a su vez implicase cambiar algún estado en objetos de los que la Cuenta se compone, cuántos round-trips a la base de datos tendrías? Al menos sin O/R-M acá podemos hacer un mega JOIN de SQL (INNER JOIN, OUTER JOIN, el que convenga) y en un solo pique a la base de datos nos podemos traer un resultado tabular que quizás en estructura sea más fulero que Betty la Fea, pero al menos le va a sacar provecho a la polenta de la base de datos, en lo que la base de datos ya tiene afinado para rendir y escalar. En quizás uno o dos roundtrips tenemos toda la data que el caso de uso necesita (uno o dos es un decir: siempre va a depender del caso de uso pero la cosa es evitar, cuando se pueda, acceder a nivel de tabla si las relaciones también son necesarias). De lo contrario, desde el punto de vista del usuario, el rendimiento de la aplicación para ese caso de uso se va a ver pobre
    La pregunta entonces es, cuándo conviene carga proactiva y cuando perezoza, de modo de no caer ni en problemas de escalabilidad ni en problemas de rendimiento?
    Entonces acá entra en juego lo que te aconsejaba en este punto: al configurar los mapeos de asociaciones de objetos en relaciones de tablas, siempre que dudes pedí carga proactiva para asociaciones de composición, carga perezoza para agregaciones. El problema de la mayoría de los mapeadores O/R es que el mapeo, se define a nivel de clase y queda fijo para todos los casos de uso. Un embole realmente porque el nivel de datos requerido para una misma clase varía una enormidad a lo largo de todos los casos de uso. Por ejemplo, si pido un Cliente, me viene ya con las Cuentas de las que el Cliente se Compone ahora, y si quiero listar todos los clientes que contrataron un determinado servicio en un dado período… para qué quiero traer sus Cuentas? Lo único que necesito listar es cierta información de cada Cliente. Pero nada asociado a sus Cuentas! Para peor, si cada Cliente en promedio tiene 3 Cuentas, y tengo que listar 500 (quinientos) clientes… hidraté de yapa 1500 (mil quinientos) objetos al cuete como oreja de sordo!! La realidad es que la reglita del pulgar de este punto es aplicable cuando lo que necesitamos traer es un número reducido de entidades de negocio: un Cliente con sus Cuentas… dos Clientes con las Cuentas de ambos si el caso de uso es de una transferencia o cosas así, pero no cuando la cantidad de Clientes no se conoce de antemano, o bien al menos se conoce de que van a ser varios. Para esos casos (tipicamente reportes) descartá esta regla por la regla que sigue

  4. En escenarios de recupero de grandes volúmenes de información (como reportes, por ejemplo), hacé uso de los lenguajes de consultas que los O/R-M traen. Por ejemplo, NHibernate viene con su Hibernate Query Language (HQL), que con una sintaxis algo similar a SQL, te permite consultar cosas de objetos en lugar de tablas. Eventualmente, y pensalo bien, estos mapeadores te permiten introducir comandos SQL nativos de la base de datos real a la que estés accediendo. Cuando te convenga, no seas gil: usalos. No te dejes ganar por la testarudez de que entonces tu aplicación va a perder portabilidad
    Es que en realidad, con los reportes, pasa algo que yo ya comentaba en el post de Desajuste por Impedancia: los reportes tienen una estructura que es de por sí tabular, cuadrada. Las tablas, como su nombre sugiere, son tabulares, cuadradas. El arquitecto que no entiende que no tiene mucho sentido hidratar tablas de la BD en grafos de objetos multidimensionales para, a su vez, transformar a estos en un reporte tabular, cuadrado… yo no digo que sea tabular él (el arquitecto) pero sí que es moooooooooooy cuadrado
  5. Y finalmente, para cerrar, vuelvo al comienzo: si podés evitar caer en los O/R-M, hacelo. Por ejemplo, te voy a contar lo que hacemos nosotros hoy. Tenemos un conjunto de casos de uso que están relacionados con un determinado tipo de objeto que a su vez tiene todo un grafo de otros objetos asociados. Normalmente en estos casos de uso en que te comento que tenemos que acceder a nuestro objeto y su grafo, aunque vos no me creas, recuperamos todo en un solo acceso a la BD y persistimos todo (leélo: todo) en un solo acceso a la BD, de nuevo. Cómo hacemos? Sencillo:
    Tanto Java como .NET tienen mecanismos de serialización, que son extensibles. La serialización por defecto en Java es binaria, aunque se puede extender para que sea XML (y si no lo querés extender vos, existe un proyecto open source llamado XStream, entre tantos otros). La serialización en .NET, en cambio, es por defecto XML excepto que le indiques al serializador que utilice el protocolo binario (claro, .NET surgió después que Java: el que ríe último ríe mejor, je-je)
    La clave de nuestro secreto está en la serialización XML puesto que las bases de datos ya hoy van comenzando a admitir XML como formato de intercambio
    Lo cierto es que en nuestro proyecto se usa una base de datos que es fija. Quiero decir, la probabilidad de que cambien es escasa (nunca voy a decir que es nula pero tiende a 0 en los próximos años). Como la base es fija y es corporativa (o sea, otro ya se tomó la molestia de eligir por nosotros), decidimos sacarle el máximo provecho. Para ello nos valemos de la facultad que esta base de datos tiene, que es capaz de generar XML como resultado de un SELECT (incluso un XML con nodos anidados si el SELECT tiene sub SELECTs anidados) y también de recibir como argumento un flujo XML y parsearlo, descomponerlo
    Cuestión que definimos un par de procedimientos almacenados (stored procedures): uno para el alta y/o modificación del grafo de objetos, otro para el recupero del mismo -oigo por ahí algún arquitecto murmurar que no se debe hacer uso de procedimientos almacenados porque no son portables… prefiriendo en cambio mandar, desde la capa de acceso a datos, una serie de comandos SQL, no? Te propongo releer Repudio de la Infraestructura si sos de los que piensan eso-
    Como te contaba, entonces, el primer procedimiento almacenado recibe el chorizo XML que .NET produjo al serializar nuestro grafo, lo parsea con el soporte XPath que la base de datos trae, cortándolo en rebanadas. Así, INSERTa, o actualiza (UPDATE) las tablas necesarias. Normalmente el alta o modificación de esta entidad de negocio suele ser en promedio un total de unos cinco (5) INSERT/UPDATE registros en unas cuatro (4) tablas distintas. Un O/R-M que no tiene soporte para procedimientos almacenados se va a pegar los cinco piques hasta la base de datos. Creéme, te lo aseguro, que eso va a demorar más que el overhead que admitidamente agrega nuestra serialización / deserialización + parseo para un solo roundtrip
    El otro procedimiento almacenado es simétrico: nos valemos de la posibilidad que la base de datos ofrece de generar SQL anidados, formateando la salidad en XML para generar una imagen serializada de mi grafo de objetos. Eso es justamente lo que la aplicación recibe y se lo pasa sin demoras al deserializador de .NET que a cambio hidrata el grafo con el que teníamos que trabajar
    Lo interesante del caso es que estos procedimientos almacenados se usan sólo en aquellos casos de uso donde recuperar / guardar ese particular grafo de objetos es necesario. Y en ningún lado más: en efecto, esas mismas tablas, con esas mismas columnas, eventualmente nutren otros grafos de objetos similares pero no equivalentes, para otros casos de uso donde no quisimos forzar situaciones por tener una única representación de objetos para toda la aplicación
    Finalmente, para reportes, el DataReader de ADO.NET es una masa (es similar al ResultSet de JDBC). Ma qué objetos ni que rabanitos. Mandamos la query que necesitamos, que nos devuelve un DataReader. Y de ahí generamos sin más demoras el reporte que necesite (y a liberar la conexión que el prójimo no puede esperar, ché)

Un abrazo y ojalá que esto sirva

Esta entrada fue publicada en patterns and practices. Guarda el enlace permanente.

9 respuestas a Mapeo de Objetos y Tablas Relacionales (O/R-M). Lo Que a Mí me Sirvió

  1. paulo dijo:

    Diego te acabo de enviar un email con mi contacto y ya que estamos aprovecho para sugerirte si puedes escribir algo del nuevo Entity Data Framework de Orcas desde un punto de vista arquitectónico.
    Nos vemos.

  2. Pablo dijo:

    Diego, muy buen post. Excelente combinación de Conceptos Tecnicos y experiencia concreta.
    En octubre del año pasado, hice una referencia en mi blog a tu post de "Too Much Architecture", agregando una experiencia propia de un proyecto nuestro, donde justamente habiamos decidido no usar un ORM para resolver la persistencia de la aplicacion. Las razones que nos llevaron a tomar la decision tenian que ver entre otras cosas con varias de las razones que citas mas arriba.
     
    Saludos.-

  3. Diego dijo:

    Gracias por leérme, Pablito
     
    Y te digo más: si que me acordaba de vos. Si mal no recuerdo no había sido Too Much Architecture el post que recomendaste: había sido Infrastructure Repudiation -sobre esos archies que antes que comprar nada ya hecho y maduro te dicen "lo arreglemo con alambre", y ahora que lo releo digo "la pucha que vale la pena mencionarlo!"

  4. Javier dijo:

    Hola Diegum:
    Acabo de leer tu artículo. Has hecho un relato muy bueno, está lleno de conceptos y ejemplos. Te felicito.
    Soy estudiante de Ingeniería con muchas ganas de aprender nuevos horizontes. Estos últimos días me senté a ver de qué trata NHibernate y cómo puedo aplicarlo a pequeños proyectos. Me he llevado una grata sorpresa, porque no me encontré con lo que esperaba, suponía una facilidad y ligereza tal que no tendría que tipear tanto código, pero no es así.
    Lamentablemente hay mucho laburo por delante, pero las ganas siguen intactas. La idea es aprender y adquirir experiencia.
    Saludos cordiales.
    Javier Ramos

  5. Diego dijo:

    Allo, Edu, un gustazo y un lujo que tu blog me haga eco! Y a ver si puedo conseguir minitas como conseguiste vos (llega a leer esto mi mujer y me acribilla)
     
    Oíme, sobre NHibernate te paso una serie de notas que se le hizo a oren Eini, el israelita que maneja proyecto
     
    Oren Eini -NHibernate and Rhino MocksOren Eini on NHibernate
    ARCast: NHibernateThe ORM Smackdown! (versus Ted Neward: Oren a favor de los ORM y Ted en contra)
     
    No está nada malo que lo aprendas, te vas a divertir un rato. Ahora, entre nos -vos confirmame si después no es así- no creo que llegues a hacer nada serio con eso

  6. Fabian Andres dijo:

    Muy bueno tu blog ….M egustaria saber que tan efectivo es agregar n ORM(nhibernate) en un proyecto cuando se actualizan datos muy periodicamente……es conveniente ……o que es mejor implementar mecanismos de serialización…

  7. Diego dijo:

    Allo Fabián,
       honestamente, es difícil decir "sí, conviene" o "no, no hagas eso nunca" por la siguiente razón:
     
       *) Por aplicar O/R-M te vas a evitar de crear y mantener enormes detalles de una capa de acceso a datos, y también la legibilidad de tu capa de negocio va a ser altísima gracias a que el O/R-M te va a habilitar con mucha sencillez a manejar objetos planos (es decir, que no heredan ni se casan con ninguna API específica más que la que vos mismo creás). Es decir, ganancia evidente en el ámbito del desarrollo de la aplicación
       *) En cambio, si la carga de trabajo concurrente (workload) que tu aplicación tiene es muy alta (varios usuarios concurrentes, varios registros siendo modificados por cada transacción o bien por unidad de tiempo -segundos, etc-) el karma del punto anterior se va a evaporar tan rapidamente que tanto a tus usuarios como a vos mismo les va a hacer perder la karma  😀
       Es decir, puede ser negativo en tiempo de ejecución
     
       Mis detractores me objetan que doy el punto oscuro de O/R-M por seguro cuando no todas las aplicaciones tienen alta carga de trabajo, etc. Lo cual es cierto
     
       Sería bueno hagas una prueba de concepto "hidratando" y "deshidratando" varios objetos de manera de simular carga para ver hasta dónde se la va a bancar tu ORM. Para esa PoC, claro, no necesitás construir la app entera sino basicamente concentrarte en hidratar / deshidratar objetos a lo pavote para encontrar el punto de quiebre (algo como "si los requerimientos concurrentes son 100, se cae de rodillas si le hacen hidratar/deshidratar 50 objetos cada uno; si son 200 usuarios, percha a los 20; etc"

  8. moebius dijo:

    Suponiendo que la probabilidad de cambiar la base de datos es baja, eso justifica que no usemos un ORM ?"Al menos sin O/R-M acá podemos hacer un mega JOIN de SQL (INNER JOIN, OUTER JOIN, el que convenga)"Con los ORM se puede hacer JOIN tranquilamente…"El problema de la mayoría de los mapeadores O/R es que el mapeo, se define a nivel de clase y queda fijo para todos los casos de uso."La verdad que no tengo idea de que pasará con la "mayoría" de los mapeadores, pero con NHibernate se puede hacer tranquilamente por caso de uso."…los O/R-M suelen decepcionar… o hidratan … demasiados objetos innecesarios … o por evitar sobrehidratación terminan viajando reiteradamente a la base de datos …"Otra vez, "suelen", eso quiere decier que hay algunos que no ?Con NHibernate se pueden traer los objetos que necesites según tu caso de uso y listo, que algunos (o muchos) ORM no puedan hacerlo no significa que los ORM no sean una buena solución."..los reportes tienen una estructura que es de por sí tabular, cuadrada." que sea cuadrada significa algo ? un reporte puede estar mostrando una tabla muy simple y con pocos datos, pero hay que ver cómo se calculan esos datos, pueden implicar una lógica muy compleja. Y si esa misma lógica ya está implementada, entonces que vas a hacer, duplicarla en un SP o en una consulta SQL porque va a andar más rápido ? o buscar alternativas que no impliquen duplicar la lógica ?Quizás el tema sea elegir un buen ORMSobre el Punto 5, se puede ver el código ? cómo queda ese procedimiento almacenado usando XPath ? Queda algo fácil de entender y mantener ?

  9. lenintv dijo:

    Muy buen Articulo. sobre todo la parte de sacarle el maximo provecho a las herramientas con las que cuenta la organizacion.

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s