Skip to content

chafroudtarek/farrahni-backend

Repository files navigation

Farrahni Project - Clean Architecture Guide

πŸ“‹ Table of Contents

πŸ—οΈ Project Overview

This project follows Clean Architecture principles combined with Domain-Driven Design (DDD) patterns to create a maintainable, testable, and scalable .NET Web API.

🎯 Architecture Pattern

The solution implements the Onion Architecture (Clean Architecture) with these core principles:

  • Dependency Inversion: Dependencies point inward toward the domain
  • Separation of Concerns: Each layer has distinct responsibilities
  • Framework Independence: Business logic is isolated from external frameworks
  • Testability: Easy to unit test business logic in isolation

πŸ“ Project Structure

Farrahni/
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ Farrahni.API/                 # 🌐 Presentation Layer
β”‚   β”œβ”€β”€ Farrahni.Application/         # πŸ“š Application Layer  
β”‚   β”œβ”€β”€ Farrahni.Domain/              # πŸ›οΈ Domain Layer (Core)
β”‚   └── Farrahni.Infrastructure/      # πŸ”§ Infrastructure Layer
β”œβ”€β”€ tests/
β”‚   β”œβ”€β”€ Farrahni.UnitTests/          # Unit Tests
β”‚   └── Farrahni.IntegrationTests/   # Integration Tests
β”œβ”€β”€ docs/                            # Documentation
β”œβ”€β”€ docker-compose.yml               # Docker configuration
β”œβ”€β”€ Farrahni.sln                     # Solution file
└── README.md                        # This file

🎯 Layer Responsibilities

🌐 Presentation Layer (Farrahni.API)

Purpose: Handles HTTP requests and responses, user interface concerns.

Farrahni.API/
β”œβ”€β”€ Controllers/          # API endpoints and HTTP logic
β”‚   β”œβ”€β”€ ProductsController.cs
β”‚   β”œβ”€β”€ UsersController.cs
β”‚   └── OrdersController.cs
β”œβ”€β”€ Middlewares/          # Custom middleware components
β”‚   β”œβ”€β”€ GlobalExceptionHandlerMiddleware.cs
β”‚   β”œβ”€β”€ RequestLoggingMiddleware.cs
β”‚   └── AuthenticationMiddleware.cs
β”œβ”€β”€ Filters/              # Action filters and attributes
β”‚   β”œβ”€β”€ ValidationFilter.cs
β”‚   β”œβ”€β”€ AuthorizeFilter.cs
β”‚   └── CacheFilter.cs
β”œβ”€β”€ Extensions/           # Service configuration extensions
β”‚   β”œβ”€β”€ PresentationServiceExtensions.cs
β”‚   └── SwaggerExtensions.cs
β”œβ”€β”€ Program.cs            # Application entry point
└── appsettings.json      # Configuration files

Responsibilities:

  • βœ… HTTP request/response handling
  • βœ… Input validation and model binding
  • βœ… Authentication and authorization
  • βœ… API documentation (Swagger)
  • βœ… Dependency injection configuration
  • ❌ Business logic (belongs in Application/Domain)
  • ❌ Data access (belongs in Infrastructure)

πŸ“š Application Layer (Farrahni.Application)

Purpose: Orchestrates business workflows and use cases.

Farrahni.Application/
β”œβ”€β”€ DTOs/                 # Data Transfer Objects
β”‚   β”œβ”€β”€ ProductDto.cs
β”‚   β”œβ”€β”€ CreateProductDto.cs
β”‚   └── UpdateProductDto.cs
β”œβ”€β”€ Interfaces/           # Service contracts
β”‚   β”œβ”€β”€ IProductService.cs
β”‚   β”œβ”€β”€ IUserService.cs
β”‚   └── IEmailService.cs
β”œβ”€β”€ Services/             # Application services
β”‚   β”œβ”€β”€ ProductService.cs
β”‚   β”œβ”€β”€ UserService.cs
β”‚   └── OrderService.cs
β”œβ”€β”€ Validators/           # Input validation rules
β”‚   β”œβ”€β”€ CreateProductValidator.cs
β”‚   └── UpdateUserValidator.cs
β”œβ”€β”€ Mappings/             # AutoMapper profiles
β”‚   β”œβ”€β”€ ProductProfile.cs
β”‚   └── UserProfile.cs
β”œβ”€β”€ Common/               # Shared application logic
β”‚   β”œβ”€β”€ Models/
β”‚   β”‚   β”œβ”€β”€ ApiResponse.cs
β”‚   β”‚   └── PaginatedResult.cs
β”‚   β”œβ”€β”€ Exceptions/
β”‚   β”‚   β”œβ”€β”€ NotFoundException.cs
β”‚   β”‚   └── ValidationException.cs
β”‚   └── Behaviors/        # MediatR behaviors
β”‚       β”œβ”€β”€ ValidationBehavior.cs
β”‚       └── LoggingBehavior.cs
└── ApplicationServiceExtensions.cs

