Programmering

Design mønstre som jeg ofte unngår: Repository mønster

Designmønstre gir påviste løsninger på virkelige problemer i programvaredesign. Repository-mønsteret brukes til å koble fra forretningslogikken og datatilgangslagene i applikasjonen din.

Datatilgangslaget inneholder vanligvis lagringsspesifikk kode og metoder for å operere dataene til og fra datalagringen. Datatilgangslaget som depotet abstraherer kan være en ORM (dvs. Entity Framework eller NHibernate), XML-fil, en webtjeneste osv. Det kan til og med være en samling SQL-setninger.

Når du bruker repository-designmønsteret, trenger ikke forretningslogikklaget i applikasjonen din ha noen kunnskap om hvordan datapresistens skjer under. I hovedsak formidler et depot mellom domenet og datakartingslagene i applikasjonen din. Det er ment å gi deg en innkapsling på den måten data faktisk vedvares i datalagringslaget.

Repository-mønsteret kan være gunstig der du har mange enheter og har mange komplekse spørsmål å jobbe med disse enhetene. Et ekstra abstraksjonslag i dette tilfellet kan hjelpe deg med å eliminere duplisering av spørrelogikken.

Det generiske depotet

Et generisk depot er en type som består av et sett med generiske metoder for å utføre CRUD-operasjoner. Imidlertid er det bare et annet antimønster og brukes ofte med Entity Framework for å abstrakte samtaler til datatilgangslaget. Etter min mening er bruk av et generisk depot generalisering for langt. Det er en dårlig idé å abstrakte samtaler til Entity Framework ved hjelp av et generisk depot.

La meg forklare dette med et eksempel.

Følgende kodeliste illustrerer et generisk depot - det inneholder generiske metoder for å utføre de grunnleggende CRUD-operasjonene.

offentlig grensesnitt IRepository

   {

IEnumerable GetAll ();

T GetByID (int id);

ugyldig Legg til (T-element);

ugyldig oppdatering (T-element);

ugyldig Slett (T-element);

   }

For å opprette et spesifikt depot, må du implementere det generiske grensesnittet som vist i kodelisten nedenfor.

public class AuthorRepository: IRepository

   {

// Implementerte metoder for IRepository-grensesnittet

   }

Som du kan se, må du implementere hver av metodene i det generiske depotgrensesnittet for å opprette en hvilken som helst spesifikk lagerklasse. Den største ulempen med denne tilnærmingen er at du må opprette et nytt depot for hver enhet.

Her er en annen ulempe med denne tilnærmingen: Den grunnleggende hensikten med depotmønsteret er å koble domenelaget ditt fra hvordan dataene faktisk vedholdes av datatilgangslaget. Her er en oppdatert versjon av lagerklassen vi nettopp opprettet.

public class AuthorRepository: IRepository

   {

private AuthorContext dbContext;

// Metoder for IRepository-grensesnittet

   }

Som du kan se i kodelisten gitt tidligere, trenger AuthorRepository AuthorContext-forekomsten for å utføre CRUD-operasjonene den er beregnet for. Så, hvor er frakoblingen, da? Ideelt sett bør ikke domenelaget ha kunnskap om utholdenhetslogikken.

Et ekstra lag med abstraksjon

Domenemodellen og utholdenhetsmodellen i en applikasjon har tydelig forskjellige ansvarsområder. Mens de tidligere modellene oppfører seg, dvs. modellerer de virkelige problemene og løsningene på disse problemene, brukes sistnevnte til å modellere hvordan applikasjonens data faktisk lagres i datalageret.

Hensikten med depotmønsteret skal være å abstrakte utholdenhetslogikken og skjule de interne implementeringene av hvordan dataene vedholdes. Driften av depotet skal være uttrykksfull nok og ikke være generisk. Du kan ikke ha et lager som er generisk og som kan inneholde operasjoner som kan passe i ethvert scenario. Dette blir en unødvendig abstraksjon og gjør dermed det generiske depotmønsteret til et antimønster. Du kan modellere alle domenegjenstandene dine på samme måte. Et generisk depot definerer ikke en meningsfull kontrakt, og du vil igjen trenge et spesifikt depot som utvider det generiske depotet og gir det spesifikke settet med operasjoner som er meningsfylt for den aktuelle enheten.

Nå som du har ganske mange modne teknologier for utholdenhet av data (NHibernate, Entity Framework, etc.) rundt, hvorfor trenger du allikevel dette ekstra laget med abstraksjon? De fleste av de modne ORM-teknologiene som er tilgjengelige i dag, har de samme mulighetene. Når du prøver å bruke et depot, legger du bare til et ekstra abstraksjonslag uten grunn. Som et eksempel kan det hende du trenger metoder som følgende for AuthorRepository.

FindAuthorById ()

FindAuthorByCountry ()

Dette blir verre ettersom du har flere og flere metoder og komplekse søk - du vil ende opp med å ha et depot som vil kartlegges nøye med det vedvarende lagringslaget som er i bruk under.

$config[zx-auto] not found$config[zx-overlay] not found