9 de octubre de 2010

Desarrollando en Capas

Hace algún tiempo llegue a trabajar a una empresa donde tenían ya algunos sistemas implementados, la empresa tenía la necesidad de añadir funcionalidad a dichos sistemas, comencé a revisarlos y me di cuenta de algo, no existía la capa de negocio (Domain o Business como la quieran llamar), me pregunte muchas veces el porque sin llegar a una respuesta, tenían 2 capas híbridas(porque no eran ni uno ni lo otro), una para la vista y  una para acceso a datos, pero, las reglas del negocio estaban mezcladas entre la vista y el acceso a datos, lo cual significa que una nueva regla de negocio o una modificación involucraba mover por todos lados sin tener la certeza que funcionara, así que pensé en escribir algo sobre el como, el porque, el cuando y el donde, yo usaría las 3 capas convencionales (Presentación, Negocio y Acceso a datos).


Definitivamente una de las formas mas frecuentes que encontramos a la hora de desarrollar alguna aplicación, sistema o lo que sea que involucre código es la programación en capas (bueno hay sus excepciones).

La teoría básica de la programación en capas, es tener la posibilidad de separar partes que conforman un sistema. Pensemos en un pastel (el 3 leches es mi favorito)  que esta hecho de varias capas de varios sabores y que aparte esta cubierto de merengue o cualquier otro menjurje que se les ocurra. La primera capa es ocultada por la segunda, la segunda por la tercera y así hasta tener un pastel de n capas, finalmente tendremos la cubierta que es la presentación al consumidor, aún cuando la presentación es la que atrae al comprador, si las demás capas tienen mal sabor seguramente el cliente no regresará por otro pastel.

La idea de las capas es también que podamos poner sobre esta una o varias mas con la idea de poder crear cosas diferentes sobre la misma base, imaginen un pastel como el siguiente (repito imaginen):

Si cortamos 3 rebanadas, una con fresa, otra con uva y otra con naranja, las tres sabrán a chocolate, pero la combinación con el sabor de la capa superior los hará diferentes (no necesariamente sabrá bien).

Lo mismo ocurre en los sistemas, sobre de una capa es posible montar otras, que tengan funcionalidades diferentes, pero en su interior comparten algo (similar a la herencia).

Así que una programación en capas proporciona muchos beneficios.

     - Desacoplar el sistema, tener ahora varias cabezas que atacan un problema.
     - Independizar el funcionamiento entre las capas.
     - Aislar la repercusión de un cambio en una capa a las demás.
     - Definir estándares para cada capa, de manera que cada una pueda tener sus propias reglas en su juego.
     - Que sobre una capa puedan montarse muchas otras aún cuando estas tengan diferentes objetivos.

Sin embargo no todo es miel sobre hojuelas, también tiene algunas desventajas.

     - El caso mas típico es que unaUI necesite mostrar algún dato y que la capa de datos no lo tenga   disponible, eso significa que se deberán modificar todas las capas desde el acceso a datos hasta al interfaz de usuario.
     - Entre mas capas se tengan mas lento se volverá el desempeño, generalmente cada capa tiende a hacer una "traducción" de lo que recibe para poder usarlo a su conveniencia, lo cual quiere decir que si existen 5 capas habrá 5 transformaciones, "malo", el desempeño se vuelve lento.

Entendiendo el asunto de las capas

En mis primeros ejercicios de programación en la escuela tenia que modificar archivos, y cosas así realmente era muy simple, no tenía la necesidad de separar mi código.


Mientras pasaba el tiempo comenzó a aumentar la complejidad de tal manera que ahora usábamos las Amadas y Odiadas Bases de Datos. Al principio siguiendo el mismo patrón era copiar cierta información de un archivo y pasarlo a la base de datos y viceversa. El problema llego cuando apareció un maestro que nos enseño a crear UIs, y después teníamos que crear un ABCC (Altas, Bajas, Cambios y Consultas), como todo buen estudiante, seguí el mismo patrón, una sola capa con todo el código, sin embargo después de crear un solo ABCC ahora tenia que crear varios, y tuve la necesidad reutilizar código especialmente la parte para establecer la conexión a la base de datos.

Fue así como tuve la necesidad de tener 2 capas (la verdad no las llamaba así), la capa para manejar la Interfaz del Usuario y la capa para acceder a los datos.


