Blogg

Agil utveckling och Progressive Enhancement går hand i hand

  • 06 november 2018
  • 0

Hos oss på NetRelations pratas det mer och mer om att arbeta enligt agila principer, och det blir också en konkret verklighet i allt fler projekt. Jag tänker inte gå in på detaljer kring agil utveckling här utan nöja mig med att nämna att en av principerna är att arbeta iterativt – att gradvis utveckla, förbättra och förfina. Det passar också väldigt bra ihop med en av de viktigaste grundprinciperna för gränssnittsutveckling – Progressive Enhancement (PE). 

Artikelverktyg:

Vi har alltid tillämpat PE på NetRelations, så för oss är det inget nytt. Men för många är det antingen nytt och okänt eller bekant och skrämmande eller missförstått. Därför vill jag med ett litet exempel försöka förklara hur agil utveckling och PE fungerar bra ihop. 

Uppgiften är följande: Utveckla ett formulär där användaren kan räkna ut pris för en produkt genom att ange mängd som längd i meter eller vikt i kilogram. 

Eftersom vi jobbar agilt delar vi upp utvecklingen i iterationer (ofta kallat sprintar). Efter varje iteration ska formuläret vara funktionellt. 

Iteration 1 

Formuläret behöver ett inputfält där användaren kan ange värdet, något sätt att välja enhet, och en knapp för att posta formuläret. 

Inputfältet för värde kan vi begränsa så det enbart accepterar numeriska värden. Vi kan också säga att värdet inte får vara mindre än 0 eftersom det kommer att gälla oavsett vilken enhet man väljer: 

<label for="amount">Mängd</label>[Textbrytning]<input type="number" min="0" name="amount" id="amount"> 

Redan här har vi i input-elementet två exempel på Progressive Enhancement. Aktuella webbläsare förstår type="number" och min="0" och tillåter inte att man postar formuläret om man matar in något som inte är ett nummer eller ett nummer mindre än 0. Äldre webbläsare hanterar istället inputfältet som ett vanligt fritextfält utan validering. 

För att välja enhet tycker jag att ett select-element passar bäst: 

<label for="unit">Enhet</label>[Textbrytning]<select name="unit" id="unit">[Textbrytning]    <option value="m" selected>Meter</option>[Textbrytning]    <option value="kg">Kilogram</option>[Textbrytning]</select> 

Slutligen behövs en knapp för att ladda om sidan och visa resultatet. 

<input type="submit" value="Visa pris"> 

Servern måste naturligtvis alltid validera inskickade värden för att säkerställa att endast korrekt data kommer in i systemet. På köpet får man då hantering av äldre webbläsare som inte har inbyggt stöd för formulärvalidering eftersom de får ett server-renderat felmeddelande istället för resultatet. 

Formuläret vi har nu fungerar och är mycket robust – endast HTML krävs på klientsidan. Viss validering sker direkt i webbläsaren för att ge snabbare feedback till användaren. 

Iteration 2 

I nästa iteration kan vi ge oss på att förbättra användbarheten genom att utöka valideringen. 

Beroende på vilken enhet man har valt gäller olika regler för vilket maxvärde och med hur stora steg värdet får ändras. Detta valideras på servern redan i iteration 1, men vi kan också göra det direkt i webbläsaren med hjälp av max- och step-attributen. Om användaren inte kunde byta enhet kunde vi ha gjort även detta i iteration 1, men eftersom avgränsningarna ändras beroende på vad som är valt i select-elementet måste vi använda JavaScript för att ge max- och step-attributen rätt värden. 

Man kan göra det här på olika sätt, men ett är att ge de olika option-elementen data--attribut som anger vilka begränsningar som gäller: 

<label for="unit">Enhet</label>[Textbrytning]<select name="unit" id="unit">[Textbrytning]    <option value="m" data-min="0" data-max="1000" data-step="1" selected>Meter</option>[Textbrytning]    <option value="kg" data-min="0" data-max="500" data-step="0.5">Kilogram</option>[Textbrytning]</select> 

När sidan laddas och när användaren byter enhet kommer en JavaScriptfunktion (som jag inte visar här för att spara utrymme) att sätta inputfältets min-, max- och step-attribut till de värden som det valda option-elementets data--attribut anger. Så om ”Meter” är valt kommer inputfältet att se ut så här: 

<input type="number" min="0" max="1000" step="1" name="amount" id="amount"> 

På servern behöver validering av värdet fortfarande ske, men nu kommer användaren att få omedelbar feedback av webbläsaren om värdet inte är tillåtet och felaktigt ifyllda formulär behöver inte ens skickas till servern – under förutsättning att webbläsaren hanterar formulärvalidering och JavaScript körs. 

Iteration 3 och framåt 

Beroende på hur det här formuläret ska användas kan man tänka sig ytterligare PE-steg: 

När användaren klickar på ”Visa pris” kan man göra formulärpostningen med Ajax och uppdatera priset utan att ladda om hela webbsidan. 

Man skulle kunna göra så att priset uppdateras direkt när värdet eller enheten ändras, utan att användaren behöver klicka på knappen (som då kan döljas). 

Progressive enhancement leder till robustare lösningar 

Det vi får i slutändan är ett formulär som reagerar direkt på användarens input med hjälp av JavaScript. Men tack vare att vi har byggt det stegvis är det robust nog för att inte vara beroende av att JavaScript faktiskt körs utan kan falla tillbaka på HTML-grunden. 

Ett par vanliga argument mot Progressive Enhancement är ”Man måste bygga allting två gånger” och ”Om allt ska fungera utan JavaScript måste vi avgränsa funktionaliteten för mycket”. Båda är ganska grova missförstånd. 

Som exemplet ovan visar handlar det inte om att bygga olika versioner utan om att tänka efter före och stegvis utöka funktionaliteten. Man behöver inte avgränsa någon funktionalitet eftersom interaktionen i den mest rudimentära lösningen (Iteration 1) inte behöver vara samma som i den slutliga versionen. Det är helt ok att det upplevs som mindre finputsat – det är precis vad det är.

Vill du veta mer om hur vi arbetar med PE?

Tveka inte att kontakta oss via formuläret så berättar vi gärna mer. Kanske är du sugen på att jobba på samma sätt som vi? Då kan vi tipsa om att kolla in våra lediga tjänster.

0 kommentarer

Skriv kommentar