Gjennom hele karriæren har jeg vært mer webutvikler enn noe annet. Her kan du lese alle artiklene mine som først og fremst har noe med webutvikling å gjøre.

WebREPL: En JavaScript-basert kommandolinje

Friday, February 22nd, 2013
Ingen kommentarer

La meg introdusere deg for et lite prosjekt jeg har begynt (og sluttet) på mange ganger i løpet av årene som har gått, men som nå endelig har resultert i noe som i alle fall virker. Si hei til WebREPL!

webrepl_logo

WebREPL er et multipurpose, HTML/JavaScript-basert terminal-interface. Det består rett og slett av et lite JavaScript som man kan inkludere i siden sin for å få en kommandolinje. Scriptet er helt “dumt”, og kan ikke gjøre annet enn å ta imot input fra brukeren og sende det videre til en funksjon som man har plugget inn. Poenget var å lage noe som er gjenbrukbart, og jeg ser for meg mange potensielle brukstilfeller.

En mulighet er å bruke den som et admin-grensesnitt på en web app, og la den sende kommandoer ned til serveren for eksempel via et JSON API – det er jo enkelt. Jeg kunne også godt tenke meg å lage et tekstbasert spill igjen (jepp, jeg er old school). Eller hva med en Eliza-klone som kan hjelpe deg å debugge programmeringsutfordringer når du ikke har noen kollegaer eller gummiender tilgjengelig?

Jeg har publisert en inntil videre ganske basic online demo du kan ta en titt på (se også skjermdump nedenfor). Ellers finner du prosjektet på Github.

Det er altså ikke særlig avanserte greier dette her, men det er noe jeg har hatt lyst på lenge. Det finnes mange som har gjort det før, men de jeg har funnet er enten hardt knyttet til det bruksområdet de er laget for (f.eks. online ssh-terminal mot Linux) eller de er lite fleksible rent utseendemessig. WebREPL er ingen av delene.

WebREPL_dump

Det jeg kommer til å jobbe videre med er å lage et bedre API for å knytte opp handler-funksjoner mot terminalen. WebREPL kan for eksempel stå for mer av input-parsingen – det vil gjøre den enklere å bruke. Det er også mulig jeg vil forsøke å legge på litt mere bling-bling muligheter i brukergrensesnittet, men det kommer ikke til å bli mye.

Jeg har ikke skrevet noen dokumentasjon enda, men kilden til demoen er kanskje godt nok foreløpig? Så hvis du elsker kommandolinjen, mener musen er en håpløs oppfinnelse, og synes dette virker interessant, så må du ta en titt!

Ferris gjør event-sourcing i UI [Luke 23, 2012]

Sunday, December 23rd, 2012
Ingen kommentarer

Thomas Ferris Nicolaisen (@tfnico) har gjort noe spenende og lurt for å gjøre webapplikasjonen sin enklere å teste og å jobbe med – han har brukt event-sourcing! Gjennom illustrasjoner og videoer får du innblikk i hvordan dette fungerer.

2012-12-07 07.59.57

Hvem er du?
Gladlaks fra Mandal, deretter Java-konsulent i Oslo, deretter emigrant i Tyskland.

Hva er jobben din?
Systemutvikler hos Viaboxx GmbH

Hva kan du?
Mye forskjellig, med hovedvekt på Java, litt sånn DevOps-glad.

Hva liker du best med yrket ditt?
Å jobbe i en bransje hvor det er utrolig gøy og samtidig kjempeviktig å holde seg oppdatert.


Event-sourcing i GUI-laget

I min luke tenkte jeg det kunne være artig å vise frem litt ekte “German Engineering”. Dette er første gang vi snakker høyt om våre siste oppfinnelse(r), og jeg kan tenke meg at i enkelte kretser vil det kunne sees på som en revolusjonerende idé, pattern eller arkitektur.

På jobben min så går en god del av arbeidet ut på å lage GUI for trykkskjermer, ala billettautomater og minibanker. Helt spesifikt så lager vi software for pakkepost-automater, men disse har ikke tatt helt av i Norge ennå visstnok. Lesere i Oslo tafser jo en del på Flexus-automater har jeg hørt, så de av dere kan jo prøve å tenke dere et slikt brukseksempel.

 Sketch2832222

Vi pleide å utvikle GUI-biten i Flash/Flex en årrekke, men slet en del med det. Flex var bra på å lage et pent og snappy grensesnitt som passet fint for berøringsskjermer, men var tungvint i drift og utvikling. Mye av brukerens tilstand og forretningslogikk ble liggende i Flash-laget, hvor det var vanskelig med automatiserte tester og debugging.

I denne omgang så tenkte vi å prøve å lage noe med HTML5 og JavaScript, en såkalt single-page application.

hSAbfAyD-fX6h5gFBL7yFJ_7eIm9udpv7T9KR8EjWvGqRkfwr2udSM8mRNd0gX6mpg=s2000

Noe spesielt vi gjorde var å ha en event-basert, nær tilstandsløs browser, hvor eneste oppgave er å vise screens som kommer fra serveren. Jeg skal forklare hvordan dette foregår, men først vil jeg sette det i litt perspektiv:

Typiske web-applikasjoner er avhengige av å bygge opp en sesjon og følge en gitt navigasjons-sti for å havne i en gitt tilstand. Hvis du vil se hva “Mine bestillinger”-siden ser ut som, så må du logge inn og trykke på en lenke.

kdE-oLCeLLCG6AHuDuMmxsFX0vr_hbTtwt_fOLPHB0kzCflAddauvw0W4fyLShU7kg=s2000

Du er avhengig av riktig tilstand på både server og klient for i det hele tatt å kunne vise “Mine bestillinger” siden.

1DEsslgIvpDmavItDXlMJSDKye0NGMT46AyCg2dpR3nK2Cl1wZHPvVZajmKWVLs2VA=s2000

Dette mønsteret har gitt oss (og sikkert mange andre også) mye hodesmerte opp i gjennom årene. For mye tilstand og logikk på klientsiden gir rom for GUI-bugs som er vanskelig å gjenskape. Teste- og debuggingsverktøy på klientsiden er også gjerne under par det vi har til rådighet for koden på server-siden.

Det vi har gjort er å fjerne så godt som all brukertilstand fra klienten. All logikk ligger på serversiden.

wkakPEZqhGObnR41bm-Ye2zEeJjsLr-uoBQDed2FWW-9CUDgqcyrVxwhSHR-s3yjDw=s2000

Hvert eneste knappetrykk resulterer i en runde til serveren, hvor en tilstandsmaskin får beskjed om hva brukeren gjorde, for deretter å spytte tilbake en ny screen (logikken der inne er også veldig interessant, men det er ikke plass til dette teamet i denne bloggposten).

qczwS2hWWUTJAVrqOO99_detMl3xWPYJm1Kgwi-Bs9IybfAQpIVEph3Mw9WfR0FKOw=s2000

Dette høres kanskje laggy ut for en berøringsskjerm som skal være kjapp og reaktiv, men vi får det til på grunn av fire ting:

  1. Server kjører i samme automat (PC) som klient/browser, så det er er en meget kort tur over nettverket.
  2. Kommunikasjonen foregår over WebSockets, så events fra server får umiddelbar virkning.
  3. Noe smart caching og JavaScript for å oppdatere siden kjapt.
  4. Vi har veldig enkle screens med relativt lite innhold.

Hvordan ser egentlig en sånn screen ut? Her er et eksempel:

"decision": {
            "def": {
                "headline": "Please decide",
                "question": "Is yellow more green than blue?",
                "type": "decision"
                "events": [
                    {
                        "id": "yes",
                        "text": "Yes"
                    },
                    {
                        "id": "no",
                        "text": "No"
                    }
                ],
            }
        }

Ren JSON som representerer absolutt alt av tilstand nødvendig for å vise en skjerm til brukeren. Dette sender vi til browseren, som kjører det gjennom en generator (Mustache) så det blir om til HTML (som vi “swapper” inn og erstatter den gamle DOM’en). Så styler vi det opp med CSS og vips så ser det slik ut:

