-
Notifications
You must be signed in to change notification settings - Fork 0
Aprende Patrones de Diseño
Los patrones de diseño se pueden definir como soluciones probadas a problemas comunes de diseño de software. Sin embargo, su utilidad va más allá, ya que también desempeñan un papel importante al transmitir la intención original de un programador a otro que retoma el trabajo en un sistema, facilitando la colaboración entre distintos programadores y asegurando una continuidad fluida.
Se podría considerar que el recurso inicial relacionado con los patrones de diseño es el artículo llamado Using Pattern Languages for OO Programs (1987) de Kent Beck y Ward Cunningham, presentado en el Taller de Programación Orientada a Objetos, Sistemas, Lenguajes y Aplicaciones (OOPSLA), donde se introdujeron varios patrones. Sin embargo, el recurso que popularizó los patrones de diseño es el libro Design Patterns: Elements of Reusable Object-Oriented Software (1994) de Gamma Erich, Helm Richard, Johnson Ralph y Vlissides John , y en este libro se presenta 23 patrones de diseño ordenados como se muestra a continuación:
graph TD;
CreationalItems["- Abstract Factory
- Builder
- Factory Method
- Prototype
- Singleton"]
StructuralItems["- Adapter
- Bridge
- Composite
- Decorator
- Facade
- Flyweight
- Proxy"]
BehavioralItems["- Chain of Responsibility
- Command
- Interpreter
- Iterator
- Mediator
- Memento
- Observer
- State
- Strategy
- Template Method
- Visitor"]
A[Design Patterns] --> B[Creational];
A --> C[Structural];
A --> D[Behavioral];
B --> CreationalItems;
C--> StructuralItems;
D--> BehavioralItems;
Otros recursos para aprender sobre patrones es el libro Patterns of Enterprise Application Architecture (2002) de Martin Fowler y el libro XUnit Test Patterns: Refactoring Test Code (2007) de Gerard Meszaros. En estos libros se encuentran algunos patrones que se mencionan en el libro "Clean Architecture: A Craftsman's Guide to Software Structure and Design" y a los cuales he adaptado su contenido solo un poco (casi nada) para relacionarlos con el tema en cuestión. Por ejemplo:
Patrón de diseño que separa el comportamiento difícil de probar (objeto humilde) del comportamiento fácil de probar (objeto inteligente), facilitando así las pruebas. Este patrón se encuentra en el libro XUnit Test Patterns: Refactoring Test Code, aunque el terminó "Humilde" tiene sus orígenes en el artículo de Michael Feathers llamado The Humble Dialog Box (2002).
flowchart LR
DifficultComponentToTest["<font color=black>Difficult component
to test"]
Humble["<font color=black>Hard to test behavior
(Humble)"]
Smart["Easy to test behavior
(Smart)"]
DifficultComponentToTest --> Humble
Humble -.-> Smart
style DifficultComponentToTest fill:#CFE4FF
style Humble fill:#CFE4FF
El objeto humilde contiene el código difícil de probar debido generalmente a su dependencia con recursos externos. Este código difícil de probar normalmente se relaciona con:
- Interacciones con servicios externos: Llamadas a servicios externos como bases de datos, APIs web u otros sistemas.
- Dependencia de componentes externos: Librerías o frameworks.
- Acceso a recursos de hardware o sistemas operativos: Operaciones directas en el hardware o interacción con el sistema operativo.
- Código asíncrono: Si la asincronía no se maneja adecuadamente en las pruebas, genera incertidumbre.
El objeto inteligente contiene el código fácil de probar que se encuentra más cercano a la lógica de la aplicación. Este código fácil de probar se relaciona con los presentadores, casos de uso, y otros.
Este patrón separa la lógica dependiente de recursos externos en un componente, módulo o clase considerado como humilde que contendrá todo el código difícil de probar reducido a funciones puntuales; por otro lado, la lógica restante independiente de recursos externos residirá en un componente, módulo o clase considerado como inteligente que contendrá el comportamiento significativo de la aplicación.
Patrón que configura una comunicación entre dos objetos independientes. Este patrón se encuentra en el libro Patterns of Enterprise Application Architecture.
flowchart LR
Service
Fee
PaymentMapper[Payment Mapper]
PaymentPackage["Payment Package"]
PaymentMapper -.-> Service
PaymentMapper -.-> Fee
PaymentMapper -.-> PaymentPackage
Este patrón permite establecer comunicaciones entre dos subsistemas sin crear dependencias directas entre ellos. Un tipo de este mapper que probablemente hayas visto en varios proyectos es el siguiente:
Es un mapeador entre el objeto de transferencia de datos (DTO) y los objetos de negocio; sin embargo, me enfocaré en la función central de este elemento, que es convertir un tipo a otro, ya que también se utiliza en otras partes del sistema. Es importante aclarar que aunque este tipo se llama "Assembler", muchos desarrolladores prefieren referirse a él simplemente como "Mapper":
classDiagram
Mapper ..> DTO
Mapper ..> BusinessObject
class Mapper{
+ convert(BusinessObject): DTO
+ convert(DTO): BusinessObject
}
class DTO
class BusinessObject
Patrón que desplaza datos entre los objetos de negocio y la base de datos, manteniendo ambos elementos independientes y ajenos entre sí, así como también ajenos al propio Data Mapper. Este patrón se encuentra en el libro Patterns of Enterprise Application Architecture.
classDiagram
direction LR
Student <.. StudentDataMapper
StudentDataMapper ..> DatabaseApi
class Student{
- id: long
- firstName: String
- lastName: String
- numberOfCredits: int
+ Student(long,String,String,int)
+ someBehavior(): boolean
+ getId(): long
+ getFirstName(): String
+ getLastName(): String
+ getNumberOfCredits(): int
}
class StudentDataMapper{
+ insert(Student): void
+ update(Student): void
+ find(long): Student
}
class DatabaseApi
Este patrón es un tipo de Mapper que además realiza operaciones en la base de datos, por lo que contiene el código de persistencia.
Patrón de diseño que proporciona una abstracción entre la lógica de negocio y las capas de mapeo de datos mediante el uso de una interfaz que se asemeja a una colección para acceder a los objetos de negocio. Este patrón se encuentra en el libro Patterns of Enterprise Application Architecture.
flowchart LR
Database[(Database)]
BusinessLogic[Business Logic]
Repository[Repository]
DataMapper[Data Mapper]
BusinessLogic <-- Persist / Recover --> Repository
Repository -.-> DataMapper
DataMapper -.-> Database
En este patrón, el repositorio no contiene el código de persistencia de forma directa, ya que es otra capa de abstracción adicional.
Es común observar en la implementación de este patrón que se incluya una interfaz con un nombre similar a "SomeRepository". A esta interfaz también Uncle Bob la llama "Database Gateway" (por favor, note que no mencioné solo "Gateway") y proporciona la siguiente definición:
Estas puertas de enlace son interfaces polimórficas que contienen métodos para cada operación de creación, lectura, actualización o eliminación que puede realizar la aplicación en la base de datos.
- Robert C. Martin (Uncle Bob), Clean Architecture: A Craftsman’s Guide to Software Structure and Design, 2017
El repositorio se encuentra por encima de Data Mapper, pero en este caso actúa como otra capa de abstracción sobre la capa de mapeo para consultas complicadas o simplemente para un desacoplamiento mayor. Por lo tanto, el repositorio pueden contener o utilizar los propios Data Mappers.
El patrón DAO es una abstracción de la fuente de datos que proporciona operaciones de datos sin exponer los detalles ligados a este y está más cercano a la fuente de datos. Por otro lado el repositorio actúa como una colección de objetos de negocio con capacidades de operaciones de datos y se encuentra a un nivel superior a DAO porque está más cerca de la lógica de negocio. Por lo tanto, el repositorio puede contener o utilizar a DAO para llevar a cabo sus operaciones.
La siguiente representación es mi intento de integrarlo con los otros conceptos:
flowchart LR
Database[(Data Source)]
BusinessLogic[Business Logic]
Repository[Repository]
DAO[Data Access Object]
BusinessLogic <-- Persist / Recover --> Repository
Repository -.-> DAO
DAO -.-> Database
Si bien DAO puede parecer similar al Data Mapper, lo hace en el sentido de que ambos contienen el código de persistencia, pero se diferencian en que DAO no tiene dependencias con los objetos de negocio, mientras que Data Mapper sí las tiene. Asimismo, Martin Fowler hace un pequeño análisis del patrón DAO basándose en el libro Core J2EE Patterns: Best Practices and Design Strategies (2001) de Deepak Alur, John Crupi y Dan Malks, como una puerta de enlace de datos de tabla, pero no tiene claro si siempre se basa en una tabla y además especifica que DAO tiene otro significado en el mundo de Microsoft de aquel tiempo.
© 2023 Vanskarner. All rights reserved.
Contact with us: contact@vanskarner.com