19 feb 2018

Tandborstning och statiska kontroller

tandkram.jpg

Treåringen hemma gillar inte att man borstar hans tänder. Jag förstår honom. Det är svårt i den åldern att se varför någon ska få vifta runt med en borste i ens mun när man hellre läser en godnattsaga eller leker med sina leksaker.

Men jag, listig pappa, har utvecklat ett trick. Erfarna föräldrar känner igen detta som en sorts distraktionstaktik.

<masak> Noa, jag ska måla i din mun.
<noa> Röd, och vit, och blå, och kudde.

Vad han har angivit här är en lista med färger (olika varje morgon eller kväll), men den sista saken är inte en färg. Jag börjar borsta, och samtidigt räknar jag långsamt upp färgerna han har valt:

* masak borstar noas tänder
<masak> Röd... vit... blå...
<masak> ...kudde... MEN, VÄNTA NU!
* noa skrattar, tandborste i munnen

Voilà — en tråkig syssla har fått ett element av tokighet, och är mycket enklare för både förälder och barn.

I programmeringstermer hör elementet "kudde" inte hemma i en lista av färger. (Dess typ stämmer inte.) Min iscensatta förvåning vid detta får treåringen att känna att han har överlistat tandborstningsrutinen — istället för att vara en ovillig mottagare så är han en aktiv deltagare (och en busig en dessutom). Han är tandborstningsrebell.

Vissa programmeringsspråk är tillåtande på det sättet: de accepterar varje (syntaktiskt riktigt) program, börjar köra det, och först senare utbrister de "MEN, VÄNTA NU!" när ens program faller i någon hyfsat uppenbar fallgrop. Programmerarens reaktion är vanligtvis "ah, visst ja, äsch, bäst att fixa det", möjligen efter visst funderande och spårande i koden.

Andra språk är striktare, och förbjuder många sådana misstag vid kompilering (eller ännu tidigare). Kontrollerna är ofta typkontroller, men kan även vara andra saker, som till exempel nåbarhetskontroller.

Och där är vi idag, anno 2018. IT-världen är huvudsakligen uppdelad i språk av den förra kategorin — som JavaScript, Perl, Python, Ruby, PHP — och språk av den senare kategorin — som Java, C#, C++, Haskell.

Det finns långa diskussioner och argument på båda sidorna om vilken sorts språk som är bäst lämpat för olika uppgifter. Kortfattat och lite vagt kan dessa sammanfattas genom att kontrastera flexibilitet/frihet å ena sidan mot korrekthet och säkerhetsgarantier å andra.

Jag har följt lite av en väg under de senaste åren med min JavaScript-utveckling:

  • För det första så gillar jag friheten som JavaScript erbjuder: ja, det är möjligt att få sena fel under körning, men... kodningsdisciplin och tillräckligt med tanke tidigt i processen kan kompensera för detta, åtminstone delvis.
  • Mer och mer har jag också börjat använda linter-verktyg, som påminner mig och mitt team om osäkra bruk av språket. Detta är särskilt motiverat eftersom JavaScript utvecklades i en helt annan miljö för decennier sedan, utan dagens krav på skalbarhet och komplexitet.  Med tiden har jag kommit att tänka på JavaScript som ett språk som helt enkelt kommer med ett linter-verktyg; annars är risken stor att man begår misstag.
  • På sistone har jag börjat uppskatta TypeScript, som kombinerar det stökiga och flexibla JavaScript med ett statiskt typsystem. Samma gamla JavaScript, samma gamla flexibilitet, men med typkontroller (och flödeskontroller, etc) vid kompilering. Med en hygglig utvecklingsmiljö kan jag få felen att dyka upp medan jag skriver koden. Otroligt nog fortsätter TypeScript att innovera med varje ny release, och fångar fler och fler saker som kan gå fel.

Jag vill göra tydligt hur extremt osannolikt TypeScript känns som koncept. Om någon hade frågat mig för några år sedan: "kan man retroaktivt passa in ett typsystem ovanpå JavaScript och samtidigt behålla fullständig bakåtkompabilitet?", så skulle jag ha sagt: "nej, självklart inte". Men det är vad TypeScript gör. En del av hemligheten verkar vara att de använder ett strukturellt typsystem, vilket passar väldigt bra ihop med JavaScripts dynamiska natur.  Typsystemet i TypeScript är förmodligen det minst störande jag någonsin har använt. (Och det sätter i stark kontrast för mig hur bristfälligt Java, med sitt nominella typsystem, är i det avseendet.)

Häromdagen hittade jag en bloggartikel vid namn Top 10 JavaScript errors from 1000+ projects (and how to avoid them). Den listartikeln är en bra sammanfattning av de vanligaste körfelen i JavaScript-kodbaser. Jag gillar den.

Men min första tanke var De flesta av de här problemen skulle TypeScript ha fångat. Åtminstone om man använder TypeScript med tillräckligt strikta flaggor (som noImplicitAny och strictNullChecks), och så länge man inte fuskar och manuellt anger variablers typ som any.

Min nästa tanke var Varför gör vi det här mot oss själva?

Jag har på senare dar slutit mig till att det inte finns någon fundamental motsättning mellan scriptspråkens flexibilitet och de statiska språkens säkerhetsgarantier. Vi kan ha kakan och äta den. Anledningen till att många projekt fortfarande under 2018 får de där körfelen är... tröghet. JavaScript är alltid där som det självklara alternativet, linter-verktyg fångar inte allt, och saker som kunde ha fångats går ut i produktion.

Så, jo, ta en titt på TypeScript om du inte redan har gjort det. Du kanske kommer att gilla det. TypeScripts skapare Anders Hejlsberg (känd från C# och Delphi) kallade en gång TypeScript för en värdeproposition som det inte är rationellt att tacka nej till. Det har bara fördelar, inga nackdelar. Det citatet sammanfattar läget rätt bra enligt mig.

Jag är nöjd med TypeScript, men jag vill expandera gränserna och töja på min begreppsvärld. Vilken säkerhet och produktivitet lurar i andra språk? Företrädesvis språk med idéer om statisk typkontroll och andra säkerhetsmekanismer inbyggda från start. Under 2018 ämnar jag dyka in i Elm, PureScript, och Reason, för att see vad jag har missat från de statiska språken. Detta är miljöer där vissa av de fåniga småfelen vi ibland lider av i JavaScript inte händer alls, för att språket är designat så att de inte händer. (Om nu null var ett miljarddollarmisstag, så är en vild idé att använda kanske använda språk som inte har null?)

Det är inte "adjöss JavaScript", men det är definitivt "hej säkra alternativ". Det är dags.

Relaterade kurser

  • TypeScript

    TypeScript tar avstamp från JavaScript och gör det till ett säkert språk. Du får gradvis typcheckning, kodkomplettering, och statisk kontroll av hur din kod hänger ihop. JavaScript har aldrig haft det hårda skyddande skal som vi är vana vid i nutida språk. TypeScript agerar som ett programmerings-exoskelett, och ger dig säkerhet, uttrycksfullhet och precision ovanpå JavaScript. 

    Kursområde: Webbutveckling
    Omfattning: 2 dagar
    Kostnad: 21 500 SEK