Repositories - spinningideas/resources GitHub Wiki

Repository Pattern

The repository pattern is a design pattern that isolates data access logic behind an abstraction, usually an interface or abstract class. It exposes data operations-such as querying, adding, updating, and deleting-through a collection-like API while hiding the underlying persistence technology. This separation keeps business logic independent of database details, making the code easier to test, maintain, and evolve.

History

The repository pattern has roots in software architecture research that predates many modern frameworks. One of the earliest published descriptions appears in An Introduction to Software Architecture by David Garlan and Mary Shaw (1994), where a repository is discussed as a central data store accessed by independent components.

The pattern later gained widespread attention through:

  • Patterns of Enterprise Application Architecture by Martin Fowler (2003) - Fowler described the Repository as a layer that mediates between the domain and data-mapping layers, presenting a collection-like interface for accessing domain objects and concentrating query construction code in one place.
  • Domain-Driven Design by Eric Evans (2004) - Evans positioned the Repository as a tactical building block that models access to aggregates as if they were in-memory collections, keeping persistence concerns out of the domain layer.

Using an interface for a repository became common practice because it decouples the domain/application code from the concrete persistence technology, making the system easier to test, replace, and evolve.

Benefits

  • Separation of Concerns: Business logic is separated from data access logic.
  • Testability: Repositories can be mocked for unit testing.
  • Flexibility: Easy to switch between different data sources (e.g., SQL, NoSQL, in-memory).
  • Maintainability: Changes to data access logic don't affect business logic.

SOLID Principles

The repository pattern helps fulfill several SOLID principles, especially when combined with interfaces:

  • Single Responsibility Principle (SRP) - Repositories isolate data-access logic from business logic, giving each layer one reason to change.
  • Open/Closed Principle (OCP) - New storage technologies are added through new adapter implementations, not by editing the domain code.
  • Liskov Substitution Principle (LSP) - Different repository implementations (SQL, in-memory, file) can be substituted without altering the application.
  • Interface Segregation Principle (ISP) - Small, focused repository interfaces avoid forcing clients to depend on methods they do not use.
  • Dependency Inversion Principle (DIP) - Application code depends on repository abstractions (interfaces), not on concrete persistence classes.

The strongest benefits show up for SRP, OCP, LSP, and DIP.


Ports and Adapters / Hexagonal Architecture

The repository pattern fits naturally into Hexagonal Architecture (also called Ports and Adapters), an architectural style formalized by Alistair Cockburn. The application core exposes ports (interfaces), and external concerns plug in through adapters (concrete implementations). A repository interface is a typical data-side port; SQL, file, or in-memory repositories are adapters.

History

Cockburn first drew the hexagonal shape in the mid-1990s, wrote it up on the Portland Pattern Repository wiki around 2004, and formalized it as "Ports and Adapters" in 2005. The goal was to let an application be driven equally by users, automated tests, batch scripts, or other systems without changing the core domain logic.

Relation to Repositories

By depending on repository interfaces rather than concrete data-access classes, the domain layer stays inside the hexagon and can be tested with in-memory adapters. When the real database is unavailable or the storage technology changes, only the adapter implementation changes.

Repository Interfaces

For language-specific repository interface examples, see Repository-Interfaces.