Arhitectură DDD în .NET Core: Cum structuri proiectele backend în mod curat și scalabil

  • Doru Bulubasa
  • 28 May 2025

🔰 1. Ce este Domain-Driven Design (DDD)?

  1. Inventat de Eric Evans, axat pe modele centrate pe domeniu.
  2. Separă codul în limbajul experților (Ubiquitous Language).
  3. Avantajele majore:

  • Cod ușor de testat
  • Separare clară a responsabilităților
  • Scalabilitate logică pe termen lung

📐 2. Structurarea soluției .NET Core în layere (proiecte)

Organizarea recomandată a soluției:
/src
  ├── Blog.Domain           <- modele, entități, Value Objects
  ├── Blog.Application      <- servicii de aplicație, comenzi, DTO-uri
  ├── Blog.Infrastructure   <- EF Core, repositories, external deps
  └── Blog.API              <- Web API Controllers, DI, prezentare
Explicarea fiecărui layer:
    • Domain: logică pură, fără dependențe externe
    • Application: orchestrare între servicii, fără acces direct la DB
    • Infrastructure: detalii tehnice (SQL, Redis, Email)
    • API: controlere, autentificare, DTO-uri externe

🧱 3. Modelul de domeniu – Crearea agregatului Post

public class Post : Entity<Guid>
{
    public Title Title { get; private set; }
    public Slug Slug { get; private set; }
    public PostContent Content { get; private set; }
    public DateTime PublishedAt { get; private set; }

    public Post(Title title, Slug slug, PostContent content)
    {
        Title = title;
        Slug = slug;
        Content = content;
        PublishedAt = DateTime.UtcNow;
    }
}

Value Object: Slug

public class Slug : ValueObject
{
    public string Value { get; }

    private Slug(string value)
    {
        Value = value;
    }

    public static Slug FromTitle(string title)
    {
        var slug = Regex.Replace(title.ToLower(), @"[^a-z0-9]+", "-");
        return new Slug(slug.Trim('-'));
    }

    protected override IEnumerable<object> GetEqualityComponents()
    {
        yield return Value;
    }
}

📦 4. Repository Pattern + Unit of Work

Interfață generică:
public interface IRepository<T> where T : class
{
    Task<T?> GetByIdAsync(Guid id);
    Task AddAsync(T entity);
    void Remove(T entity);
}

Unit of Work:
public interface IUnitOfWork
{
    Task<int> SaveChangesAsync();
}

În Infrastructure, vom implementa PostRepository cu EF Core.


💡 5. Application Layer + MediatR

Comandă de creare post:

public record CreatePostCommand(string Title, string Content) : Irequest<Guid>;

Handler:

public class CreatePostHandler : IRequestHandler<CreatePostCommand, Guid>
{
    private readonly IPostRepository _postRepo;
    private readonly IUnitOfWork _uow;

    public CreatePostHandler(IPostRepository postRepo, IUnitOfWork uow)
    {
        _postRepo = postRepo;
        _uow = uow;
    }

    public async Task<Guid> Handle(CreatePostCommand request, CancellationToken ct)
    {
        var slug = Slug.FromTitle(request.Title);
        var post = new Post(new Title(request.Title), slug, new PostContent(request.Content));
        await _postRepo.AddAsync(post);
        await _uow.SaveChangesAsync();
        return post.Id;
    }
}

🔚 Concluzie

Acest articol marchează începutul implementării backend-ului nostru folosind DDD în .NET Core. Am discutat conceptele cheie, structura proiectului și am implementat un prim agregat (Post) cu pattern-uri robuste.

🧭 Ce urmează

În articolul următor, vom:
    • Adăuga un controller REST pentru POST /posts
    • Conecta frontend-ul React la acest endpoint
    • Afișa și trimite articole din UI

Scrie un comentariu

Adresa de mail nu va fi publicata. Campurile obligatorii sunt marcate cu *