Repository Pattern

The Repository pattern provides an alternative to Active Record by separating data persistence from domain objects. While CQL primarily uses Active Record, you can implement Repository patterns for specific use cases.

What is the Repository Pattern?

In the Repository pattern:

  • Domain objects (entities) hold data and business logic

  • Repositories handle all database operations

  • The domain layer doesn't know about persistence

┌──────────────┐     ┌──────────────┐     ┌──────────────┐
│   Domain     │────>│  Repository  │────>│   Database   │
│   Objects    │<────│              │<────│              │
└──────────────┘     └──────────────┘     └──────────────┘

Why Use Repository Pattern?

Separation of Concerns

Domain objects focus on business logic, not database operations:

# Entity - no database knowledge
struct User
  property id : Int64?
  property name : String
  property email : String

  def full_name
    name.split.map(&.capitalize).join(" ")
  end
end

# Repository - handles persistence
class UserRepository
  def find(id : Int64) : User?
    # Database query
  end

  def save(user : User) : Bool
    # Insert or update
  end
end

Testability

Easily mock repositories for testing:

Flexibility

Switch data sources without changing domain logic:

Implementing Repository with CQL

Step 1: Define Your Entity

Step 2: Create a CQL Model (Internal)

Step 3: Implement the Repository

Step 4: Use the Repository

When to Use Repository Pattern

Good Use Cases

  1. Complex domain logic - Keep business rules separate from persistence

  2. Multiple data sources - Same domain, different storage

  3. Heavy testing - Easy to mock repositories

  4. Large teams - Clear boundaries between concerns

Not Ideal For

  1. Simple CRUD apps - Overkill for basic operations

  2. Rapid prototyping - Slows initial development

  3. Small projects - Adds unnecessary complexity

Comparison: Active Record vs Repository

The difference is subtle in simple cases but significant for complex domains.

Hybrid Approach

You can mix both patterns:

This gives you the best of both worlds: simplicity for CRUD and separation for complex logic.

Last updated

Was this helpful?