Webbserverprogrammering 1 · område 4 · lektion 25
Att flytta logiken
Sex övningar om det som faktiskt bedöms i inlämningen: var koden ligger. De fyra första flyttar kod, den femte drar gränsen och den sjätte kontrollerar att flytten blev av på riktigt.
Lektion 25 var ett övningspass – ingen genomgång, inget nytt. Du missade handledningen, inte innehållet. Så här arbetar du ikapp, räkna med två timmar:
- Har du inte gjort övning 51–56, gör dem först. De här bygger på dem.
- Läs guidens steg 7, där statistiken flyttar in i tjänsten. Det är samma flytt som övning 59 och 60.
- Lös övning 57 till 62 nedan, i ordning. Övning 62 sist – den kontrollerar de andra.
Var går gränsen?
Frågan återkommer i varje övning på den här sidan, och på provet. Formuleringen att hålla i huvudet:
Väljer koden vilka poster som ska visas hör den till tjänsten. Bestämmer den hur de ska se ut hör den till komponenten.
| Koden gör… | Hör hemma i | Varför |
|---|---|---|
| Filtrerar en lista på ett villkor | tjänsten | Väljer vilka. Nästa sida som behöver samma urval ska slippa upprepa det |
| Räknar ut ett snitt eller en summa | tjänsten | Är applikationslogik. Svaret är detsamma oavsett vem som frågar |
| Sorterar | tjänsten | Väljer ordningen på vilka |
| Avrundar till en decimal vid utskrift | komponenten | Är hur. Ett annat ställe kanske vill ha två decimaler |
| Väljer mellan "1 film" och "2 filmer" | komponenten | Är språk, inte data |
| Sätter en CSS-klass beroende på ett värde | komponenten | Är utseende |
57. Konstruktorinjektion
Lätt · tränar: att ta emot ett beroende i konstruktorn
Ge tjänsten från övning 54 en
konstruktor som tar emot en ILogger<Ovning54> och sparar den i
ett readonly-fält. Skriv en loggrad i
HamtaNamnAsync.
Du registrerar inte loggaren – ramverket har den.
Klart när: raden syns i terminalen där dotnet run körs, med
klassnamnet framför.
@inject, på ett annat ställe
En komponent ber om sina tjänster med @inject. En vanlig klass
kan inte det – den ber i stället genom sin konstruktor. Det är samma mekanism:
du säger vad du behöver, och ramverket skickar in det när objektet skapas.
Ingen av dem skapar något med new. Det är hela idén med
dependency injection: den som behöver något ber om det, och någon
annan bestämmer vad som levereras.
58. En tjänst som använder en annan
Medel · tränar: att beroenden går mot gränssnitt även mellan tjänster
Gör IOvning58 med Task<int> AntalNamnAsync().
Implementationen ska inte ha någon egen lista – den ska injicera
IOvning54 i konstruktorn och räkna det den får.
Klart när: sidan visar 4, och Ovning58 inte innehåller ett
enda namn.
59. Uträkningen lämnar komponenten
Medel · tränar: gränsen mellan presentation och logik
Given kod, en komponent som räknar själv:
<p>Snitt: @Snitt().ToString("0.0")</p>
@code {
private List<int> tal = new() { 4, 8, 15, 16, 23 };
private double Snitt()
{
int summa = 0;
foreach (var t in tal)
{
summa = summa + t;
}
return (double)summa / tal.Count;
}
}
Flytta både listan och uträkningen till en tjänst bakom ett gränssnitt.
Klart när: komponenten innehåller ingen foreach och ingen
lista, och visar samma siffra som förut.
Lägg märke till vad som inte ska flytta: .ToString("0.0")
stannar i komponenten. Antalet decimaler är utseende.
60. Ett svar som håller ihop flera värden
Medel · tränar: ett litet objekt som returtyp
Bygg vidare på övning 59. Låt tjänsten svara med ett objekt som innehåller antal, summa och snitt – i stället för tre metoder.
Klart när: komponenten anropar tjänsten en gång och visar tre värden.
Filmarkivets motsvarighet heter Arkivstatistik och byggs i
guidens steg 7. Tre metoder hade betytt att
listan gås igenom tre gånger för att visa en enda rad.
61. Vem väljer ut posterna?
Svår · tränar: att skilja vilka från hur
Given kod, en sida som filtrerar:
@code {
private List<Film> visade = new();
protected override async Task OnInitializedAsync()
{
List<Film> alla = await Arkivet.HamtaAllaAsync();
foreach (var film in alla)
{
if (film.Betyg >= 4)
{
visade.Add(film);
}
}
}
}
Urvalet hör inte hemma i komponenten. Flytta det.
Klart när: sidan har ingen foreach och inget
if, och tjänsten har en metod vars namn säger vad urvalet är.
Koden ovan ser oskyldig ut. Den bygger, den fungerar, och den kräver ingen ansträngning att skriva. Men den betyder att komponenten bestämmer vad ett bra betyg är – och nästa sida som vill visa samma urval måste upprepa villkoret.
Metodnamnet är halva övningen. HamtaAsync säger ingenting.
HamtaHogtBetygsattaAsync säger vad urvalet är, och gör det
möjligt att ändra villkoret på ett enda ställe.
62. Två träffar, inte fler
Svår · tränar: att kontrollera att lagren faktiskt är separerade
Sök i hela projektet på din implementations klassnamn – inte gränssnittet.
Klart när: det finns exakt två träffar: klassens egen fil, och
registreringsraden i Program.cs. Hittar du fler, rätta dem.
Det här är samma kontroll som jag gör när jag rättar inlämningen, och den tar tio sekunder. Gör den innan du lämnar in, inte efter.
Avprickning
Kryssen sparas i din webbläsare.
Lösta övningar i det här temat
Övning 61 och 62 är de två som avgör om du når C. Den första flyttar urvalet, den andra bevisar att flytten blev av.