Skip to main content
The Domain Layer represents the heart of Chapi’s business logic, containing enterprise-wide business rules and entities. It follows Clean Architecture principles by being independent of external frameworks and infrastructure.

Layer Overview

Location: ~/workspace/source/Chapi/Domain/ Responsibilities:
  • Define core business entities
  • Establish repository interfaces (contracts)
  • Define domain models and value objects
  • Implement business rules and validation
  • Remain framework-agnostic and testable
Key Principle: The Domain Layer has zero dependencies on other layers. All other layers depend on it.

Core Components

Entities

Entities represent core business objects with identity and lifecycle.

Repository Interfaces

Repository interfaces define contracts for data access without implementation details.

Result Pattern

Chapi uses the Result pattern to handle success/failure without exceptions.

Domain Models

Models represent data structures without identity or behavior.

Enumerations

Domain-level enums define valid states and options.
// Git Provider Types
public enum GitProvider
{
    Unknown,
    GitHub,
    GitLab
}

// Git Reset Modes
public enum ResetMode
{
    Soft,
    Mixed,
    Hard
}

// Task Priority Levels
public enum TaskPriority
{
    Low,
    Medium,
    High,
    Critical
}
Source: Domain/Enums/

Domain Services

Domain services encapsulate business logic that doesn’t naturally fit in entities.

Dependency Flow

Key Points:
  • Domain Layer is at the center
  • No dependencies on external layers
  • All layers depend on Domain contracts
  • Infrastructure implements Domain interfaces

Design Patterns

Repository Pattern

Abstracts data access through interfaces like IGitRepository

Result Pattern

Type-safe error handling without exceptions

Value Objects

Immutable models like GitCommit with validation

Domain Services

Business logic services like AvatarCacheService

Testing Strategy

The Domain Layer is highly testable due to its isolation:
[Test]
public void Project_IsValid_ReturnsFalse_WhenDirectoryDoesNotExist()
{
    var project = new Project { FullPath = "/nonexistent/path" };
    Assert.IsFalse(project.IsValid());
}

[Test]
public void GitCommit_ShortHash_ReturnsFirst7Characters()
{
    var commit = new GitCommit { Hash = "abc123def456" };
    Assert.AreEqual("abc123d", commit.ShortHash);
}

Best Practices

  • No references to UI frameworks (WPF, etc.)
  • No references to infrastructure libraries (Entity Framework, etc.)
  • Only .NET standard types and domain logic
Define IGitRepository, IProjectRepository instead of concrete implementations
public bool IsValid() => Directory.Exists(FullPath);
Return Result<T> for operations that can fail gracefully

Application Layer

Use cases and application services

Infrastructure Layer

Implementation of domain interfaces

Clean Architecture

Overall architecture principles

Build docs developers (and LLMs) love