Repository Pattern
Repository: separate a useful responsibility
See the responsibility boundary
Order rules need to load and save orders, while database queries are repeated throughout the business code. A change in persistence details should not force every rule to understand indexes, row mapping and connection management.
This application-pattern lesson connects local organization with the system contracts discussed elsewhere in the course. The code is an original small local example, not a production persistence or web framework.
What you’ll learn
- Explain the responsibility Repository separates.
- Follow its local example and identify the implementation boundary.
- Compare related patterns and test the required guarantees.
How the responsibility is divided
Repository presents a domain-oriented access boundary over persisted objects. Its operations reflect useful queries and changes rather than exposing every storage command. A repository implementation maps the model to the chosen storage and its actual guarantees.
The example loads an order by identity through a repository contract. It uses a Map for teaching, not a durable database. Replacing it with SQL or another store must preserve defined error, query, concurrency and transaction behaviour.
Follow a small JavaScript example
Read the program and compare the expected output. Its state is local to one execution context; a real implementation needs the persistence, request and effect contracts described in the trade-offs.
JavaScript · local teaching example
const rows = new Map([['O1', {id: 'O1', status: 'ready'}]]);
const orders = {findById: id => rows.get(id)};
function orderStatus(repository, id) {
const order = repository.findById(id);
return order ? order.status : 'not found';
}
console.log(orderStatus(orders, 'O1'));Expected output
readyChoose a boundary from the situation
Compare boundary choices
Compare the visible consequences. With JavaScript enabled, choose an option in each scenario to assemble your decision record.
This is an exploratory design exercise. It does not run infrastructure, measure capacity or replace the lesson’s quiz.
All alternatives and consequences remain visible. Select one per situation to record your reasoning.
Choose it for a concrete need
Use it when a domain-oriented persistence boundary improves separation and testability. Keep important query shape and transaction scope deliberate.
An excessively generic CRUD wrapper can hide expensive queries without providing a useful domain contract. Repositories do not make all databases interchangeable; uniqueness, isolation and mapping differences still matter. Specify whether returned objects are snapshots or mutable tracked entities.
Compare the neighbouring responsibilities
Adapter reconciles an interface mismatch. Repository expresses a domain persistence boundary and may use adapters internally. Unit of Work can coordinate changes across repositories within one supported transaction.
Continue with coordinating one transaction’s changes, adapting component interfaces, storage guarantees and access patterns.
For primary further reading, use the Repository catalog entry and compare the responsibilities with this course’s original example.
Check your pattern reasoning
Check your pattern reasoning
Keep the boundary and its guarantees explicit
Use Repository when its responsibility matches the actual problem. Keep implementation lifetime, concurrency and error behaviour visible rather than treating an organizational label as proof.
Return to the design-pattern guide or apply this alongside storage guarantees and access patterns.
Reaching the recap and completing the quizzes are separate milestones.