onsdag 5 oktober 2016

GOTOconf Copenhagen 2016, dag 2

Jag har varit på GOTO i Köpenhamn i dagarna två och sitter nu på hotellrummet i väntan på morgondagens tåg hem. Tänkte som vanligt när jag varit på konferens dela lite minnesanteckningar och reflektioner...

Dag 2

Keynote: Small Is Beautiful - Kevlin Henney
Vi värderar möjligheten att slänga bort saker för lågt. 
Han pratade mycket om hur projektstorlek påverkar storleken på produkten som blir utvecklad (utan att det levereras ett större värde). Att när man tänker stort och börjar lägga till sätt att hantera komplexitet för problem som borde vara enkla. Även om FizzBuzz Enterprise Edition är på skämt så är det ofta som våra lösningar innehåller mer komplexitetshantering än problemlösning.


Disrupting Development using Reactive Event Sourced Systems - Jan Ypma
Visade hur de hade börjat använda eventsourcing som en väg för att trassla sig ur sina tillväxtproblem. 
Han hade en slide med krav på en fristående komponent. 
1) Inga utgående förfrågningar när man hanterar en inkommande (om databasen inte kan accessas utifrån kan den betraktas som intern i systemet).
2) Ingen single-point-of-failure.
3) Designen skall med triviala medel skala till minst 10x förväntat last, tex genom att dra i en slider på Amazon.
Den sista handlar om att om inte du kan hantera ökningen av last så skjuter du över problemet på någon annan och då är du per definition inte längre fristående. 

Microservices: A utopian mystery - Praveena Fernandes
Plockade 10 punkter ur ett projekt som hon varit i. Kanske inte så unika i sig själv men kopplat mot caset ändå intressanta med hur resonemangen gått och vad som hände när de gjorde på ett annat sätt. 


Educating the builders of tomorrow with science and technology skills using LEGO® Education WeDo 2.0 - Hanne Hylleberg Ravn, Flemming Bjørn Jessen
Jag kanske inte förstod det pedagogiska men kändes som en lång reklamfilm. 


Reclaim the stack: Why cross-functional teams build better microservices - Peter-Gillard Moss
Här hade jag en stund av koma och hade svårt att hålla mig vaken så min bedömning kanske inte är helt klar... men känslan var att det handlade mycket mer om teams än microservices. Inga noteringar.


Distributed - of Systems and Teams - Bridget Kromhout
Poängen gick mig helt förbi. Diverse anektoter men jag fick inget sammanhang eller idé om att det ledde åt något håll och gick därifrån undrande över vad jag sett. 

Sammanfattning av konferensen
Jag är på det stora lite besviken och tycker kanske inte att det konferensens fel i sig själv utan att jag kanske kunde läst på lite mer om vad talarna faktiskt skulle prata om. Jag hade hoppats på lite mer teknik och kanske lite mindre av team-building. Kanske lite mindre conways-law och mer kod. Det som var roligast för mig var fallstudierna med deras förväntningar och utfall. 

I sig själv var konferensen väl utformad med utställning, mat och dryck. Schemat höll och det kändes allt rullade på enligt plan. De flesta föreläsarna verkade vara kunniga i sina respektive ämne och ingen var helt borttappad på scenen. En detalj som de kanske hade kunnat utöka var möjligheten att ladda sina bärbara enheter där de hade små bås som kunde sitta i och till vilka ström var framdraget. 

Så, jag åker nog inte dit igen 2017. Det var för lite som när jag faktiskt skulle välja nästa föreläsning som faktiskt lockade mig. Men det kanske var lika mycket mitt fel. 



GOTOconf Copenhagen 2016, dag 1



Jag har varit på GOTO i Köpenhamn i dagarna två och sitter nu på hotellrummet i väntan på morgondagens tåg hem. Tänkte som vanligt när jag varit på konferens dela lite minnesanteckningar och reflektioner...


Dag 1


Öppning och Agile 2016 med Dan North
Outcomes creates options, om att faktiskt komma till leverans. Det är inte förrän folk faktiskt arbetar med en funktion som de bra idéerna om hur funktionen skall förbättras kommer.

Mycket Agil historia och ett något modifierat agilt manifesto med förflyttning mot hela tiden, i stället för regelbundet...

Han slog hårt mot kommersialisering av agila begrepp. Det finns inga agila arbetssätt, man är agil, följer inte en agil plan. Scrum-certifiering är världens största ponzi-bedrägeri.


The comming machine revoluition, Raffaello d'Andrea
Man har sett hans videos på nätet sedan tidigare med drönare som flyger synkroniserat, spelar pingis m.m. Berättade inte så mycket om hur det fungerade. 

Avslutade med att prata med faran som maskinerna utgör för människan nu när de blir smartare och smartare. Han är inte orolig alls för terminiator. Mer konkret däremot är han rädd att vi kopplar ihop system allt mer vilket kan ge upphov till ganska katastrofala feedback-loopar (ni som vet vad som kan hända om blixen slår ner i ett ställverk har en liten föraning om hur stor en sådan kaskad kan utveckla sig).

Monolithic batch goes microservice streaming – story about one transformation,
Anton Polyakov, Charles Tye

Visade hur de i ett projekt gått från relationsdatabas till eventsourcing för att lösa en applikation som testade de två senaste årens förändringar på en dags transaktioner... många nollor på antalet beräkningar som skulle göras.
Det stora de visade var att de använde en ramminnesdatabas för att utföra aggregeringar på stora datamängder. Man kan väl säga att det går att få in mycket data i ram nu för tiden.
Citat:
Building an app alongside the old one is an antipattern.
Turning spagetti to spagetti with a meatball. (om Microservices)

When DevOps Meets Regulation: Integrating 'Continuous' with 'Government', Jez Humble
Om de overthere kan sätta ihop ett team som kan ta fram gemensamma lösningar för flera myndigheter tänker man att hoppet kanske inte är helt förlorat här hemma heller. Mycket amerikansk förvaltning vilket kanske var intressant om man ska flytta dit. Sömnpiller för mig.
Cloud.gov 


Building an effective delivery culture, Stephen Foreshew-Cain
I stort sett samma samma som förra fast i Storbrittannien där han byggt en medborgarportal som väg in till ett stort antal myndigheter. GDS, ett kompetenscenter för myndigheter.


Exploring StackOverflow data - Evelina Gabasova
Här hade jag förväntat mig lite mer teknik om hur hon gjorde analyserna. Att det går ett bakgrundsjobb i F# som kan skanna av första raden i filer m.m. kändes inte så imponerande som hon ville göra gällande, men visst, det var en juste genväg. 
"Om du kan trycka in det i ram är det inte ett bigdata problem". Och stackoverflow fick hon inte i i minnet på sin bärbara, men den stationära hemma gick det bra.

Panel Discussion: The future of Robotics - Wouter Kuijpers, Dan North, Gregory Pelcha, Jørn Larsen, Marjon van ‘t Klooster
Här kändes det väldigt oförberett och närmast lite taffligt. Blev ingen diskussion. Fick svar på min fråga om vad som ligger runt hörnet för mig som vanlig människa (robotdammsugare och robotgräsklippare ganska vanliga inslag numera). Svaret var att jag förmodligen kommer att äta robot-stekt hamburgare på McDonalds. 

JavaScript, the Cloud and the Rise of the New Virtual Machine - Scott Hanselman
De här två dagarnas bästa framträdande, en ståuppshow på it-tema. Visste inte att Scott var rolig. Vet inte om jag fick med mig några lärdomar dock. 

söndag 2 oktober 2016

Ändra databasstruktur under drift

Här kommer en liten programmeringsövning till. Denna syftar på att använda mönster som låter dig ändra ditt system under drift.

