- Organize projects into distinct layers: `Presentation` (WinForms/WPF/ASP.NET), `Application` (services, DTOs), `Domain` (entities, business rules), `Infrastructure` (data access, external APIs).
- Define interfaces in the `Application` or `Domain` layer and implement them in `Infrastructure` — outer layers depend on abstractions, not concrete classes.
- Use constructor injection for dependencies: `Sub New(userService As IUserService)` — register all services in the `IServiceCollection` composition root.
- Keep domain entities free of infrastructure concerns: no `SqlCommand`, `HttpClient`, or file I/O in domain classes — those belong in repository implementations.
- Use Data Transfer Objects (DTOs) to cross layer boundaries: map domain entities to DTOs in the Application layer before returning to the Presentation layer.
- Use the Repository pattern: `Interface IUserRepository; Function GetByIdAsync(id As Integer) As Task(Of User); End Interface` with an EF Core implementation in `Infrastructure`.
- Apply the `IOptions(Of T)` pattern for typed configuration injection — bind to config sections in `Program.vb` and inject into services via constructor.