← Område 4 Övning 57–62 · Logiken lämnar komponenten Avprickning

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.

Missade du passet?

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:

  1. Har du inte gjort övning 51–56, gör dem först. De här bygger på dem.
  2. Läs guidens steg 7, där statistiken flyttar in i tjänsten. Det är samma flytt som övning 59 och 60.
  3. 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 iVarför
Filtrerar en lista på ett villkortjänstenVäljer vilka. Nästa sida som behöver samma urval ska slippa upprepa det
Räknar ut ett snitt eller en summatjänstenÄr applikationslogik. Svaret är detsamma oavsett vem som frågar
SorterartjänstenVäljer ordningen på vilka
Avrundar till en decimal vid utskriftkomponentenÄ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ärdekomponentenÄ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.

Samma sak som @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.

Det här är exakt det som sänker uppgiften på C

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.