Saltar a contenido

Stable Abstractions

El principio de "Stable Abstractions" de arquitectura limpia establece que los módulos más estables deben ser los más abstractos, mientras que los módulos menos estables deben ser los menos abstractos. Esto significa que los módulos más estables deben tener la mayor cantidad de abstracciones posibles, mientras que los módulos menos estables deben tener menos abstracciones.

En términos simples, la abstracción se refiere a la capacidad de un módulo de ocultar sus detalles de implementación y exponer solo una interfaz pública. La estabilidad se refiere a la frecuencia con la que se realizan cambios en el módulo. Por lo tanto, un módulo estable es uno que cambia con poca frecuencia y un módulo inestable es uno que cambia con frecuencia.

La idea detrás del principio de "Stable Abstractions" es que los módulos más estables deben ser más abstractos porque es menos probable que cambien y, por lo tanto, pueden tener abstracciones más complejas. Por otro lado, los módulos menos estables deben tener menos abstracciones porque es más probable que cambien y, por lo tanto, es más importante que su implementación sea clara y fácil de modificar.

Al aplicar este principio, se busca minimizar el impacto de los cambios en los módulos menos estables, ya que estos cambios no deben afectar a los módulos más estables. Además, los módulos más estables pueden reutilizarse más fácilmente en otros sistemas o proyectos, ya que tienen abstracciones más complejas que pueden ser útiles en diferentes contextos.

En resumen, el principio de "Stable Abstractions" busca equilibrar la estabilidad y la abstracción de los módulos de un sistema para mejorar su mantenibilidad y reutilización.

Recomendaciones

Para aplicar el principio de "Stable Abstractions" en el diseño de un sistema, se deben seguir los siguientes pasos:

  1. Identificar los módulos del sistema: Primero, se deben identificar los módulos del sistema y clasificarlos en función de su estabilidad. Los módulos más estables son aquellos que cambian con menos frecuencia, mientras que los módulos menos estables son aquellos que cambian con mayor frecuencia.

  2. Analizar la abstracción de cada módulo: A continuación, se debe analizar la abstracción de cada módulo. La abstracción se refiere a la capacidad del módulo de ocultar sus detalles de implementación y exponer solo una interfaz pública. Los módulos más abstractos son aquellos que tienen una interfaz pública más compleja y menos dependencia de los detalles de implementación.

  3. Equilibrar la estabilidad y la abstracción: Una vez que se han analizado la estabilidad y la abstracción de cada módulo, se debe buscar equilibrar estos factores. Los módulos más estables deben tener una mayor abstracción, mientras que los módulos menos estables deben tener una menor abstracción. De esta manera, se garantiza que los cambios en los módulos menos estables no afecten a los módulos más estables, y que los módulos más estables puedan ser reutilizados en diferentes contextos.

  4. Refinar la abstracción: Finalmente, se debe refinar la abstracción de los módulos a medida que se realizan cambios en el sistema. Si un módulo se vuelve más estable con el tiempo, se puede aumentar su abstracción. Por otro lado, si un módulo se vuelve menos estable, se debe reducir su abstracción para garantizar que sea más fácil de mantener y modificar.

En resumen, para aplicar el principio de "Stable Abstractions" se debe analizar y equilibrar la estabilidad y la abstracción de los módulos del sistema, y refinar la abstracción a medida que se realizan cambios. De esta manera, se garantiza que el sistema sea más mantenible y reutilizable.

¿Cómo aplicar el principio?

Supongamos que estamos desarrollando un sistema de gestión de inventarios para una tienda. Podríamos aplicar el principio de "Stable Abstractions" de la siguiente manera:

  1. Identificar los módulos del sistema: Los módulos del sistema podrían ser: gestión de productos, gestión de clientes, gestión de ventas, gestión de inventarios y gestión de pedidos.

  2. Analizar la abstracción de cada módulo: Por ejemplo, el módulo de gestión de productos podría tener una interfaz pública que permita agregar, eliminar y actualizar productos. El módulo de gestión de clientes podría tener una interfaz pública que permita agregar, eliminar y actualizar clientes. El módulo de gestión de ventas podría tener una interfaz pública que permita registrar ventas y generar facturas. El módulo de gestión de inventarios podría tener una interfaz pública que permita verificar la disponibilidad de productos en el inventario. El módulo de gestión de pedidos podría tener una interfaz pública que permita registrar pedidos de productos.

  3. Equilibrar la estabilidad y la abstracción: En este caso, los módulos de gestión de productos y gestión de clientes podrían ser más estables, ya que no cambian con tanta frecuencia como los módulos de gestión de ventas y gestión de pedidos. Por lo tanto, se podría aumentar su abstracción para hacerlos más reutilizables. Por otro lado, los módulos de gestión de ventas y gestión de pedidos podrían tener una menor abstracción, ya que cambian con más frecuencia y están más ligados a los detalles de implementación.

  4. Refinar la abstracción: Si en el futuro se realizan cambios en el sistema y se identifica que el módulo de gestión de inventarios se vuelve más estable, se podría aumentar su abstracción para hacerlo más reutilizable en otros contextos.

Para implementar esto en un proyecto de Java, podríamos organizar nuestros paquetes y clases de la siguiente manera:

  • com.tienda.gestionproductos
    • Producto.java
    • GestionProductosService.java
    • GestionProductosRepository.java
  • com.tienda.gestionclientes
    • Cliente.java
    • GestionClientesService.java
    • GestionClientesRepository.java
  • com.tienda.gestionventas
    • Venta.java
    • Factura.java
    • GestionVentasService.java
    • GestionVentasRepository.java
  • com.tienda.gestioninventarios
    • Inventario.java
    • GestionInventariosService.java
    • GestionInventariosRepository.java
  • com.tienda.gestionpedidos
    • Pedido.java
    • GestionPedidosService.java
    • GestionPedidosRepository.java

En este ejemplo, los módulos de gestión de productos y gestión de clientes están en paquetes separados y tienen sus propias interfaces públicas, lo que permite su reutilización en diferentes contextos. Los módulos de gestión de ventas, gestión de inventarios y gestión de pedidos están en paquetes separados y tienen una menor abstracción, ya que están más ligados a los detalles de implementación y cambian con más frecuencia.

Ejemplo

graph TD;
    A[UI]-->B[Application Layer];
    B --> C[Domain Layer];
    C --> D[Infrastructure Layer];
    D --> E[External Services];
En esta representación, se muestra que la capa de la interfaz de usuario (UI) depende de la capa de aplicación, que a su vez depende de la capa de dominio, y así sucesivamente. Se observa que las capas más internas (de dominio e infraestructura) tienen una mayor estabilidad en comparación con las capas externas (UI y servicios externos), lo que se traduce en una mayor independencia y capacidad de reutilización. Esto es consistente con el principio de Stable Abstractions, que busca que las capas más estables de la aplicación sean las que contengan las abstracciones más importantes y de mayor valor para el negocio.