Validering og mapping
Tjek data ved døren
En DTO er det første, dit program ser af data udefra. Derfor er den det rigtige sted at tjekke, at data er gyldige, før de kommer videre ind i systemet.
Valider ved grænsen
Alt, der kommer udefra, kan være forkert, ufuldstændigt eller ondsindet. Valider derfor den indgående DTO, så snart den er læst: er de påkrævede felter der, har de den rigtige type, og ligger værdierne inden for det tilladte. Afvis anmodningen med en tydelig fejl, hvis ikke. Så kan resten af koden stole på sine data.
interface OpretBrugerDto {
navn: string;
email: string;
}
function tilOpretBrugerDto(input: unknown): OpretBrugerDto {
if (typeof input !== "object" || input === null) throw new Error("Forventede et objekt");
const { navn, email } = input as Record<string, unknown>;
if (typeof navn !== "string" || navn.trim() === "") throw new Error("navn mangler");
if (typeof email !== "string" || !email.includes("@")) throw new Error("email er ugyldig");
return { navn: navn.trim(), email: email.trim().toLowerCase() };
}Bemærk, at funktionen kun plukker de felter ud, den kender. Sender klienten et ekstra felt som rolle: "admin", bliver det ignoreret. Det er den bedste beskyttelse mod mass assignment.
Mapping mellem DTO og entity
Der skal være kode, der laver en entity om til en DTO og omvendt. Du kan skrive den i hånden eller bruge et mapping-bibliotek. Håndskrevet mapping er længere, men tydelig, og compileren fanger det, hvis et felt forsvinder. Automatisk mapping sparer kode, men kan skjule fejl, når felter bliver omdøbt.
public static class BrugerMapping
{
public static BrugerDto TilDto(this Bruger bruger) => new(
bruger.Id,
bruger.Navn,
bruger.Email,
bruger.Oprettet);
}Navngivning
- Navngiv efter formål, ikke kun efter entity:
OpretBrugerRequestogBrugerResponsesiger mere endBrugerDto, når der er flere slags. - Hold én stil i JSON, fx camelCase, og lad serialiseringen oversætte, hvis sproget bruger en anden stil.
- Vær konsekvent med null. Bestem, om et felt uden værdi udelades eller sendes som
null, og hold fast i det.
Versionering
Når klienter først bruger dit API, er DTO'erne en kontrakt. Det er normalt sikkert at tilføje nye, valgfrie felter. Det er ikke sikkert at fjerne felter, omdøbe dem eller ændre deres type. Skal det ske, så lav en ny version af DTO'en og lad den gamle leve, til klienterne er flyttet.
Undgå logik i DTO'en
Når en DTO begynder at få metoder som beregnRabat(), er den ved at blive en entity. Læg reglerne i domænet, og lad DTO'en forblive en enkel pakke med data. Det gør den let at teste, serialisere og ændre.