Förberedelse:
1) Sätt upp en rest-tjänst som tar emot ett objekt (tex en postadress) och sparar denna i en databas.
2) Sätt upp en resttjänst som listar de 10 senaste adresserna ur databasen.
3) Skriv en liten applikation som skickar en en random adress och sedan listar de 10 sista adresserna, varje sekund så länge applikationen är igång.

Övningen:
Utan att störa din applikationen som skickar in och listar data (den ska ticka in en adress varje sekund medans övningen pågår), migrera databasformatet, tex slå ihop två fält som sparades som ett tidigare, eller dela informationen till två fält. Ändringen ska inte påverka informationen som går ut i rest-tjänsten.

Denna artikel kanske kan vara till hjälp, men det finns säkerligen fler sätt att lösa det på.

fredag 23 september 2016

En enkel övning

Den här övningen går ut på att implementera kraven i den ordning som de anges, utan att ta hänsyn till de krav som kommer senare. Du ska alltså inte implementera som om kände till samtliga krav från början utan bara ett krav i taget och sedan anpassa lösningen för varje nytt krav.

Du kan naturligtvis innan du börjar, sätta ramar för hur du implementerar, tex om ditt data ska vara på normalform eller någon form av blobbar. Övningen görs med fördel flera gånger, där du kan ställa upp olika ramar för den implementation du tänker göra för att sedan jämföra resultaten.

Du kan välja vilket gränssnitt du vill mot dessa krav, men tipset är att lägga minimalt med tid på gränssnittet och i fokusera på kraven i första hand. Unittester räcker väldigt långt.

Krav 1:
Implementera en enkel shoppingkorg. Du ska kunna lägga till en vara, ta bort en vara och lista varorna i korgen.

Krav 2:
Du ska kunna summera priserna på varorna i korgen. Du ska också kunna markera korgen som "klar", alltså markera att korgen har avslutats och inte längre kommer att uppdateras.

Krav 3:
För en given tidsrymd, beräkna den den mest sålda varan, både till antal och pris.

Krav 4:
En kundkorg anses vara övergiven om den inte har uppdaterats på två timmar. För en given tidsrymd, beräkna totalt värde på de övergivna kundkorgarna.

Krav 5:
Beräkna värdet på den vara som till antalet plockats in i varukorgen och sedan tagits bort ur varukorgen, alltså produkter som kunden visat intresse av men sedan aktivt valt bort (som extra krav skilj på avslutade och övergivna korgar)

Krav 6:
Om en kund har lagt 3 stycken av en vara i kundkorgen, ta bara betalt för två i prisberäkningen.

Krav 7:
Ge 50% på den billigaste varan om värdet på korgen överstiger 1000 kr.

Krav 8:
Ge 10% rabatt på dagens mest sålda vara om den sålts för mer än 1000 kr (när varan läggs i korgen).

Krav 9:
Ge 10% rabatt om det totala försäljningsvärdet före rabatter under innevarande timme överstiger 10000. Rabatten skall upphöra om ny timme påbörjats.

Som variant och överkurs kan du för varje krav skapa upp någon/några miljoner med varukorgar och sedan kräva att varje operation ska vara snabbare än 10 ms.

Man kan också göra övningen så att man tar höjd för alla kraven men stannar efter att man gjort några stycken. Är designen onödigt komplicerad och har du blivit sinkad jämför med den lösning de skulle ha gjort för en mindre uppsättning av krav? Kan du göra lösningen bra utifrån färre krav utan att det blir jobbigt sen?

torsdag 22 september 2016

Öva agila lösningmönster

När man får ett krav kan man implementera det eller så spenderar man en stund med att fantisera om vad som kan bli framtid krav. Ta tex en enkel shoppingkorg på en ehandelssida byggd på två tabeller, korg och varor där korgen innehåller information om vem som "äger" korgen. Korgen innehåller varor. Men när säljavdelningen kommer och säger att de vill veta vilka varor som kunden lagt i korgen men tagit bort innan köp kommer valet att implementera varukorgen med två tabeller kanske framstå som naivt och kortsiktigt.

Nu kan man förstås inte frångå kraven som ställts utifrån att man har en livlig fantasi där man kan föreställa sig ett antal framtida krav. Men det kan man göra är att känna till ett antal lösningsmönster och vilka vinster och förluster man gör med respektive lösning. Om man övat på dessa mönster kanske man ibland kan använda de lösningar som ger bäst möjligheter att hantera framtiden, vad den den nu kan tänkas ge oss.

I skrivande stund har jag två axlar som man kan variera sina övningar runt. Strukturerad/flexibel och stömmande/snapshot. Strukturerad/flexibel är mest utforskad inom programmeringsspråken där diskussionerna om dynamiska och statiska språk pågått länge. Diskussionen finns även i databasvärlden, då främst i konflikten mellan Nosql och relationsdatabaser.

Strömmande lösningar, tex genom eventsourcing syftar till att följa en ström av händelser och sedan agera på dessa, beroende på hur man väljer att bygga kan man återspela händelserna och agera på ett annat sätt då eller så är händelserna flyktiga. En snapshot-lösning håller ett tillstånd i systemet och uppdaterar detta tillstånd.

Ett mer traditionellt system lutar ganska tungt åt att vara strukturerat och av snapshot-karaktär. Man definierar typer och lagrar i tabeller i relationsdatabaser. I alla fall för mig är det mönstret jag kan och där jag känner till vägarna runt många många problem numera. Men som vi känner till finns det ibland godis i dynamiskta och strömmande lösningar men för att kunna komma åt det goda måste man öva, precis som vi gjort i många år med den traditionella lösningen.

måndag 28 mars 2016

Ett case till på immutability

Detta kanske är något krystat, men när jag gjorde det slogs jag av att det sättet jag gjorde det på åtminstone påminde om principer runt immutable infrastructure. Ja, inte i alla delar, men det påminde om...

Vad gjorde jag? Jo, jag bytte ut min gamla router mot en ny. Detta utan att någon tjänst stod still mer än några sekunder och med möjlighet att rulla tillbaka föregående steg.

Så hur gjorde jag detta då? Eller låt oss först börja med varför jag valde att göra på detta sätt. Svaret på den frågan är att jag inte kommit åt administrationsgränsnittet på den gamla routern på flera år då gränssnittet bara fungerar IE7 som var typ antikt när jag köpte routern. Alltså kände jag att det fanns en risk att jag kanske bara skulle kunna några tjänster till den nya routern och låta någon eller några få ligga kvar tills jag klurat ut vad jag behöver göra ytterligare.

Så, hur gjorde jag...

Steg 1
Koppla in den nya routern till ström (duh) och kolla att alla inställningar med portnummerserie m.m är vad jag förväntar mig. Aktivera trådlösa nätverk.

Steg 2
Koppla in den nya routern som slav bakom den gamla så att den nya når internet genom den gamla via sladd.

Steg 3
Kontrollera att den nya routern når internet och flytta över de trådlösa enheterna som jag telefoner, chromecast, skrivare och bärbara datorer så att de når internet (och varandra) till den nya routern.

Steg 4
Här är steget jag var mest orolig över att jag inte hade koll på vilken information som faktiskt gällde. Men jag satte upp port forwards mot det fasta ip-nummer som min server skulle få i det nya nätet. Flyttade sladden från den gamla routern till den nya och bytte ip-nummer på servern.

Tekniskt blev det två steg i ett. Hade jag vetat hur man gjorde hade jag föredragit att ip-numret hade varit orört så att jag kunna flytta sladden mellan routrarna utan att behöva ändra något på servern. Men riktigt så bra blev det inte.

