Programmering

Designmønstre, som jeg ofte undgår: Repository mønster

Designmønstre giver gennemprøvede løsninger på virkelige verdensproblemer i softwaredesign. Repository-mønsteret bruges til at afkoble forretningslogikken og dataadgangslagene i din applikation.

Dataadgangslaget indeholder typisk lagringsspecifik kode og metoder til at fungere på dataene til og fra datalagringen. Dataadgangslaget, som depotet abstracts, kan være en ORM (dvs. Entity Framework eller NHibernate), XML-fil, en webservice osv. Det kan endda være en samling af SQL-sætninger.

Når du bruger repository-designmønstret, behøver virksomhedens logiklag i din applikation ikke at have nogen viden om, hvordan datapersistens sker under. I det væsentlige formidler et lager mellem domænet og datakortlagene i din applikation. Det skal give dig en indkapsling på den måde, at data faktisk er vedvarende i datalagringslaget.

Repository-mønsteret kan være nyttigt, hvor du har mange enheder og har mange komplekse forespørgsler til at arbejde med disse enheder. Et ekstra abstraktionslag i dette tilfælde kan hjælpe dig med at eliminere duplikering af forespørgselslogik.

Det generiske arkiv

Et generisk lager er en type, der består af et sæt generiske metoder til udførelse af CRUD-operationer. Det er dog bare et andet antimønster og bruges ofte sammen med Entity Framework til abstrakte opkald til dataadgangslaget. Efter min mening er anvendelse af et generisk lager generalisering for langt. Det er en dårlig idé at abstrakte opkald til Entity Framework ved hjælp af et generisk lager.

Lad mig forklare dette med et eksempel.

Følgende kodeliste illustrerer et generisk lager - det indeholder generiske metoder til at udføre de grundlæggende CRUD-operationer.

offentlig grænseflade IR-depot

   {

IEnumerable GetAll ();

T GetByID (int id);

ugyldig Tilføj (T-element);

ugyldig opdatering (T-element);

ugyldigt Slet (T-punkt);

   }

For at oprette et specifikt lager skal du derefter implementere den generiske grænseflade som vist i kodelisten nedenfor.

public class AuthorRepository: IRepository

   {

// Implementerede metoder til IRepository-grænsefladen

   }

Som du kan se, skal du implementere hver af metoderne i den generiske lagergrænseflade for at oprette en bestemt arkivklasse. Den største ulempe ved denne tilgang er, at du bliver nødt til at oprette et nyt lager for hver enhed.

Her er en anden ulempe ved denne tilgang: Den grundlæggende hensigt med depotmønsteret er at afkoble dit domænelag fra, hvordan dataene faktisk opretholdes af dataadgangslaget. Her er en opdateret version af lagerklassen, vi lige har oprettet.

public class AuthorRepository: IRepository

   {

privat AuthorContext dbContext;

// Metoder til IR-depotgrænsefladen

   }

Som du kan se i den tidligere angivne kode, har AuthorRepository brug for AuthorContext-forekomsten for at udføre de CRUD-operationer, den er beregnet til. Så hvor er afkoblingen så? Ideelt set burde domænet ikke have noget kendskab til persistenslogikken.

Et ekstra abstraktionslag

Domænemodellen og persistensmodellen i en applikation har forskellige ansvarsområder. Mens de tidligere modeller opfører sig, dvs. modellerer de virkelige problemer og løsningerne på disse problemer, bruges sidstnævnte til at modellere, hvordan applikationens data faktisk lagres i datalageret.

Hensigten med depotmønsteret skal være at abstrakte persistenslogikken og skjule de interne implementeringer af, hvordan dataene vedholdes. Driften af ​​lageret skal være tilstrækkelig udtryksfuld og ikke være generisk. Du kan ikke have et lager, der er generisk, og et, der kan indeholde operationer, der kan passe i ethvert scenarie. Dette bliver en unødvendig abstraktion og gør derfor det generiske arkivmønster til et antimønster. Du kan modellere alle dine domæneobjekter på samme måde. Et generisk lager definerer ikke en meningsfuld kontrakt, og du vil igen have brug for et specifikt lager, der udvider dit generiske lager og giver det specifikke sæt operationer, der er meningsfuldt for den pågældende enhed.

Nu hvor du har en hel del modne datapersistens teknologier (NHibernate, Entity Framework osv.) Omkring, hvorfor har du brug for dette ekstra lag af abstraktion alligevel? De fleste af de modne ORM-teknologier, der er tilgængelige i dag, har de samme muligheder. Når du prøver at bruge et lager, tilføjer du bare et ekstra abstraktionslag uden nogen grund. Som et eksempel skal du muligvis bruge metoder som følgende til din AuthorRepository.

FindAuthorById ()

FindAuthorByCountry ()

Dette bliver værre, da du har flere og flere metoder og komplekse søgninger - du vil ende med at have et lager, der nøje vil kortlægge med det vedvarende lag i brug nedenunder.