Skip to content

Commit 816fbcb

Browse files
committed
Refactor notes on Repository pattern
1 parent c13c676 commit 816fbcb

File tree

2 files changed

+36
-63
lines changed

2 files changed

+36
-63
lines changed

README.md

-2
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@ repository contains a collection of design patterns, principles, and best practi
1212
4. Behavioral Patterns
1313
5. Concurrency Patterns
1414
6. Enterprise Patterns
15-
7. Architectural Approaches
16-
8. Microservices Patterns
1715

1816
## Principles of Design
1917

src/enterprise/README.md

+36-61
Original file line numberDiff line numberDiff line change
@@ -105,78 +105,53 @@ objects.
105105

106106
## Data Access Object
107107

108+
> **Data Access Object** (DAO) pattern comes from **early enterprise application design**, and its
109+
> formalization can be found in the book "Core J2EE Patterns: Best Practices and Design Strategies" by Deepak Alur, John
110+
> Crupi, and Dan Malks, published in 2001. DAO abstracts and encapsulates all access to a data source, separating
111+
> persistence logic from business logic. This allows changes to the underlying data source without affecting the rest of
112+
> the application, which is especially useful in enterprise contexts where systems might switch databases or data
113+
> storage
114+
> mechanisms over time.
115+
108116
**DAO** (Data Access Object) is an enterprise pattern that is used as abstraction of data persistence.
109117

110118
## Repository
111119

120+
> The **Repository** pattern originates from **Domain-Driven Design** (DDD), as described by Eric Evans in his book, "
121+
> Domain-Driven Design: Tackling Complexity in the Heart of Software." (2003) Repositories are not just about managing
122+
> data; they encapsulate business logic, ensuring that operations adhere to the Ubiquitous Language of the domain.
123+
112124
**Repository** is an enterprise pattern that mediates between the domain and persistence layers using a collection-like
113125
interface for accessing domain objects.
114126

115-
### Collection-oriented vs Persistence-oriented
116-
117-
* **Collection-oriented**: can be thought as an in-memory set of entities which can track object changes.
127+
* **Collection-like repository**: can be thought as an in-memory set of entities which can track object changes.
118128
Usually, you deal with this kind of repository when you are working with SQL databases and an ORM.
119129

120-
* **Persistence-oriented**: as a list or table of entities where you cannot track their changes.
130+
* **Persistence-oriented repository**: as a list or table of entities where you cannot track their changes.
121131
Persistence-oriented repositories are more common in document (NoSQL) databases and an ODM.
122132

123-
### Use Specific repositories instead of Generic
124-
125-
E.g. UserRepository vs Repository[User]
126-
127-
**Generic repository** is an a priori anti-pattern, since the repository encapsulates the logic of storing aggregates,
128-
not a specific domain model. However, it is allowed to move the general functionality to the base class.
129-
130-
### Manage transactions outside the repository
131-
132-
The transaction management can not be the responsibility of the repository. It is the responsibility of the client
133-
code to manage transactions. Therefore, repositories controlling transaction are considered an anti-pattern.
134-
135-
### Use Aggregate-centred repository instead of Model-centred
136-
137-
E.g. OrderRepository vs OrderRepository+OrderItemRepository
138-
139-
* **Aggregate-centred** repository is the only correct approach. Order should be able to save the whole aggregate
140-
at once. This way, you can ensure that the aggregate is always consistent.
141-
142-
* **Model-centred** repository is considered an anti-pattern. The trouble with this approach is that it doesn't take
143-
into account the consistency boundaries. You can't save Order and OrderItem separately, because they are part of the
144-
same aggregate. Otherwise, you might end up with inconsistent data.
145-
146-
If you have a simple business logic, you might not need to use the repository pattern at all since there
147-
is DAO pattern that can be used to access the database directly.
148-
149-
### Repository vs ORM Session
150-
151-
**ORM Session** is more about data access, while **Repository** is more about business logic.
152-
Repository may include pagination, filtering, caching, and other business logic, while ORM Session is more about
153-
CRUD operations.
154-
155-
### Repository vs Data Access Object
156-
157-
The **Repository** pattern originates from **Domain-Driven Design** (DDD), as described by Eric Evans in his book, "
158-
Domain-Driven Design: Tackling Complexity in the Heart of Software." (2003) Repositories are not just about managing
159-
data; they
160-
encapsulate business logic, ensuring that operations adhere to the Ubiquitous Language of the domain.
161-
162-
On the other hand, the **Data Access Object** (DAO) pattern comes from **early enterprise application design**, and its
163-
formalization can be found in the book "Core J2EE Patterns: Best Practices and Design Strategies" by Deepak Alur, John
164-
Crupi, and Dan Malks, published in 2001. DAO abstracts and encapsulates all access to a data source, separating
165-
persistence logic from business logic. This allows changes to the underlying data source without affecting the rest of
166-
the application, which is especially useful in enterprise contexts where systems might switch databases or data storage
167-
mechanisms over time.
168-
169-
The primary distinction between Repository and DAO lies in the semantics of the API they expose:
170-
171-
* **DAO**: DAO is data-centric, providing database operations such as insert, update, delete, and find. These methods
172-
directly map to database actions, focusing on how data is stored and retrieved.
173-
* **Repository**: This is domain-driven and aligns with the business logic. It represents a collection of aggregate
174-
roots
175-
or entities. Instead of database operations, repositories offer operations that reflect the domain language. For
176-
instance, in a hotel system, a Repository might provide checkIn, checkout, or checkReservation, abstracting away the
177-
actual data operations.
178-
179-
Repository could be implemented using DAO's, but you wouldn't do the opposite.
133+
Best practices:
134+
135+
1. **Don't use generic repository**. Generic repository is an a priori anti-pattern, since the repository encapsulates
136+
the logic of storing aggregates,
137+
not a specific domain model. However, it is allowed to move the general functionality to the base class.
138+
2. **Manage transactions outside the repository**. The transaction management can not be the responsibility of the
139+
repository. It is the responsibility of the client
140+
code to manage transactions.
141+
3. **Focus on aggregates, not entities**. E.g. you can't save Order and OrderItem separately, because they are part of
142+
the
143+
same aggregate. Otherwise, you might end up with inconsistent data.
144+
145+
| Criterion | Repository | Data Access Object (DAO) | ORM Session |
146+
|----------------------------|-------------------------------------------------------|----------------------------------------------------|-----------------------------------------------------|
147+
| **Main Idea** | Abstraction over a collection of domain model objects | Abstraction for working with a data source | Object managing ORM transactions and sessions |
148+
| **Level of Abstraction** | High (works with domain objects) | Medium (works with database objects) | Low (works with specific SQL queries via ORM) |
149+
| **ORM Dependency** | Not tied to ORM (but can use it) | Can use ORM, JDBC, ADO.NET, and other technologies | Part of ORM (e.g., SQLAlchemy, Hibernate) |
150+
| **Focus** | Business logic and working with aggregates | Encapsulation of CRUD operations | Managing connections and transactions |
151+
| **Where Used** | DDD (Domain-Driven Design), complex systems | Smaller projects, clean architecture | ORM frameworks (SQLAlchemy, Hibernate) |
152+
| **Flexibility** | High, can switch between data sources | Medium, requires adaptation for a data source | Low, tightly coupled with ORM |
153+
| **Ease of Testing** | High, easily mockable | Medium, testing is possible | Low, requires mocks or a test database |
154+
| **Example Implementation** | `UserRepository.get_active_users()` | `UserDAO.get_user_by_id(id)` | `session.query(User).filter(User.id == id).first()` |
180155

181156
## Specification
182157

0 commit comments

Comments
 (0)