Steg 5
Fram med skruvdragare och skruva upp den nya routern. Naturligtvis förbannar man att man var duktig och buntade upp saker snyggt förra gången eftersom alla sladdar är på fel ställe, för korta etc etc.

Steg 6
Flytta internetet från den gamla routern till den nya då inga tjänster längre antas gå vi den gamla routern.

Så, i princip (om än inte helt) så gick varje steg i processen att backa till det föregående. Tjänsterna var inte helt ovetandes om att de flyttats men brydde sig väldigt lite om vilken router som de faktiskt använde. Dessutom var båda routrarna igång samtidigt utan att ställa det för varandra vilket torde vara det mest centrala kravet för att kunna räknas som en immutable leverans.

Bara en liten notering ur verkligheten.

tisdag 22 mars 2016

Ett case på immutability

Jag sitter och pillar med en presentation som jag eventuellt ska hålla någon gång i framtiden. Kanske skulle våga mig på att spela in den här gången.

Till denna presentation behöver jag ett case på hur en applikation kan utvecklas om man tar Open/Closed-principle lite mer på allvar.

Steg 1
En entitet, Person. Fälten id och namn.
En tjänst, PersonRepository. Fem metoder, create, read, update, delete och list100AfterId. De fyra första slänger en händelse, PersonUpdated. Sparar data i en relationsdatabas, tabellen Person.
Vi produktionsätter.

Steg 2
Vi upptäcker en brist i PersonEntiteten, det borde vara separata fält för förnamn och efternamn. För att inte förstöra för alla klienter till PersonRepository väljer vi att skapa en ny entitet, Person2 och ett nytt repository Person2Repository som sparar i tabellen Person2. Person2Repository använder list100AfterId från PersonRepository för att synka upp existerande data. För att fortsätta vara i sync lyssnar p2r även på PersonUpdated-händelsen.
Vi produktionsätter, allt fortsätter att fungera som tidigare. Vi kan bekräfta att den nya tjänsten fungerar som den ska och successivt skriva om klienter från den gamla tjänsten till den nya.

Steg 3
Ett behov av att kunna söka efter personer har identifierats. Då vi inte vill förändra i Person2Repository då det också skulle kräva ändringar hos tjänstens klienter väljer vi att skapa en PersonSök-tjänst.
PersonSök använder list100AfterId för att bygga upp ett index (Lucene, Elasticsearch, egen tabell i databasen eller något annat). Vi väljer att inte smälta ihop PersonRepository och PersonSok genom att integrera dessa i databasen. PersonSok lämnar alltid en lista av PersonId som svar på en sökning.
Vi produktionsätter. Det gamla rullar på, det nya kan verifieras och klienter kan snart börja använda.

Steg 4
Vi ska en tid senare implementera en tjänst som kan hitta personer som är nära dig. Vi kallar den för NäraDig. NäraDig använder sig av PersonSök7 som låter dig söka på fälten senastKändaPosition och returnera PersonId sorterat på tidFörSenastKändaPosition. Efter sökning hämtas Person-objekt från Person14Repostitory. Eftersom sök-tjänsten kan returnera många svar är vi oroliga för om Person14Repository orkar med den förväntade lasten. Därför implementerar vi olika anrops-scheman, ett anrop i taget, x synkrona anrop i taget och alla anrop på en gång. Vi implementerar en feature-toggle för att kunna ändra schema utan att behöva stoppa några tjänster.

Steg 5
Det visar sig att Person14Repository inte har tillräckligt goda prestanda för att NäraDig ska kunna användas och att kundnyttan är för dålig om man begränsar antalet personer som man hämtar information om. Man väljer att öka prestanda i PersonRepository.
I p15r byter man databas, egenskapen man söker är att man kan öka prestanda genom att lägga till fler noder av databasen. Man skriver dessutom om så att alla anrop till metoden read hanteras asynkront så att en instans av p15r kan hantera flera hundra tusen samtidiga anrop till read-metoden.

Steg 6
Person har nu efter ett antal "förändringar" blivit en trång punkt. Man väljer att lägga till nya fält för ofta, vilket leder till att övriga delar av systemet måste följa med (och synkronisering över flera versioner över lång tid är pita). Inom Person-entiten identifieras ett flertal objekt, namn, adresser, telefonnummer, epost, positioner, arbetsplatser etc, etc. Så nu har vi en mängd med entiteter med lika många repositories.

Steg 7
Det visar sig att förändringarna i steg 6 blir dyra att implementera då varje klient behöver skriva om all funktionalitet som berör Person till att hantera en mängd nya objekt. Så vi inför en ny tjänst, PersonAggregat. PersonAggregat samlar ihop all information om en Person som vi bröt isär i steg 6. Klienterna kan nu välja att bygga sina egna Person-objekt eller använda det färdigbyggda aggregatet.

Steg 8
Verksamheten vill kunna ta ut rapporter från det data som systemet innehåller, men har noterat att vi har minst tre datakällor, den vanliga databasen, PersonDatabasen som egentligen är 10 databaser och sökindexet, vilket ställer till det för det valda rapportverktyget. Vi tar fram en datamodell och använder list100AfterId-metoderna för att fylla en rapporteringsdatabas. Uppsidan blir att man kan köra så mycket rapporter man önskar utan att störa produktionssystemen.

Det jag tycker är intressant i dessa steg är att de aldrig kräver att klienterna måste vara klara att använda det nya. Det problemet blir en administrativ fråga där man får väga problemet med att synkronisera datakällor mot att kunna gå frammåt.

Att vi helt undviker att utföra joins i databasen och i stället väljer att ha en aggregat-tjänst som gör joinen mycket senare och som tillåter underliggande struktur att förändras är också värt att notera.

Detta är bara ett hypotetiskt case. Många frågor måste lösas. Tex om vi har flera versioner av en tabell, vilken är sanningen och hur upprätthåller man den? Eller hur ska händelser propageras på ett rimligt sätt?

onsdag 24 februari 2016

JFokus 2016

Jag var på JFokus 2016 och här kommer mina anteckningar och lite allmänna kommentarer. Jag gör ingen ansats att fylla ut anteckningarna till en ordentlig text, så ta det för vad det är, anteckningar.
Måndag
Chris Richardson - Introduction to microservices.
Elefanten och ryttaren, om hur vår hjärna fungerar.
The art of scalabiliy, bok
Det är olyckligt att de kända exemplen på microservices främst handlar om high-scalability.
Fred George, testning in production.
Microservices kräver agile och devops...
Antipatterns:
*Nano-service
*Distributed monolith

Aron Gupta - Docker & Kubernetes 
Inga anteckningar

Tisdag
Brian Goetz - Keynote
Java 10, immutable var det stora nya.

Holly Cummins -  Microservices: dream to reality
Don't unless you have devops.

Petter Måhlen - Modelling microservices at Spotify
Squad äger en "funktion" från DB till Gui.
System Z för att hålla ordning metadata
Scaling of the team drives microservices more than perforamace?

Bert Ertman - Microservices for mortals
Var inte naiv, du måste först vad du gör.

Ivar Grinstad - SnoopEE
SnoopEE kanske kan vara något för min nuvarande kund.

Kristoffer Erlandsson - Fault tolerant microservices
Relase it
Hystrix
Circuit breakers
Bulkheads
Har du inga nätverksproblem, mäter du fel.

Kathrine Stanley -Testning microservices
Inga anteckningar

Onsdag
Tim Berglund - Git from the bits and up. 
Läs Beowulf

Barush Sadogursky - Docker container lifecycles
Every plays with docker but noone gets to production
Docker images is just another artifakt, like jar-files.
The promotion pyramid. The promotion pipeline. Quality gates.
Build only once, including the Docker packaging. Only once. Only once, only once.
Arifactory metadata kan användas för att visa vilka qualitygates som passerats och dess resultat.

