Repository Pattern
- In Turkish
- Repository Deseni
In short
The repository pattern hides data access behind a collection-like interface, so business code can load and save objects without knowing where they are stored.
What is the repository pattern?
A repository is an object that acts like an in-memory collection of domain objects, such as users or orders, while actually reading from and writing to a database, an API, or files. Business code calls methods such as findById, save, and findOverdueInvoices, and the repository handles the SQL, ORM calls, or HTTP requests behind the scenes. The pattern was described by Martin Fowler in the early 2000s and became a core building block of domain-driven design.
Usually you define the repository as an interface in the business layer and write one or more implementations: a SQL or ORM-based one for production and an in-memory one for fast tests. Methods are named in the language of the domain, not the database, and in domain-driven design there is typically one repository per aggregate, a cluster of objects saved together, rather than one per table. In clean and hexagonal architecture, the repository interface is a port and the database implementation is an adapter.
An analogy is a library's front desk: you ask for a book by title, and the librarian fetches it from the shelves, the archive, or another branch, without you needing to know where it was stored. Repositories make code easier to test, since services can be given a fake repository, and they keep database details from spreading through the business logic.
The repository pattern is often confused with a DAO (data access object) and with an ORM. A DAO usually mirrors the database, with one class per table and generic create, read, update, and delete methods, while a repository speaks the language of the domain and may combine several tables. An ORM maps objects to tables and a repository can wrap one, but many ORMs already provide repository-like APIs, so adding your own layer on top only pays off when it simplifies testing or hides real complexity. Despite the shared name, it also has nothing to do with a Git repository.
Key takeaways
- A repository gives business code a collection-like interface for loading and saving objects.
- Its methods use domain language, such as
findOverdueInvoices, not database terms. - Production code can use a database implementation, while tests use an in-memory one.
- In clean and hexagonal architecture, the repository interface is a port.
- A DAO usually mirrors tables; a repository is shaped around the domain.
Example
interface User { id: string; email: string }
// The business layer depends only on this interface
interface UserRepository {
findById(id: string): Promise<User | null>;
save(user: User): Promise<void>;
}
// An in-memory implementation for tests (production would use SQL or an ORM)
class InMemoryUserRepository implements UserRepository {
private users = new Map<string, User>();
async findById(id: string) { return this.users.get(id) ?? null; }
async save(user: User) { this.users.set(user.id, user); }
}Readers ask
What is the difference between a repository and a DAO?
A DAO is usually tied to the database structure, often one class per table with generic CRUD methods. A repository is tied to the domain, offering methods that match business needs and possibly combining data from several tables into one object.
Do I need the repository pattern if I use an ORM?
Not always. Many ORMs already give you repository-like methods, and wrapping them again can add boilerplate. A custom repository is most useful when you want domain-specific queries in one place, easy test doubles, or the freedom to change the data source later.
What is the difference between a repository and a service?
A repository is responsible only for storing and retrieving objects. A service contains business logic, such as placing an order, and uses one or more repositories to load and save the data it works with.
See also
- ORMDatabases, p. 33An ORM is a library that maps database tables to objects in your programming language, letting you read and write data with code instead of raw SQL.
- Domain-Driven DesignSoftware Architecture, p. 15Domain-driven design is an approach to building software that models the code closely on the business domain, using the same language as the domain experts.
- Hexagonal ArchitectureSoftware Architecture, p. 21Hexagonal architecture is a way of structuring software so the core business logic talks to the outside world only through ports and swappable adapters.
- Clean ArchitectureSoftware Architecture, p. 5Clean architecture is a way of structuring software in layers so that the core business rules never depend on frameworks, databases, or user interfaces.
- MockingTesting & Quality, p. 16Mocking is a testing technique that replaces a real dependency, such as a database or API, with a fake you control so that code can be tested in isolation.
- Layered ArchitectureSoftware Architecture, p. 25Layered architecture splits an application into horizontal layers, such as presentation, business logic, and data access, each calling only the layer below it.
Spotted a mistake or something missing on this page?Suggest an edit