Responsibilities:

  • βœ… Use case implementation
  • βœ… DTO mapping and transformation
  • βœ… Input validation
  • βœ… Business workflow orchestration
  • βœ… Cross-cutting concerns (logging, caching)
  • ❌ UI concerns (belongs in Presentation)
  • ❌ Data persistence logic (belongs in Infrastructure)
  • ❌ Core business rules (belongs in Domain)

πŸ›οΈ Domain Layer (Farrahni.Domain) - CORE

Purpose: Contains pure business logic and domain models.

Farrahni.Domain/
β”œβ”€β”€ Entities/             # Domain entities (business objects)
β”‚   β”œβ”€β”€ Product.cs
β”‚   β”œβ”€β”€ User.cs
β”‚   β”œβ”€β”€ Order.cs
β”‚   └── Category.cs
β”œβ”€β”€ ValueObjects/         # Immutable domain values
β”‚   β”œβ”€β”€ Money.cs
β”‚   β”œβ”€β”€ Address.cs
β”‚   └── Email.cs
β”œβ”€β”€ Interfaces/           # Domain contracts
β”‚   β”œβ”€β”€ IRepository.cs
β”‚   β”œβ”€β”€ IUnitOfWork.cs
β”‚   └── IDomainService.cs
β”œβ”€β”€ Events/               # Domain events
β”‚   β”œβ”€β”€ ProductCreatedEvent.cs
β”‚   └── OrderPlacedEvent.cs
β”œβ”€β”€ Services/             # Domain services
β”‚   β”œβ”€β”€ PricingService.cs
β”‚   └── InventoryService.cs
β”œβ”€β”€ Enums/                # Domain enumerations
β”‚   β”œβ”€β”€ OrderStatus.cs
β”‚   └── UserRole.cs
└── Common/               # Shared domain logic
    β”œβ”€β”€ BaseEntity.cs
    β”œβ”€β”€ IAggregateRoot.cs
    └── IDomainEvent.cs

Responsibilities:

  • βœ… Core business entities and rules
  • βœ… Domain services and logic
  • βœ… Value objects and enumerations
  • βœ… Domain events and behaviors
  • βœ… Repository interfaces
  • ❌ External dependencies (UI, Database, APIs)
  • ❌ Framework-specific code

⚠️ IMPORTANT: Domain layer should have NO external dependencies!

πŸ”§ Infrastructure Layer (Farrahni.Infrastructure)

Purpose: Handles external concerns and technical implementations.

Farrahni.Infrastructure/
β”œβ”€β”€ Data/                 # Database-related implementations
β”‚   β”œβ”€β”€ Context/
β”‚   β”‚   └── ApplicationDbContext.cs
β”‚   β”œβ”€β”€ Repositories/
β”‚   β”‚   β”œβ”€β”€ Repository.cs
β”‚   β”‚   β”œβ”€β”€ ProductRepository.cs
β”‚   β”‚   └── UserRepository.cs
β”‚   β”œβ”€β”€ Configurations/   # Entity Framework configurations
β”‚   β”‚   β”œβ”€β”€ ProductConfiguration.cs
β”‚   β”‚   └── UserConfiguration.cs
β”‚   └── Migrations/       # EF Core migrations
β”œβ”€β”€ Services/             # External service implementations
β”‚   β”œβ”€β”€ EmailService.cs
β”‚   β”œβ”€β”€ FileStorageService.cs
β”‚   └── CachingService.cs
β”œβ”€β”€ External/             # Third-party integrations
β”‚   β”œβ”€β”€ PaymentService.cs
β”‚   β”œβ”€β”€ GoogleMapsService.cs
β”‚   └── AzureBlobStorage.cs
└── InfrastructureServiceExtensions.cs

Responsibilities:

  • βœ… Database access and ORM configuration
  • βœ… External API integrations
  • βœ… File system operations
  • βœ… Email/SMS services
  • βœ… Caching implementations
  • βœ… Third-party service integrations
  • ❌ Business logic (belongs in Domain/Application)

πŸ”„ Dependency Flow

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚             Presentation                β”‚
β”‚           (Farrahni.API)               β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
          β”‚                   β”‚
          β–Ό                   β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   Application   β”‚  β”‚ Infrastructure  β”‚
β”‚ (Farrahni.App)  β”‚  β”‚ (Farrahni.Infra)β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜
          β”‚                   β”‚
          β–Ό                   β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚              Domain                     β”‚