Rafael Winterhalter - Making java more dynamic
Använd agenter i stället för ramverk. Skriv plain old java applikations instead of EE, spring etc.
Bytebuddy

Manuel Bernhart - Reactive web applikation
(inga anteckningar)

Markus Esiele - CI Docker and JEE
Fabric8 kanske kan vara skoj om man vill gå redhat.

Sammanfattning
Devops är förutsättningen för microservices. Med egen drift eller molnet spelar ingen roll. Applikationsdriften sköts av utvecklingsteamet.
CD som en del av devops är förutsättning för microservices.
När du har CD och devops på plats, kan du börja med microservices.
Storleken på utvecklingsteamen driver Microservices lika mycket som prestanda.
Kunskap är viktigt, microservices kräver kunskap så att verkligen vara engagerad i ämnet är viktigt. Akta sig för hypen. Även om det finns verktyg så måste du känna till begränsningarna och fallgroparna.
Lite synd om Holly Cummins vars dator inte fungerade. Arun Gupta kändes trött och oinspirerad jämfört med vad jag sett tidigare.


fredag 12 februari 2016

En agil mjukvaruarkitektur

En agil mjukvaruutveckling brukar beskrivas som att man låter programvaran växa genom evolution i stället för genom en förutbestämd plan. Man hävdar alltså (korrekt) att det är svårt att i förväg förstå vilka konsekvenser beslut om en applikation får, förrän man faktiskt upplever hur det fungerar i "verkligheten", alltså när det är implementerat och klart.

Så, om du är agil så ska du göra fel, ändra, se att det fortfarande inte är bra och ändra igen. När du är klar med detta så ska du välkomna förändrade krav. Men i de projekt jag har jobbat i har man ansett att en utforskande ansats är för dyr, eftersom det är svårt att förändra när saker väl blivit skrivna. När kraven förändras väljer man ta långa omvägar för att det är så svårt att ändra i det man redan har. Med andra ord väljer man bort ett agilt förhållningssätt och lägger stor möda på att försöka att göra rätt på första försöket.

Jag ska nedan försöka beskriva några mönster och dess möjlighet till att göra det lättare att arbeta agilt. Dessa mönster kommer inte gratis på något sätt. Man kan se det lite som att med dessa mönster hoppas man på en komplexitetsökning som ser ut som O(log n) där den traditionella modellen något elakt skulle efterlikna O(n*n) (n i kvadrat alltså). Dock så börjar den agila modellen med en mycket större insats i kunskap och stödjande tjänster för att inte leda till katastrofens rand. Vet du inte vad du gör är det läge att låta bli och inte härma de som faktiskt vet vad de gör och varför.

Microservices
Med microservices väljer man att dela upp sin applikation i många små fristående delar i stället för en. Varje microservice blir simpel men man blir inte av med komplexiteten, utan den flyttar ut i nätverket där man hoppas att den ska gå och hantera på ett bättre sätt. Microservices stödjer det agila arbetssättet genom att du kan byta ut en microservices relativt enkelt utan att påverka resten av systemet och du är fri att ta beslut om hur din microservices ska fungera internt utan hänsyn till hur de andra är implementerade, kanske byta till ett mer lämpat programmeringsspråk, uppgradera bibliotek etc etc.

Prestanda brukar vara den brukar beskrivas som  drivkraften för microservices, men jag skulle hävda att möjligheten till att olika utvecklingsteam kan arbeta utan att påverka varandra är mycket starkare i normalfallet (Amazon och Netflix är inte normalfall)

Eventsourcing
Med eventsourcing sparar du ditt data utifrån vilka förändringar som har gjorts i systemet (verben) i stället för att lagra entiteter (substantiven). Man kan jämföra med en läkare som har sparat din journal (med alla undersökningar, prover och anteckningar) och använder den som grund för att ställa diagnos och väljer att inte ordinera jordnötter eftersom det står att du är allergisk i journalen till motsats till en akutläkare som ser att blodet sprutar och får utgå från det hen kan se just nu.

Med eventsourcing har du inte en modell utan snarare en modell per händelse och en modell per slutsats eller rapport du önskar skapa från dina händelser, även om du naturligtvis kan ha en övergripande modell någonstans i bakgrunden. Flera modeller gör det svårare att hitta hur ett enskilt attribut kom till världen men som å andra sidan gör att du kan anpassa dina modeller efter olika behov i stället för att anpassa behovet efter modellen. Attribut som tex rubrikfärg har jag sett många gånger krypa in i tex en person-entitet eller telefonnummer-entitet där man kanske hade varit mer betjänt av att ha en modell över presentations-stöd och en annan över domän-information. Så i stället för att ha en modell där en förändring påverkar all annan funktionalitet väljer man att kunna förändra en funktions modell separat från de andra. Notera att detta kan innebära en hel del dubbellagring av data och synkronisering av detta data måste ske på ett kontrollerat sätt.

Immutable
Att vara immutable innebär att man aldrig modifierar sitt data, man lägger bara till ny information till systemet. Det kanske låter som lite slöseri med hårddisk men det ger en del intressanta möjligheter, främst att du får möjlighet att titta på hur ditt data såg ut vid en tidigare tidpunkt. Som extra bonus blir cachning enkelt, eftersom den information som finns där aldrig förändras (det kommer ny information naturligtvis, men de gamla värdena är orörda).

Man kan dra immutable-begreppet längre än data och ta in begreppet immutable-everywhere. I princip innebär det att du aldrig ändrar i integrationer, du skapar en ny och den gamla får leva vidare tills det är säkert att ta bort den. Du ändrar aldrig i dina installationer på dina servrar utan gör en ny och låter den gamla leva vidare tills det är säkert att ta bort den gamla. Det ger bland annat möjlighet att skapa en ny integration till en ny klient som innehåller alla de senaste funktionerna, samtidigt som övriga klienter kan fortsätta att använda den gamla tjänsten tills de är redo att uppgradera. Drar man den tanken till sin spets får varje klient sin egen tjänst och kan där med förändras oberoende av andras behov.

Även vid serverdrift, särskilt i mer eller mindre virtuella sammanhang kan man välja att skapa en ny "image" som kan driftsättas parallellt med den gamla installationen och testas om den fungerar i produktion på en delmängd av trafiken innan man "pekar om" alla användare till den nya servern.

Automatisering
Människan är ganska dålig på att utföra repetitiva uppgifter och detta leder till ett kontrollbehov, eftersom vi kort och gott inte är att lita på. Detta leder till ett behov av kontrollstrukturer som i sig själva driver behovet av fler människor som ska utföra alla kontroller och i sin tur kontrolleras och ingen tillför värde för användaren av systemet (åtminstone inte direkt).

Vägen ut ur detta är automatisering. Efter att ha kontrollerat att automaterna(?) fungerar (tex gör rätt sak vid feltillstånd) kan de släppas lösa. Eftersom du kan ha ett större förtroende för att saker och ting fungerar kommer du också våga att förändra och förbättra i dina system. Detta leder till att ditt system blir större efter som fler uppgifter behöver programmeras och underhållas.

Sammanfattning
Att vara agil är så mycket mer än att ha en iterativ process. Det handlar också om att inte bara vara en döv, stum och blind idiot för vad kraven på systemet säger idag utan även för vad de kan komma att säga i morgon och förutsätta att saker kommer att förändras. Att placerat sig i en position där man kan välkomna förändringar även sent i projektet.

De mönster jag skrivit om ovan kommer inte gratis utan är dyra, både i tid och kunskap. De löser vissa problem men för med sig många andra som du också måste förstå innan du börjar, oavsett projektstorlek. Men när du börjar få problem med att du inte längre kan anpassa ditt system snabbt och smidigt kommer du önska att du tittat på ovanstående mycket tidigare.

