Skip to main content

Design Application using Clean Architecture

 Clean Architecture, introduced by Robert C. Martin (Uncle Bob), aims to create systems that are:

  • Independent of frameworks
  • Testable
  • Independent of UI
  • Independent of database
  • Independent of any external agency

Clean Architecture emphasizes separating the concerns of different parts of the system and ensuring that each part has a clear responsibility.

.NET clean architecture as a development approach, available in a layered form to reduce dependency.

The architecture consists of several layers, each with a specific role and dependencies that flow in one direction: from the outer layers to the inner layers.

Inner most Layer is independent to its outer layer, means inner most layer does not have any references, it builds and stand independently.

Dependency Rule

The core principle of Clean Architecture is the Dependency Rule, which states that source code dependencies can only point inward. This means:

  • Nothing in inner circle can depend on anything in an outer circle.
  • Data formats and structures should also follow this rule.

Infrastructure Layer and Presentation Layer are outer most layer so these two layers does not depend on each other.

The main four layers of clean architecture consist of below layers:

  • Domain Layer
  • Application Layer
  • Infrastructure Layer
  • Presentation Layer

I have created project for better understanding, let’s Learn in detail.

I have created below Diagram for better understanding.

Key Points

a. Database implementation happens on Infrastructure layer so consider we connected to SQL database and tomorrow if requirement changes then and client says we need to change database to oracle then we can do with impacting other part of application

b. Similarly, Presentation Layer, today in this example we have used api end point and instead of it we want to use ASP.net MVC or any other UI framework we can use it without impacting rest of application.

Domain Layer

This layer Consist of business Models and entities

Example

This layer will have entities like below

namespace Domain.Entities
{
public class Customer
{
public int Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
}
}

Project screen shot

Application Layer

The application layer resides in the middle of the presentation and domain layer and functions as an intermediate between them. Primarily, it maintains the data between corresponding layers but is independent of the infrastructure and presentation layer.

This layer contains Interfaces and classes for all Use cases or Business Logic like below

Application Layer Dependent on domain layer, means this layer need to add reference of Domain layers or entities

Use Cases -> Defining Interfaces for CRUD operations

using Domain.Entities;

using System.Threading.Tasks;

namespace ApplicationLayer.Interfaces
{
public interface ICustomerRepository
{
void Add(Customer customer);
Customer GetById(int id);
IEnumerable<Customer> GetAll();
}
}

Implementation of Use Cases

using Domain.Entities;
using ApplicationLayer.Interfaces;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ApplicationLayer.UseCases
{
public class CreateCustomer
{
private readonly ICustomerRepository _repository;

public CreateCustomer(ICustomerRepository repository)
{
_repository = repository;
}

public void Execute(Customer customer)
{
// Business logic for creating a customer
_repository.Add(customer);
}
}
}

Infrastructure Layer

This layer Contains of DbContext class for database connection and repository classes which will implement ICustomerRepository interface defined on Applicaiton layer.

This layer Depend on Application layer and Domain layer

DB Context classes

using Microsoft.EntityFrameworkCore;
using Domain.Entities;

namespace Infrastructure.Data
{
public class AppDbContext : DbContext
{
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options)
{

}

public DbSet<Customer> Customers { get; set; }
}

}

Customer Repository class

using Domain.Entities;
using Infrastructure.Data;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ApplicationLayer.Interfaces;

namespace Infrastructure.Repository
{
public class CustomerRepository : ICustomerRepository
{
private readonly AppDbContext _context;

public CustomerRepository(AppDbContext context)
{
_context = context;
}

public void Add(Customer customer)
{
_context.Customers.Add(customer);
_context.SaveChanges();
}

public Customer GetById(int id)
{
return _context.Customers.Find(id);
}

public IEnumerable<Customer> GetAll()
{
return _context.Customers.ToList();
}
}
}

We can see here Add Use case have reference of application Layer.

Dependency Injection

using Core.Interfaces;
using Infrastructure.Data;
using Microsoft.Extensions.DependencyInjection;

namespace Infrastructure.DI
{
public static class DependencyInjection
{
public static IServiceCollection AddInfrastructure(this IServiceCollection services)
{
services.AddDbContext<AppDbContext>(options =>
options.UseSqlServer("YourConnectionString"));

services.AddScoped<ICustomerRepository, CustomerRepository>();

return services;
}
}
}

Presentation Layer

This layer we use to execute our action; this you can call as UI layer but, in our cases, this is Controller class from where user start action.

This layer depends on Domain Layer and Applicaiton Layer only

using Core.Entities;
using Core.UseCases;
using Microsoft.AspNetCore.Mvc;

namespace WebApi.Controllers
{
[ApiController]
[Route("api/[controller]")]
public class CustomerController : ControllerBase
{
private readonly CreateCustomer _createCustomer;

public CustomerController(CreateCustomer createCustomer)
{
_createCustomer = createCustomer;
}

[HttpPost]
public IActionResult Create(Customer customer)
{
_createCustomer.Execute(customer);
return Ok();
}
}
}

Code flow

[User] -> [Web (Controllers)] -> [Core (UseCases)] -> [Core (Interfaces)] -> [Infrastructure (Data)] -> [Database]
  1. User sends a request to add a Customer.
  2. Web Layer (CustomerController) receives the request and converts the input to a domain entity.
  3. Core Layer (Use Case) processes the business logic.
  4. Core Layer (Interface) defines the contract for data operations.
  5. Infrastructure Layer (Data) implements the contract and performs database operations.

Conclusion

We have understood each layer in detail.

Please clap if this is adding any value to your knowledge.

Comments

Popular posts from this blog

How to Earn online from Medium.com

  As freelancer I started writing on medium (Tech blogs) from  Aug 2024   but I was already writing tech blogs on c-sharpcorner.com “The purpose of this post is to encourage new writers by helping them understand how they can earn as freelancers.” “Medium is a great platform for writers. When I started writing, I had no idea that I would reach the $100 benchmark in just four months. Now, I’m feeling self-inspired, as it has become a valuable source of income as a freelancer.” AUG 2024 ( $0 ) It was just beginning, and I posted 4 articles and had only few views 455 and 165 reads. During this time, I was learning about medium rules for writers and partner program. It will take some time to understand over all process. SEP 2024 ($6) As I started writing and I was getting few cents on Aug 2024, I posted 8 more articles in SEP, and it was good month because my blogs were getting noticed and I started getting claps etc. “This month, I went from $0 to $6, which was an achievemen...

Fixing High CPU Usage in .NET Core using Parallelism

  We will fix problem occurs due to incorrect use Parallelism in .NET Core To increase application performance sometimes we use process task or work extensively in Parallel and that may lead performance issue. When we do code, we should understand our requirement very carefully along with hardware resources those we have. We should code like that there should be less CPU usage and server should work without issues. In .NET Core, when you’re using parallelism (like Parallel.For, Task.WhenAll, or Task.Run), you might encounter performance issues if the number of concurrent threads or tasks exceeds what your system can efficiently handle. A common issue is high CPU usage or resource contention, which can degrade overall performance, cause excessive context switching, and even lead to thread starvation or deadlocks. Non members can access from here Effective Parallelism Strategies to Mitigate High CPU Usage in .NET Core We will fix problem occurs due to incorrect use Parallelism in .NE...