Regla de la Separación: poniendo aparte el negocio y la convención

Enviado por jstitch el Vie, 19/07/2019 - 11:58
Rule of Separation

Hace un tiempo, describíamos la arquitectura de los sistemas que desarrollamos en Podemos. Nos enfocamos en describir la misma, una arquitectura de capas, con las clásicas Modelo, API e Interfaz. El post además habla de los límites que debe haber en el código que se coloque en cada uno.

De ese artículo podemos extraer también algunos puntos importantes.

  • ¿Qué principios de diseño pretendemos fomentar usando una arquitectura así?
    • Básicamente, el DRY: Don't Repeat Yourself . Con responsabilidades bien definidas en lo que el código de cada capa debe realizar, evitamos que, en principio entre capas, se repita código y por lo tanto se multiplique innecesariamente el esfuerzo para dar mantenimiento al mismo.
  • Nos gusta el cambio y lo buscamos. Este es uno de los valores que definen a Podemos Progresar. Y en Podemos TI lo reflejamos en el hecho de que siempre queremos estar a la vanguardia tecnológica. Buscamos siempre poder ofrecer las mejores soluciones a nuestros usuarios. Para ello, en el aspecto arquitectónico, tratamos de facilitar las cosas para que la interfaz no se quede amarrada a un estilo, a una tecnología, a una forma única de hacer las cosas. La forma en que implementamos la arquitectura en capas nos permite esa independencia, llamémosle así, para poder implementar cualquier interfaz que nosotros deseemos de forma mucho más sencilla.
  • Además nos da la flexibilidad para agregar más capas intermedias si así lo creemos conveniente. La capa API, por ejemplo, no es una capa definida de forma dura que deba seguir lineamientos especificados antaño como grabados en las tablas de la Ley. Todo lo contrario. En ese sentido, una API es consumida por una interfaz, pero también puede ser que una API sea consumida por otra API (la versión 2 de la API de control de desembolsos consumiendo la antigua versión 1 es un ejemplo, la última versión fue construida sobre la versión 1 precisamente porque desde la versión 1 nunca amarramos todo para permitir esa flexibilidad). Una API de cierta tecnología puede estar consumiendo otra API de distinta naturaleza (la API REST de SARAHI es un ejemplo de esto: nuestra REST no pretende ser la API definitiva en que vivan las reglas de negocio, sino una especie de 'interfaz' para que un programa consuma la API, esta sí con el negocio).

Esto último nos lleva a tocar un tema relacionado con una regla muy importante en el diseño de sistemas: la Regla de Separación. En su libro The Art of Unix Programming (del cual hablamos aquí), Eric S. Raymond la menciona como una de las reglas de diseño que sigue Unix.

La regla básicamente indica que un sistema bien diseñado debe mantener bien separadas las cosas cuando se traten del mecanismo (digamos, la forma en que se hacen las cosas), de las que tratan de las políticas (es decir, las reglas bajo las que las cosas deben ser hechas).

Nuestra arquitectura por capas nos permite esta separación en muchos aspectos. El simple hecho de tener capas que se encarguen, la más interna de los datos en sí mismos, la intermedia de las APIs para acceder a estos datos, y la más externa de las interfaces con que los usuarios acceden a los datos a través de las APIs es ya una separación de mecanismos y políticas.

Otro aspecto que definimos es también que ÚNICAMENTE las APIs pueden contener reglas de negocio. Mientras que la capa más inerna, la de datos, se encarga del modelado de los mismos para que puedan ser almacenados y adquiridos vía un cierto motor de acceso a datos, y solamente eso, las APIs se encargan, además de permitir el acceso a los mismos, de contener las reglas de negocio que se definen por los procesos en Podemos Progresar. Tenemos entonces que las APIs contienen el, por así decirlo, mecanismo, al que llamamos negocio.

Por otro lado, las interfaces, en especial las interfaces de usuario (pues una API es, al final y al cabo también una interfaz, pero de programación), pueden contener todo aquello que es accesorio, todo aquello que, por convención, permitimos al usuario hacer con respecto a los datos (vía las APIs). De este modo las interfaces de usuario contienen las, por así decirlo, políticas, o más correctamente en nuestro contexto, convenciones.

Esto, claro, deja a las interfaces en un nivel de 'terminales tontas' que sólo se encargan de gestionar las acciones de los usuarios, al nivel que, por convención, acordemos con ellos. Esto es, muchas veces, más que suficiente para el usuario promedio. Sin embargo, también somos conscientes que algunos usuarios, conforme avanzan en su expertise en el negocio, así como en la forma en que interactúan con los sistemas, se llegan a convertir en lo que comúnmente se denomina como power user.

Para un power user, una terminal tonta no basta. Necesita más del sistema. Usualmente, nos va a pedir cambios en el sistema, y claro nosotros los implementaremos. Pero además sabe pedir requerimientos, sabe dar información útil cuando reporta un error o una anomalía. Y sobre todo, si tuviera las posibilidades a su alcance, haría uso de un sistema de una manera mucho más potente que un simple usuario. ¿Cómo conciliar la posibilidad de que una interfaz le deje a los posibles power users de nuestro sistema hacer más sin que la interfaz deje de dedicarse únicamente a la convención, al policy, es decir a mantener la regla de separación?

Bueno, pues hay maneras. Poco hemos incursionado en este campo, dado que casi no tenemos power users. Un ejemplo:

El diseño de los paths (urls) que un módulo del sistema al que accede un usuario puede convertirse en una forma de otorgar más a un usuario fuera de lo común.

Digamos que un path dice lo siguiente:

control_desembolsos/?estatus_id=2

para acceder a los folios que tengan dicho estatus.

Otro path similar dice

control_desembolsos/?fecha_desembolso_from=YYYY-MM-DD&fecha_desembolso_to=yyyy-mm-dd

para acceder a los folios cuya fecha de desembolso haya caído entre esas fechas.

La interfaz de usuario, la que usan todos, permite filtrar con estos dos criterios, o incluso combinarlos, vía los controles de la misma interfaz, para dar algo como

control_desembolsos/?fecha_desembolso_from=YYYY-MM-DD&fecha_desembolso_to=yyyy-mm-dd&estatus_id=2

Que indica una búsqueda de folios en ese rango de fechas de desembolso Y que se encuentren en ese estatus.

PERO, la interfaz por sí misma, aunque permite un variado número de combinaciones de parámetros de búsqueda, puede quedar restringida únicamente a lo que la interfaz dictamine. Un power user puede, si lo desea, editar por sí mismo la URL y establecer sus propios parámetros de búsqueda.

O puede, por otro lado, aprovechar ese conocimiento para guardar bookmarks de sus búsquedas más recurrentes, y evitar tener que navegar por toda la interfaz para lograr su búsqueda y hacer su trabajo, simplemente usa siempre la misma URL y con eso consigue ahorrarse pasos navegando por la interfaz.

En otras palabras, es posible que la interfaz tenga ciertos comportamientos off-the record que se salten la convención establecida con el usuario. Precisamente para darle a la interfaz más capacidades que las que originalmente se plantearon, y dar más de sí a los usuarios que quieran explotar más su interfaz. Esto claro que no es un requerimiento que los programadores de Podemos TI estén forzados a incluir. Pero es algo que ellos, pensando no como programadores sino como power-users, pueden agregar si siguen una filosofía de diseño al estilo Unix, y por sí mismos lo incluirán.

O, como reza el adagio:

Easy things should be easy, hard things should be at least possible

(Las cosas fáciles deben ser fáciles, y las cosas difíciles deben ser, cuando menos, posibles)

 

 

Etiquetas