torsdag 4 februari 2016

En ny skön värld

Ibland får man uppenbarelser, en känsla av att man förstått något och nu vet hur en aspekt av världen fungerar och varför det är som det är. Allt är självklart och nu är det dags att agera och inte svamla något om kanske och eventuellt.

Professionellt som programmerare är det ganska långt mellan varven som jag upplevt detta men nu de sista 1-2 åren har det hänt ganska ofta. Begrepp som
* händelsebaserat
* immutable
* functional
* reactive
* single responsibility
* continious delivery
* micro services
har allt gått som en blixtar genom mitt huvud.

Det är inte så att jag levt i en bunker isolerad från omvärlden. Det är inte nytt, men en förståelse för vad de faktiskt innebär och vad var de hör hemma har kommit till mig (hoppas jag i alla fall).

Den senaste blixten i allt detta är insikten att ingen av dessa är fantastisk i sig själv utan att de tillsammans bildar en helhet. En ganska radikalt annorlunda helhet än den vi är vana med men ändå en helhet som tar sin utgångspunkt i reaktion. Detta kanske motställt till den traditionella modellen som åtminstone i praktiken fokuserar på planering och förutsägelse.

tisdag 29 december 2015

Är transaktioner blott en historisk parantes?

Jag har haft förmånen att få jobba med folk med erfarenhet ett antal gånger, jag menar närmare 50 års erfarenhet av programmering. Det som jag ofta hör, när dessa erfarna personer beskriver hur de gjorde förr, är det vi försöker att åstadkomma nu. Vi har bara varit ute på en utflykt, en normaliserad och transaktionstät utflykt, men just bara en utflykt.

Min tes är att någon gång i samband med att vi fick tillgång till RDBMS så slutade vi hantera två viktiga aspekter av vår programvara, tid och felhantering.

När man förr tog en fil (eller två) som indata till sitt program körde sitt program och producerade en ny fil var det data man hade i praktiken immutable. Om man upptäckte ett fel i programvaran kunde man kör det uppdaterade programmet utifrån de gamla filerna. Om man sparade sina filer hade man ett arkiv över alla förändringar man gjort på sitt data. Tiden var kanske inte lika mycket "up your face" som den är i eventsourcing, men den fanns där. Att modellera med tid på ett normaliserat sätt är ingen barnlek någonstans, för beroende på vilket delsystem som körs har de olika och ofta motstridiga krav som är väldigt svåra att slå ihop.

Vilket leder oss till nästa del av min tes. Förr, när man hade kört ett jobb och kontrollerade om det gått som det skulle, då fick man hantera vad som skulle hända. Om något gått fel tex fick någon besluta om att köra jobbet en gång till, tillkalla utvecklaren eller kanske till och med börja om från en tidigare tidpunkt. Det är lite som att lägga ett meddelande på en kö, man får välja hur man vill hantera om något gått fel, tex göra omskick, låta meddelandet dö, eller notifiera tjänsten som skickade meddelandet. I vilket fall är detta något som måste hanteras.

I dagens system tappar vi bort tiden eftersom vi glatt skriver över och raderar värden i vår databas utan information om vem, när eller varför. Om något går fel gör vi en rollback och tappar all information om vad som gjordes. Smidigt många gånger, men våra system är inte så flexibla på att möta nya krav och vår kompetens i hur man hanterar olika problemsituationer är låg.

Med tekniker som eventsourcing och microservices behöver vi återigen lära oss att leva utan den alltid närvarande transaktionen och vi måste lära oss att hantera problemsituationer på fler sätt än att rulla tillbaka en transaktion.

tisdag 22 december 2015

Fördomar inom mjukvaruutveckling

Jag fick en gång lära mig att fördomar kommer ifrån att vi människor inte är tillräckligt smarta för att kunna hantera allt i världen individuellt, utan istället måste generalisera och begränsa den information vi hanterar. Så det är lönlöst att bekämpa fördomar, de är ett nödvändigt redskap för att vi ska fungera. Men det vettiga personer gör, regelbundet och ofta, är att ifrågasätta sina fördomar och sprida dem med stor försiktighet. Så i stället för att säga att "så är det" kanske man använder uttryck mer i stil med "i min erfarenhet" eller liknande.

Med detta intro tänkte jag utforska den som jag upplever den största fördomen inom it, nämligen att dubbelt är dåligt.

Sedan jag började med programmering har jag fått lära mig kod ska organiseras på ett sådant sätt att man inte behöver skriva samma logik två gånger. Det är egentligen inget att ifrågasätta om det gör korrekt, men i korrekt ligger haken. För hur identifierar man vad som är samma logik och vad som inte är det?

En tanke man kan ha i bakhuvudet när man ska eliminera duplicerad kod är att en dålig abstraktion är dyrare än duplicerad kod. Med det menas att om du har tagit ett beslut om att slå ihop funktioner som ligger utspridda i systemet till en enda, då bör du inte bara vara säker på att den kod du refaktorerar representerar samma logik idag, utan även i morgon. För hur ska du hantera att en funktion som är beroende på din funktion i morgon har önskemål på en liten variation i din funktion? Duplicera din funktion och modifiera kopian? Lägga till en if-sats?

Problemet omfattas av single responsibility pattern. Din kod ska bara ha en anledning att ändras. Så om ekonomiavdelningen vill se vissa attribut på en produkt som inte får visas till kund på webben (täckningsbidrag tex) kan det vara bättre att ha två olika produktklasser, anpassade för sina respektive behov och inte riskera att ändringar i en ände av koden påverkar något annat.

Mitt andra exempel på "dubbelt är dåligt" är runt lagring. Vi anstränger oss bland annat hårt för att normalisera våra databaser så att inget data ska finnas på mer än ett ställe och det är först när vi tvingas av prestandaskäl som vi bryter "dubbelt är dåligt" och då oftast genom att använda en cache.

Men precis som med duplicerad kod är det en god idé att ifrågasätta om den enda datamodellen är den rätta. Tänk en ansökan som ska gå igenom en process, där olika attribut i datamodellen är relevanta beroende på var i processen du är. Ansökan har kanske ansökta uppgifter, bekräftade uppgifter, beslutade uppgifter och ett antal uppgifter som är relevanta för alla tre stadierna. Alla attributen tillhör en ansökan och refererar till samma identitet så det är samma ansökansobjekt. Kanske det då kan vara bättre att ha tre separata objekt, som representerar sitt respektive tillstånd, trots att ett antal uppgifter då blir dubbellagrade, att bara de uppgifter du behöver är tillgängliga och de uppgifter som är brus är borttagna ur scopet.

När man börjar gruppera sin modell efter vad man ska göra kan man få en modell där samma objekt dyker upp flera gånger men med olika attribut beroende på vad man ska göra. Den stora vinsten med detta tänk är att man designar bort många missförstånd genom att eliminera möjligheten att använda attribut som inte är relevanta. Å andra sidan måste man snurra igenom och sammanfoga de olika varianterna till en rapport för att kunna se tex hur många objekt man har och vilket tillstånd dessa objekt är i då data inte är lagrat på ett enda sätt längre. Som jag skrivit någon gång tidigare, komplexitet försvinner inte utan du kan bara välja hur du vill hantera den. Men jag vågar påstå att anpassa objekt till situation är en möjlighet vi slagit dövörat för då vi varit rädda för att dubbellagra information.

lördag 19 december 2015

Om inget får ändras

Om man ska utveckla ett "modernt datasystem", nu i slutet av 2015 kan man inte undvika termen immutable.

