Learn Design Patterns - vanskarner/CleanMovie GitHub Wiki
Design patterns can be defined as proven solutions to common software design problems. However, their usefulness goes beyond that, as they also play an important role in conveying the original intent of one programmer to another who takes up work on a system, facilitating collaboration between different programmers and ensuring smooth continuity.
It could be considered that the initial resource related to design patterns is the article called Using Pattern Languages for OO Programs (1987) by Kent Beck and Ward Cunningham, presented at the Workshop on Object Oriented Programming, Systems, Languages and Applications (OOPSLA ), where several patterns were introduced. However, the resource that popularized design patterns is the book Design Patterns: Elements of Reusable Object-Oriented Software (1994) by Gamma Erich, Helm Richard, Johnson Ralph and Vlissides John, and this book presents 23 design patterns arranged as shown below:
graph TD;
A[Design Patterns] --> B[Creational];
A --> C[Structural];
A --> D[Behavioral];
B --> CreationalItems["• Abstract Factory<br>• Builder<br>• Factory Method<br>• Prototype<br>• Singleton"];
C --> StructuralItems["• Adapter<br>• Bridge<br>• Composite<br>• Decorator<br>• Facade<br>• Flyweight<br>• Proxy"];
D --> BehavioralItems["• Chain of Responsibility<br>• Command<br>• Interpreter<br>• Iterator<br>• Mediator<br>• Memento<br>• Observer<br>• State<br>• Strategy<br>• Template Method<br>• Visitor"];
Other resources to learn about patterns is the book Patterns of Enterprise Application Architecture (2002) by Martin Fowler and the book XUnit Test Patterns: Refactoring Test Code (2007) by Gerard Meszaros. In these books you will find some patterns that are mentioned in the book Clean Architecture: A Craftsman's Guide to Software Structure and Design and to which I have adapted their content just a little (almost nothing) to relate them to the topic in question. For example:
Design pattern that separates difficult-to-test behavior (humble object) from easy-to-test behavior (smart object), thus facilitating testing. This pattern is found in the book XUnit Test Patterns: Refactoring Test Code, although the term "Humble" has its origins in the article by Michael Feathers called 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
The humble object contains code that is difficult to test usually due to its dependency on external resources. This hard to test code usually relates to:
- Interactions with external services: Calls to external services such as databases, web APIs or other systems.
- Dependence on external components: Libraries or frameworks.
- Access to hardware resources or operating systems: Direct operations on the hardware or interaction with the operating system.
- Asynchronous code: If asynchrony is not handled properly in testing, it generates uncertainty.
The smart object contains the testable code that is closest to the application logic. This testable code relates to presenters, use cases, and so on.
This pattern separates the logic dependent on external resources into a component, module or class considered as humble that will contain all the code difficult to test reduced to point functions; on the other hand, the remaining logic independent of external resources will reside in a component, module or class considered as intelligent that will contain the significant behavior of the application.
Pattern that configures a communication between two independent objects. This pattern is found in the book Patterns of Enterprise Application Architecture.
flowchart LR
Service
Fee
PaymentMapper[Payment Mapper]
PaymentPackage["Payment Package"]
PaymentMapper -.-> Service
PaymentMapper -.-> Fee
PaymentMapper -.-> PaymentPackage
This pattern allows to establish communications between two subsystems without creating direct dependencies between them. One type of this mapper that you have probably seen in several projects is the following:
It is a mapper between the data transfer object (DTO) and the business objects; however, I will focus on the core function of this element, which is to convert one type to another, since it is also used in other parts of the system. It is important to clarify that although this type is called "Assembler", many developers prefer to refer to it simply as "Mapper":
classDiagram
Mapper ..> DTO
Mapper ..> BusinessObject
class Mapper{
+ convert(BusinessObject): DTO
+ convert(DTO): BusinessObject
}
class DTO
class BusinessObject
Pattern that moves data between the business objects and the database, keeping both elements independent and external to each other, as well as external to the Data Mapper itself. This pattern is found in the book 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
This pattern is a type of Mapper that also performs operations on the database, so it contains the persistence code.
Design pattern that provides an abstraction between business logic and data mapping layers by using a collection-like interface to access business objects. This pattern is found in the book 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
In this pattern, the repository does not contain the persistence code directly, as it is another additional abstraction layer.
It is common to see in the implementation of this pattern that an interface with a name similar to "SomeRepository" is included. This interface is also called by Uncle Bob "Database Gateway" (please note that I didn't just mention "Gateway") and provides the following definition:
These gateways are polymorphic interfaces that contain methods for every create, read, update, or delete operation that can be performed by the application on the database.
- Robert C. Martin (Uncle Bob), Clean Architecture: A Craftsman’s Guide to Software Structure and Design, 2017
The repository sits above the Data Mapper, but in this case it acts as another abstraction layer above the mapping layer for complicated queries or simply for further decoupling. Therefore, the repository can contain or use the Data Mappers themselves.
The DAO pattern is an abstraction of the data source that provides data operations without exposing the details linked to it and is closer to the data source. On the other hand the repository acts as a collection of business objects with data operations capabilities and is at a higher level than DAO because it is closer to the business logic. Therefore, the repository can contain or use DAO to perform its operations.
The following representation is my attempt to integrate it with the other concepts:
flowchart LR
Database[(Data Source)]
BusinessLogic[Business Logic]
Repository[Repository]
DAO[Data Access Object]
BusinessLogic <-- Persist / Recover --> Repository
Repository -.-> DAO
DAO -.-> Database
While DAO may seem similar to Data Mapper, it does so in the sense that both contain persistence code, but they differ in that DAO has no dependencies on business objects, while Data Mapper does. Also, Martin Fowler does a little analysis of the DAO pattern based on the book Core J2EE Patterns: Best Practices and Design Strategies (2001) by Deepak Alur, John Crupi and Dan Malks, as a table data gateway, but he is not clear whether it is always table-based and also specifies that DAO has another meaning in the Microsoft world of that time.