Du är här: keryx/Lars blogg/67. Hoppa till huvudinnehållet (h) Sidans menysektion:
Keryx logotype

Lars Gunthers bloggsida

Framtidens programmeringsundervisning = web first (del 2)

(Detta är del 2 av 3 i en serie om programmering på gymnasiet, med anledning av ett seminarium där jag deltog för ett par veckor sedan. Läs gärna del 1 först om du inte gjort det.)

En annan av föreläsarna uttryckte följande ståndpunkt i ett samtal med mig: För mig är webben bara ett gränssnitt. Ju mer jag tänkt på kommentaren, desto tydligare kommer skillnaden mellan våra synsätt i dagen. För mig är webben en revolution, en transitional teknik, som påverkar systemens arkitektur, deras förutsättningar och möjligheter i grunden.

Webben ändrar allt

Samtidigt som detta händer, så plockar webbutvecklingen in alltfler verktyg, tekniker och metodik från traditionell programmering. De två disciplinerna närmar sig helt enkelt varandra.

Exemplet luffarschack

Strunta i exemplet och hoppa till det fortsatta resonemanget.

Det första föredraget på träffen för programmerare hölls av André Jaoui och han visade hur han använt luffarschack som ett exempel för att introducera olika begrepp i undervisningen. Självklart började min hjärna genast skriva om hans idé till JavaScript. Du kan view sourca mitt work in progress för se hur det skulle kunna funka. Här visar jag bara själva skriptet.


 // SVG som bakgrund kan inte detekteras
 // Vi hoppas att det sammanfaller med stöd för SVG som img
 function SVGSupported() {
     var testImg = 'data:image/svg+xml;base64,';
     var img = document.createElement('img');
     img.setAttribute('src', testImg);
     var svgok = img.complete;
     // Catch annoying bug in Firefox 4 that makes SVGSupported sometimes fail
     if ( !svgok  && $.browser.mozilla && +$.browser.version.slice(0,3) >= 2.0 ) {
         svgok = true;
     }
     return svgok;
 }
 
 if ( SVGSupported() ) {
     // Generera tabell
     var table = $("<table></table>");
     for (var i = 0; i < 25; i++) {
         var row = $("<tr></tr>");
         for (var j = 0; j < 25; j++) {
             var cell = $("<td id='" + j + "_" + i + "'></td>");
             cell.appendTo(row);
         }
         row.appendTo(table);
         // table.append(row); // Alternativ syntax
     }
     $("#spelplan").append(table);
 
     // Vems tur är det?
     var inturn = "kryss"; // Global
 
     $("td").click( function makemove() {
         if ( $(this).hasClass("cirkel") || $(this).hasClass("kryss") ) {
             alert("upptagen");
             return false; // Stops both propagation (bubbling) and default action
             // Must be used with care
         }
         inturn = (inturn === "cirkel") ? "kryss" : "cirkel"; // Överkurs
         $(this).addClass(inturn);
         var winning = detect_winning_move(inturn, this);
         if ( winning) {
             alert(inturn + " vann");
         }
     });
 } else {
     $("#spelplan").append("Gammal webbläsare");
 }
 /**
  * Funktion som kontrollerar om ett vinnande drag gjorts
  *
  */
 function detect_winning_move(inturn, cell) {
     var directions = [
         [-1,  0], // väster
         [-1, -1], // nordväst
         [ 0, -1], // norr
         [-1,  1]  // nordost
     ]; // Array literal som innehåller 4 andra arrayer
     var winning = false; // Sätts till true om segrande drag gjorts
     // Testa alla 4 riktningar
     var curcell   = cell.id.split("_");
     for ( var i = 0; i < 4; i++ ) {
         // Gå till ena änden - börja alltid med kryssad ruta
         // Akta sig för konkatenering - vi vill ha addition -
         // så byt från sträng till Number med plustecknet
         var nextpoint = [ +curcell[0], +curcell[1] ];
         do {
             nextpoint    = [ nextpoint[0] + directions[i][0], nextpoint[1] + directions[i][1] ];
             var nextid   = "#" + nextpoint.join("_");
             var nextcell = $(nextid);
         } while ( nextcell.hasClass(inturn) );
         // Gå till andra änden och räkna antal
         var inrow = -1;
         do {
             // Byt håll = subtraktion
             nextpoint = [ nextpoint[0] - directions[i][0], nextpoint[1] - directions[i][1] ];
             nextid    = "#" + nextpoint.join("_");
             nextcell  = $(nextid);
             inrow++;
         } while ( nextcell.hasClass(inturn) );
         if ( console ) {
             console.log(inrow);
         }
         if ( inrow >= 5 ) {
             winning = true;
         }
     }
     return winning;
 }
 