De enda anledningarna till att bygga något med mutable state är prestanda givet några  specifika krav och ohejdad vana. Men faktum är att vi inte haft datorer förrän kanske de 10 (?) senaste åren där vi faktiskt kunnat hantera immutable state på ett sådant sätt att vi kunnat dra nytta av det till vardags. Vi har tex inte haft minne nog för att inte välja att återvinna det vid första tänkbara tillfälle och hårdvara har varit dyrt. Så, trots att det finns mycket forskning i ämnet har det bara varit akademiska övningar. I praktiken var vi tvungna att använda alla trick och möjliga optimeringar vi kunde och därav har lösningar och processer varit mutable.

Men idag med servrar där terrabytes av ramminne är och petabytes av långtidslagring är möjlig har vi en helt annan situation och dåtidens krav på optimeringar är idag är ofta kontraproduktiva. För som ni vet, optimeringens första lag: optimera inte förräns du faktiskt vet att det behövs, gäller fortfarande.

Det finns ett antal dåliga aspekter med låta saker ändra på sig i systemet och det spelar i sak inte roll om vi pratar om integrationer mellan system, installationer av system eller ett värde på ett fält i en klass. De ger alla problem med synkronisering och om du ändrar en del av systemet (oberoende var) riskerar du att ställa till det för en annan del av systemet. Och synkronisering är svårt, väldigt svårt och vi behöver inte ens ha ett flertrådat system för att få problem med mutable state.

Så, finns det någon bra lösning på detta som inte introducerar en massa ny komplexitet? Svaret är naturligtvis nej, men vi kan välja att hantera en annan komplexitet som vi tror att vi har större möjligheter att bemästra.

En sådan lösning skulle kunna vara att enbart lägga till information i systemet och aldrig inom ramen "den dagliga verksamheten" radera (inte ens uppdatera) existerande information. Ändra inte värden på objekt, skapa nya. Ändra inte i listor av värden, skapa nya listor, ändra inte i existerande tjänster, skapa nya tjänster, ändra inte i integrationer, skapa nya.

Med tekniker som immutable infrastructure så finns det ingen gräns för att "inte ändra, skapa nytt", utan det handlar mer om den mognad som din organisation har för vad som går att realisera och vilka steg som är möjliga för att förbättra situationen. Om det tar tex din driftsavdelning 4 veckor att sätta upp en " ny" server som kan köras parallellt med den gamla tills den gamla blivit utfasad, ja då har ni en resa framför er. Andra saker som att ta bort alla setters från dina klasser och bara initiera genom konstruktörer och factories kanske är ett enklare steg.

Vad blir vinsten med att bara lägga till ny information i ditt system? Du blir av med synkroniseringsproblemet. Bara en sådan enkel sak som att en yttre loop inte behöver vara orolig för att en inre loop ändrar på förutsättningarna för den yttre är värd mycket. I andra sammanhang tillåter oförändringsbara objekt en närmast oproblematisk cachning, för du behöver aldrig invalidera förändrade objekt för att något har ändrat på det, bara lägga till nya. Historik blir enkelt när du inte har skrivit över den gamla informationen.

Ja, så summa summarum, har du och stället du arbetar på inte börjat att ta till er ordet immutable på allvar i hur ni arbetar är det hög tid att göra det nu. Det finns mycket att läsa och ämnena är många, allt från funktionella språk till eventsourcing till docker containers. Men allt landar i att mutable state borde förpassas till historien, tillsammans med mänskliga computers, hålkort och goto.

Memory lane

För någon vecka sedan återupptäckte jag den här bloggen som jag började skriva i samband med att jag läste Robert "Uncle Bob" Martins bok "Clean code".

Ja, det blev några blogginlägg och jag drog igång Jönköping Developer Dojo i processen. Det var roligt att läsa igen och väckte en hel del minnen.

Det har runnit en hel del vatten under bron sedan dess så jag tänkte försöka att dela med mig av en del erfarenheter jag har tagit med mig sedan dess, om sådant som inte gått så bra och om sådant som har gått bra och förmodligen en hel del av sådant jag skulle vilja göra nästa gång jag får bestämma över hur saker ska göras.

Ord som  immutable, simple, complect (nej, inte complex), essensial complexity, monolit m m kommer säkerligen att dyka upp lite här och var.

Ja, nu får vi se hur detta går. En ambition har blivit nedskriven i en blogg. Återstår att se vad det blir för resultat.

lördag 8 oktober 2011

Olika typer av xUnit-tester

Jag fick ett ett uppdrag av jobbet för någon dag sedan och har funderat lite på det och tänkte att jag skulle skriva ner lite tankar runt detta så att jag kanske kan komma ihåg det. Det vi ska försöka att åstadkomma är ett gemensamt tänk runt automatiska tester på xUnit-formen.

Som de flesta som har läst lite om tester automation vet är det mycket billigare att rätta ett fel direkt än om man väntar en dag, eller en månad. Tar det tid innan man rättar felet har man hunnit glömma mycket om vad det var man skulle lösa och hur man resonerade när man skulle lösa det. Koden som blir kvar blir ett dokument på hur det är löst men säger inte så mycket om varför du valde den ena av två lösningar. Det skulle bli hela romaner i kommentarerna om man skulle få med de typen av information.

Hur drabbar detta dina tester. Jo, det ger att du vill ha snabba tester som du kan se till att de körs i samband med kompilering. Det är då du vet vad du har gjort och vad det är du har ändrat. Det finns en regel som säger att du bör kunna köra åtminstone tusen tester på en sekund för att de ska räknas som snabba. Det innebär i de allra flesta fall att dina tester inte har tid att vänta på en sql-fråga eller webbservice-anrop.

Men ibland vill man trots allt testa sina integrationer och även få en "hela vägen" känsla för att det fungerar. De snabba testerna kommer att per definition bara testa små fragment av din applikation. Många små tester kan testa hela applikationen men om du inte börjar med en strikt tdd-approch kommer det målet vara väldigt svårt att uppnå och många gånger även väldigt dyrt. Det kan alltså vara idé att ha en uppsättning med tester som där det är tillåtet att testerna får ta tid. Dessa skulle förslagsvis köras på natten i en bygg-server.

Vi har alltså behov av två testbibliotek för våra xUnit-tester. Snabba och långsamma. Jag kan dock se behov av ett tredje bibilotek med tester och det är integrationstester. Med integration i detta fall menar jag den integration som inte kan fungera likadant i utvecklar, byggmiljö som i produktionsmiljö. Saker som skulle kunna separera ett test från de andra är att ett anrop måste göras över en vpn-tunnel och att detta inte går att lösa i de långsamma testerna. Alltså att ett manuellt arbete måste utföras vilket man inte kan kräva att det görs varje natt.

Så för att summera. Jag kommer att rekomendera att vi från nästa beslutspunkt har två obligatoriska xUnit-projekt i våra lösningar och i dessa organiserar våra tester. Detta för att kunna fånga så många fel som möjligt i tidigast möjliga skede utan att för den skull offra möjligheten till att ha långsamma "täcker allt" tester där de kan vara lämpliga. Om man önskar kan man naturligtvis ha flera av varje testtyp men det är testprestanda som bestämmer i första hand.

torsdag 12 maj 2011

Seven languages in seven weeks - Erlang

Det femte språket i boken Seven Languages in Seven weeks av Bruce Tate är Erlang. Ett språk som togs fram av Ericsson då inga andra var bra nog. Erlang har ett par designmål som skiljer det från andra språk. Det hanterar väldigt många saker parallellt. Språket är tar även ett annat grepp på felhantering som kort och gott går ut på att det är helt ok att en process dör ibland.