VyjkcLUZVtMtntceg8EwzaYxSDYKmnuVXtPkKtLDHK-WwCJZTNcbw-qkjTUrnB6rHA=s2000

Det som er utrolig digg å ha denne løse koblingen mellom hva som skal vises, og hvordan det blir generert.

Fordeler med dette da?

Fikse på webdesign uten å måtte trykke masse rundt i applikasjonen.

Du behøver ikke jobbe deg til riktig tilstand for å se på det du vil designe. Du trenger bare et snupp JSON (som den over). Her har jeg fyrt opp vår lille screen-IDE, den kjører på en lokal liten Node-server (se i høy oppløsning):

Man kan velge fra noen forhåndsdefinerte JSON-eksempler, eller man kan copy/paste inn fra loggfiler, og man kan justere innholdet for hånd for å få den tilstanden man vil se.

Dette gir ekstrem kjapp feedback til webdesigneren. Etter å ha endret CSS (eller LESS som vi bruker), Mustache-template eller Javascript trenger man bare å trykke F5/Refresh i browseren for å se screen’en bli rendret på nytt med det siste innholdet. Man kan også simulere enkle server-side events med litt JavaScript.

Man kan teste GUI akkurat i hvilken grad man vil

Tradisjonelt er det mange ulemper med å teste applikasjonen gjennom GUI, men mange gjør det fordi de har ingen annen måte å teste GUI på.

Vi kan derimot teste at..

  • riktig screen object blir produsert av tilstandsmaskinen (ren unit-test)
  • forventet JSON blir spyttet ut av gitt screen  (ren unit-test)
  • riktig HTML blir produsert fra gitt JSON (men da må man ha en headless browser som kan kjøre Javascript, ala PhantomJS)
  • HTML fra en screen ser OK ut (man kan ta screenshots med PhantomJS)
  • HTML fra en screen ser akkurat riktig ut (men da må man bruke produksjonsbrowseren (Chrome) på riktig operativsystem og ta screenshots med Selenium/WebDriver)

Alle disse typer tester gjør vi i forskjellige grader: de øverste veldig mye, og i mindre grad dem lenger ned på listen fordi de er dyrere ressursmessig, og brekker lettere.

Det som hjelper en del er at vi kan skille mellom (a) kommer det riktige innholdet ut (screens) fra serveren, og (b) blir en gitt screen seende riktig ut i browseren. Denne delingen gjør at vi kan holde testene våre utrolig kjappe: Rene unit-tester tester tilstandsmaskinen og screensene som spyttes ut, mens forskjellige browser-tester lager screenshots for screens.

Man kan også teste hele stacken sammen, eller i faser. Vi gjør sistnevnte når vi genererer dokumentasjon og screenshots basert på story-tester (men vi mocker ut hardware og tjenester):

  • Story-tester genererer dokumentasjon med JSON der screenshots skal legges inn
  • Dokumentasjonen kjøres gjennom et script, hvor JSON blir rendret til ekte screenshots.

Det hele går utrolig kjapt, og man trenger fortsatt ikke fyre opp noen ekte applikasjonsserver – det holder med Node simulatoren.

Se nøyaktig hva brukeren så på skjermen på et gitt tidspunkt

La oss se for oss dette scenarioet: Noen leverer en pakke i en automat, sender hente-kode over SMS, mottaker kommer og henter pakke:

Siden vi logger det meste som skjer på en automat, inkludert hvilke screens som sendes, så burde det jo være en smal sak å lese gjennom en hel loggfil, og så generere et hendelsesforløp over hva som har skjedd på en automat den siste tiden, og kunne spille av gamle screens på nytt.

Så vips, etter et par dager med utvikling:

Ikke bare kan vi spole frem og tilbake i hva brukeren opplevde i villkårlig tempo, vi kan også kopiere screens ut herfra for så å jobbe med dem i simulatoren.

Det skulle ikke mye kode for å få dette til: en loggparser og en side JavaScript. Den flotte timeline-widgeten er laget med dette Timeline-biblioteket.

Ennå kan vi ikke se hvor brukeren trykker på skjermen, men vi jobber i disse dager med å få til det også.

Nå forstår du kanskje hvorfor tittelen på denne posten er Event Sourcing.

Vanligvis så bruker man Event Sourcing for events i domenelaget, for ting som pakkesporing og sånnt, men det er sannelig utrolig mektig å bruke det i  GUI-laget også.

Konklusjon

Det er ikke sikkert at denne arkitekturen passer for alle applikasjoner, men vi har lekt med tanken av å bruke det videre i ekte web-applikasjoner, spesielt hvis det er interaksjon av typen veiviser/wizard eller lignende, slik som vi har på automatene våre.

Videre er det utrolig gøy å jobbe med denne teknologi-stacken. Det går knapt en sprint uten at vi jubler over hva vi har fått til, og hvor relativt enkelt det var å få til. En viktig del av det er nok at vi har skrudd sammen mesteparten selv, og ikke bundet oss fast i noe svært rammeverk.

Håper dette gir dere noe å tygge på i ferien. God jul og godt nyttår!

Brodwall finner opp hjulet [Luke 20, 2012]

Thursday, December 20th, 2012
10 kommentarer

Johannes Brodwall (@jhannes) har lenge vært et kjent fjes i det smidige utviklermiljøet i Norge. Han er ildsjelen bak Oslo XP Meetup, har vært med å arrangere flere av smidig-konferansene, og holder kurs om smidig utvikling, TDD og arkitektur. Johannes uttaler seg stadig vekk i Computerworld, og har sin egen blogg han kaller Thinking Inside a Bigger Box. Du finner også endel innlegg fra ham på Sterk Blanding.

I dagens bloggpost snakker Johannes om no så rart som viktigheten av å finne opp hjulet på nytt, med et konkret eksempel i C#.

Johannes portrettbilde

Hvem er du?
Flakkende programmerer som var overbevist om at han aldri kunne lære å programmere før han startet på universitetet.

Hva er jobben din?
Chief scientist og code coach i Exilesoft i Norge, Sverige og Sri Lanka.

Hva kan du?
Få nysgjerrige programmerere til å lære nye teknikker for å programmere og for å forstå hva de skal programmere.

Hva liker du best med yrket ditt?
At jeg kan lære meg litt om mange forskjellige problemstillinger som gjennomsyrer samfunnet og at jeg må forene den kompromissløse og kalde verdenen til maskinen med den ubesluttsomme, nyanserte verdenen til mennesker.


Når jeg lærte matte i barneskolen grep jeg etter kalkulatoren. Men min far sa til meg: “Du får ikke bruke kalkulator før du kan klare deg uten”. Jeg syntes naturligvis dette var både urettferdig og upraktisk, men etter en stund fant jeg ut hvilken fordel det har å forstå grunnferdighetene før man griper etter et verktøy.

For mange utviklere dreier det neste kompetansevalget seg om hvilket fancy rammeverk skal man skal lære seg. Eller hvilket programmeringsspråk som ville løse alle våre problemer (med et glimt i øye til fjorårets julekalender her i programmeringsbloggen). Før vi griper etter verktøyene kan det være nyttig å lære seg hvordan de egentlig fungerer. Mitt motto er “jeg vil ikke bruke et rammeverk jeg ikke kunne laget selv”. Det ville naturligvis vært problematisk å lage et like komplett rammeverk som mange av de som er tilgjengelig, men jeg burde i det minste klare å løse alle problemene under normale omstendigheter selv.

Fordelen med å ha gjort det samme som et rammeverk gjør er at da skjønner jeg hvordan denne koden må være implementert. Jeg får en større intuitiv forståelse for hvordan jeg skal bruke rammeverket, jeg skjønner raskerer hva som er problemet når ting ikke fungere og ikke minst: Jeg skjønner når rammeverket gir meg mer problemer enn hjelp.

