Why Traditional Repositories Fail DDD and How the ‘Repository Entity Transfer’ Pattern Solves It
This article explores the challenges of implementing Repository in Domain‑Driven Design, introduces the innovative “Repository Entity Transfer” concept, compares in‑memory and relational implementations, discusses concurrency, specifications, and architectural patterns, and provides practical code examples to help developers build cleaner, model‑centric back‑end systems.
一、前言
DDD emphasizes focusing on the domain model rather than technical details. The author quotes Eric Evans and argues that many implementations treat repositories as mere data‑processing tools, losing sight of the model.
The article aims to re‑examine the Repository layer, propose a new “Repository Entity Transfer” concept, and offer fresh insights even for seasoned readers.
二、概念剖析
Repositories should serve as collection containers for aggregate roots. Key characteristics of aggregate entities include identity, mutable state, lifecycle, and context‑specific usage.
Unified language is essential: terms like “intermediate process” and “use‑case process” are abstracted into the domain concept of a repository, which acts as a temporary storage that domain experts can understand.
Placement: create a new aggregate and store it after the use‑case ends.
Lookup: retrieve an existing aggregate during a use‑case.
Management: hide intermediate‑process details and provide a uniform abstraction.
Repositories must function as collection abstractions, handling both placement and retrieval of entities, often requiring indexing and single‑instance design for each aggregate type.
三、实现剖析
Two main implementation styles are discussed:
In‑memory (collection‑oriented) repository – essentially a HashMap storing aggregates.
Relational‑database (persistence‑oriented) repository – uses save/put operations and may employ specifications for flexible queries.
Code example of an in‑memory repository:
public class CalendarRepository extends HashMap {
private Map<CalendarId, Calendar> calendars;
public CalendarRepository() {
this.calendars = new HashMap<CalendarId, Calendar>();
}
public void add(Calendar aCalendar) {
this.calendars.put(aCalendar.getId(), aCalendar);
}
public Calendar findCalendars(CalendarId calendarId) {
return this.calendars.get(calendarId);
}
}An enhanced version adds logical removal to support the “entity transfer” idea:
public class CalendarRepository extends HashMap {
private Map<CalendarId, Calendar> calendars;
private Map<CalendarId, Thread> calendarsTakenAway;
public CalendarRepository() {
this.calendars = new HashMap<CalendarId, Calendar>();
}
public synchronized void add(Calendar aCalendar) {
this.calendars.put(aCalendar.getId(), aCalendar);
calendarsTakenAway.remove(aCalendar.getId());
}
public synchronized Calendar takeCalendars(CalendarId calendarId) {
if (calendarsTakenAway.containsKey(calendarId)) {
return null;
}
Calendar calendar = this.calendars.get(calendarId);
calendarsTakenAway.put(calendarId, Thread.currentThread());
return calendar;
}
}Concurrency strategies (pessimistic lock, optimistic lock) are examined, showing how the transfer model aligns naturally with non‑blocking pessimistic locks.
For relational databases, the article outlines DAO vs. repository thinking, the need for diff‑based updates, specifications to avoid interface explosion, and implicit read/write‑copy tracking. Sample repository interface:
public interface TaskRepository {
Task taskOf(String taskId);
void addTask(Task task);
void removeTask(String taskId);
// other collection / statistics operations
}The “entity transfer” pattern is adapted by using a single put/save operation and renaming find to take, making the repository appear to lose ownership of the aggregate after retrieval.
Architectural diagrams illustrate dependency inversion and clean‑architecture layering, positioning the repository as a domain‑level abstraction that depends on infrastructure (memory, DB) but not vice‑versa.
四、结束语
Understanding repositories bridges domain knowledge and engineering concerns, supporting transaction boundaries, value‑object handling, and long‑term system evolution. The article emphasizes that a well‑designed repository, even if initially messy, becomes a cornerstone for maintainable DDD‑based systems.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Alibaba Cloud Developer
Alibaba's official tech channel, featuring all of its technology innovations.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
