El mundo avanza veloz, y con el la supervivencia económica empresarial y los negocios. Este hecho ha influido notablemente en el mundo de la tecnología de la información y en especial en el sector del desarrollo de software. Por ello cada vez existe más la necesidad de reutilizar y aprovechar soluciones a problemas comunes que son encapsulados bajo marcos de trabajo o Frameworks.
Más allá del subjetivo y retórico debate acerca del pragmatismo o purismo de utilizar un framework por asunción y por resolver un problema de negocio cuanto antes, dejando de lado aveces el conocimiento en profundidad del mismo; es una labor más obligatoria que loable de un ingeniero de software conocer la posible deuda técnica y rendimiento de cara al futuro de la selección de un marco de trabajo frente a otro. Elegir es eliminar y por tanto cuando usamos un Framework seleccionamos y eliminamos problemas que pueden aparecer a corto o largo plazo.
Una de las partes más críticas cuando se emprende un proyecto de software empresarial es la parte de los datos –capa de Datos– [1]; y por ello es necesario a la hora de utilizar un Framework de persistencia conocer a que nos enfrentamos y tratar de tomar la mejor decisión. El problema principal a resolver en esta capa es el GAP existente entre los datos almacenados en la base de datos –SQL o NOSQL– y los datos almacenados temporalmente en el modelo de dominio, particularmente en las base de datos relacionales que no contemplan la herencia. En ese sentido, el nivel de abstracción requerido para hacer frente al GAP, nos puede conducir a plantearnos entre usar Clases que Persistan o utilizar Persistencia de Clases.
Las Clases que persisten
Las Clases que Persisten, generalmente se apoyan en el modelo ActiveRecord y su filosofía es la de que los objetos almacenen datos, comportamiento y algo de lógica de negocio para el dominio de ese objeto. De esta forma, cada objeto es responsable de conocer sus limitaciones de dominio y sabe además como persistir en la base de datos. Este patrón de diseño se apoya en el uso de la abstracción por herencia de clases –generalización– y tal como describe Martin Fowler en [2] la estructura de datos de los objetos deben ser idénticas a las de la base de datos.
El uso de esta técnica es ideal cuando nos encontramos con lógica de negocio que no presenta mucha dificultad más allá del típico CRUD. Resulta fácil de implementar y de entender, por lo que si se está comenzando un proyecto que requiere «arranque rápido» o se está trabajando en un prototipo, pudiese ser un buena elección.También puede resultar válido cuando se presenten objetos de dominio cuya responsabilidad solo sea persistir data.
Según Fowler en [2], uno de los principales problemas de las clases que persisten viene dado cuando las tablas de la base de datos no son isomórficas con respecto al modelo de dominio. Esto sucede cuando la lógica de negocio es muy compleja, lo que obliga a utilizar relaciones directas, colecciones y herencia, que no son fáciles de «mapear» con Active Record. Otro problema con ésta estrategia es la imposibilidad de usar herencia entre los objetos de dominio, pues ya el objeto esta extendiendo de la clase padre con las operaciones propias de ActiveRecord, lo que abre un cuadro de limitaciones importantes de cara a mantener clases que reflejen el negocio que se está representando. Muchos detractores de éste patrón alegan además, que al encapsular lógica técnica y de negocios en un mismo objeto viola el principio SRP (Single responsibility principle), por lo que para los más «puristas» puede culminar siendo una pesadilla. El siguiente código es un ejemplo en el lenguaje Ruby del patrón:
class Order < ActiveRecord::Base belongs_to :customer end
La persistencia de clases
Esta estrategia se apoya en el modelo Data Mapper y su filosofía consiste en partir de la base de que los objetos y las bases de datos relacionales contienen mecanismos distintos de estructuración. En ese sentido, y siguiendo los principios SRP(Single responsibility principle), se mantienen separadas las responsabilidades de lógica de negocio y de persistencia. Así el modelo Data Mapper actúa como pieza de software mediadora entre los objetos de negocio en memoria y la capa de datos.
Como afirma Fowler en [2], el principal argumento a favor de ésta estrategia es cuando se presenta el caso de que los objetos de dominio y las bases relacionales evolucionan independientes entre sí. Esto propicia que se pueda enfocar directamente en los problemas de negocio sin importar la capa de datos subyacente. Además, no requiere uso de herencia por parte de los objetos de dominio, lo cual puede ser muy valioso–sobre todo en entornos de test–.Es muy recomendado para modelos de dominio complejos.
En cuanto a las principales desventajas, este modelo debe pagar un precio por el beneficio de la separación de responsabilidades: La capa extra entre el dominio y los datos. Ésta capa al usar la técnica de nivel de indirección, por otro lado introduce un marco de complejidad con el que muchas veces es difícil de lidiar y costoso de implementar. Afortunadamente hoy en día existen infinidad de marcos de trabajo que nos pueden ayudar en ésta peligrosa y dura tarea. El siguiente ejemplo en Ruby ilustra el patrón:
class Article attr_reader :comments def initialize(args = {}) @comments = args.fetch(:comments) { Array.new } end def << comment comments << comment end end
¿Con cual me quedo?
Como todo en este mundo, y en especial en el mundo de la ingeniería, la respuesta es simple: Depende del contexto y el problema a solucionar. Para algunos casos será mejor usar clases que persistan (modelos de dominio sencillos, prototipos, proyectos de mínima viabilidad económica, etc) y para otros la persistencia de clases (modelos de dominio complejos, aplicaciones de evolución de datos isomórficas). Lo importante –y el error que muchos desarrolladores cometemos a menudo de acción por omisión– es entender los fundamentos de cada propuesta y tomar una decisión solida que nos permita saber a que atenernos de cara al futuro. En ese sentido, tal como dice Ralph Waldo Emerson, filósofo estadounidense:
En lo que respecta a los métodos, puede que haya un millón o más, pero de principios hay pocos. El hombre que comprende sus principios acierta eligiendo sus propios métodos. El hombre que va probando métodos, ignorando los principios, tendrá problemas.
REFERENCIAS
[1] Fox and Patterson.Engineering Long-Lasting Software: An Agile Approach Using SaaS and Cloud Computing . Strawberry Canyon LLC (2012)
[2] Fowler, Martin.Patterns of enterprise application architecture. Addison Wesley (2002)