Et eksempel jeg har likt å bruke mye er å lage en webapplikasjon i Java uten webrammeverk. Jeg bruker gjerne et enkelt eksempel med en adressebok der man kan registrere kontakter og søke etter disse kontaktene. Til ære for C#-utviklere som leser denne bloggen har jeg løst den samme oppgaven i C#: Hvordan ville du laget en webapplikasjon som verken brukte MVC, ASP.NET eller en gang IIS?

Personlig er jeg veldig avhengig av TDD for å tenke. (Jeg har gjort et unntak fra den overnevnte kalkulatorregelen for tester og bruker SimpleBrowser.WebDriver, FluentAssertions og NUnit). For å starte, har jeg skrevet en test som demonstrerer hva webapplikasjonen skal gjøre:

[Test]
public void ShouldFindSavedPerson()
{
    // Start a web server INSIDE THE TEST :-D
    var server = new My.Application.WebServer();
    server.Start();

    var browser = new SimpleBrowser.WebDriver.SimpleBrowserDriver();
    browser.Url = server.BaseUrl;

    // Navigate to the "add contact" page
    browser.FindElement(By.LinkText("Add contact")).Click();

    // Add a new contact
    browser.FindElement(By.Name("fullName")).SendKeys("Darth Vader");
    browser.FindElement(By.Name("address")).SendKeys("Death Star");
    browser.FindElement(By.Name("saveContact")).Submit();

    // Navigate to the "find contact" page
    browser.FindElement(By.LinkText("Find contact")).Click();

    // Execute some queries:
    browser.FindElement(By.Name("nameQuery")).SendKeys("vader");
    browser.FindElement(By.Name("nameQuery")).Submit();
    browser.FindElement(By.CssSelector("#contacts li")).Text
           .Should().Be("Darth Vader (Death Star)");
    browser.FindElement(By.Name("nameQuery")).SendKeys("anakin");
    browser.FindElement(By.Name("nameQuery")).Submit();
    browser.FindElements(By.CssSelector("#contacts li"))
           .Should().BeEmpty();
}

Når jeg kjører denne testen første gang, vil den feile allerede på linjen browser.Url = server.BaseUrl, fordi det er ikke noen faktisk server.

For å implementere WebServer har jeg brukt en liten artig klasse som kommer med .NET: System.Net.HttpListener. Her er den essensielle koden:

class WebServer
{
    public void Start()
    {
        var listener = new System.Net.HttpListener();
        listener.Prefixes.Add(BaseUrl);
        listener.Start();
        new Thread(HttpThread).Start(listener);
    }

    private void HttpThread(object listenerObj)
    {
        HttpListener listener = (HttpListener)listenerObj;
        while (true)
        {
            var context = listener.GetContext();
            using (context.Response)
            {
            }
        }
    }
}

Jeg kjører testen igjen og kommer et skritt videre. Denne gangen får jeg beskjed om at testen ikke finner linken til “Add contact”. Ikke så rart, vi produserer ikke noe HTML! En liten endring i koden over:

var context = listener.GetContext();
using (context.Response)
{
    new AddressBookController().Service(context);
}

Og så må vi bare implementere AddressBookController.Service:

class AddressBookController
{
    internal void Service(HttpListenerContext context)
    {
        var html = "<html>" +
            "<p><a href='/contact/create'>Add contact</a></p>" +
            "<p><a href='/contact/'>Find contact</a></p>" +
            "</html>";
        var buffer = Encoding.UTF8.GetBytes(html);
        context.Response.OutputStream.Write(buffer, 0, buffer.Length);
    }
}

Testen kommer et skritt videre. Vi ser at vi får opp hovedsiden med valgene “Add Contact” og “Find contact”. Når vi klikker på “Add contact” finner vi naturligvis ikke feltet “fullName” fordi vi ikke har laget skjemaet enda. Metoden “HandleGetRequest” sjekker URL’en for å bestemme hvilken side som skal vises:

internal void Service(HttpListenerContext context)
{
    var html = HandleGetRequest(context.Request);
    var buffer = Encoding.UTF8.GetBytes(html);
    context.Response.OutputStream.Write(buffer, 0, buffer.Length);
}

private string HandleGetRequest(HttpListenerRequest request)
{
    if (request.Url.LocalPath == "/contact/create")
    {
        return "<html>" +
            "<form method='post' action='/contact/create'>" +
            "<p><input type='text' name='fullName'/></p>" +
            "<p><input type='text' name='address'/></p>" +
            "<p><input type='submit' name='saveContact' value='Save'/></p>" +
            "</form>" +
            "</html>";
    }
    else
    {
        // som før
    }
}

Vi er nesten ferdig med å registrere kontakter. Nå finner vi ikke linken “Find contact” etter at vi har postet formen. Metoden “Service” må håndtere POST requester med redirect:

internal void Service(HttpListenerContext context)
{
    if (context.Request.HttpMethod == "GET")
    {
        var html = HandleGetRequest(context.Request);
        var buffer = Encoding.UTF8.GetBytes(html);
        context.Response.OutputStream.Write(buffer, 0, buffer.Length);
    }
    else
    {
        context.Response.Redirect(context.Request.Url.GetLeftPart(UriPartial.Authority));
    }
}

Nå mangler skjema for å søke etter personer. Her hjelper copy-paste pattern oss:

private string HandleGetRequest(HttpListenerRequest request)
{
    if (request.Url.LocalPath == "/contact/create") ...
    else if (request.Url.LocalPath == "/contact/")
    {
        return "<html>" +
            "<form method='get' action='/contact/'>" +
            "<p><input type='text' name='nameQuery'/></p>" +
            "<p><input type='submit' value='Find'/></p>" +
            "</form>" +
            "</html>";
    }
    else ...
}

Feilen nå er åpenbar: Vi har ikke med svaret med kontakter:

    class Contact
    {
        public string FullName { get; set; }
        public string Address { get; set; }
    }

    private static List<Contact> contacts = new List<Contact>();

    private string HandleGetRequest(HttpListenerRequest request)
    {
        else if (request.Url.LocalPath == "/contact/")
        {
            var contactsHtml = string.Join("",
                contacts.Select(c => "<li>" + c.FullName + " (" + c.Address + ")</li>")))
            return string.Format("<html>" + ...
                "<ul id='contacts'>{0}</ul>" +
                "</html>", contactsHtml);

        }

Så gjenstår det bare å ta vare på kontaktene når vi gjør en POST fra “Add contact” skjemaet:

internal void Service(HttpListenerContext context)
{
    if (context.Request.HttpMethod == "GET") ...
    else
    {
        // Read the parameters from the POST body (Request.InputStream)
        var request = context.Request;
        var encoding = context.Request.ContentEncoding;
        var reader = new StreamReader(context.Request.InputStream, encoding);
        var parameters = HttpUtility.ParseQueryString(reader.ReadToEnd(), encoding);

        context.Response.Redirect(HandlePostRequest(request, parameters));
    }
}

private string HandlePostRequest(HttpListenerRequest request, NameValueCollection parameters)
{
    contacts.Add(new Contact() { FullName = parameters["fullName"], Address = parameters["address"] });
    return request.Url.GetLeftPart(UriPartial.Authority);
}

En siste test feiler: Vi filterer ikke kontaktene basert på søket.

private string HandleGetRequest(HttpListenerRequest request)
{
    if (request.Url.LocalPath == "/contact/create") ...
    else if (request.Url.LocalPath == "/contact/")
    {
        var query = request.QueryString["nameQuery"];
        var contactsHtml = string.Join("",
            contacts
                .Where(c => query == null || c.FullName.ToLower().Contains(query.ToLower()))
                .Select(c => "<li>" + c.FullName + " (" + c.Address + ")</li>"));
        return string.Format("<html>" +
                ...
                "<ul id='contacts'>{0}</ul>" +
                "</html>", contactsHtml);
    }
    else ...
}

Nå gjenstår det bare å lagre personene til en ordentlig database og å rette den åpenbare sikkerhetssårbarheten ved vising av kontaktene. AddressBookWebServer bør også få en Main metode, slik at du faktisk kan kjøre koden. Men det overlater jeg til deg, kjære leser.

Og nå kommer vi til moralen