Hasta ahí todo era felicidad, sin embargo llego el momento de desarrollar sistemas mas complejos basados en especificaciones mas realistas lo que se llamaría como "Lógica de Negocio" o "Modelo de Dominio" o "Lógica de Dominio", se llame como se llame esta parte hace referencia a reglas especificas de como funciona alguna situación en particular, por ejemplo:

Cuando un estudiante va a reinscribirse, primero hay que ver si tiene derecho, revisando si aprobó el 50% de sus materias del curso pasado, y si tiene derecho a beca por haber obtenido un promedio "X" y además si hay cupo en las materias que selecciono.

Ahora no se trata solo de agregar un registro a la base de datos, se trata de que antes de eso hay que validar varias cosas .

Para ser franco cuando esto paso, mi primer instinto fue poner todas esas reglas como parte de la presentación y todo sencillo, pero en algún momento llego el caso que para que un alumno solicitará un certificado de estudios, debería de validar que no debiera mas del 50% de sus materias del semestre pasado, AAHHH yo ya tenia el código para hacer esto, así que "Copy/Paste", en una nueva interfaz, luego si un alumno solicitaba su numero de cuenta para pagar la inscripción se debería de revisar si tenia beca o no, SIII también tenia ese código hecho y nuevamente "Copy/Paste". En algún momento en la vida me di cuenta que tenia código repetido por todos lados, lo mismo que paso con las conexiones a la base de datos, así que pensé en aislar esa parte de código y tenerla como una "librería de funciones", lo que estaba haciendo realmente era tener una nueva capa, la capa de "Dominio", "Negocio" o "Lógica de negocio", como sea que la llamen, de tal manera que accidentalmente descubrí que una aplicación podía ser dividida en capas (aún cuando yo no las llamara así).


Después de un tiempo leyendo el libro de Patterns of Enterprice Application Architecture de Martin Fowler descubrí que lo que había hecho no estaba del todo descabellado y que era algo muy cotidiano en el mundo del desarrollo de sistemas, lo a lo cual di gracias por no estar tan loco.

Básicamente Fowler dice que esta es la forma principal de dividir un sistema en 3 capas básicas.

Capa Uso
Presentación: Dedicada a mostrar la información al usuario y recibir las entradas del mismo
Dominio o Negocio: Todo lo concerniente a las reglas del negocio como validaciones y tomas de decisión
Acceso a datos o fuente de datos El mecanismo por el cual se accede a la fuente a donde esta la información (No necesariamente debe ser una base de datos, puede ser un txt un excel u otra cosa)

Sin embargo no es una regla tallada en la piedra que tengamos estas capas o dicho mejor solo estas capas, es muy común que algunas de estas sean separadas en mas, dependiendo de los requerimientos y también el tipo de sistema que vayamos a desarrollar o las herramientas que vayamos a utilizar.

Fowler dice en su libro que hay ocasiones muy particulares cuando si es posible juntar la capa de presentación y la de dominio, específicamente cuando la complejidad de el dominio es muy baja o prácticamente nula, yo digo que no, que siempre hay que sepáralas, por una simple razón, el negocio tiene a cambiar y hacerse mas complejo, si todo esta en la presentación tendremos un problema a la larga.

Cada cosa en su lugar

También se preguntarán “Oye y que va en que parte”, bien pues resulta que todo lo que tenga que ver con acceso a datos deberíamos de ponerlo en la capa de datos, muchos la llamamos como DAO (Data Access Object), aquí deberíamos controlar desde abrir las conexiones, explotar la información o agregarla hasta cerrar las conexiones, salvo que implementes un patrón Singleton.

La parte difícil comienza cuado tienes que decidir que va en la capa de presentación y que va en la capa de negocio.

Lo que yo digo es que todas aquellas acciones que tienen que ver exclusivamente con la vista pues van en la vista, y aquellas que tienen algún matiz de ser parte de la operación de de cómo funciona algo en la empresa son parte del negocio.

Por ejemplo en la vista yo pondría validaciones sobre longitudes de campos, sobre si debe ir un campo alfanumérico y cosas por el estilo, porque estas no son parte del negocio, si se ingresa en un campo de texto un entero o una letra, no es algo que al negocio le importe.

Imaginemos que en una tienda debe aparecer una alerta en la interfaz cada vez que haga falta algún producto, si involucramos la palabra interfaz podría parecer que es parte la interfaz, cuando en realidad la interfaz esta llamado un procedimiento de negocio y tomando una decisión sobre el resultado, veamos esto en el siguiente diagrama de secuencia.