För att dölja komplexiteten i DOM-funktionerna, vilket ligger utanför programmeringsämnet, så använder jag JQuery. Det första som jag märker är med vilken lätthet jag kan presentera konceptet för mina elever och få in olika moment:

Loopar
Spelplanen görs som en tabell i HTML, vilken genereras med en dubbel loop.
Funktioner
Första funktionen är till innehållet ganska avancerad, men dess syfte är lätt att förklara. Stödjer webbläsaren SVG som bild? Eleven kan använda den utan att förstå exakt hur den funkar.
Kryss och cirklar som bakgrundsbilder i CSS aktiveras genom att man i funktionen makeMove kontrollerar om rutan är ledig och i så fall sätter klasser på cellerna. (Alternativt skulle jag kunna göra så att kryss och cirklar sattes som bokstäverna x och o med en specialdesignad webfont.)
Funktionerna SVGSupported och detect_winning_move Funktionen makemove definieras som en function expression, också kallad lambda. Den skulle kunna vara namnlös.
Logiska villkor
I funktionen makeMove finns en logisk eller-konstruktion och en ternär operator. Den sista är överkurs.
Variablers räckvidd
I sin första tappning så är den variabel som håller reda på vems tur det är global: Deklarerad utanför men använd inuti en funktion. På enklaste nivå låter jag detta passera, men påpekar att det längre fram är en felkälla som bör undvikas.
Också buggfixen för SVGSupported bygger på en global variabel. Det skulle kunna vara en uppgift till eleverna att flytta in den logiken in i funktionen och göra variabeln överflödig.
Händelser
Klicka på en ruta för att sätta kryss eller cirkel – en busenkel introduktion till händelsedriven programmering.
Namngiving
Funktionen SVGSupported inleds med en versal. Detta kan ge mig anledning till att diskutera bättre namn. Versal som första bokstav reserveras traditionellt i JavaScript för funktioner som skall instaniseras med operatorn new.
Hoisting
Inte alla vet att JavaScript normalt tolkas i 2 omgångar. Funktions- och variabeldeklarationer flyttas upp automatiskt, så man kan anropa en funktion innan den deklarerats. Detta kallas hoisting, och är en smidig sak rätt använd. Det är också en felkälla för ovana programmerare eller vid arbete i team.
Crockford förbjuder detta i JSLint och det finns fler stilistiska fel som man kan upptäcka med den sortens verktyg. (Jag rekommenderar numera JSHint!)

Händelsedriven programmering

Ett av skälen till varför undervisningen fortsätter lära ut modellen exekvera - vänta - exekvera - vänta och data skickad via STDOUT och STDIN är att i traditionella språk är det ett jättearbete att sätta upp händelsehantering. Exempelvis måste man i Java instansiera klasser som i sin tur implementerar interface. Detta är begrepp som eleven möter på allvar först i den sista kursen (Programmering C idag, Programmering 2 i Gy-11.)

Men i JavaScript med JQuery är det enkelt och lättbegripligt. Identifiera objektet till vilket händelsen kopplas, sätt en funktion som händelsehanterare. Klart!

Redan på programmering A nivå (med nuvarande kursplaner) kan man alltså skapa ett spel där två spelare möter varandra sittandes vid samma dator. Algoritmer för att automatiskt kontrollera om endera spelaren har vunnit, som i exemplet ovan, kan introduceras för Programmering B.

Programmering C (2 i Gy-11) skulle kunna introducera en enkel spelmotor för att spela mot datorn, men det jag verkligen ser fram emot är att skapa funktionalitet för att spela över Internet mot andra människor. För fjärde året har jag föreslagit en kurs i nätverksprogrammering och som en spinoff till HTML5 finns det en teknik som heter WebSockets som passar perfekt för detta.

Det jag försöker visa är att JavaScript funkar precis lika bra som Java för att lära ut programmering. JavaScript är inte en lättversion av Java!

Min erfarenhet av att köra Programmering A med JavaScript

Jag har kört kursen Programmering A med JavaScript några gånger nu. Dels med elever som inte läser webbdesign alls och dels med en grupp som läser kurserna parallellt. Eftersom man måste lära ut ett minimum HTML och CSS så är det inte givet att det blir bättre i första fallet. Det är få timmar man har till förfogande och elever som inte direkt få blodad tand och blir självlärande kommer sällan upp till mer än knappt G-nivå. Men jämfört med att jobba i konsollmiljö så är sannolikheten för att de skall tycka att kursen är kul betydligt större. Och då så att de blir just självlärande. För dessa tycker jag alltså att för- och nackdelar tar ut varandra.