I denne artikkelen har du lært hvordan HTTP egentlig fungerer og hvordan rammeverk som ASP.NET MVC fungerer bak kulissene. Det er mange detaljer vi er glade for å slippe å håndtere, slik som konvertering mellom tegnsett og lesing av innholdet i en POST request. Og det er mange ting som slett ikke er så vanskelig, som for eksempel å gjøre ordentlig “redirect-on-post”. Jeg har på mer enn ett prosjekt innsett at etter at jeg hadde gjort et par dagers investering for å forstå den underleggende teknologien klarte jeg å levere prosjektet bedre uten de åpenbare, populære rammeverkene som alle anbefaler at man skal bruke.

Har jeg funnet opp hjulet på nytt her? Det er mulig å argumentere for det, men jeg ønsker å strekke “finne opp hjulet på nytt” metaforen så langt som den lar seg strekke:

Min erfaring er at det er mange “biler” i dag som har skjeive hjul der akslingen ikke er i midten. Det kan være at hjulet er dårlig eller det kan være at hjulet bare er montert feil. Så merker vi kanskje at bilen humper fordi vi har to hjul som begge har akslingen montert feil. Og så bruker vi masse innsats på å få justert disse to hjulene slik at de humper i takt.

Dersom vi har erfaring med i det minste å lage et “hjul” eller to, kan det hende vi klarer å identifisere de egentlige problemene med de “hjulene” som vi blir gitt, slik at vi kan finne ut hvilke “hjul” som er bra og hvilke som er dårlige, og ikke minst: Hvordan å bruke dem riktig.

Finn opp på nytt de hjulene du ikke forstår, ikke bruk et rammeverk du ikke kunne laget selv og ikke bruk en kalkulator før du forstår matematikken.

God (h)jul!

Cecilie begeistrer på 50 millisekunder [Luke 6, 2012]

Thursday, December 6th, 2012
Ingen kommentarer

Da jeg bodde i Oslo og var en del av talk2me – altså for godt over syv år siden – jobbet jeg sammen med en dyktig utvikler som het Cecilie Tveter. I dag har hun funnet seg nye utfordringer som digital rådgiver i selskapet Nortern Beat, og bloggposten hennes er interessant for langt flere enn programmererne som normalt er å finne her.

IMG_1124.jpg

Hvem er du?
Oslojente med hjerte for fag som tror på deling og raushet.

Hva kan du?
Bruke digitale kanaler for å maksimere potensiale til norske virksomheter.

Hva liker du best med yrket ditt?
Sette spor!

Og her har dere Cecilie sin blogpost…


Det digitale fokuskaos’et

Hva skal være førende fokus når digitale kommunikasjonsutfordringer skal løses? Skal brukerne, strategien, organisasjonen eller rollen i den totale kanalmiksen være i sentrum? Hvem skal stå igjen som vinner når brukerbehov og organisasjonens strategi tilsynelatende står imot hverandre? Finnes det egentlig noen fasit?

Når en bruker er inne på nettstedet ditt har du 50 millisekunder på å begeistre – eller så går brukeren videre til konkurrentens nettsted. Denne utfordringen må tas på alvor.

Hva skal vi på nett å gjøre?

Alle er enige om er at organisasjonen må ha en klar målsetting med nettstedet. Hvis ikke den overordnede kommunikasjonsideen til nettstedet gjennomsyrer alle deler av løsningen vil det ikke lykkes. Et nettsted som gir en stor grad av opplevelse, som er fullt ut universelt utformet eller som legger opp til stor grad av brukerinvolvering vil i seg selv ikke skape en suksess. Informasjonsarkitektur, visuelt uttrykk, språk, innhold og funksjonalitet må bygge opp om og sammen styrke hensikten med nettstedet.

Følgende må komme tydelig frem, hvorfor skal vi på nett? Hvem snakker vi med? Hvilken effekt forventer vi?

Det må defineres realiserbare målekriterier som kan etterprøves. Typiske eksempler på dette kan være generering av leads, rekruttering av abonnenter til nyhetsbrev eller det å bygge kjennskap. Målene skal være en styrende faktor når nettstedet skal utvikles. Ved hjelp av metodikker som brukertesting, fokusgrupper og monitorering av besøksmønster, må det kontinuerlig gjøres justeringer for å oppnå maksimal effekt, også etter lansering.

Hva med de besøkende?

Å sette brukeren i sentrum er en selvfølgelighet for de fleste. Et godt nettsted må ta utgangspunkt i brukerens forventninger, forutsetninger og behov.

Men virkeligheten er ofte mer kompleks enn som så. Politiske, tekniske, praktiske, organisatoriske og ressursmessige forhold kan ofte være en faktor som påvirker løsningen. Det er ofte en stor utfordring for en organisasjon å sette egne behov til side for å skape en god brukersentrert løsning. Plutselig forstår en at den nye nettløsningen griper inn og påvirker organisasjonen.

Og hva betyr det egentlig å sette brukerne i fokus og å ta deres behov på alvor? Brukerne er ikke en homogen gruppe. Det er sammensatte grupper av mennesker med ulike behov, forventninger og forutsetninger. Og det kan ikke tas like mye hensyn til alle. Det betyr at vi må prioritere hardt mellom brukergruppene. Og å prioritere noen betyr at vi nedprioriterer andre. Dette må vi tørre å gjøre. Gjør man ikke det vil man ikke lykkes.

Hva kreves av organisasjonen?

Et vellykket nettsted er forankret i organisasjonen. Ledelse og ansatte må føle eierskap og stolthet. For å få til dette må et tverrsnitt av organisasjonen være sentrale deltagere i alle deler av webprosessen. De må være med på å utforme føringene og utarbeide konstruktive forvaltningsrutiner. Deltakerne må ha et tydelig mandat og bli tildelt beslutningsmyndighet.

Å få en løsning på nett er i prinsippet en triviell operasjon. Det finnes utallige leverandører av standardløsninger som raskt og effektiv får deg på nett. Men her kan det raskt gå galt. En webløsning som ikke har en strategisk forankring i organisasjonen vil ikke kunne bidra til å skape verdier. Verken for brukerne eller organisasjonen.

Det må initielt være vilje til å tilpasse organisasjonen slik at et nytt nettsted skal kunne møte dagens lys. Det må innføres nye interne rutiner, det må jobbes med en plan for håndtering av innhold, det må dedikeres ansvar og beslutningsmyndighet, og det må tilføres riktig kompetanse.

Hvilken rolle skal webben ha i forhold til det totale digitale bildet?

Nettstedet er som oftest bare en av flere digitale kanaler som skal håndteres. De ulike kanalene oppnår størst effekt når de spiller på lag. Dette må tas hensyn til når et nytt nettsted skal planlegges. Nettstedet er ikke en isolert løsning, vi må løfte blikket og se det i en større sammenheng. Summen av alle interaksjonspunktene er det som til sammen gir brukerne en optimal totalopplevelse.

Med den lynraske utviklingen av enheter, teknologi og flater som skjer i dag, har vi blitt gitt fantastiske muligheter til målrettet kommunikasjon. Flatene henger tettere sammen. Der hvor vi tidligere hadde ulike flater som dekket ulike behov ser vi nå at og flere flater dekker flere behov. Iphone, facebook, søkemotorannonsering, blogger og mms er eksempler på helt naturlige elementer i vår digitale hverdag. Dette må dagens nettsteder ta hensyn til – og utnytte potensialet til!

Det helhetlige fokuset – den gode brukeropplevelsen

Så hva skal man ha fokus på når et nytt nettsted skal utvikles?

Dagens brukere er kravstore, morgendagens brukere er enda mer krevende. For å gi brukerne en relevant opplevelse, må nettstedet samsvare med forventningene. Det overordnede fokuset må være å skape den gode brukeropplevelsen.

Det visuelle uttrykket, den logiske oppbyggingen, interaksjonen og samhandlingen, tilgjengeligheten og det redaksjonelle innholdet, og et optimalisert forhold mellom disse elementene er det som skaper den gode brukeropplevelsen.

