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?