För elever som läser kurserna parallellt, så funkar de som varandras förstärkning. Nästan allihop vill ha med JQuery-effekter och vågar använda JQuery widgets för sina inlämningsarbeten för webbdesign. Detta i sin tur inskärper kunskaperna om CSS-selektorer, skillnaden mellan klass och id, värdet av välskriven, semantisk HTML och andra moment webbdesignen.

Det bör tilläggas att jag lär ut en aning Java också. Jag använder kontrastverkan mellan dessa två språk, som är så väldigt olika att de utöver C-syntax och fyra bokstäver i namnet knappast har något gemensamt. Saker som jag tycker blir tydliga genom kontrasten är:

Notera att jag inte emulerar STDOUT och STDIN med document.write(). Den metoden är totalförbjuden på mina lektioner och jag säger åt mina elever att om de ser en sida som använder den, så skall de tvätta ögonen med såpa!

Att lära sig grunderna

Genom att börja med webben som körmiljö, så introducerar man på ett naturligt sätt flera begrepp som ofta kan bli svåra att lära ut. Grundläggande begrepp och principer, som borde komma in tidigt i undervisningen!

Applikationslogik

Tredelningen…

  1. HTML för struktur och innehåll.
  2. CSS för design och layout.
  3. JavaScript för beteende.

…är en naturlig introduktion till olika slags logik och separation of concerns. På webbservern lär jag eleverna tidigt skilja ut presentationslogiken från bearbetning och databashantering. I vanlig programmeringsundervisning så ser jag exempel efter exempel på hur olika slags logik blandas, så att när detta moment dyker upp så måste eleven lära sig av med dåliga vanor. Och elever som redan skrivit ganska så omfattande program tappar sugen när de inser att de måste skriva om det från grunden, då dess arkitektur inte håller måttet.

De flesta jag sätt som börjar med vanlig programmering lär sig skriva spagetti-kod, där bearbetning blandas huller om buller med in- och utmatningar. Detta därför att metoderna för de senare är såpass avancerade att man måste lära sig programmera på (gymnasiets) C-nivå, innan de kan användas med någon slags behållning. Kort sagt, man behöver stora förkunskaper för att kunna separera logik. Men på webben kan man börja göra det från dag noll!

Mitt stridsrop webben först är inte nödvändigtvis detsamma som att ämnet Programmering på gymnasiet skall börja med JavaScript – även om jag försökt göra gällande att det är ett bra val av förstaspråk för undervisningen. Webbutveckling och programmering kan som ämnen korsbefrukta varandra även om man jobbar med ett annat språk.

Java applets är däremot inte en möjlighet för sådan korsbefruktning. Det finns massor av vettiga saker att göra med Java, mängder av körmiljöer som språket är lämpligt för: Desktop, mobiler, inbäddade system, servrar… Applets är helt enkelt bara inte en av dem.

En bra introduktion till objekt

Ett av problemen som presenterades på seminariet med att lära ut objects first är att studenterna inte verkar riktigt förstå vad de lär sig… De använder klasser och objekt, men kan inte på ett tillfredsställande sätt förklara vad det egentligen är.

Jag ser två sätt på vilket en web first metodik kan råda bot på detta:

  1. Dels så bekantar sig eleven tidigt med systemens arkitektur, enligt ovan, vilket gör objektens sammanhang tydligare. Objektorientering utan kunskaper om designmönster blir sällan annat än onödig komplexitet. (För fjärde året har jag föreslagit en kurs med designönster som ett av sina huvudsakliga innehåll.)
  2. Objekt i webbmiljö blir ofta konkreta och manipulering av deras egenskaper skapar ett omedelbart visuellt resultat.

Ett av problemen i objektorienterad programmering är att de första exemplen som eleven får lära sig är ofta väldigt fiktiva. Klasser och arv illustreras med biologin eller fordonsindustrin:


 class monkey extends Mammal {}
 class sportscar extends fourwheelcar {}
 

Så gjorde jag också förut, eftersom det var vad jag hade läst mig till från andra. Nu börjar jag med:


    document.getElementsByTagName("h1")[0].innerHTML = "Alternativ text";
    document.getElementById("foo").style.backgroundColor = "fuchsia";
 

Resultatet syns direkt!

Ett element som har egenskaper som textinnehåll, bredd, höjd, färg och x/y/z position och metoder för att finna och ändra på deessa gör objektorienteringen konkret och användbar. JavaScript ihop med DOM funkar superbt här, men för att visa eleverna ett väldesignat api, så lär jag dem relativt snabbt JQuery. DOM-metoderna i sin grundform är ju tyvärr rätt åbäkiga. (Utvecklarna var för påverkade av Java, tror Douglas Crockford och jag, och missade att föra över elegansen i JavaScript till DOM.)

Samlingar av HTML-element är array-liknande och ger mig som lärare snabbt naturliga exempel på när man just kan använda arrayer, hur man loopar igenom dem, etc.