Dette krever et bevisst forhold til målsettinger, identifiserte brukerbehov, endringsvilje i organisasjonen og strategisk bruk av digitale flater. De aktørene som lykkes med å realisere dette er de store vinnerne.

JavaCoffeeLispyPogoScript

Sunday, September 23rd, 2012
3 kommentarer

JavaScript er som alle vet et viktig språk, men syntax-messig har det sine utfordringer. For godt over et år siden fant jeg det populære språket CoffeeScript, som kompileres ned til JavaScript. Det vil si at det i praksis kan erstatte JavaScript-utvikling.

Men det finnes mange slike språk som forsøker å gjøre JavaScript-koding mindre smertefullt. I denne blogposten har jeg tatt litt JavaScript og kodet det samme i tre slike språk: CoffeeScript, LispyScript og PogoScript. Alle disse språkene er plugins til node.js, og er enkle å komme igang med. Målet var å illustrere de ulike syntaksene, og se om noen av dem er “bedre” enn andre.

Bowling i JavaScript

Koden er en løsning for å finne poengscoren for en bowlingserie. Serien er representert som et array av kast – dvs. av hvor mange sjegler som ble felt av kastet. Løsningen definerer to funksjoner: en som finner poengscoren til en frame (omgang), og en som looper over hele spillet og samler opp totalscoren. Spill-arrayet “spises opp” underveis i denne løsningen – dette er altså ikke funksjonell programmering, her muterer jeg rått og hemningsløst.

var frameScore = function(rolls) {
  if(rolls[0] === 10)
    return rolls.shift() + rolls[0] + rolls[1];
  if(rolls[0] + rolls[1] === 10)
    return rolls.shift() + rolls.shift() + rolls[0];
  return rolls.shift() + rolls.shift();
};

var score = function(rolls) {
  var score = 0;
  for(var i = 0; i < 10; i++)
    score += frameScore(rolls);
  return score;
};

var gameZeros = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    gameRandom = [10,8,2,5,5,7,3,10,10,7,1,10,10,10,10,8],
    gamePerfect = [10,10,10,10,10,10,10,10,10,10,10,10];

console.log(score(gameZeros));    // => 0
console.log(score(gameRandom));   // => 213
console.log(score(gamePerfect));  // => 300

I de siste linjene definerer jeg tre test-omganger, beregner poengsummen, og skriver den ut.

Disclamer: Koden er en modifisert utgave av Karl Westin’s Bowling Game Kata-løsning som man kan finne på Github.

Bowling i LispyScript

Det finnes flere Lisp-varianter som kompilerer til JavaScript. Den mest kjente er kanskje ClojureScript. Et annet heter Sibilant, og det ser veldig egentlig veldig bra ut. Men jeg har valgt språket LispyScript, som i alle fall for øyeblikket er en veldig enkel Lispifisering av JavaScript.

Igjen har jeg de to samme funksjonene – jeg har forsøkt å løse oppgaven så likt som den orginale løsningen som mulig.

(var frameScore
  (function (rolls)
     (if (= 10 rolls[0])
       (+ (rolls.shift) (+ rolls[0] rolls[1]))
       (if (= 10 (+ rolls[0] rolls[1]))
         (+ (rolls.shift) (+ (rolls.shift) rolls[0]))
         (+ (rolls.shift) (rolls.shift))))))

(var score
  (function (rolls)
     (loop (i score) (0 0)
       (if (< i 10)
         (recur ++i (+ score (frameScore rolls)))
         score))))

(var gameZeros [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0])
(var gameRandom [10,8,2,5,5,7,3,10,10,7,1,10,10,10,10,8])
(var gamePerfect [10,10,10,10,10,10,10,10,10,10,10,10])

(console.log (score gameZeros))  ; => 0
(console.log (score gameRandom)) ; => 213
(console.log (score gamePerfect)); => 300

En utfordring i forhold til denne oppgaven er at LispyScript ikke har noen normal for-løkke. Jeg valgte å bruke en rekursiv loop-makro med en teller (i) som jeg inkrementerer og kontrollerer underveis i score-funksjonen. At pluss-funksjonen bare kunne ta to argumenter gjorde også at frameScore ble noe mindre oversiktelig enn jeg hadde håpet.

Konklusjon: Jeg er glad i Lisp, og kan tenke meg å bruke det for JavaScript-utvikling – men for oppgaver som denne kom LispyScript til kort. Språket trenger flere utvidelser (makoer) for å bli elegant, men bare det at det i det hele tatt finnes makro-støtte gjør det hele interessant.

Bowling i CoffeeScript

CoffeeScript har jeg vist frem før, og jeg liker det veldig godt. Spesielt er det  kraftfullt med sine list comprehensions – noe som gjorde score-funksjonen du ser nedenfor ganske elegant og kompakt (noen vil kanskje si kryptisk, men man kan ikke gjøre alle fornøyde). Indenteringsreglene i CoffeeScript gjør også koden enklere å skrive enn både JavaScript og LispyScript-variantene.

scoreFrame = (rolls) ->
  if rolls[0] == 10
    rolls.shift() + rolls[0] + rolls[1]
  else if rolls[0] + rolls[1] == 10
    rolls.shift() + rolls.shift() + rolls[0]
  else
    rolls.shift() + rolls.shift()

score = (rolls) ->
  (scoreFrame rolls for _ in [0..9])
    .reduce (t, s) -> t + s

gameZeros = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
gameRandom = [10,8,2,5,5,7,3,10,10,7,1,10,10,10,10,8]
gamePerfect = [10,10,10,10,10,10,10,10,10,10,10,10]

console.log score gameZeros    # => 0
console.log score gameRandom   # => 213
console.log score gamePerfect  # => 300

Konklusjon: Fortsatt den mest realistiske JavaScript-erstatningen. Koden er fin, men vil føles fremmed for dem som bare har erfaring med C-lignende språk.

Bowling i PogoScript

Jeg avslutter med det som kanskje er det mest interessante av disse språkene; PogoScript er et språk som legger ekstra vekt på lesbarhet, og som kan være veldig egnet til å skrive domenespesifike språk. Dette kommer nok ikke så godt frem overalt i koden min, men du kan se noen interessante ting som for eksempel at variabelnavn kan inneholde space. Funksjonsnavn inneholder også sine parametre (i paranteser), og disse kan plasseres hvor som helst i navnet. Dermed kan du lage funksjoner som heter ting som for eksempel “move the file (filename) to (directory)”. Noe lignende har jeg aldri sett i noe annet språk.

score of next frame in (rolls) =
    if (rolls.0 == 10)
        rolls.shift() + rolls.0 + rolls.1
    else if ((rolls.0 + rolls.1) == 10)
        rolls.shift() + rolls.shift() + rolls.0
    else
        rolls.shift() + rolls.shift()

score (rolls) =
    result = 0
    for (i = 0, i < 10, i = i + 1)
        result = result + score of next frame in (rolls)

    result

game zeros = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
game random = [10,8,2,5,5,7,3,10,10,7,1,10,10,10,10,8]
game perfect = [10,10,10,10,10,10,10,10,10,10,10,10]

console.log (score (game zeros))   // => 0
console.log (score (game random))  // => 213
console.log (score (game perfect)) // => 300

Slik jeg forstår det er PogoScript veldig utvidbart; indentering definerer en ny kodeblokk, og denne eksekveres av funksjonen kodeblokken sendes til. Hvis du har erfaring fra Lisp, Rebol, Ruby eller Io skjønner du kanskje hva jeg mener. I praksis betyr dette at språket har markoer. For-løkken i score-funksjonen er til eksempel egentlig ingen for-løkke i vanlig forstand, men en funksjon som heter for.

Konklusjon: PogoScript er nok ikke et språk jeg ville valgt som en erstatter for JavaScript. Men det er et interessant språk å studere nærmere, og det kan være aktuelt om man en elle rannen gang har behov for å skrive ekstremt lesbar kode.

Resultatet

  • Språket jeg synes er vakrest å se på: LispyScript
  • Språket som var mest interessant: PogoScript
  • Språket som var enklest til denne oppgaven: CoffeeScript
  • Grunnen til at Gud og Hverman lager alle disse språkene: JavaScript

