Kommando–frågeseparation
Command-query separation ( CQS ) är en princip för imperativ datorprogrammering . Det utarbetades av Bertrand Meyer som en del av hans banbrytande arbete med Eiffels programmeringsspråk .
Den anger att varje metod antingen ska vara ett kommando som utför en åtgärd, eller en fråga som returnerar data till den som ringer, men inte båda. Att ställa en fråga bör med andra ord inte ändra svaret . Mer formellt bör metoder endast returnera ett värde om de är referenstransparenta och därför inte har några biverkningar .
Samband med projektering genom kontrakt
Kommando-frågeseparation är särskilt väl lämpad för en design by contract (DbC) metodologi, där designen av ett program uttrycks som påståenden inbäddade i källkoden , som beskriver programmets tillstånd vid vissa kritiska tidpunkter. I DbC betraktas påståenden som designanteckningar – inte programlogik – och som sådan bör deras exekvering inte påverka programtillståndet. CQS är fördelaktigt för DbC eftersom alla värdereturerande metoder (vilken fråga som helst) kan anropas av vilket påstående som helst utan rädsla för att ändra programtillstånd.
I teoretiska termer etablerar detta ett mått av förnuft, varigenom man kan resonera om ett programs tillstånd utan att samtidigt modifiera det tillståndet. Rent praktiskt tillåter CQS alla påståendekontroller att kringgås i ett fungerande system för att förbättra dess prestanda utan att oavsiktligt ändra dess beteende. CQS kan också förhindra förekomsten av vissa typer av heisenbugs .
Bredare inverkan på mjukvaruutveckling
Även utöver kopplingen med design by contract anses CQS av dess anhängare ha en förenklingseffekt på ett program, vilket gör dess tillstånd (via frågor) och tillståndsändringar (via kommandon) mer begripliga. [ citat behövs ]
CQS lämpar sig väl för den objektorienterade metoden, men kan även appliceras utanför objektorienterad programmering. Eftersom separationen av bieffekter och returvärden inte är i sig objektorienterad, kan CQS tillämpas lönsamt på alla programmeringsparadigm som kräver resonemang om biverkningar. [ citat behövs ]
Kommandoförfrågan Ansvarssegregering
Command Query Response Segregation ( CQRS ) generaliserar CQS till meddelandedrivna och händelsedrivna arkitekturer: den tillämpar CQS-principen genom att använda separata Query- och Command - meddelanden för att hämta respektive modifiera data.
Andra arkitektoniska mönster
- När vi går bort från en enda representation som vi interagerar med via CRUD kan vi enkelt flytta till ett uppgiftsbaserat användargränssnitt.
- CQRS passar bra med händelsebaserade programmeringsmodeller. Det är vanligt att se ett CQRS-system delas upp i separata tjänster som kommunicerar med Event Collaboration. Detta gör att dessa tjänster enkelt kan dra fördel av Event Driven Architecture .
- Att ha separata modeller väcker frågor om hur svårt det är att hålla dessa modeller konsekventa, vilket ökar sannolikheten för att använda eventuell konsekvens.
- För många domäner behövs mycket av den logik som krävs när du uppdaterar, så det kan vara vettigt att använda Eager Read Derivation för att förenkla dina frågesidor.
- Om skrivmodellen genererar händelser för alla uppdateringar kan du strukturera läsmodeller som Event Posters, så att de kan vara Minnesbilder och på så sätt undvika en hel del databasinteraktioner.
- CQRS lämpar sig för komplexa domäner, den typ som också drar nytta av Domain-Driven Design .
Begränsningar
CQS kan introducera komplexitet för att implementera återkommande och flertrådad programvara korrekt. Detta inträffar vanligtvis när ett icke-trådsäkert mönster används för att implementera kommando-frågeseparationen.
Här är ett enkelt exempel som inte följer CQS, men är användbart för flertrådig programvara eftersom det löser komplexiteten med låsning för alla andra delar av programmet, men genom att göra det följer den inte CQS eftersom funktionen båda muterar tillstånd och returnerar det:
privat int x ; public int incrementAndReturnX () { lock x ; // av någon mekanism x = x + 1 ; int x_copy = x ; låsa upp x ; // genom någon mekanism returnera x_copy ; }
Här är en CQS-kompatibel version. Observera att den endast kan användas säkert i enkeltrådade applikationer. I ett flertrådigt program finns det ett race-tillstånd i anroparen, mellan där increment()
och value()
skulle anropas:
privat int x ; public int värde () { return x ; } void inkrement () { x = x + 1 ; }
Även i enkeltrådade program är det ibland utan tvekan betydligt bekvämare att ha en metod som är en kombinerad fråga och kommando. Martin Fowler nämner pop()
-metoden för en stack som ett exempel.
Se även
Vidare läsning
- Meyer, Bertrand (september 1994) [1988]. Objektorienterad mjukvarukonstruktion . Prentice Hall. ISBN 0-13-629049-3 .