Andra vinster

Ett av skälen till att man ofta dröjer med grafiska metoder i traditionell programmering är att det blir så komplext. Java Swing kan användas genom monkey sees, monkey does programmering, men eleven måste läsa flera kurser innan det som har kodats blir begripligt. Men med JQuery kan en elev på några minuter göra detta:


 $("#btn1").click(function () {
     $("foo").hide("slow").
 });
 

Webben är också en bra introduktion till SOA och SaS. Och om man lär sig XHR först, gärna med JQuerys förenklade api, så kan CORBA bli mindre avskräckande.

Sammanfattning

Web first är dels en teknisk nödvändighet. Världen går åt detta håll.

Dels är det en pedagogisk möjlighet. Inget att beklaga, utan en möjlighet att ta vara på.

Epilog 1

Jag uppmuntrar till diskussion om denna artikeldela.

Epilog 2: Finn fem fel

JavaScript är en förenklad variant av Java som nästan uteslutande används på webbsidor på samma sätt som applets. Ett JavaScript kan alltså bara köras inbakat i en webbsida med hjälp av en webbläsare.

… Rent språkligt ligger den största skillnaden i att JavaScript inte är renodlat objektorienterat… men du kan inte skapa egna klasser.

Citatet kommer från Erik Ronnes bok Avancerad Pocket Java (Docendo läromedel) och har några år på nacken.

  1. JavaScrip är inte en variant av Java, utan har sitt ursprung i Self, Scheme och Lisp. Fast det har fått en C-syntax likt Java.
  2. JavaScript är inte enklare i betydelsen har mindre kraft. Det är bara enklare i betydelsen har en smidigare och enklare syntax.
  3. Till skillnad från Java applets, så körs JavaScript inte inbakat i webbsidor, utan är en integrerad del av dem. Applets är (oftast) otillgängliga och isolerade från webbsidan. JavaScript kan göras tillgängliga och är en del av webbstacken.
  4. JavaScript tillåter såväl procedurell, objektorienterad som funktionell programmering. Arv genom prototyp är kraftfullare än arv genom klasser. Man kan enkelt emulera klasser i JavaScript, men det är en plåga utan dess like att emulera prototyp i klassbaserade språk.
  5. Jag skulle dock vilja påstå att den största skillnaden är att Java har strikt typsystem och JavaScript ett dynamiskt typsystem.

Ronne är tyvärr inte ett undantag. Den sortens desinformation har nått åtskilliga årskullar av elever. Om du inte gör någon annan förändring i din undervisning, så tag åtminstone med dig detta till dina elever:

Java och JavaScript är två skilda språk, med olika förmågor, men språkligt är Java det svagare, mindre kapabla språket, som dock har två andra fördelar: Det kan köras på fler olika system och det får en något högre prestanda när man kompilerat det. Alla andra påstådda fördelar är ljug eller personliga preferenser.

Epilog 3: MDC och Stackoverflow

Utöver JQuery-manualen ocj Wikipedia, så går nästan alla länkar i min artikel till antingen Mozilla Developer Center eller Stack Overflow. Det första är nätets auktoritativa resurs om JavaScript. Det senare en plats för utbyte av frågor och svar, som utmärks av kunniga och engagerade deltagare.

De absolut största svagheten för JavaScript är att nätet vimlar av dålig information. Föråldrade och usla exempel finns det gott om.

Varningstecken på dåliga sidor:

Tecken på att sidorna är uppdaterade och ger bra information:

Publicerad: 2011-05-08 14:35
Uppdaterad: 2011-05-08 14:35


Permalink

Senaste bloggar

Ny lärobok: Webbserverprogrammering 1 med PHP
2013-09-05 15:26

Köp min lärobok
2012-08-03 21:21

Vad är diskreta domskript?
2011-10-11 21:02

Framtidens programmeringsundervisning = patterns and paradigms first (del 3)
2011-05-22 07:00

Framtidens programmeringsundervisning = user first (del 1)
2011-04-19 13:38

Mina tankar och resurser om gy11 kurserna
2011-03-17 20:46

Alternativ utformning av arbetsplatsförlagt lärande
2010-11-07 07:16

Kort politiskt mellanspel
2010-09-05 18:34

Tyck till om mina kursplaner och köp min bok!
2010-05-31 16:00

Gy -11 webbkursernas inbördes relation
2010-02-26 09:13

Bloggar i samma ämne

Framtidens programmeringsundervisning = patterns and paradigms first (del 3)
2011-05-22 07:00

Framtidens programmeringsundervisning = user first (del 1)
2011-04-19 13:38

Artiklar i samma ämne

Inga artiklar finns i ämnet.

Technorati


RSS-ikon
Uppdaterad: 2011-05-08 14:35    © Keryx