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
- Webben demokratiserar data och applikationer som ingen annan teknik. Spelfält utjämnas och nya tekniker och idéer kan slå sig fram enklare än på någon annan plattform.
- Webben har just blivit en körmiljö för applikationer av flera slag: Kontorsprogram, utvecklingsmiljöer, anteckningar (typ Evernote), projekthantering, konferens- och kommunikation och inte minst spel. Beräkning och exekvering sker för dessa applikationer till stor del i klienten, för närvarande i Flash men alltmer i HTML5 (med spinofftekniker).
- Webben är den körmiljö som man först måste etablera sin produkt inom. Sedan kan den kanske kompletteras med appar eller regelrätta program, men webben kommer först! Facebook hade aldrig kunnat börja som en iPhone app.
- Webbens tekniker erövrar område efter område också i systemens arkitektur. Exempelvis så används ReST (som bygger på http) exempelvis för kommunikation mellan program och databaser i många noSQL system. Och program skrivna för traditionella miljöer är ofta klienter till webbtjänster.
- Webbens tekniker används alltmer inom traditionell programmering. Gränssnitt för desktop och mobiler byggs med deklarativa tekniker som XAML eller QML. Data utväxlas med XML eller JSON.
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:
- Värdetyper och skillnaden mellan statiska och dynamiska värdesystem.
- Skillnaden mellan att jobba i sekvensiella flöden och händelsedrivet.
- (Längre fram:) Skillnaden mellan
klassisk
objektorientering och funktionell programmering.
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…
- HTML för struktur och innehåll.
- CSS för design och layout.
- 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:
- 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.)
- 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 artikel på dela.
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.
- 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.
-
JavaScript är inte
enklare
i betydelsen har mindre kraft. Det är bara enklare i betydelsen har en smidigare och enklare syntax. - 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.
- 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.
-
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:
document.write()
- Inline event handlers (blandar HTML och skript), typ
<body onload="foo()">
- Eval
Tecken på att sidorna är uppdaterade och ger bra information:
- Hänvisningar till JSHint (eller JSLint)
- Begreppet
unobtrusive
används. - Begreppet
progressive enhancement
används. - Begreppet
dom script
används.
Publicerad: 2011-05-08 14:35
Uppdaterad: 2011-05-08 14:35