Erlang - dag 1
Erlang har fått en del inspiration från Prolog. Faktum är att man började med att modifiera Prolog för att få det resultat man önskade. Så mycket av syntaxen är relativt lik. Man har tuples, atoms. Men inga objekt.

Erlang är trots att det är ett högnivå-språk lämpligt att köra hårdvarunära då det finns stöd för att manipulera bits och bytes. Erlang dessutom ruskigt stora tal naturligt. Så många siffror du får plats med i minnet.

Precis som med Prolog använder man rekursiva strukturer för att lösa problem.

Erlang - dag 2
För en Java-utvecklare är annonyma funktioner inget nytt. Även om det skiljer en del mellan den objektorienterade approchen och den i Erlang. Dock blir det lite mer spännande i Erlang som som är dynamiskt typat. Funktionen du får kan ju vara vilken funktion som helst.

En styrka med annonyma funktioner är att du precis som i Ruby kan skriva en funktion som du kör på varje element i en lista och du kan enkelt återanvända dina funktioner på vilken lista som helst.

Erlang - dag 3
Dag tre går igenom de parallella verktyg som Erlang har. Principen är väldigt enkel och bygger på koncepten om Actors och Messages som vi sett tidigare. Det finns några inbyggda sätt att skapa processer och att skicka meddelanden till den kö som varje process är utrustad med. Sedan kommer processen att beta av kön ett meddelande i taget. Det är höggradigt asynkrona meddelanden som skickas så vill man åstadkomma synkrona meddelanden får man ta till lite trick, men i princip får man vänta på att man får ett asynkront meddelande tillbaka. I princip kanske man kan säga att alla applikationer man bygger i princip blir som en liten svärm med webservrar som löser var sin uppgift.

Felhantering i Erlang går i mångt och mycket ut på att låta saker dö. Tricket är att inte hantera något tillstånd. Alla funktionsanrop bär med sig all information den behöver och nästa anrop kommer, förutsatt att samma information skickas in, ge samma resultat. Poängen med detta är att det lättare att döda en process och starta den igen om något blivit sjukt än att försöka att hantera fel. Den nya processen kommer att ge samma resultat som den gamla så det är ingen som kommer att bry sig kort och gott.

Jag är lite besviken på kapitlet om Erlang. Jag känner att jag saknar kopplingen till verkligheten. Kapitlet kändes akademiskt. Jag förstår att tillstånd är något som är dåligt om man vill hantera många saker samtidigt men samtidigt så har de flesta applikationer jag träffat på små beroenden på vad klockan är, eller hur många som är inloggade. Var tar all denna information vägen i en Erlangapplikation?

Jag har en teori om den här boken. Den är inte till för att ge en översikt på ett antal språk så att man ska kunna jämföra dem och kanske välja ut ett för att lära sig "på riktigt". Bokens syfte är att lära ut funktionell programmering, men genom att sockra med Ruby som objektorienterat språk och Io som är likt javascript så märker man inte hur man sakta lär sig funktionsbaserat tänkande.

fredag 6 maj 2011

Seven languages in seven weeks - Scala

Dags för språk nummer fyra ur boken Seven languages in seven weeks. Nu blir det Scala. Ett språk som många ser som språket som kommer att Java som huvudspråk till JVM. En av fördelarna med Scala är att det är kompatibelt med Java. Har du 10 år av kod med dig från Java så behöver du inte börja med att skriva om den utan du kan återanvända dina favoritfunktioner från Scala.

Scala - dag 1
Första dagen med Scala var rätt trist, lite syntax varav det mesta känns igen från de flesta c-derivat. Så det var inte mycket som kändes nytt. Det som var lite intressant var att man valt att ha mixins eller moduler (ruby resp io) och för att förvirra lite kallar dem för traits. Jag hoppas på en roligare dag två :)

Scala - dag 2
Idag har vi gått igenom Scalas nyckelord var och val. Skillnaden mellan dessa är om variabeln som deklareras är mutable (kan förändras) eller inmutable (kan inte förändras). Genom att ha stora delar av sin kod inmutable kan man utradera mycket av de problem som objektorienterade språk har med parallell körning, tex över flera processorer.

En stor del av kapitlet ägnas åt Scalas collections. Dessa är i mångt och mycket också uppbygda runt inmutable objects. Tex om du lägger till ett objekt i en lista får du tillbaka en helt ny lista i stället för att behöva oroa dig för om din lista har förändrats på oväntat sätt. Jag uppfattar det som kanske något ineffektivt men förstår att vinsten kommer när man börjar arbeta med parallell bearbetning.

Scalas collections kan användas i vanliga for-loopar men tanken är att man ska använda dem funktionellt. Alltså finns det sätt att skicka in en funktion som ska köras på alla objekt tex på din lista.

Scala - dag 3
Under dag 3 visades den inbyggda xml-hanteringen där xml kan definieras som vilken variabel som helst.

Patternmatching är en funktion som lite kan jämföras med de logiska vilkoren i prolog.

Parallellism i Scala liknar till viss del den i Io då den använder actors och meddelanden.

Lite sammanfattning om Scala.
Jag uppfattar Scala som en utveckling av Java där man kunnat släppa kravet på bakåtkompabilitet som finns. Så att byta ut trådbaserad parallellsim mot actors. Införa inmutable objects och functionalism m.m. Trots allt detta nya så kan man ändå återanvända sina gamla javabibliotek. Det är ganska trevligt tycker jag.

lördag 30 april 2011

Seven languages in seven weeks - Prolog

Det tredje språket i boken Seven languages in seven weeks är Prolog och det är det första språk i boken som jag faktskt provat då det var en av programmeringskurserna på högskolan. Då tyckte jag prolog var ganska roligt.

Prolog - dag 1
Prolog är baserat på fakta och regler. Det som skiljer prolog från de tidigare språken i boken är att du inte talar om för Prolog hur dessa fakta och regler ska behandlas. Det fixar Prolog själv. Det enda du behöver göra efter ha matat Prolog med fakta och regler är att ställa frågor och Prolog svarar. För ett antal applikationer ger detta fantastiskt små och överskådliga program.

Prolog - dag 2
Dag 2 handlade mest om rekursiva anrop och listor. Att med hjälp av en rekursiv logisk regel summera ihop värdena i en array ställer begreppen lite på huvudet. Jag förstår vad som händer men jag känner att jag har en lång resa innan jag skulle komma på själv att jag skulle behandla en array på det sättet. Det ser synnerligen inneffektivt ut med alla rekursiva anrop men man har tydligen lyckats att optimera för det.

Prolog - dag 3
Prolog har några styrkor och en av de mest uppenbara visades med ett exempel av hur kort ett program blir som löser soduko. 25-30 rader med logiska regler, sedan är det bara att köra. Det är så att jag kommer på mig att undra om det inte finns prolog-motorer för java eller .net som man skulle kunna använda på de problem som man kan beskriva med logiska regler. För på rätt problem hinner du inte starta kompilatorn i Visual Studio innan Prolog har levererat en färdig applikation.

Allt är inte lätt och smidigt i Prolog men jag kan definitivt se att det finns många problem där man skulle ha mycket att vinna på att hitta en prolog-inspirerad väg till lösningen. Att inte beskriva lösningen utan att beskriva problemet är ibland mycket enklare helt enkelt.

Tyvärr är Prolog gammalt och inte speciellt utvecklat för att köras över flera trådar, flera processer etc etc. Det gör att jag känner att det här kapitlet mest har varit en teoretisk övning. En mycket intressant tankeexperiment men jag kommer nog inte att ta den vidare till någon mer användbar nivå.

torsdag 21 april 2011

Seven languages in seven weeks - Io

Då var det dags för språk nummer två. Jag tror väl inte att jag klarar att hålla ett språk i veckan nu jag har det första språket som facit. Det andra språket heter Io, ett namn som gör det svårt att söka på. Io Language ger lite bättre träffar men det är ett illa valt namn.

