In the ever-evolving world of software development, architects and developers continuously seek methodologies that enhance code organization, maintainability, and scalability. Two prominent architectural patterns that have emerged are the Traditional Layered Architecture and Vertical Slice Architecture. While the former has been a staple in the industry for decades, the latter is gaining traction for its innovative approach to structuring code. This article delves into a comprehensive comparison between these two architectures, highlighting their benefits, drawbacks, and real-world applications with C# .NET code examples.
Traditional Layered Architecture, also known as N-tier architecture, organizes an application into horizontal layers, each responsible for a distinct aspect of the system. The common layers include:
// Presentation Layer: Controller in ASP.NET Core
public class ProductController : ControllerBase
{
private readonly IProductService _productService;
public ProductController(IProductService productService)
{
_productService = productService;
}
[HttpPost("products")]
public IActionResult CreateProduct([FromBody] CreateProductRequest request)
{
var result = _productService.CreateProduct(request);
if (result.IsSuccess)
return Ok(result.Value);
return BadRequest(result.Error);
}
}
// Application Layer: Service
public class ProductService : IProductService
{
private readonly IProductRepository _productRepository;
public ProductService(IProductRepository productRepository)
{
_productRepository = productRepository;
}
public Result<ProductResponse> CreateProduct(CreateProductRequest request)
{
var product = new Product
{
Name = request.Name,
Price = request.Price
};
_productRepository.Add(product);
return Result.Success(new ProductResponse(product.Id, product.Name, product.Price));
}
}
// Domain Layer: Domain Model
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
}
// Data Access Layer: Repository
public class ProductRepository : IProductRepository
{
private readonly AppDbContext _context;
public ProductRepository(AppDbContext context)
{
_context = context;
}
public void Add(Product product)
{
_context.Products.Add(product);
_context.SaveChanges();
}
}
Vertical Slice Architecture takes a different approach by organizing code around features rather than technical concerns. Each vertical slice encompasses all the necessary components to fulfill a specific functionality, from the user interface to the data access.
public static class CreateProduct
{
public record Request(string Name, decimal Price);
public record Response(int Id, string Name, decimal Price);
public class Validator : AbstractValidator<Request>
{
public Validator()
{
RuleFor(x => x.Name).NotEmpty().MaximumLength(100);
RuleFor(x => x.Price).GreaterThanOrEqualTo(0);
}
}
public class Endpoint : IEndpoint
{
public void MapEndpoint(IEndpointRouteBuilder app)
{
app.MapPost("products", Handler).WithTags("Products");
}
public static async Task<IResult> Handler(
Request request,
IValidator<Request> validator,
AppDbContext context)
{
var validationResult = await validator.ValidateAsync(request);
if (!validationResult.IsValid)
{
return Results.BadRequest(validationResult.Errors);
}
var product = new Product
{
Name = request.Name,
Price = request.Price
};
context.Products.Add(product);
await context.SaveChangesAsync();
return Results.Ok(new Response(product.Id, product.Name, product.Price));
}
}
}
How to start with it?
We prepared a simple VSA Project Template that you can download for free.
Download the source code and start exploring.
Download here:
https://medium.com/codenx/code-in-clean-vs-traditional-layered-architecture-net-31c4cad8f815