En este pequeño diagrama podemos apreciar principalmente 3 cosas.

     1.- Aún cuando la vista inicia el proceso, esta no tiene ninguna participación en el procedo de toma de decisiones, solo reacciona de acuerdo a la información que obtenga de la capa de negocio, lo cual quiere decir que el proceso de saber si existe o no inventario no le pertenece. 

     2.- La capa de negocio toma una decisión dependiendo del nivel del inventario, si este es menor a 5 coloca un pedido esto es una “Regla de negocio” y de esto no se entera ni la capa de vista ni la capa de datos, si en algún momento la tienda crece y tenemos la necesidad de tener mejor surtidos nuestros almacenes, incrementaremos la condición y eso no afecta absolutamente a nadie.

     3.- Ni a la capa de la presentación ni a la capa de negocio le interesa de donde sale la información, esto es una preocupación única y excesiva de la capa de Acceso a Datos, así si en algún momento deciden utilizar una base de datos, solo se deberá modificar la capa de acceso a datos y tampoco afecta absolutamente a nadie.

Hasa aquí llega la parte básica del desarrollo en Capas, mas adelante veremos como algunas de estas capas pueden transformarse en otras y daremos paso a nuevos patrones de diseño.

9 comentarios:

  1. Esta chido, pero cambia esa foto tuya cabron, vas asustar a las personas...

    ResponderEliminar
  2. Nice job!!! ;D just some spelling mistakes :P

    ResponderEliminar
  3. Me parece interesante, aunque creo que te perdiste un poco en la metáfora del pastel, pero también fue ilustrativa y un tanto cómica.

    Puntualmente del DAO, creo que seria bueno que mencionaras que es un patrón de diseño, solo como nota.

    Me gusto aunque creo que antes de hablar de capas podrías hablar de POO que es, todo un mundo y una vez que se domina, la arquitectura en capaz y los patrones de diseño se ven mas fáciles.

    En conclusión me agrado.

    ResponderEliminar
  4. Es cierto lo del DAO Os pero difiero contigo en algo, las arquitecturas en capas no son únicas para POO puedes aplicarlas donde sea, siempre que tengas la necesidad de separar las funcionalidades, pero... prometo que escribiré algo sobre POO,

    Muchas gracias por los comentarios

    ResponderEliminar
  5. Solo una pequeña aclaración, sé que la arquitectura en capas no solo es para POO, pero si creo que si es más fácil conceptual izar la arquitectura en capas una vez que se conoce la POO, creo que seria más estructurado partir de una filosofía de programación y luego a arquitecturas, esto lo digo partiendo de lo que dice la descripción del blog, bueno espero te sirva un punto de vista más, cuídate un saludo y estera siguiendo lo que escribes para ver que me pirateo jajajaja perdón que aprendo

    ResponderEliminar
  6. Algunas aclaraciones:

    1) Tier es distinto de layer. Aqui el autor habla exclusivamente de divisiones lógicas (no físicas).

    2) La perfección en la división de las capas, es un asunto de niveles de pragmatismo (o carencia del mismo). Fowler encuentra en sus años de experiencia que violar las líneas divisorías de las capas -en ciertos escenarios-, no es un gran pecado, tan no lo es que se obtienen beneficios de esta práctica.

    3) Algo típico al desarrollar proyectos en capas, es el abandono parcial o total de las prácticas de OO aplicadas al diseño del Dominio.

    Uno termina realizando un desarrollo tipo procedural, con código dividido en distintas capas. En etapas medias de un proyecto desarrollado así, uno cae en cuenta que la división del código de negocio en clases de la capa de Negocio, está lejos de ser suficiente para una adecuada conceptualización y "reutilización" de las reglas que describen al negocio. El "Domain Driven Design" pretende ser una puerta en este muro.

    4) La "reutilización" se va convirtiendo a mi parecer, en el santo grial del desarrollo de software. Parecemos dispuestos a las más fantásticas y complicadas cruzadas para alcanzarla, y así, en esta mítica jornada, hemos perdido nuestro pragmatismo.

    5)No olvidar que los conceptos J2EE han influenciado en gran medida a nuestra conceptualización de sistemas en capas. Esto a derivado en infinidad de vicios, uno de ellos son los Modelos de Dominio Anémicos.

    En concreto este último vicio puede ser consecuencia de los antiguos EJB's, que al estar comprometidos con clases e interfaces propietarias, no permitían aplicar sobre los mismos prácticas de OO. Parece ser que hacemos exactamente lo mismo con nuestra llamada capa de "Negocio", sin importarnos que estos sean ya POJO's.

    6)Si se dibuja el modelo de 3-capas y se compara con el patrón MVC, se verá una diferencia topológica básica. Me parece que el autor mezcla ambas indiferentemente, de ahi la aclaración.

    Por último, qué bueno que estos esfuerzos se den, felicidades al autor. No obstante, él mismo debe reconocer que su redacción es muy pobre, así que a trabajar en ese punto también.

    Saludos.

    ResponderEliminar
  7. Gracias por los comentarios

    Os, prometo que pronto escribiré algo sobre POO y espero me des tu punto de vista.

    Anónimo (me gustaría tener alguien a quien agradecer el comentario).

    Estoy de acuerdo en tus comentarios, en mayor o menor medida, veo que quizá generé algunas confusiones sobre el objetivo del artículo e intentaré aclararlas:

    1.- Es cierto, el articulo solo habla de divisiones lógicas ya que considero que solo es el punto de partida para el diseño de una aplicación, el diseño de capas físicas involucra mucho mas que solo una aplicación.

    2.- Es cierto, no es una regla tener forzosamente una división en 3 capas, todo depende del problema que se quiera resolver mediante la aplicación, pero si tu aplicación lo amerita pues ciertamente debería de estar ahí.

    3.- Tienes mucha razón, y es muy bueno el comentario, pero no fue mi intención hablar sobre patrones de diseño en cada una de las capas ya que para cada una de ellas existen varios

    4.- La reutilización de código no debería de ser un santo grial, por el contrario con una buena aplicación de POO debería de ser suficiente, sin embargo la aplicación de tecnologías modernas y patrones novedosos, hacen que tengamos al final muchos recovecos, que suelen ser llenados con código replicado, malas practicas de programación y muchos regaños a los desarrolladores, dando lugar a una programación procedural. En mi experiencia esto pasa cuando, no se plantea inicialmente un buen diseño de la arquitectura, cuado se abandonan los desarrolladores a tirar líneas de código a diestra y siniestra y no se tiene una base sobre la cual construir, es decir, no existe un "Core" para la aplicación.

    5.- Ciertamente en el boom del J2EE muchos intentamos aplicar sus patrones, forzando muchas cosas y acomplejando el problema mas de lo que ya estaba, sin embargo creo que no debemos culpar a nadie sobre las malas practicad adquiridas ya que nada nos forzó a usar e implementar sus patrones.

    Por ejemplo: Algún devoto de los patrones J2EE podría leer los patrones de Microsoft DNA y considerarlos casi, casi blasfemia, porque hablan de que los RecordSet deben viajar desde la capa de datos hasta la capa de vista, lo cual nos diría que todas las capas deben tener conocimiento sobre la capa de datos, y sin embargo son patrones que funcionaban bien para tecnologías Microsoft.

    Lo que quiero expresar en este punto, es que, el diseño de la aplicación debe estar basado principalmente en los requerimientos de la misma, porque usar un modelo de dominio cuando la aplicación que se va a desarrollar solo es para alimentar catálogos, no tendría mucho sentido ya que las BD Orientadas a Objetos hoy en día son solo un sueño y tener clases que modelan las tablas de una BD Relacional no es implementar un patrona de dominio, por el contrario un patrón "Transaction Script" o "Table Module", sería mucho mas útil.
    6.- Mi intención al mostrar el pastel, no fue compararlo contra un patrón MVC, ya que el MVC habla sobre como esta construida la cubierta y yo intento hablar de forma muy general sobre todo el pastel.

    7.- SIII!!, necesito mejorar mucho mi redacción y trabajaré arduamente sobre ese punto.

    Muchas gracias por los comentarios, espero haber aclarado la confusión.

    Un saludo

    ResponderEliminar
  8. Hola podrias por favor hacer una comparación entre modelo de 3-capas y el patrón MVC cual es el que mas conviene usar para proyectos complejos?

    ResponderEliminar
  9. Muchas Gracias, la verdad la explicacion me aclaro muchas dudas conceptuales!

    ResponderEliminar