NodeJS vs. ASP.NET

Wednesday, May 16th, 2012
Ingen kommentarer

Jeg har snakket om det før – det blir mye spennende web-teknologi på NDC i år. Og nå avslører vi at det hele kommer til å kulminere i et svært oppgjør mellom de to største leirene…

NDC_CAGE_MATCH_500

Daminan Edwards jobber på ASP.NET-teamet hos Microsoft, og står bak open source-prosjektet SignalR, som hjelper deg å lage real-time, multi-user interaktive webapps i .NET. Rob Conery er en velkjent ex-Microsofter som nå er helfrelst på NodeJS. I en munter setting ledet av Jon Galloway vil du få oppleve de to teknologiene side om side – og endelig skal vi få se hva som er best!

Det er fortsatt ledige biletter til NDC 2012, og folkene fra Programutvikling kan hjelpe deg med å få hotellrom. Ikke gå glipp av Nord-Europas beste utviklerkonferanse!

NDC 2012 agendaen: Webutvikling

Saturday, March 17th, 2012
1 kommentar

I fjor var jeg (som nevnt tidligere) så heldig å bli invitert til å få være med å forme 2012-utgaven av Norwegian Developers Conference. Vi har jobbet hardt med å velge ut de beste av over 500 foreslåtte foredrag, og nå er endelig agendaen lansert.

Vi har forsøkt å fokusere agendaen rundt noen tydelige tema, men innholdet er likevel ganske variert, og det kan nok være vanskelig å få en god oversikt. Det er jo tross alt tre fulle dager med i år åtte tracks hver dag, pluss workshops. Derfor vil jeg nå skrive en rekke blogposter som tar for seg de ulike hovedtemaene for konferansen – de røde trådene – og trekke frem noen av de forelesere og foredragene jeg mener folk bør få med seg.

Og her kommer den første…

agenda_web

Webben er en sentral plattform for de aller fleste utviklere, og er selvfølgelig også et av de viktigste fokusområdene for NDC 2012. Det skjer mye på denne fronten, og det kan være vanskelig å henge med. NDC vil forsøke å gi deg en god oversikt over mulighetene som finnes, og det blir flere muligheter for dypdykk i utvalgte teknologier.

ASP.NET

Det er mange som kommer til Oslo i sommer får å høre hva som er nytt for webutviklere på .NET-plattformen. Og vi har vært så heldige å få med oss Brad Wilson, som er utvikler på ASP.NET MVC-teamet hos Microsoft. Han vil introdusere deg for det som nå heter ASP.NET Web API, som gjør det enklere å lage gode html-baserte API’er. Dominick Baier vil så fortelle deg alt du trenger å vite om sikkerhet knyttet til Web API.

HTML5 og CSS3

Alle snakker om HTML5 for tiden, og det vil man gjøre under konferansen også. Jeg vil trekke frem Lea Verou, som er spesielt dyktig på og kjent for sine presentasjoner om CSS. Bruce Lawson er også med, og vil blant annet holde et foredrag om HTML5 Multimedia. Og Jon Galloway (kjent fra podcastet Herding Code) vil lære “gamle grinebitere” å bli glad i HTML og CSS.

Remy Sharp fra jQuery-teamet er det nok også spennende å få med seg. Han vil kaste lys over noen av de delene av HTML5 som folk ikke snakker så mye om, men som likevel er viktige.

Grafikk og Canvas

Rob Ashton er også tilbake i år, og vil nå snakke om noe han brenner veldig for – nemlig WebGL, et subset av OpenGL for browseren. David Geary er også en interessant fyr med de spennende sesjonene: Mind-blowing Apps with HTML5 Canvas og HTML5 Game Development. Hvem har vel ikke lyst til å lære å lage kule spill for web?

Node.js

Node.js lar deg kode JavaScript på serveren, og har vært veldig populært en stund nå. Sara Chipps, kjent fra Girl Develop It, vil vise nybegynnere hvordan man lager en webapplikasjon med Node.js på 60 minutter. Rob Conery er tilbake i år også, og vil følge opp med et noe mer avansert node.js-foredrag.

Web Sockets

Guillermo Rauch er mannen bak JavaScript-bibloteket Socket.io. Å få ham til Norge er ganske stort! Guillermo vil holde sesjoner om både web sockets og node.js. Konferansen vil dessuten ha foredrag som omfatter SignalR – et .NET-rammeverk for full duplex mellom browser og webserver uten å nødvendigvis kreve støtte for web sockets.

Konklusjon

Som du forstår er programmet tettpakket med innhold om webutvikling, og om du ønsker å få med deg alt i denne røde tråden så rekker du ikke stort annet. Personlig er jeg veldig interessert i web sockets, så det må jeg få med meg. Og så har jeg veldig lyst å bli inspirert av David Geary’s presentasjoner.

Lykke til med dine egne valg, og følg med videre for flere poster om agendaen for NDC 2012!

Conway’s Game of Life

Wednesday, January 18th, 2012
5 kommentarer

I kveld har Bergen CodingDojo hatt sitt andre møte. Jeg skulle vært med, men måtte desverre trekke meg i siste liten pga. sykdom.

Oppgaven det skulle jobbes med i dag var Conway’s Game of Life. Dette er en god dojo-oppgave fordi det er mange måter å angripe problemet på, og det finnes flere løsninger med ulike kvaliteter. Corey Haines og de andre som arrangerer Code Retreats rundt omkring i verden bruker også denne oppgaven. Er du interessert i å vite mer om hva det er for noe anbefaler jeg å ta en titt på Corey’s introduksjon til en Code Retreat som ble arrangert i Cleveland.

Jeg løste Game of Life i forrige uke i påvente av kveldens dojo. Da brukte jeg CoffeeScript og HTML. Jeg brukte ingen enhetstester, men testet interaktivt i browseren hele tiden.

Og jeg tok det opp på video. Har du 12 minutter til overs kan du se hva jeg gjorde. Bruk full screen, og pass på at du ser den i HD. Skru også opp lyden, for jeg la på litt kul musikk.

Conway & Coffee from Torbjørn Marø on Vimeo.

Etter at jeg lagde videoen utvidet jeg også løsningen til å støtte et uendelig grid. Har du Chrome (virker i alle fall ikke i IE) kan du se løsningen live her (pass på, den begynner å bli ressurskrevende etterhvert hvis griddet vokser seg stort).

Vi jobbet også med Conway’s Game of Life i en intern coding dojo i PSWinCom i forrige uke, og vi har tenkt å gjøre det igjen i flere uker fremover – som en Code Retreat strukket utover i tid. Og vi begynner på nytt hver gang – fokuset er ikke å fullføre en komplett løsning, men å trene på å skrive “perfekt kode”.

Nå er jeg spent på å høre hvordan det har gått på kveldens dojo…

CoffeeScript

Tuesday, December 13th, 2011
5 kommentarer

CoffeeScript er et rykende ferskt språk som rett og slett forsøker å fikse alle problemene med JavaScript. Koden kompileres ned til JavaScript, og har en syntaks inspirert av Ruby, Python og Haskell. CoffeeScript gir deg som webutvikler også noen nye muligheter som list comprehensions, pattern matching, og klasse-basert objektorientering.

coffeescript_legacy

CoffeeScript er mye mer kompakt og elegant enn JavaScript, og har blitt godt mottatt av mange utviklere. Språket er blant annet inkludert i Ruby on Rails, og er også mye brukt på serversiden i Node.js. For noen måneder siden gikk også utviklingsteamet mitt over fra JavaScript til å skrive CoffeeScript, uten nevneverdige problemer.

coffeescript

CoffeeScript-compilatoren er skrevet i JavaScript, og selve kompileringen av scriptene kan derfor skje i browseren. Men dette er selvsagt ikke optimalt – det normale er at man som en del av build-prosessen genererer JavaScript-filer fra CoffeeScript’ene.

