clean-architecture-layers
Krev avhengighetsretning i ren arkitektur — indre lag må ikke referere til ytre lag.
Regeldetaljer
Section titled “Regeldetaljer”Ren arkitektur krever at avhengigheter peker innover: API -> Application -> Domain. Domain-laget må ha null eksterne avhengigheter, Application-laget må ikke referere til Infrastructure direkte, og ingen lavere lag skal referere til API-prosjektet. Denne regelen sjekker using-direktiver (C#) eller import-setninger for å håndheve disse grensene.
Det samme mønsteret gjelder for enhver lagdelt arkitektur i ethvert språk — tilpass importmønstrene og lagstiene deretter.
Eksempler på feil kode
Section titled “Eksempler på feil kode”using Microsoft.EntityFrameworkCore; // ✗ Domain → Infrastructureusing StavangerChallenge.Infrastructure; // ✗ Domain → Infrastructureusing StavangerChallenge.Infrastructure; // ✗ Application → Infrastructureusing StavangerChallenge.API; // ✗ Application → APIEksempler på riktig kode
Section titled “Eksempler på riktig kode”namespace StavangerChallenge.Domain.Entities;// No external dependencies — pure domain logicusing StavangerChallenge.Domain.Entities; // ✓ Application → Domain// Uses IRepository<T> interface, not Infrastructure directlyRegelimplementasjon
Section titled “Regelimplementasjon”/// <reference path="../rules.d.ts" />
export default { rules: { "no-infrastructure-in-domain": { description: "Domain layer must not reference Infrastructure or ORM packages", async check(ctx) { const domainFiles = await ctx.glob("backend/src/**/Domain/**/*.cs"); for (const file of domainFiles) { const matches = await ctx.grep( file, /using\s+(Microsoft\.EntityFrameworkCore|MyApp\.Infrastructure)/ ); for (const match of matches) { ctx.report.violation({ message: `Domain must not reference Infrastructure: "${match.content.trim()}"`, file: match.file, line: match.line, fix: "Remove this using directive. Domain entities should have zero external dependencies.", }); } } }, }, "no-infrastructure-in-application": { description: "Application layer must not reference Infrastructure directly", async check(ctx) { const appFiles = await ctx.glob("backend/src/**/Application/**/*.cs"); for (const file of appFiles) { const matches = await ctx.grep(file, /using\s+MyApp\.Infrastructure/); for (const match of matches) { ctx.report.violation({ message: `Application must not reference Infrastructure: "${match.content.trim()}"`, file: match.file, line: match.line, fix: "Define an interface in Application and implement it in Infrastructure.", }); } } }, }, "no-upward-api-references": { description: "No layer should reference the API project", async check(ctx) { const lowerLayerPatterns = [ "backend/src/**/Domain/**/*.cs", "backend/src/**/Application/**/*.cs", "backend/src/**/Infrastructure/**/*.cs", ]; for (const pattern of lowerLayerPatterns) { const files = await ctx.glob(pattern); for (const file of files) { const matches = await ctx.grep(file, /using\s+MyApp\.API/); for (const match of matches) { ctx.report.violation({ message: `Lower layers must not reference the API project: "${match.content.trim()}"`, file: match.file, line: match.line, fix: "Dependencies flow inward: API → Application → Domain.", }); } } } }, }, },} satisfies RuleSet;For TypeScript-prosjekter, tilpass mønstrene:
// Check that domain/ does not import from infrastructure//import\s+.*from\s+["'].*\/infrastructure\//
// Check that no layer imports from api//import\s+.*from\s+["'].*\/api\//Når bør du bruke den
Section titled “Når bør du bruke den”Når prosjektet ditt følger ren arkitektur, heksagonal arkitektur, eller en annen lagdelt arkitektur der avhengighetsretning må håndheves.
Når bør du ikke bruke den
Section titled “Når bør du ikke bruke den”Når prosjektet ditt ikke bruker en lagdelt arkitektur, eller når lagene ikke er organisert i separate mapper.