Io - dag 1

Io är inte ett objektorienterat språk som Ruby, Java eller C# även om det finns objekt. Io är likt Javascript protoyp-baserat. I sak handlar det om att man i stället för att skriva klasser som man har som fabrik för att skapa objekt så kopierar man existerande objekt och använder dessa som mall.

Precis som med första dagen för Ruby så har vi gått igenom lite syntax. Precis som med Ruby så använder Io få paranteser och något som gör Io lite mer annorlunda syntaxmässigt är att man inte heller håller ihop objekt och egenskap med punkt. Det gör det lite svårt att läsa Io-kod för mig då jag inte riktigt lyckas lista ut om det är objekt, metod eller egenskap som jag tittar på. Något som osökt leder mig in på nästa egenskap för Io.

Allt är objekt. Man gör kort och gott inte skillnad på om det är en metod eller egenskap som du arbetar på. Kanske något förenklat man kan säga när du begär att få ett värde från en egenskap så körs det en liten metod som returnerar den egenskapen och om en metoden är en rad eller hundra som i sin tur anropar hundra andra spelar ingen roll.

Vad mer att säga från första dagen med Io. Jo, syntaxen är väldigt avskalad. Syntaxsocker existerar inte eller kommer i väldigt små mängder.

Dags för dag två.

Io - dag 2
Dag två handlade mycket om att använda de slots och även att ge en insikt i att allt som sker i Io är en form av meddelanden.

En av konsekvenserna av att Io är uppbyggt som det är ger att du kan modifiera väldigt mycket, tex är alla operatorer som ==, < etc metoder, något speciella metoder men i princip som vilken annan metod som helst.

Meddelanden tog mig en stund att förstå, jag läste sidorna både tre och fyra gånger innan jag lyckades förstå vad det var som hände. Känns ganska självklart nu så jag kanske hade en dålig dag :-). Kort och gott är i princip alla anrop i Io ett meddelande och meddelanden har en avsändare, mottagare, namn och argument. Att ha kunskapen om vem som anropar, och vad som anropades och med vilka parametrar kan ge en del spännande lösningar.

Io - dag 3
Dag 3 börjar med en diskussion om domänspecifika språk. En av uppgifterna i slutet av dagen gick ut på att man skulle ta en text-fil och mer eller mindre behanda innehållet i text-filen som kod. Samtidigt som jag blir imponerad över möjligheterna blir jag också lite rädd över om någon kommer att förstå vad som händer.

Io har precis som Ruby en method-missing metod och den erbjuder mer eller mindre samma möjligheter som i Ruby

Io har funktioner för Concurrency där jag bitvis förstår storheten men för vissa saker går den mig helt förbi. Där jag inte förstår är varför cooperativ multitasking är bra. Anledningen till att den inte är bra att utvecklaren måste komma ihåg att lägga in anrop som släpper kontrollen på lämpliga ställen. Preemtive multitasking befriar oss från den uppgiften och vi slipper bekymra oss om att vår applikation kommer att göra systemet oresponsivt. Men Io har en kooperativ modell. Syftet är kort och gott att om inte en "tråd" inte kan avbrytas när som helst så blir systemen förutsägbara då din process inte kan avbrytas hur som helst. Jag kan förstå men det känns som ett steg tillbaka.

En annan sak som har jag lite lättare att ta till mig är att man har en Actor-baserad modell för trådarna. I princip innebär det att varje tråd äger sitt eget data. Jämför man med C# eller Java så delar alla trådar i en process på samma minne och kan därmed också ställa till problem för varandra på oväntade sätt.

Efter har testat lite med Io känner jag att jag förstår Javascript bättre. Men jag kan inte säga att jag på något sätt känner mig hugad att använda språket. Den avskalade syntaxen som gör det enkelt att göra domänspecifika språk skulle kunna vara intressant men jag känner inte att jag kan komma på något projekt där Io styrkor skulle få mig att välja bort "standard"-språken.

lördag 9 april 2011

Seven languages in seven weeks - Ruby

Jag har börjat läsa Bruce Tates bok, 7 languages in 7 weeks och tänke skriva lite "dagbok" om upplevelsen.

Sju språk är ett ganska mastigt projekt att ge sig på men boken aspirerar inte på att göra dig till mästare på något sätt utan snarare att ge en översikt de olika språkens styrkor och svagheter så att man kan utvärdera vilket språk som lämpar sig för vilken uppgift.

Ruby - dag 1
Första går igen lite av den grundläggande syntaxen. Installation av Ruby var smidig och med språkreferensen på nätet så löste jag till och med extrauppgiften utan någon större utmaning. Jag hoppas att det blir lite svårare framåt, även om självförtroendet mådde bra av första dagen. Som java/C# programmerare kände jag igen mig väldigt mycket och det var bara avsaknaden av parenteser som kändes lite konstig.

Ruby - dag 2
Den andra dagen gav en betydligt större utmaning än dag ett och jag får erkänna att jag har fuskat med övningsuppgifterna. Jag får gå tillbaka och göra ett nytt försök på dem lite senare när begreppen har trillat ner lite bättre.

Dagen började lite stilla med syntax för funktioner, arrayer och hashmaps. Att hashmaps är implementerade direkt i syntax kändes lite konstigt men när jag tänker efter så är det inte ofta som jag använt något annat än standardvarianten i vare sig Java eller C# och då kanske man lika gärna kan stöjda dem direkt i syntax.

Code blocks är ett av de begrepp jag ännu inte lyckats ta till mig helt och hållet. Det kanske i viss mån kan liknas vid delegater i C#. Kort och gott kan du definiera ett block med kod som argument till en metod. Nyckelordet yield agerar som en platshållare för blocket. Lite som att skriva en Template Method.

Mixin kan liknas vid Visitor-pattern. Man implementerar en mixin genom att skriva en module. Denna modul kan sedan inkluderas i vilken klass som helst, i princip. Två vanliga mixins är enumerable och comparable som man använda i sina klasser för att iterera och jämföra.

Nu är jag lite lätt skräckslagen inför dag 3. :-)

Ruby - Dag 3
Dag tre börjar vi titta var det är som Ruby speciellt och inte bara en annan syntax. I Rubys fall är det speciella metaprogrammering. Alltså att kunna skriva kod som bygger annan kod.

Öppna klasser är något som går emot mycket av det jag lärt mig tidigare där open-closed-priciple har varit en grundsten. Att en klass i Ruby är öppen innebär att du när som helst kan definiera om hur en klass fungera. Det är bara att definiera om metoden till att göra det du vill att den ska göra just nu. Men som Bruce skriver i boken. Har du bett om en vass kniv kan du skära dig rejält. I C# är det nog närmast method extensions som till viss del utför samma funktionallitet, fast mycket mer begränsat.

En annan vanlig metaprogrammerings metod är att använda en "systemmetod" som heter method_missing. Denna metod skulle jag jämföra med en 404 i html och precis som med en 404 där du kan ha en handler som utför någon operation så kan du välja att implementera vad som ska hända när någon försöker att anropa en metod som inte finns. Detta verkar vara användbart när man har scenarion där man i java eller c# hade använt en parameter för att hantera att det finns för många varianter för att det ska gå att hantera med metoder. Kraftfullt i en del situationer kan jag tänka mig.

Det tredje begreppet är modul och jag är inte riktigt säker på vad som skiljer det från en mixin från dag två. Konceptet är att lägga till funktionalitet till sin klass.

Övningen upplevde jag som enklare än för dag 2 av någon anledning. Men nu får det gå någon dag innan jag ger mig på nästa språk, Io.