β”‚          (Farrahni.Domain)              β”‚
β”‚             ⭐ CORE ⭐                   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Dependency Rules:

  • βœ… API β†’ Application + Infrastructure
  • βœ… Application β†’ Domain only
  • βœ… Infrastructure β†’ Domain + Application
  • βœ… Domain β†’ No external dependencies
  • ❌ Domain should never depend on outer layers

πŸš€ Workflow Guidelines

Creating a New Feature (e.g., Product Management)

1️⃣ Start with Domain (Inside-Out Approach)

// Farrahni.Domain/Entities/Product.cs
public class Product : BaseEntity
{
    private Product() { } // EF Constructor
    
    public Product(string name, decimal price)
    {
        if (string.IsNullOrEmpty(name)) 
            throw new ArgumentException("Name is required");
        if (price <= 0) 
            throw new ArgumentException("Price must be positive");
            
        Name = name;
        Price = price;
    }
    
    public string Name { get; private set; }
    public decimal Price { get; private set; }
    
    public void UpdatePrice(decimal newPrice)
    {
        if (newPrice <= 0) 
            throw new ArgumentException("Price must be positive");
        Price = newPrice;
    }
}

2️⃣ Create Application Services

// Farrahni.Application/DTOs/ProductDto.cs
public class ProductDto
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    public decimal Price { get; set; }
}

// Farrahni.Application/Interfaces/IProductService.cs
public interface IProductService
{
    Task<ApiResponse<ProductDto>> GetByIdAsync(Guid id);
    Task<ApiResponse<ProductDto>> CreateAsync(CreateProductDto dto);
}

// Farrahni.Application/Services/ProductService.cs
public class ProductService : IProductService
{
    // Implementation using repository and mapping
}

3️⃣ Implement Infrastructure

// Farrahni.Infrastructure/Data/Configurations/ProductConfiguration.cs
public class ProductConfiguration : IEntityTypeConfiguration<Product>
{
    public void Configure(EntityTypeBuilder<Product> builder)
    {
        builder.Property(p => p.Name).HasMaxLength(200);
        builder.Property(p => p.Price).HasPrecision(18, 2);
    }
}

4️⃣ Create API Controller

// Farrahni.API/Controllers/ProductsController.cs
[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
    private readonly IProductService _productService;
    
    [HttpGet("{id}")]
    public async Task<IActionResult> GetById(Guid id)
    {
        var result = await _productService.GetByIdAsync(id);
        return result.Success ? Ok(result) : NotFound(result);
    }
}

5️⃣ Register Dependencies

// Update ApplicationServiceExtensions.cs
services.AddScoped<IProductService, ProductService>();

// Update InfrastructureServiceExtensions.cs  
services.AddScoped<IProductRepository, ProductRepository>();

πŸ”„ Development Workflow

  1. Domain First: Start with entities and business rules
  2. Test Early: Write unit tests for domain logic
  3. Application Layer: Create DTOs, services, and validators
  4. Infrastructure: Implement repositories and external services
  5. API Layer: Create controllers and configure endpoints
  6. Integration: Wire up dependency injection
  7. Test: Integration and end-to-end testing

πŸ“‹ Development Standards

Naming Conventions

  • Entities: Product, User, Order
  • DTOs: ProductDto, CreateProductDto, UpdateProductDto
  • Services: IProductService, ProductService
  • Repositories: IProductRepository, ProductRepository
  • Controllers: ProductsController (plural)

File Organization

βœ… One class per file
βœ… Namespace matches folder structure
βœ… Group related functionality together
βœ… Separate interfaces from implementations

Dependency Injection

// βœ… Use interfaces for loose coupling
services.AddScoped<IProductService, ProductService>();

// ❌ Don't register concrete classes directly
services.AddScoped<ProductService>();

Error Handling

// βœ… Use custom exceptions with meaningful messages
throw new NotFoundException($"Product with ID {id} not found");

// βœ… Use ApiResponse for consistent API responses
return ApiResponse<ProductDto>.FailureResult("Product not found");

πŸš€ Getting Started

Prerequisites

  • .NET 8.0 SDK
  • SQL Server or PostgreSQL
  • Docker (optional)

Setup

  1. Clone the repository

    git clone <repository-url>
    cd Farrahni
  2. Restore dependencies

    dotnet restore
  3. Update connection string

    // appsettings.json
    {
      "ConnectionStrings": {
        "DefaultConnection": "your-connection-string-here"
      }
    }
  4. Run migrations

    dotnet ef database update --project src/Farrahni.API
  5. Run the application

    dotnet run --project src/Farrahni.API
  6. Access Swagger UI

    https://localhost:7xxx/swagger
    

Docker Setup

  1. Build and run with Docker Compose

    docker-compose up --build
  2. Access the application

πŸ“š Additional Resources

Remember: The goal is to keep business logic pure and independent of external frameworks, making the application maintainable, testable, and adaptable to change.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors