Struktura solution i projektów
Dobrze podzielona solucja .NET to taka, w której zależności płyną w jedną stronę, a warstwa domenowa nie wie nic o bazie ani o HTTP. Ta lekcja pokazuje, jak strukturyzujemy projekty w ProfessNet.
Podział na projekty
Typowa solucja serwisu dzieli się na warstwy jako osobne projekty:
Zeus.Inventory.sln
├── src/
│ ├── Zeus.Inventory.Api/ # kontrolery, Program.cs, DI
│ ├── Zeus.Inventory.Application/ # logika, serwisy, interfejsy
│ ├── Zeus.Inventory.Domain/ # encje, reguły domenowe (zero zależności)
│ └── Zeus.Inventory.Infrastructure/ # EF Core, klienci HTTP, repozytoria
└── tests/
├── Zeus.Inventory.UnitTests/
└── Zeus.Inventory.IntegrationTests/
Kierunek zależności
Zależności wskazują do wewnątrz, ku domenie. Domena nie zależy od niczego.
Api → Application → Domain
↑
Infrastructure
Standard ProfessNet: projekt
Domainnie ma referencji do EF Core, ASP.NET ani żadnej infrastruktury. Reguły biznesowe są niezależne od technologii dostępu do danych. Interfejsy repozytoriów żyją wApplication, a ich implementacje wInfrastructure.
Centralne zarządzanie pakietami
Wersje pakietów NuGet trzymamy w jednym pliku Directory.Packages.props, żeby
wszystkie projekty używały tych samych wersji.
<!-- Directory.Packages.props -->
<Project>
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="9.0.0" />
<PackageVersion Include="Serilog.AspNetCore" Version="8.0.0" />
</ItemGroup>
</Project>
W .csproj podajesz już tylko nazwę pakietu, bez wersji:
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" />
</ItemGroup>
Wspólne ustawienia projektów
Powtarzalne ustawienia (Nullable, LangVersion, warnings as errors) wynosimy
do Directory.Build.props w korzeniu repo.
<!-- Directory.Build.props -->
<Project>
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>
</Project>
Standard ProfessNet:
NullableiTreatWarningsAsErrorswłączone globalnie wDirectory.Build.props. Żaden projekt nie obniża tych ustawień bez uzasadnienia w PR.
| Projekt | Zna | Nie zna |
|---|---|---|
| Domain | nic | EF, HTTP, DI |
| Application | Domain | konkretnej bazy/HTTP |
| Infrastructure | Domain, Application | kontrolerów |
| Api | wszystkie | — |
Wskazówka: testy jednostkowe celują w
ApplicationiDomain(bez infrastruktury), a testy integracyjne wInfrastructureiApiz prawdziwą bazą testową.
Warstwy jako osobne projekty, zależności do wewnątrz, wersje i ustawienia scentralizowane. Taka solucja rośnie bez zamieniania się w plątaninę referencji, a domena pozostaje czysta i testowalna.