Powrót do strony głównej

DDD w ASP.NET: problemy skalowalności po 30 agregatach

W projektach na ASP.NET z ponad 30 agregatami DDD prowadzi do spadku wydajności z powodu ciężkich zapytań EF Core, eksplozji specyfikacji i trudności z transakcjami. Analiza problemów i rekomendacje dotyczące hybrydowych podejść: CQRS, Vertical Slices.

Dlaczego DDD psuje się w dużych projektach ASP.NET z 30+ rejestrami
Advertisement 728x90

Skalowalność DDD w ASP.NET: problemy po 30 agregatach

Przekroczenie 30 agregatów w projekcie ASP.NET z Entity Framework Core prowadzi do krytycznych problemów z zasadą "jeden zapytanie – jeden agregat". Każdy agregat wymaga pełnej ładowania z obiektami zagnieżdżonymi, co generuje zapytania SQL z wieloma JOIN. To szczególnie widoczne w systemach ERP czy marketplacach, gdzie głębokość zagnieżdżenia osiąga 5–6 poziomów.

Przykład typowego zapytania dla agregatu Order:

var orders = await context.Orders
    .Include(o => o.Customer)
        .ThenInclude(c => c.Address)
    .Include(o => o.Customer)
        .ThenInclude(c => c.Contacts)
    .Include(o => o.Items)
        .ThenInclude(i => i.Product)
            .ThenInclude(p => p.Category)
    .Include(o => o.Items)
        .ThenInclude(i => i.Discount)
    .ToListAsync();

Odpowiednie zapytanie SQL zawiera dziesiątki LEFT JOIN, co znacznie spowalnia działanie. Aktualizacja jednego pola w nagłówku zamówienia wymaga załadowania wszystkich pozycji OrderItems jako części agregatu, co dodatkowo obciąża system.

Google AdInline article slot

Eksplozja specyfikacji i ich ograniczenia

Wzorzec Specification inkapsuluje logikę filtrowania, ale przy 30+ agregatach kolekcja klas Specification rośnie do setek plików. Kompozycja przez And/Or prowadzi do nieoptymalnego kodu SQL ze względu na zależność od IQueryable EF Core.

Główne problemy:

  • Zależność od konkretnego ORM: specyfikacje nie działają z Dapperem ani gRPC bez ponownego pisania.
  • Złożoność kompozycji w rzeczywistych scenariuszach z rolami, statusami i strefami czasowymi.
  • Czas poświęcony na abstrakcje przekracza czas potrzebny na implementację logiki biznesowej.

Transakcje między agregatami i nadmiarowa infrastruktura

Scoped DbContext w ASP.NET Core pasuje do wzorca Unit of Work w małych projektach. W dużych systemach przypadki biznesowe wymagają zmian w 5+ agregatach jednocześnie: tworzenie zamówienia, płatności, rezerwacji magazynowej i zadania w call centerze.

Google AdInline article slot

Rozwiązania są sprzeczne z DDD:

  • Jedna transakcja bazy danych – powoduje powstanie "God-serwisów" i narusza granice agregatów.
  • Rozproszone Saga lub Outbox – zwiększają złożoność nawet 10-krotnie.

W rezultacie 70% kodu to infrastrukturalny "klej" do synchronizacji, a nie logika biznesowa.

Navigacja w kodzie: tysiące plików i spowolnienie iteracji

Struktura DDD (API/Application/Domain/Infrastructure + Features) przy 30+ agregatach generuje ponad 1000 plików. Zmiana jednego pola w encji dotyka:

Google AdInline article slot
  • Encji domenowej.
  • Konfiguracji Fluent API.
  • Migracji.
  • Polecenia (Command).
  • Walidatora (FluentValidation).
  • Obsługiwacza (Handler).
  • DTO.
  • Mapera (AutoMapper).
  • Specyfikacji.
  • Testów.

To zmniejsza szybkość rozwoju, utrudnia onboardowanie i utrzymanie kodu.

Co jest ważne

  • Wydajność: ciężkie Include/ThenInclude generują nieefektywne zapytania SQL, czas odpowiedzi API rośnie wykładniczo.
  • Specyfikacje: nie skalują się, są związane z EF Core, kompozycja prowadzi do błędów.
  • Transakcje: operacje między agregatami wymagają kompromisów między DDD a wymaganiami biznesowymi.
  • Baza kodu: ponad 1000 plików spowalnia iteracje o 50–70%.
  • Hybrydowy podejście: DDD tylko w jądrze, CQRS/Vertical Slices dla obrzeży.

Rekomendacje migracji

Dla projektów z 30+ agregatami przejdź na hybrydowe architektury:

  • CQRS: rozdziel komendy i zapytania, używaj modeli odczytu bez Include.
  • Vertical Slices: grupuj kod według funkcjonalności, minimalizując warstwy.
  • Feature-Sliced Design: modułowość bez sztywnej architektury "lukowej".

To zachowuje zasady DDD w skomplikowanych domenach, upraszczając resztę.

— Editorial Team

Advertisement 728x90

Czytaj dalej