For .NET, som er vår plattform, finnes det også HTTP-handlers som kompilerer CoffeeScript on the fly, og server ut JavaScript. Dette er veldig praktisk under selve utviklingen.

La oss se på litt kode

Da er det på tide å løse Euler1-oppgaven igjen. Jeg skriver her CoffeeScript-kode som jeg tenker vil bli konvertert til JavaScript og plassert i en webside. Svaret vises ved hjelp av en alert-box.

Her er en enkel, imperativ kodesnutt som finner summen av alle multipler av 3 eller 5 under 1000:

 2 answer = 0
 3 for n in [1...1000]
 4   if n % 3 is 0 or n % 5 is 0
 5     answer += n
 6 alert answer

Koden kompileres til JavaScript’et nedenfor. Her ser du at CoffeeScript blant annet har “ranges” man kan iterere over, og  at koden bruker ord som is og or for å bli mere leservennlig. Du kan også se at den kompilerte koden følger best practises, og er wrappet inn i et funksjonskall, slik at det ikke opprettes noen variabler i det globale navnerommet.

10 (function() {
11   var answer, n;
12   answer = 0;
13   for (n = 1; n < 1000; n++) {
14     if (n % 3 === 0 || n % 5 === 0) {
15       answer += n;
16     }
17   }
18   alert(answer);
19 }).call(this);

Nedenfor har jeg laget en løsning til, som viser hvordan man oppretter funksjoner i CoffeeScript. Den bruker også en if bak et uttrykk, en teknikk arvet fra Ruby. Og numbers-variabelen settes ved hjelp av en list comprehension som utfører selve filtreringen.

10 multipleOf = (n, d) -> n % d is 0
11 
12 multipleOf3or5 = (n) ->
13   for divisor in [3,5]
14     return yes if multipleOf(n, divisor)
15 
16 numbers = (n for n in [1...1000] when multipleOf3or5 n)
17 
18 answer = 0
19 answer += n for n in numbers
20 alert "The answer is #{answer}!"

Den nest siste linjen som summerer opp tallene er også litt snedig, og den aller siste linjen viser at CoffeeScript støtter string interpolation. Og å kunne returnere “yes” i stedet for true fra multipleOf3or5 er jo også litt søtt da :)

Prototyping og monkey patching

JavaScript er jo et språk som støtter prototype-basert objektorientering. Her viser jeg hvordan jeg kan bruke dette i CoffeScript for å løse Euler1-oppgaven. Først oppretter jeg en isMultipleOf-metode på alle tall. Deretter kan jeg lage en fin multipleOf3or5-funksjon som bruker dette.

24 Number::isMultipleOf = (d) -> this % d is 0
25 
26 multipleOf3or5 = (n) ->
27   n.isMultipleOf(3) or n.isMultipleOf(5)
28 
29 Array::sum = ->
30   answer = 0
31   answer += n for n in this
32   return answer
33 
34 alert do (n for n in [1...1000] when multipleOf3or5 n).sum

Den tredje funksjonen opprettes som en metode på Array – den summerer opp alle tallene i arrayet. Til slutt bruker jeg list comprehension til å filtrere en range, og så kalle sum-metoden jeg lagde på resultatet.

Klasse-basert abstraksjon

CoffeeScript introduserer også en abstraksjon for klasse-basert objektorientering. Dette lar deg implementere klasser tilnærmet slik man gjør det i språk som f.eks. Ruby, og kompilatoren gjør dette om til prototype-basert JavaScript-kode.

Her følger klassen EulerProblem1 som har en kontruktør og to metoder. @limit og @sum er instansvariabler – den siste brukes til a cache resultatet av kalkuleringen. Selv om jeg sier calculate flere ganger vil selve kalkuleringen bare skje én gang slik jeg har valgt å gjøre det.

38 class EulerProblem1
39   constructor: (@limit) -> @sum = null
40 
41   include: (n) -> n % 3 is 0 or n % 5 is 0
42 
43   calculate: ->
44     if not @sum?
45       @sum += n for n in [1...@limit] when @include(n)
46 
47 ep1 = new EulerProblem1 1000
48 do ep1.calculate
49 alert ep1.sum

I de tre siste linjene ser du hvordan jeg oppretter en instans av klassen, hvordan jeg kaller metoden calculate, og hvordan jeg henter ut summen.

Hvorfor bruke tid på CoffeeScript

De fleste av oss har et forhold til JavaScript. Dette forholdet er gjerne litt ambivalent. JavaScript blir viktigere og viktigere for å kunne tilfredstille de økte forventningene til dagens webløsninger, men JavaScript er et språk med mange svakheter. Da er det interessant at man ikke kode i JavaScript direkte, men kan velge et renere og rikere språk som “kompileres” til JavaScript.

Det er viktig å poengtere at du kan benytte alle JavaScript-biblotekene du er vandt med også i CoffeeScript.

Er du Python- eller Ruby-utvikler er det nesten garantert at du kommer til å like CoffeeScript bedre enn JavaScript. Du bør uansett forsøke det, og så vurdere om det er verdt å legge denne ekstra abstraksjonen over JavaScript i akkurat ditt tilfelle.

Kan man bruke Coffee uten å kunne JavaScript?

Svaret på dette spørsmålet er desverre nei. Det finnes ikke enda (så vidt jeg vet) noen måte å debugge CoffeeScript på. Får man problemer vil man derfor få behov for å se på og debugge den genererte javaScript-koden. Koden er derimot helt grei, så dette er ikke et stort problem. Men man må kunne JavaScript!

Hvordan komme igang

Den offisielle CoffeeScript-siden finner du her. Den har en god primer som side-ved-side sammenligner CoffeeScript og JavaScript. Der kan du også teste språket direkte i browseren din.

Mye av det som finnes for å ta i bruk CoffeeScript er tilrettelagt for Linux og node.js-brukere. Hvis du er en Windows-bruker bør du ta en titt på CoffeeSharp, som gir deg det meste av hva du trenger.

JavaScript revolution

Friday, October 21st, 2011
1 kommentar

JavaScript har i løpet av 15 år gått fra å være et forferdelig mareritt til å bli en av de mest spennende og pulserende teknologiene man kan holde på med. Det skjer så mye rundt JavaScript for tiden at det rett å slett er vanskelig å henge med.

Denne artikkelen er et forsøk på å skape en oversikt over viktige open-source biblotek det kan være nyttig å vite om. I takt med modningen av HTML5 har jeg blitt mer og mer interessert i JavaScript-utvikling det siste året. Denne listen inneholder noen ting jeg har testet ut, men vel så mange ting jeg ikke har jobbet med, men ønsker å få sett nærmere på i tiden fremover.

Finner du noen åpenbare mangler i listen min – spennende biblotek eller rammeverk jeg har utelatt – så må du slenge inn en kommentar!

De generelle bibloteken

Først og fremst bør alle webutviklere kjenne til det jeg tenker på som de store, generelle JavaScript/Ajax-biblotekene. Jeg tenker da på Prototype, DOJO, Moo Tools, YUI Library, og sist men ikke minst jQuery, som er det som nå er aller mest populært. Siden jeg bruker jQuery selv, ser jeg ingen åpenbar grunn til å se på de andre.

jQuery har som kjent også et hav av plugins for alt mulig man kan komme til å trenge. Det kan være viktig å lete litt blant dem før man begynner å lage noe selv.

JavaScript også utenfor browseren

JavaScript er et kraftig språk med noen av de raskeste, dynamiske tolkerne (interpreters) som finnes. Og det brukes til langt mer enn å bare lage websider. Node.js er det mest populære rammeverket som tar JavaScript server-side, og er basert på Google’s V8-motor som kjører i Chrome. Jeg har lekt meg litt med Node tidligere, og synes det er veldig spennende.

CommonJS er et initiativ som skal definere et standard API for JavaScript utover det som språket selv definerer. Fokuset her er nettopp på det å bruke JavaScript utenfor browseren – til å lage server-applikasjoner, kommandolinje-verktøy, desktop GUI-applikasjoner, og hybridapplikasjoner i f.eks. Titanium og Adobe AIR. Titanium har jeg også testet litt, og det er et veldig spennende alternativ hvor du lager programmer som kjører på Windows/Mac/Linux ved å bruke HTML og CSS pluss en valgfri kombo av JavaScript, Ruby og Python.

