Mostrando las entradas con la etiqueta #arquitectura. Mostrar todas las entradas
Mostrando las entradas con la etiqueta #arquitectura. Mostrar todas las entradas

miércoles, 13 de noviembre de 2024

Arquitectura hexagonal (HA): integrando principios SOLID desde 2008

La Arquitectura Hexagonal, también conocida como Puertos y Adaptadores, del Dr. Alistair Cockburn 2006, es un enfoque y propuesta de diseño de software basado en el #solidprinciples. Estos principios #SOLID son un conjunto de cinco principios de diseño que promueven la creación de código limpio, flexible y mantenible. La H.A. expone que podríamos dividir nuestro Proyecto de Arquitectura. Exploremos cómo HA. se alinea con los principios SOLID en varios puntos clave.

Es importante recalcar que HA no es reciente y ha estado en proceso desde antes de 2008, cuando comencé a aplicarlo. Si bien es posible que no se haya referido a él como HA en ese momento, los principios subyacentes ya se estaban aplicando en nuestra comunidad antes de 2006. La idea central de separar la lógica empresarial de las preocupaciones técnicas y de infraestructura ha sido un tema de interés durante más de dos décadas. Con el paso de los años, ha ido evolucionando y perfeccionándose, adquiriendo diversos nombres como "Puertos y Adaptadores" y "Arquitectura Hexagonal". Esto es efectivo en aplicaciones donde la flexibilidad es esencial (spoiler: #messagebroker, #workflow o #microservices).

 

1. Principio de Responsabilidad Única | Single Responsibility Principle SRP:

HA tiene como objetivo separar las responsabilidades de la lógica empresarial de las preocupaciones técnicas, como la persistencia de los datos o la interfaz de usuario. Esto se logra mediante la creación de adaptadores responsables de interactuar con estas preocupaciones técnicas, permitiendo que los puertos se concentren únicamente en sus cosas.

2. Principio Abierto/Cerrado | Open/Closed Principle OCP:

HA promueve la extensibilidad y la flexibilidad. Los puertos definen interfaces que pueden implementarse y deben implementarse mediante múltiples adaptadores (clases que hacen que suceda la magia). Cuando se requiere nueva funcionalidad, se pueden crear nuevos adaptadores para implementar estas interfaces sin modificar el código existente en los puertos. Esto cumple con el OCP, lo que permite la extensión sin alterar el código existente.

3. Principio de sustitución de Liskov | Liskov Substitution Principle LSP:

Al definir interfaces en los puertos, los adaptadores deben cumplir con estas interfaces. Esto garantiza que los adaptadores sean intercambiables sin afectar el comportamiento del sistema. El cumplimiento del LSP permite la sustitución de adaptadores sin cambios en la lógica de la aplicación principal.

4. Principio de segregación de interfaces | Interface Segregation Principle ISP:

En HA las interfaces en los puertos se mantienen específicas para las necesidades de los clientes. Esto evita que los clientes se vean obligados a implementar métodos no utilizados. Al dividir las interfaces en puertos según las necesidades de los clientes, se logra el cumplimiento del ISP.

5. Principio de inversión de dependencia | Dependency Inversion Principle DIP:

HA. invierte las dependencias al permitir que los puertos definan las interfaces que implementan los adaptadores. Esto significa que los puertos no dependen de implementaciones concretas sino de abstracciones (las interfaces). Aplicar el DIP facilita la sustituibilidad de los componentes mejorando la mantenibilidad, la flexibilidad, facilitando la solidez de la solución y ahorrando dinero en tiempo.

Cabecera

Fuentes:

 Para conocer más sobre esta arquitectura consulta el creador del termino Alistair Cockburn en archive.org , ya que, el su web está en actualización alistair.cockburn.us.

 Robert C. Martin (Uncle Bob)

 

domingo, 18 de septiembre de 2016

Los patrones de diseño más utilizados en el desarrollo de software

Están organizados en tres categorías principales según el libro "Design Patterns: Elements of Reusable Object-Oriented Software" (Gang of Four, GoF). A continuación, los patrones más usados dentro de cada categoría y algunos otros populares adicionales:


1. Creacionales

Estos patrones abordan la creación de objetos, asegurando que el sistema sea independiente de cómo se crean, componen y representan.

  1. Singleton

    • Garantiza que una clase tenga una única instancia y proporciona un punto de acceso global a ella.
  2. Factory Method

    • Define una interfaz para crear objetos, pero permite que las subclases decidan cuál clase instanciar.
  3. Abstract Factory

    • Proporciona una interfaz para crear familias de objetos relacionados o dependientes sin especificar sus clases concretas.
  4. Builder

    • Separa la construcción de un objeto complejo de su representación, permitiendo que el mismo proceso de construcción cree diferentes representaciones.
  5. Prototype

    • Permite clonar objetos existentes en lugar de crearlos desde cero, evitando el costo de inicialización compleja.

2. Estructurales

Estos patrones se ocupan de cómo componer clases y objetos para formar estructuras más grandes.

  1. Adapter

    • Permite que clases con interfaces incompatibles trabajen juntas mediante un "adaptador".
  2. Decorator

    • Añade funcionalidad adicional a un objeto de forma dinámica.
  3. Proxy

    • Proporciona un sustituto o marcador de posición para controlar el acceso a un objeto.
  4. Composite

    • Compone objetos en estructuras de árbol para representar jerarquías parte-todo, permitiendo que los clientes traten objetos individuales y compuestos de manera uniforme.
  5. Bridge

    • Desacopla una abstracción de su implementación para que ambas puedan variar de manera independiente.
  6. Facade

    • Proporciona una interfaz simplificada a un conjunto de interfaces en un subsistema.
  7. Flyweight

    • Reduce el costo de creación de objetos, reutilizando instancias existentes cuando es posible.

3. Comportamentales

Estos patrones se centran en la interacción y la responsabilidad entre objetos.

  1. Strategy

    • Define una familia de algoritmos, encapsula cada uno y los hace intercambiables.
  2. Observer

    • Permite que un objeto notifique a múltiples objetos interesados cuando cambia su estado.
  3. Command

    • Encapsula una solicitud como un objeto, permitiendo parametrizar clientes con diferentes solicitudes, hacer colas o registros de comandos, y soportar deshacer/rehacer.
  4. State

    • Permite que un objeto cambie su comportamiento cuando cambia su estado interno.
  5. Template Method

    • Define el esqueleto de un algoritmo en una operación, permitiendo que las subclases redefinan ciertos pasos sin cambiar la estructura general.
  6. Mediator

    • Descentraliza la comunicación entre objetos mediante un mediador.
  7. Chain of Responsibility

    • Permite que varios objetos manejen una solicitud, pasando la solicitud a lo largo de una cadena.
  8. Iterator

    • Proporciona una manera de acceder a los elementos de un objeto compuesto de forma secuencial sin exponer su representación subyacente.
  9. Visitor

    • Permite agregar nuevas operaciones a estructuras de objetos sin modificar sus clases.
  10. Memento

    • Captura y externaliza el estado interno de un objeto para poder restaurarlo más tarde.

Patrones Adicionales y Modernos

Además de los patrones clásicos de GoF, algunos patrones más modernos son ampliamente usados en el desarrollo de software:

  1. Dependency Injection (DI)

    • Permite inyectar dependencias en lugar de que un objeto las cree por sí mismo.
  2. Model-View-Controller (MVC)

    • Desglosa una aplicación en tres componentes principales: modelo, vista y controlador.
  3. Repository

    • Abstrae la lógica para acceder a datos de una base de datos o fuente externa.
  4. Unit of Work

    • Mantiene un registro de los cambios realizados a los datos para coordinar actualizaciones atómicas.
  5. Event Sourcing

    • Representa el estado de una entidad como una secuencia de eventos en lugar de un único estado.
  6. CQRS (Command Query Responsibility Segregation)

    • Separa las operaciones de lectura (query) de las operaciones de escritura (command) en diferentes modelos.

Estos patrones forman la base de muchas soluciones de software modernas y se eligen según las necesidades del problema y el contexto de la aplicación.