What is Clean Architecture?
Clean Architecture is a software design philosophy created by Robert C. Martin (Uncle Bob) that emphasizes separation of concerns and independence of frameworks, UI, databases, and external agencies.Core Principles
1. Independence
The architecture is independent of:- Frameworks: The architecture doesn’t depend on WPF, LibGit2Sharp, or other libraries
- UI: Business logic works without any UI
- Database: Domain logic doesn’t care about storage mechanisms
- External Services: Core business rules don’t depend on external APIs
2. Testability
Business rules can be tested without:- UI
- Database
- Web server
- External dependencies
3. The Dependency Rule
Dependencies must point inward toward the DomainSource code dependencies can only point inward. Inner circles cannot know anything about outer circles.
The Four Layers
Domain Layer (Core)
Location:Chapi/Domain/
Purpose: Contains the core business entities, rules, and abstractions
Responsibilities:
- Define business entities (
GitCommit,FileChange,Project) - Define domain interfaces (
IGitRepository,INotificationService) - Contain business rules and validations
- Define value objects and enumerations
- No dependencies on other layers
- No references to external libraries (except .NET base classes)
- Pure business logic
Application Layer (Use Cases)
Location:Chapi/Application/
Purpose: Contains application-specific business rules and orchestrates data flow
Responsibilities:
- Implement Use Cases (business operations)
- Coordinate between Domain and Infrastructure
- Transform data between layers
- Enforce business workflows
- Can depend on Domain layer
- Uses Domain interfaces
- Independent of UI and Infrastructure implementations
Infrastructure Layer
Location:Chapi/Infrastructure/
Purpose: Implements interfaces defined in Domain layer using external libraries and services
Responsibilities:
- Implement repository interfaces
- Handle external API calls (Git, AI services)
- Manage file system operations
- Handle persistence and caching
- Depends on Domain layer (implements its interfaces)
- Can use external libraries (LibGit2Sharp, HTTP clients, etc.)
Presentation Layer
Location:Chapi/Presentation/
Purpose: Handles UI concerns and user interactions
Responsibilities:
- Implement ViewModels (MVVM pattern)
- Define Views (XAML)
- Handle UI events and commands
- Data binding and UI state management
- Depends on Application layer (uses Use Cases)
- Depends on Domain layer (uses entities)
- Can use WPF-specific libraries
Dependency Flow
Correct Dependencies (Inward)
Incorrect Dependencies (Avoid)
Benefits in Chapi Assistant
Before Clean Architecture
- Cannot test without UI
- Cannot reuse logic
- High coupling
- Difficult to maintain
After Clean Architecture
Domain:- ✅ Each layer is testable independently
- ✅ Business logic is reusable
- ✅ Low coupling
- ✅ Easy to maintain and extend
Dependency Injection Setup
All dependencies are wired inApp.xaml.cs:
Testing Strategy
Domain Layer
Application Layer
Migration Journey
Chapi Assistant underwent a significant refactoring to implement Clean Architecture:- Phase 1: Created layer structure and domain entities
- Phase 2: Extracted Git operations to Infrastructure layer
- Phase 3: Implemented Use Cases in Application layer
- Phase 4: Created ViewModels and reduced MainWindow complexity
- Phase 5: Added comprehensive testing
~/workspace/source/doc/migrate/ for detailed refactoring examples.
Best Practices
Keep Domain Pure
Keep Domain Pure
Never reference UI frameworks or external libraries in the Domain layer. It should contain only pure business logic.
Use Interfaces
Use Interfaces
Define abstractions in Domain and implement them in Infrastructure. This enables dependency inversion.
One Use Case per Operation
One Use Case per Operation
Each business operation should have its own Use Case class. Don’t create “God” Use Cases.
Result Pattern Over Exceptions
Result Pattern Over Exceptions
Use the Result pattern for expected failures. Reserve exceptions for unexpected errors.
Inject Dependencies
Inject Dependencies
Always use constructor injection. Never use service locator pattern or static dependencies.
Related Resources
- Clean Architecture Blog by Robert C. Martin
- Layer Details - Deep dive into each layer
- Use Cases - Understanding the Use Case pattern