Når jeg sier JavaScript så mener jeg forresten egentlig CoffeeScript. Dette er en rykende ferskt språk som kompileres ned til JavaScript. Man kan bruke alt som finnes av biblotek fra JavaScript-verdenen, men koder selv i en mye mere behagelig syntaks. Jeg har allerede konvertert teamet mitt på jobben til å bruke CoffeeScript fremfor JavaScript, og anbefaler deg til å vurdere det samme.

Noen sentrale byggeklosser

RequireJS laster JavaScript-filer og moduler. Å bruke dette vil gjøre løsningen din både raskere og enklere å holde oversiktelig etterhvert som den vokser seg større. RequireJS gjør det enklere for deg som utvikler å lage større JavaScript-løsninger, samtidig som den optimaliserer selve deploymenten av løsningen.

Underscore.js er en verktøykasse som gir JavaScript bedre støtte for funskjonell programmering. Her finner du rundt 60 generelle funksjoner som each, map, select, reduce, range osv.

HTML5_Logo_128

Modernizr er et biblotek som skal hjelpe deg å bygge neste generasjons HTML5- og CSS3-løsninger som også vil virke for dem som bruker browsere som ikke støtter de nye featurene. Dvs., Modernizr utfører ikke mirakler – det får ikke disse nye tingene til å virke i gamle browsere – men det forteller deg hva som virker, slik at du kan ta høyde for det og kode deretter.

WebSockets har potensialet til å revolusjonere hvordan vi lager rike webapplikasjoner, og er noe av det aller mest spennende som ligger i HTML5-standarden (en bra presentasjon om dette). Socket.IO er et biblotek som skal gi deg realtime apps, uavhengig av hvilken browser eller mobil-device brukeren har. Det bruker WebSockets om det er tilgjengelig, og faller tilbake på andre løsninger om det ikke er det. Socket.IO kan også brukes på server-siden i f.eks. Node.js.

Og så må jeg få nevne Date.js, et lite biblotek som lar deg jobbe med datoer i JavaScript på en enkel måte.

MVC-aktige rammeverk

Nå har vi kommet til de rammeverkene som skal legge til rette for å lage JavaScript-tunge webløsninger. Jeg tenker da spesielt på såkalte single-page JavaScript applications. GMail er et typisk eksempel på en sånn app.

Backbone.js gir deg (meget kort fortalt) muligheten til å lage datamodeller, definere views, og å knytte disse sammen med en toveis databinding. Backbone.js bruker også Underscore.js for å tilby et rikt API.

Sammy.js er et lite men veldig spennende rammeverk som lar deg designet single-page JavaScript apps etter en restfull tankegang med ruter (routing). Du kan bruke ulike template/rendering-motorer, og Sammy føles både enkel og elegant.

Brunch beskrives også som et lettvekts rammeverk for å lage HTML5-applikasjoner med fokus på eleganse og enkelhet. Det kombinerer CoffeeScript, Backbone.js, Underscore.js, jQuery og flere andre biblotek til en pakke for å lage MVC-lignende løsninger.

Andre rammeverk jeg har fått med meg som er populære, men som virker noe større (men ikke dårligere av den grunn) inkluderer SproutCore, Cappuccino og Sencha. For rendering / templates finnes det enda flere muligheter, som Eco, Stitch, mustache, EJS, pure og meld. Ett av disse bør man nok lære seg å bruke.

Grafikk og effekter

Det finnes mange, gode biblotek for å lage ulike typer grafer, men jeg orker ikke liste dem her. Det finnes også flere biblotek som fokuserer på å tilby ulike JavaScript-effekter, som f.eks. Script.aculo.us.

$fx() er et annet biblotek for å animere HTML-elementer. Med bare 4k JavaScript lar det deg endre CSS-properties over en tidslinje på en ganske så elegant måte. Er du kreativ kan du lage noen veldig spennende websider med dette kompakte scriptet.

Er du en av dem som behersker 3D-grafikk er WebGL noe du bør se på. Ved å bruke canvas-elementet i HTML5 gir det deg 3D rett i browseren, uten å bruke plug-ins. WebGL er basert på OpenGL.

Og er du helt sprø så lærer du deg Processing.js. Processing er et programmeringsspråk og en utviklingsplattform for å lage elektronisk kunst og visuelt design, og Processing.js er en portering av dette til JavaScript. Ta en titt på linken for å se hva du kan gjøre med det.

Testdreven JavaScript

Når det kommer til testing så virker det som om det mest populære rammeverket en stund har vært QUnit (det er det jQuery bruker). Et alternativ som bruker begreper som er mer kjente for dem som driver med BDD er Jasmine. I tillegg kan det være nyttig å bruke Sinon.JS for mocking, og jsTestDriver for å kjøre testene.

Buster.JS er et annet testrammeverk som det snakkes mye om, men som ikke har nådd noen release enda. Det virker som det vil være kompatibelt med QUnit, bruke Sinon.JS for mocking, ha BDD-syntax for dem som ønsker det, og ha støtte for det samme som man finner i jsTestDriver. Her blir det altså en mere komplett løsning i én pakke.

Headless browser

Helt til slutt vil jeg nevne PhantomJS. Dette er et kommandolinje-verktøy som inneholder en “usynlig” web-browser. Man kan gjøre alt man kan gjøre med en vanlig browser, og styre den med JavaScript. Dette egner seg veldig godt til ting som testing av webapplikasjoner, “webskraping”, og mye, mye mer om du har litt fantasi.

Mye å sette klærne i her altså. Har du noen erfaring med disse biblotekene som du vil dele?

Siste kommentarer

Torbjørn
PS: Takk til Børge Hansen, som delte SCARF-modellen med meg!...
Børge Hansen
Denne likte jeg veldig godt. Du skriver godt og har gode betraktninger  Keep it up – flere trenger å tørre å lære mer om ledelse – du l...
Tormod
Er egentlig ikke overrasket. F# sin fortè er programmererens produktivitet/kvalitet og anledning til parallell kjøring. Men kjøremotoren har ...
Stian
Ville også prøvd med et større problem (x100 eller x1000 f.eks). Når man snakker så små brøkdeler av et sekund som her så kan tiden for en ell...
Torbjørn
Har ikke sjekket - tar en titt i morgen hvis tid :)...
Einar W. Høst
Mhp tco: hva sier ILSpy?...
Torbjørn
Har ikke sett noe på PSeq før, men kjenner til den typen funksjoner fra blant annet Clojure. Og problemet med slike funksjoner i sammenhenger som de...
Håvard
Veldig bra sammenligning! Har du sett på ytelsen av PSeq.* fra powerpakken? Tipper den vil gi performancehit på små mengder, men kan kanskje resul...
Torbjørn
Jeg kom på en demonstrasjon-variant til jeg burde inkludere, nemlig bruk av list comprehension (en type computation expression (også kalt monads)). ...
Einar W. Høst
Interessant, det blir en trade-off mellom eleganse og fart på en måte. Den funksjonelle løsningen med vanlig filter er ren og pen, mens den imperat...
Creative Commons-lisens
Innholdet på denne bloggen er tilgjengelig under Creative Commons Navngivelse-Ikkekommersiell-DelPåSammeVilkår 3.0 Norge lisens.

Programmeringsbloggen
Kjempekjekt.com

© 2006-2013 Torbjørn Marø

Jeg har vært en profesjonell programmerer siden 1999, og dette er min blogg. Målet med bloggen er å stimulere meg selv og alle andre til kontinuerlig eksperimentering og læring.

Jeg forsøker å være allsidig, og programmerer blant annet i C#, Ruby, Erlang og Clojure.

Jeg praktiserer TDD og andre smidige utviklingspraksiser. Jeg er opptatt av kvalitet og ren kode.

Dette og ganske mye mer kan du lese om på denne bloggen!