SplitApp Onion Arhitektuur — joonis ja võrdlus TalTech-i loenguga
1. Sibula-joonis (ringid seestpoolt väljapoole)
┌─────────────────────────────────────────────────┐
│ WebApp (Presentation) │
│ MVC Controllers · API Controllers (v1) │
│ Areas/Admin · Areas/Identity · Views │
│ ViewModels · Program.cs (DI Composition Root) │
│ ┌───────────────────────────────────────────┐ │
│ │ App.BLL (Application Services) │ │
│ │ TripService · ExpenseService · │ │
│ │ SettlementService · AdminServices │ │
│ │ (kasutab IAppUnitOfWork liidese kaudu) │ │
│ │ ┌─────────────────────────────────────┐ │ │
│ │ │ App.Domain (Core / Süda) │ │ │
│ │ │ Entities: Trip, Expense, ... │ │ │
│ │ │ Enums, AppUser, AppRole │ │ │
│ │ │ Contracts: IAppUnitOfWork, │ │ │
│ │ │ ITripRepository, ... │ │ │
│ │ │ ┌───────────────────────────────┐ │ │ │
│ │ │ │ Base.Domain · Base.Contracts │ │ │ │
│ │ │ │ BaseEntity · IBaseRepository │ │ │ │
│ │ │ │ IUnitOfWork · LangStr │ │ │ │
│ │ │ └───────────────────────────────┘ │ │ │
│ │ └─────────────────────────────────────┘ │ │
│ └───────────────────────────────────────────┘ │
└─────────────────────────────────────────────────┘
▲ ▲
│ │
│ ┌────────────────────────────────────┐ │
│ │ App.DAL.EF (Infrastructure) │ │
│ │ AppDbContext · AppUnitOfWork │─── implementeerib ───┘
│ │ Repositories · Migrations │ IAppUnitOfWork,
│ │ Seeding · ServiceCollectionExt │ ITripRepository
│ └────────────────────────────────────┘
│ ▲
│ │ plugitav (saab vahetada nt Dapperi vastu)
│
│ ┌────────────────────────────────────┐
└────│ App.DTO · App.Resources │
│ v1 DTOs · Mappers · .resx │
└────────────────────────────────────┘
Tähtis: Infrastructure (DAL.EF) on väljaspool sibulat ja osutab sissepoole — just nagu TalTech-i loengus: "Infrastructure -> Domain <- Application <- Web".
2. Sõltuvuste graaf (nooled = ProjectReference)
Base.Domain ◄──── Base.Contracts
▲ ▲
│ │
└──── App.Domain ─┤
▲ │
┌────────┼───────┴─────────┐
│ │ │
App.DTO App.BLL App.DAL.EF
▲ ▲ ▲
│ │ │
└────────┴──── WebApp ─────┘
(Composition Root)
Tähelepanu: App.BLL ei viita App.DAL.EF-le. BLL näeb ainult liideseid (IAppUnitOfWork), mis elavad Domain-is. See ongi Onion-i "Dependency Inversion" — täpselt nagu loengus kirjeldatud.
3. Võrdlus TalTech-i loengu nõuetega
| TalTech-i Clean/Onion nõue | SplitApp teostus | Vastab? |
|---|---|---|
| "Who owns the interfaces" → liidesed elavad Domain-is | IAppUnitOfWork, ITripRepository jt asuvad App.Domain/Contracts/ |
Jah |
| Entities in Domain (mitte DAL-is) | Kõik entiteedid App.Domain/, POCO, ilma EF-atribuutideta | Jah |
| Infrastructure → Domain (pöördsuund) | App.DAL.EF viitab App.Domain-le, mitte vastupidi |
Jah |
| Application ← Web, Application → Domain | WebApp → App.BLL → App.Domain |
Jah |
| Infrastructure pluginatav | BLL kasutab ainult liideseid; EF-i saaks teoreetiliselt Dapperi vastu vahetada | Jah |
| Repository pattern | BaseRepository.cs + spetsiifilised repod | Jah |
Unit of Work (SaveChangesAsync() atomic commit) |
AppUnitOfWork.cs, lazy-load repod | Jah |
| DTOs ("dumb objects, no logic") | App.DTO/v1/ + Mappers | Jah |
| Mappers entiteet↔DTO | Staatilised mapper-klassid App.DTO/Mappers/ | Jah |
| Dependency Injection (konstruktori kaudu) | Teenused AddScoped-ina Program.cs-is, konstruktori-injection |
Jah |
| DI Composition Root välimises ringis | Ainult Program.cs teab konkreetseid implementatsioone | Jah |
| SOLID → DIP: kõrgemad kihid sõltuvad abstraktsioonidest | BLL sõltub IAppUnitOfWork-ist, mitte AppUnitOfWork-ist |
Jah |
| ViewModelid (mitte entiteedid vaadetes) | WebApp/Models/ sisaldab ViewModel-eid | Jah |
4. Lisaväärtused üle loengu miinimumi
- Versioneeritud API (
[ApiVersion("1.0")],api/v{version}/...) — Asp.Versioning - JWT + Cookie hübriid-autentimine — MVC ja REST samaaegselt
- Admin Area eraldi teenustega (12 AdminService-t)
- Lokaliseerimine läbi
LangStr(Domain-is) + .resx (App.Resources/) - DataProtection võtmed DB-s (
PersistKeysToDbContext) - PostgreSQL + Docker tootmiseks
- Swagger versioonidega (ConfigureSwaggerOptions.cs)
5. Projektide detailne kirjeldus
Sisemine südamik
Base.Domain — BaseEntity (Guid Id, CreatedAt, UpdatedAt), LangStr (mitmekeelne string, implitsiitne cast string ↔ LangStr).
Base.Contracts — generic abstraktsioonid:
IBaseRepository<T>— CRUD (GetAllAsync, GetByIdAsync, Add, Update, RemoveAsync, ExistsAsync)IUnitOfWork—SaveChangesAsync()IBaseEntity
App.Domain — puhas äridomeen, POCO entiteedid:
- Trip, Expense, ExpenseSplit — reisid ja kulud
- TripParticipant, TripInvitation — osavõtjad ja kutsed
- SettlementPlan, SettlementPayment — arveldused
- TripPoll, TripPollOption, TripPollVote — küsitlused
- TripWishlistItem, TripWishlistVote — sooviste nimekiri
- BudgetCategory, Currency, SplitPreset — abi-entiteedid
- Identity/ —
AppUser,AppRole - Contracts/ —
IAppUnitOfWork+ repo-liidesed (ITripRepositoryjne) - Enumid:
ETripStatus,EParticipantRole,ESplitMethod,ESettlementStatus,EPaymentStatus,EInvitationStatus,EWishlistPriority,EWishlistCategory
Infrastructure — DAL
App.DAL.EF — EF Core + PostgreSQL (Npgsql):
- AppDbContext.cs —
IdentityDbContext<AppUser, AppRole, Guid>, ~13 DbSet, UTC DateTime converter, unique indexid,DeleteBehavior.Restrict,LangStrJSON-seerimine. - AppUnitOfWork.cs — lazy-load repod, generic
GetRepository<T>(). - Repositories/ —
BaseRepository<T>+ spetsiifilised (ntTripRepositoryGetUserTripsAsync,GetByIdWithDetailsAsync). - Migrations/ — EF Core migreeringud.
- Seeding/ —
InitialData.cs,AppDataInit.cs. - ServiceCollectionExtensions.cs —
AddDalServices()DI registreerimine,NoTrackingWithIdentityResolution, SplitQuery käitumine.
Application Layer — BLL
App.BLL — ärieteenused, sõltub ainult Domain-ist (mitte DAL-ist otse):
- Services:
TripService,ExpenseService,SettlementService,InvitationService,PollService,WishlistService,BudgetCategoryService,SplitPresetService - Admin services — 12 eraldi admin teenust (
BudgetCategoryAdminService,CurrencyAdminServicejne) - Helpers/ —
CurrencyConverterjt
DTO kiht
App.DTO — API- ja teenuste-tasemel andmeobjektid:
- v1/ — versioneeritud API DTO-d (
TripDto,TripCreateDto,TripUpdateDto,ExpenseDto,SettlementPlanDto,BudgetCategoryDto) - v1/Identity/ —
LoginInfo,RegisterInfo,JWTResponse,TokenRefreshInfo - Mappers/ — staatilised mapper-klassid (
TripMapperjt)
Presentation — WebApp
MVC Controllers Controllers/ — Razor Views:
TripsController, ExpensesController, BudgetController, MembersController, PollsClientController, WishlistClientController, SettlementController
API Controllers ApiControllers/ — REST API:
[ApiVersion("1.0")]+api/v{version:apiVersion}/[controller]- JWT Bearer autentimine
Areas:
- Admin — 13 admin-controllerit (Users, Currencies, Trips, Expenses, Polls, Wishlist, SettlementPlans jne)
- Identity — Razor Pages (Register jne)
Models/ — ViewModelid (õppejõu nõue, mitte ViewBag/ViewData)
Program.cs — DI konfig:
- Identity (
AppUser,AppRole) - JWT Bearer + Cookie autentimine (SlidingExpiration)
AddDataProtection().PersistKeysToDbContext<AppDbContext>()- Request localization
- Swagger + API versioning
InvariantDecimalModelBinderProvider— kümnendkoha parser
Kokkuvõte
SplitApp on korrektne Clean/Onion Architecture täpselt nii, nagu TalTech-i loeng "architecture1" kirjeldab:
"The entire difference between N-tier and Clean Architecture is who owns the interfaces."
Meie projektis liidesed kuuluvad Domain-ile (App.Domain.Contracts), Infrastructure (App.DAL.EF) asub välimises ringis ja osutab sissepoole, mistõttu BLL-i äriloogika ei tea midagi EF Core-ist ega PostgreSQL-ist. See on just see "pööratud sõltuvus", mida Onion nõuab.