fredag den 23. november 2007

Godt efterår

Jeg synes, at vi har haft et rigtigt flot efterår i år. Og jeg er ikke helt alene med den betragtning, for jeg har ladet mig fortælle, at fraværet af rigtige efterårsstorme faktisk lod os beholde efterårsløvet længere end sædvanligt.

Fra Autumn


Efteråret er for mig den tid af året, hvor jeg får taget flest billeder for billederne egen skyld. Der er simpelthen så meget flot at vise frem og samtidig så har jeg tiden.

Vinteren er nok trods alt for mørk og kold, foråret for kort og sommeren for travl (om sommeren bliver taget rigtig mange billeder, men det er mest turistbilleder, og de er mest interessant for dem, som også har minderne).

Derfor er vist meget naturligt, at det eneste sæsonprægede album, som jeg har fået lavet, netop er et album om efteråret (følg linket "Autumn" ovenfor). Jeg håber at jeg har formået at formidle bare en smule af efterårets stemning.

tirsdag den 13. november 2007

Efterårets lyksageligheder

I vores have har der på det seneste sneget sig en række sene sorter ind. Jeg indrømmer gerne, at jeg som udgangspunkt var meget skeptisk - jordbær kommer når der er jordbærsæson, og hindbær hører også sommeren til. Og helt ærligt, hvor meget kan man trække en plantes blomstring og frugtsætning...?

Et af vores hindbær (11. oktober 2007)En hel del, tilsyneladende. Vores hindbær - en gul sort som hedder noget med "Autumn bliss" - har været det helt store hit, og her det her i starten af november stadigvæk (men mon ikke snart frosten får sat en stopper for det?). Vi har på få planter haft en forrygende høst af marmeladesøde bær, som har været lige til at spise - og det bedste af det hele er, at blomstringen har været så sen, at der ingen skadedyr har været længere.

Vores sene jordbær har derimod været en blandet fornøjelse. Der har godt nok været mange (og der kommer stadig flere), men vi har ikke fået så meget som et eneste selv. Der er nogle gæster i vores have, som ikke har noget imod at spise den modne del af et halvmodent bær, og det er svært at konkurrere med.

søndag den 11. november 2007

Repræsentativt demokrati

Und wenn du lange in einen Abgrund blickst, blickt der Abgrund auch in dich hinein.
Nietzsche, Jenseits von Gut und Böse

I Danmark har vi jo et såkaldt repræsentativt demokrati - folket vælger en række personer til at repræsentere sig, og til at tage de nødvendige beslutninger - nemme som tunge - for en periode. Der er en række alternativer, som f.eks. direkte demokrati, hvor folket stemmer i tide og utide om alting, og en række variationer over indirekte demokrati.

Medmindre at man lever under en sten (og i så fald, så har man næppe internet, og kan derfor ikke læse denne blog), så vil man vide, at vi for tiden er inde i slutspurten på et folketingsvalg. Et af de sikre tegn er daglige meningsmålinger og mange såkaldte politiske kommentatorenes udlægning af disse. Politikerne, nyhedsmedierne, kommentatorerne og analyseinstitutterne er alle samlet om at tillægge disse målinger stor værdi - og man har på et seneste hørt institutterne selv rose deres egen nøjagtighed - jeg tror at det, som der blev sagt var, at "vi kan med stor nøjagtigt måle dem, som har besluttet sig - usikkerheden er udelukkende for dem, som endnu ikke har taget stilling".

Jeg er skeptisk. Lad os - ihukommende min underviser i markedsanalyse på Handelshøjskolen - spørge os selv om, hvis vi nu antager at denne undersøgelse siger noget som helst, hvad den så siger noget om? Den siger ikke noget om de, som har besluttet sig - den siger noget om dem, som vil give udtryk for deres beslutning. Og hvordan fylder man så hullerne ud? Jo, normalt ved at efterstratificere ud fra sidste valg, og det er da at indrømme, at man sådan set ikke er meget klogere end det. Mon ikke det, at de kommer frem til samme resultat, skyldes at de bruger samme metode, med samme indbyggede bias?

Men det forudsætter så, at folk svarer oprigtigt, når de bliver spurgt. Jeg er for tiden ansat i et stort firma - ja, faktisk et rigtigt stort firma. Så stort, at vi afholder vores egne meningsmålinger. Det hedder så godt nok medarbejdertilfredshedsundersøgelser, og det er vi bestemt ikke ene om at lave. Vores ledelse ligger stor vægt på resultaterne af disse undersøgelser - så stor, at man skal være temmeligt naiv for ikke at kunne se en omvendt proportionalitet imellem budgettet til "sociale aktiviteter" og "medarbejdertilfredsheden". Og når man indser dette, så kræver det en høj moral at svare oprigtigt, for man bliver jo belønnet for ikke at gøre det...

Sådan frygter jeg også, at der er mange mennesker som har fået det med meningsmålinger. Ja, dem som vil give udtryk for en mening altså, for mange er grundlæggende set ligeglade - de tror stadig på, at selve valget er der hvor de kan gøre deres indflydelse gældende, og selvom de har taget en beslutning, så vil de vente med at give udtryk for den, indtil de står i kabinen med forhæng for.

Hvordan skal man så agere, hvis man f.eks. har en holdning, hvor det ville være opportunt med et snarligt folketingsvalg - jo, man kan give udtryk for, at man vil stemme for den siddende regering, selvom det ikke passer. Det vil give regeringslederen en falsk tryghed, som gør det mere sandsynligt at han tør udskrive valget.

Hvordan skal man agere, hvis man vil trække den politiske dagsorden i en given retning? F.eks. hvis man synes at regeringen skulle trække mere i retning af Dansk Folkeparti? Så giv udtryk for, at man sidste gang stemte på Venstre og denne gang foretrække DF - uanset om sandheden måske var, at du allerede sidste gang stemte på DF.

Tænk over det, næste gang et analyseinstitut ringer til dig - ved valget er din stemme en blandt millioner, i en meningsmåling kun en blandt knapt tusinde - du får aldrig mere magt!

Grundlæggende set, så er problemet, at dagens beslutningstagere lægger alt for stor vægt på meningsmålingerne. De har stirret så længe på meningsmålingerne, at de i stedet for selv at have en mening, så former deres mening efter meningsmålingerne. En god ven af mig kom med et godt citat: "Engang var en leder en, som sagde: 'Jeg går den vej, hvem vil med?' - i dag er en leder en, som siger: 'Hvad vej går I, for jeg vil gerne foran?'". Han tilskrev citatet Uffe Elleman Jensen, og det skal såmænd nok passe.

Og hvis det er sandt, så må det i sandhed siges at være et indirekte, repræsentativt demokrati, som vi har i Danmark. Vi vælger knapt 200 til at lade sig styre af godt 1000 repræsentativt udvalgte danskere...

lørdag den 3. november 2007

Mere om Planning poker

Efter jeg tidligere skrev om Planning Poker, så er der lige et par forhold, som jeg synes fortjener at få et par ord mere med på vejen.

For de mange, som gerne vil vide noget om, hvordan det egentlig fungerer i praksis, så er der kommet et glimrende video interview på InfoQ med Niels Haugen om Planning Poker.

Når noget får så megen opmærksomhed, som Planning Poker har fået, så kommer der næsten selvfølgeligt også en modreaktion. En af disse stammer fra Jeff Atwood i hans blog Code Horror, hvor han har skrevet et indlæg med titlen Lets play Planning Poker! Han betegner meget rammende Planning Poker som en solid gruppedialog og en estimat baseret på en form for konsensus - eller som han siger, en wideband Delphi i ny indpakning. Wideband Delphi har sine problemer, og dem har Planning Poker i vid udstrækning arvet (jeg kommer ind på nogle af dem i min tidligere blog), så er man interesseret i planning poker, så bør man også lige kaste et blik på erfaringerne med wideband Delphi.

Jeff Atwood fortsætter med at sige, at de bedste estimater er de estimater, som baserer sig på historiske data - og det bruger han så som afsæt til at foreslå en alternativ teknik (som jeg ikke vil forholde mig til her). I Scrum vil man typisk bruge Planning Poker i ideal dage, og så bruge erfaringer med teamet produktivitet (dets velocity) til at omforme estimatet til mandedage. Ved at tage turen forbi velocity, så får man et element af historiske data med i udregningen - og man få muligheden for efterfølgende at justere planerne, når produktiviteten ændrer sig (f.eks. fordi at teamet bliver bedre over tid, men måske også fordi at vilkårene for teamets arbejde ændrer sig over tid).

Det er oplagt, at måler man systematisk velocity, så vil man efterhånden få justeret for eventuelle systematiske bias, som måtte eksistere i estimeringsprocessen. Og selvom begrebet idealdage er godt udgangspunkt, så vil en brug af velocity forudsætte en stabilitet i estimaterne, som gør at det ikke længere er idealdage man skal estimere i, men i højere grad "det som vi dengang troede at vi kunne nå på en ideal dag".

Scrum er en proces, hvor man i høj grad fokuserer på stadige forbedringer af arbejdet (arven fra Lean fornægter sig ikke), og derfor undrer det mig egentlig, at man ikke i stedet fokuserer på, at give teamet feedback på dets evne til at estimere, så estimaterne kunne forbedre sig. Måske er årsagen, at man ikke kan skille omfang fra effektivitet, og teamet kun skal have feedback på det dets evne til at forudsige omfang?

En anden modreaktion er ikke så meget imod Planning Poker som sådan, men mere imod at den baserer sig på User stories. James O. Coplien advarer os om, at user stories kun rummer krav, og at der er brug for en bedre forståelse af, hvad det er, som giver værdi for kunden. Det nærmeste jeg har kunnet finde på skrift er denne anbefaling fra hans blog med titlen Religion's Newfound Restaint on Progress:
That means using Use Cases [...] instead of XP-style user stories (so you understand feature interactions up-front), [...]
Coplien fortsætter med en snusfornuftig advarsel om, at man i praksis skal overveje, hvad der er omkostningseffektivt. Det læser jeg på den måde, at han nok altid vil hævde at use cases er user stories overlegne, men at der selvfølgelig kan være situationer, hvor det bedste valg vil være user stories. Han opfordrer os mest af alt til at bruge hovedet!

Hvis vi lige trækker linjen tilbage til wideband delphi, så var grundlaget for den metode, en work breakdown structure. Det er et meget detajleret gæt på, hvad en løsning vil indebære, og langt fra den kravspecifikation som en userstory er. Uden at overfortolke Copliens budskab, så må man vel sige, at han opfordrer os til at overveje, om vi altid mener, at en kravspecifikation i virkeligheden er grundlag nok? Personligt har jeg en stærk tvivl - jeg har deltaget i en del planning poker sessioner, og det er tit at jeg sidder tilbage med en fornemmelse af, at vi er sprunget i mål med et estimat førend vi i virkeligheden har forstået, hvad opgaven gik ud på. Og alt det man overser, er jo 100% underestimeret!

tirsdag den 30. oktober 2007

Lokale bøller

Det hænder efterhånden jævnligt, at jeg bevæger mig i trafikken, og hvis man har oplevet det, så vil man vide, at jeg tilstræber at køre efter forholdene. Det betyder blandt andet, at jeg som udgangspunkt tager det så meget med ro indenfor bymæssig bebyggelse, at loven er overholdt - i hvert fald som udgangspunkt.

Når det sker, så hænder det ganske ofte, at der er folk, som bliver endog meget utålmodige - og det viser de ved ikke at holde en rimelig eller fornuftig afstand. Ikke at de får noget ud af det, ikke andet end at de får en større andel af min opmærksomhed end en bagvedkørende ellers ville have fået.

Derfor har det slået mig, at det som oftest er lokal trafik - ikke de sædvanlige by-til-by-pendlere, næh, det er den helt lokale trafik: De folk, som ikke har tålmodighed til at følge den almindelige trafik igennem Hasselager, de drejer ofte fra ned af de små veje i Hasselager. Og de folk, som synes at vejen igennem Hørning burde være en landevej, de skal oftest ind i industrikvarteret. Og så fremdeles.

Her den anden morgen var jeg, på Frichvejen på vej indad imod Århus, ved at få en utålmodig medtrafikant på trækkrogen. Jeg kørte de 40-45 km/t, som man højest kan køre, hvis man vil have grøn bølge. Det er i og for sig OK igennem boligområdet og forbi skolen, men da vi nåede igennem det sidste kryds inden Ringgaden (der hvor industrikvarteret begynder), da var det selv for mit temperament i underkanten, så øgede jeg selvfølgelig hastigheden til noget efter forholdende mere passende. Alligevel havde jeg ham udenom som et hult drøn allerede inden Fragtmandscentralen, og jeg lover jer at der var klem på. Han skulle ikke engang ned til Frichsparken, førend han var drejet ind ved en af de industribygninger som ligger ud til Frichvejen. Hmmm.

Det er ikke noget nyt fænomen, for jeg husker stadig en af min morfars yndlingshistorier. Det var en lille by på Sjælland (jeg husker ikke hvilken, men det kunne f.eks. have været Kr. Hvalsø), hvor de lokale var stærk pikerede over trafikken på den landevej som gik igennem byen. Den var uansvarlig hurtig, og det var til fare for de lokale beboere og ikke mindst deres børn, var den almindelige mening. Det blev der så klaget godt og grundigt over - og på et tidspunkt mistede politiet tålmodigheden og lavede en morgen fartrazzia i myldretiden. Hovedparten af dem som blev snuppet var lokale, flere var mand og kone i hver sin bil, og mange var at finde som underskrivere på underskriftsindsamlingen. Her kunne historien så være slut, hvis ikke det var fordi, at nogen hos politiet havde humor - de var der igen om eftermiddagen, da myldretiden myldrede den anden vej, og her kunne de så snuppe mange af de lokale for anden gang. Der blev ikke klaget mere over trafikken i den by - historien melder dog ikke noget om, det var fordi at den var blevet mere civiliseret, eller om det bare var fordi, at man havde affundet sig med tingenes tilstand.

Disse lokale fartbøllers opførsel er uforståelig for mig. At køre uforsvarligt er - ja, dumt - men at gøre det hjemme hos sig selv, er da dobbelt dumt. Hvorfor skulle man ikke netop passe bedre på sit eget lokalområde? Det er som at smide affald foran sin egen fordør (bortset fra, at der ikke er nogen, som får deres liv ødelagt af affald!). Hvis ikke man selv har børn som færdes langs disse veje, så er det stor sandsynlighed for at naboen har. Er der nogen, som kan forklare mig, hvad årsagen til denne tilsyneladende irrationelle adfærd er?

søndag den 28. oktober 2007

Nikon vinder...!

Nå, fotonørd, der fik jeg nok din opmærksomhed, hva'r? For udenforstående kan jeg så afsløre, at der er en rivalisering i fotokredse imellem de i dag de facto to største leverandører, Nikon og Canon, som ofte i fanskaren svinger sig op (eller måske rettere, ned...) på et niveau svarende til det, som findes imellem nabolandes fodboldslandshold. Jeg har det lidt på samme måde med de to ting - jeg har godt nok valgt side (Nikon hhv. Danmark), men jeg har svært ved at se, hvad der at hidse sig sådan op over. Men nok om fodbold for denne gang.

Jeg bliver af og til spurgt af folk, hvilket kamera som jeg vil anbefale dem at vælge. Havde jeg været fanatisk, så ville jeg have lydt som en salgsbrochure for "mit" kameramærke, men jeg plejer faktisk at anbefale folk at vælge en levendør, som man kan tro på vil noget på det marked (vælger man blandt de store bliver man ikke snydt), og for digitale spejlrefleks (DSLR) kameraer plejer jeg at sige, at man skal være opmærksom på, at man ikke bare køber et kamerahus, men derimod et helt system med linser og tilbehør, hvor huset nok bliver den mindste del. Det sidste råd er, at prøve at holde de forskellige kameraer - det er vigtigt at man føler, at det ligger godt i hånden, og det er i høj grad et spørgsmål om smag og behag.

Når det så er sagt, så vil jeg selvfølgelig gerne, at det går "mit" kameramærke godt, for dels betyder det, at der alt andet lige bliver mere overskud til nyudvikling, og - lad os bare indrømme det - det er bekræfter mig i, at jeg har taget en rigtig beslutning, at se andre tage den samme...

Og der nogle tegn på, at Nikon har medvind for tiden. Overskriften hentyder ikke til at krigen er afgjort, og end ikke, at et slag har fundet sin afslutning. Men der har været nogle træfninger, som er faldet ud til Nikons fordel. På tide, vil nogen mene, for Nikon har uomtvisteligt sovet i timen, og ladet Canon løbe med det prestigefyldte marked for presse-, og ikke mindst, sportsfotograferne. Hvis man kigger på pressefotograferne ved et sportarrangement, så har de næsten alle de for Canon så karakteristiske hvide linser.

Hvad er der så, at jeg baserer min optimisme på? Tjo, f.eks. denne undersøgelse af tilfredshed blandt DSLR købere, hvor Nikon får en rigtig flot placering. Personligt går jeg og kigger kameraer, når jeg kommer rundt omkring, og efter i nogen år at have været stort set alene med mit Nikon D70 i en skov af EOS'ere, så var der i år i Legoland en tilsyneladende overvægt af Nikons blandt de DSLR'er, som jeg fik øje på (og iøvrigt var der langt flere DSLR'er end der plejer at være).

Det andet punkt er introduktionen af Nikons high-end model D3 - Canon kom godt nok en anelse før med deres nye topmodel, men det var Nikon som løb med opmærksomheden, for det ser ud til, at Nikon har fintet Canon til at fortsætte ligeud i megapixel-ræset, mens Nikon tog bolden ved at sætte kvalitet over kvantitet.

Den nye Nikon har nogenlunde den samme opløsning som hidtil, men sensoren var langt mere lysfølsom (ja, for os som har taget turen med fra filmdagene, nærmest urealistisk følsom), og samtidig yderst støjsvag. Normalt er det sådan, at større følsomhed resultaterede i højere støj, og desværre hurtigt så meget, at resultatet i praksis var ubrugeligt. De eneste udveje har været hhv. kunstbelysning (som i parantes bemærket ikke lige går af mode, for hvis man kan kontrollere den faktor, så indebærer det bestemt store fordele), eller hvis det var umuligt, store, tunge og hundedyre linser. Et eksempel på, hvad man nu kan opnå, kan ses i denne samling sportfotos med Nikon D3. Dertil kommer, at det selvfølgelig stadig er muligt at få den bedste af begge verdener ved at sætte de førnævnte store, tunge og hundedyre linser foran... Som for næsten at føje spot til skade, så vil et støjfyldt billede komprimere dårligere end et støjfattigt - så Canon står med større billeder pga. den højere opløsning, som oveni ikke kan komprimeres så meget, pga. den højere støj.

D3'eren, som jo er tiltænkt professionel brug, er udstyret med en fullframe sensor, hvor det tilsvarende D300 til forbrugersegmentet "kun" har en noget mindre sensor i DX-format. Der kan selvfølgelig ikke realiseres lige så fine resultater på en fysisk mindre sensor, men til sammenligning er her en række sportfotos med Nikon D300. Det er nu ikke så ringe endda.

Det andet punkt, som Nikon har valgt at prioritere, er image preview. Dels er det på kameraet monterede LCD display nu i væsentlig højere opløsning - hvor det førhen reelt kun kunne anvendes til at vurdere komposition, så kan det nu reelt bruges til at vurdere skarpheden. Samtidigt er der en HDMI udgang på kameraet - og det betyder at det nu også er en reel option, at koble kameraet direkte til en monitor. Kun med HDMI er kvaliteten tilstrækkelig god.

Med ovenstående argumenter, så synes jeg faktisk ikke, at det er urimeligt at sige, at Nikon fintede Canon denne gang. Spændende at se, hvad svaret fra Canon bliver - og om sportsfotografernes linser nu igen skal til at være sorte...

onsdag den 24. oktober 2007

Valg af ny linse?

En arbejdskammerat spurgte mig i dag et godt spørgsmål: "Hvordan vælger du en ny linse?". Jeg havde lyst til at svare noget i retning af "med besvær" eller "velovervejet", men et høfligt spørgsmål fortjener et høfligt svar...

Den ene del af at vælge en ny linse, er at finde ud af, hvilket behov man har? Er det indendørs sport eller sommerlandskaber? Er det fester eller rejser? Eller er det f.eks. dyr eller mennesker (og hvis der er dyr, er det så myrer, fugle eller elefanter)? Nok det allervigtigste spørgsmål at stille sig sig, men også det, som jeg elegant vil springe over her, for det er i bund og grund et personligt spørgsmål.

Når man er klar over sit behov, så kan man gå igang med at samle information om de forskellige linser i den kategori, som man er interesseret i. Her bruger jeg faktisk lang tid (ikke mindst fordi, at jeg også lige skal nå at spare "lidt" penge op undervejs...) med at lytte til diskussioner på diverse diskussionfora. Specielt følger jeg dpreview's Nikon SLR Lens Talk Forum (jeg har et Nikon D70, så jeg er naturligvis mest interesseret i linser til Nikon's kameraer). Der er tæt trafik i forummet, og der er væsentligt mere snot end der er skæg, men med lidt strategisk skimning af overskrifter, så kan man faktisk finde overraskende mange interessante tråde.

Her kigger jeg til dels efter kommentarer til den linse, som jeg har i tankerne. Kommentarerne deler sig dels i den temmeligt unyttige "den har jeg og den er god" og "den har jeg, og jeg vil hellere have en anden" kategori og så i den langt mere interessante kategori, hvor folk prøver at perspektivere linsen i forhold til dens nærmeste alternativer - det være sig dels i forhold til nærvedliggende linser i sortimentet (hvad er f.eks. forskellen på en Nikon 80-200mm og Nikon 70-300mm telezoom - og hvad der forskellen på en 70-300mm G, EF og VR?), men også i forhold til andre fabrikater, som f.eks. Sigma, Tamron eller Tokina). Samtidig kan man være så heldig, at folk diskuterer, hvad den er velegnet til, og hvor den halter.

Men jeg kigger også efter kommentarer vedr. det behov, som jeg har besluttet mig for er vigtigt (husk første trin var finde ud af behovet, for vi vælger jo linsen ud fra behovet - og ikke omvendt, vel?). Man starter måske med en ide om, at man gerne vil fotografere fugle - diskussionerne kan så hjælpe en med at forstå, at der er stor forskel på de behov man har, hvis man skal fotografere et par tamme svaner (her er det vigtigste nok at have brød i lommen!), og så de behov, som man får, hvis man vil fotografere vilde fugle (f.eks. er vores småfugle i de danske haver faktisk ganske små, og kræver væsentligt mere end man måske først havde forestillet sig).

Pointen er undgå at låse sig alt for fast på en enkelt mulighed for tidligt, for der er ofte for og imod for alle linser (om ikke andet, så fordi nogle er væsentligt dyrere end andre...) - og måske er der alternativer, såsom nærlinser eller telekonvertere.

Når jeg har fået mig en rimelig ide om, hvad der kunne være interessant, så er mit næste trin at grave mig ned i specifikke anmeldelser af den eller de linser, som jeg har fået kig på. Her bruger jeg hovedsageligt SLRGear (det er vist et subsite til Imaging Resource). SLRGear har ikke alle linser, men de har rigtigt mange - og mit indtryk er, at de er ganske grundige. Man skal lige huske at skelne imellem, hvad der er egentlige test, og hvad som i første omgang er afskrift af tekniske specifikationer + nogle brugerkommentarer.

Et andet site, som jeg også bruger flittigt til at vurdere linser er Bjørn Rørslett's Naturfotograf.com. Han fremtræder meget kompetent, og han har sine meningers mod - ikke alene får man de mere objektive fakta, man får også hans uforbeholdne personlige mening.

Da jeg skulle finde adresserne til de forskellige sites i denne blogpost, så faldt jeg faktisk over et mere, som jeg ikke kendte, nemlig PhotoZone - og det ser da også meget lovende ud. Kom ikke og sig, at ikke man kan blive klog af at blogge.

Ofte bliver sidste trin i min proces, at jeg undersøger prisen på linsen - og så er vi tit tilbage ved trin 1, men nu med et reduceret ambitionsniveau...!

lørdag den 20. oktober 2007

En lille afstemning

Affødt af Rasmus' kommentar til mit seneste indlæg om Microsoft og deres to nye opensource licenser, så har jeg startet en lille, og sikkert fuldkommen misvisende, afstemning her på siden , om hvordan du, kære læser, har det med Microsoft og deres produkter?

Vi er nok ikke enige, men mon ikke at vi alle har en mening om det emne? Kommentarer til afstemningen kan du passende skrive her...

PS: Hvis du bruger en feedreader af en slags, så bliver du nok nødt til at komme helt ind på siden for at se den...

Opdateret 28. oktober 2007: Afstemningen er nu afsluttet, og der er fem personer, som har givet deres mening til kende om "Hvordan har du det med Microsoft og deres produkter?":
  • Ingen elskede dem.
  • Ingen hadede at elske dem.
  • Fire elskede at hade dem.
  • En hadede dem.
Konklusionen må være, at det er utaknemmeligt at være den største...

onsdag den 17. oktober 2007

Microsoft og OpenSource

Så skete det - Open Source Initiative (OSI) godkender to licenser forfattet af Microsoft som værende OK efter deres standard. Se evt. denne blog om beslutningen.

Det er ikke kommet uden forudgående diskussion, og der er ingen tvivl om, at der var været en slem kamel at sluge for mange. Microsoft har dog vist sig villige til at høre på kritik, og selv navngivningen (som jeg tidligere kommenterede på) er blevet mere dækkende.

Betydningen af dette kommer vi nok til at snakke længe om - er det i virkeligheden et udspekuleret angreb fra det onde imperie - et forsøg på at underminere opensource bevægelsen med dens egne våben? Eller er det i virkeligheden Microsofts erkendelse af nederlag til tonerne af "if you can't beat them - then join them!"? Og hvis vi ikke længere kan elske at hade Microsoft, hvem skal vi så elske at hade?

mandag den 15. oktober 2007

Arkitekten er død...

...længe leve arkitekturen!

På dette års JAOO var der del, som luftede den mening, at arkitekter var en udøende race, og at agile udviklingsmetoder vil gøre arkitekter overflødige. Jeg kender efterhånden en hel del folk, som er gode arkitekter, og jeg så faktisk flere af dem gå og dukke sig efter denne svada.

På den anden side, så var der yderst interessant og velbesøgt spor, som delte sig over to hele dage om arkitektur, så faktisk var det ganske uretfærdigt. Pointen er ikke, at det være agil betyder, at man ikke længere behøver en arkitektur ("vi laver det som synes rigtigt nu, og hvis det senere viser sig at være forkert, så kan vi bare refactore det...!" synes det naive synspunkt at være).

Jim Coplien havde et tankevækkende, og til tider provokerende, foredrag på JAOO om agil arkitektur, og i det understregede han klart behovet for at få taget de nødvendige beslutninger på rette tidspunkt. Hvis man undlader at tage beslutninger, så vil du se god fremdrift de første par sprint, var hans påstand, men derefter man blive indhentet af virkeligheden med nedsat produktivitet til følge (eller velocity som vi vist ynder at kalde det nu om dage).

Coplien blev i høj grad bakket op af talerne fra ovennævnte arkitekturspor, og i virkeligheden så er det et faktum, at du får en arkitektur uanset om du planlægger det (intentional architecture) eller om det opstår mere som en eftertanke (accidental architecture).

Accidental architecture har en lidt kedelig klang af held fremfor dygtighed over sig, men hånden på hjertet, så er det heldigvis ikke alt, som sker som logiske videreførelser af allerede eksisterende ideer (jeg boede engang i samme opgang som en, der yndede at sige, at selv den mest metodiske og grundige planlægning aldrig vil kunne erstatte det rene og skære svineheld!). Grady Booch anerkender da også tilfældig arkitektur som værende positiv under to klare forudsætninger:
  • de bagvedliggende beslutninger tydeliggøres.
  • de vigtige synliggøres igennem resten af projektforløbet.
(se Grady Booch: The accidental architecture). Iøvrigt kan "rigtig" Accidental Architecture faktisk være ganske flot.

Men hvad er så egentlig arkitektur for noget? Kevlin Henney stiller også spørgsmålet (Kevlin Henney: What is Software Architecture), og besvarer det med henvisning til Martin Fowler og Grady Booch med, at det er de designbeslutninger, som er svære eller dyre at omgøre. Ud fra den definition er det tydeligt, at arkitektur ikke er noget, som man kan komme ind i systemet på et vilkårligt sent tidspunkt.

Betyder det så, at agile metoder er et luftkastel, og at vi stopper os selv blår i øjnene? Skal vi i virkeligheden tilbage til tidligere tiders dyder om et kæmpe design på forhånd? Så langt fra. Tanken om ikke at tage alle beslutninger på forhånd, hvor grundlaget for at træffe dem iøvrigt i bedste fald ville være tvivlsomt, holder stadig. Budskabet er udelukkende, at det ikke modsætningsvis betyder, at man ikke behøver tage nogen beslutninger overhovedet!

Nogle beslutninger kan man med fordel beslutte at tage på forhånd. Andre kan man - som Kevlin Henney fint illustrede i hans foredrag om Performance Art (man kan vist ikke beskylde ham for at være beskeden...) - tage en bevidst beslutning om at udskyde til senere, ved at afkoble sig fra et konkret valg. Man bliver nødt til at beslutte sig for et interface, men hvis man ligger tilstrækkelig omhu i konstruktionen af dette, så kan valget af implementation udskydes til et tidspunkt, hvor man har et bedre grundlag for at træffe en korrekt beslutning.

At det er et emne, som udfordrer alle med en agil tilgang til systemudvikling, kan ses af at ThoughtWorks var i stand til at lave en seksmands paneldiskussion om emnet med sig selv på dette års QCon-konference.

Hvad er så min konklusion? Jo, at den klassiske arkitekt som den store leder og beslutningstager, som vi kun så i opstartsfasen af et projekt, hvor han lagde de endegyldige rammer for en succesfuld applikation (som så på det groveste blev misforstået og fejlimplementeret efterfølgende!) er en udryddelsestruet race - og godt det samme!

Hvis vi er agile, så er arkitektur noget som fastlægges løbende og af os alle i fællesskab. Derfor har vi mere end nogensinde brug for folk med arkitektonisk flair, til at virke som facilitatorer for de "dyre" beslutninger og mentor for hele udviklingsgruppen, for at få forankret de gode beslutninger.

FY?

Mit team arbejder med scrum, og selvom der er gjort mange gode erfaringer, så er der (heldigvis!) stadig megen plads til eksperimenter. Der lægges stor vægt på, at man lærer af egne erfaringer - alligevel så er der nu ikke noget bedre end, også at kunne lære af andres. Og derfor kan jeg ikke lade være med at studere de scrumboards, som jeg kommer forbi på min vej.

Jeg kom fordi et den anden dag, og der hæftede jeg mig ved, at der var en task seddel på boardet, hvor nogen med fed rød tusch havde skrevet:
FY!

Halløj, tænkte jeg, her måtte der virkelig være tale om en større overtrædelse af teamets interne aftaler, og jeg nærlæste derfor sedlen. Det eneste, som jeg lige kunne se var specielt ved den var, at det oprindelige estimate på 6 var blevet nedskrevet til 3, og derefter skrevet op igen til 6.

Hmm. At blive klogere undervejs er vel kun en god ting, og lige så vel som man kan blive positivt overrasket over, hvor nemt noget, som i første omgang så svært ud, viste sig at være - lige så vel kan man blive overrasket over, at det som ved første øjekast så nemt ud, ved nærmere øjensyn viser sig at være sværere end ventet. Det er selvfølgeligt godt jysk trælst, at resttiderne stiger, men det er nu engang en konsekvens af, at vi gætter. Vi vinder nogle og vi taber nogle...

Så var det at jeg tænkte på, hvad der ville ske, hvis opgaver, hvor man opskrev resttiderne, alle skulle hænges ud til almindelig spot og spe? Ja, dels kunne man nok forvente en vis ulyst til at påtage sig andet end de mest trivielle opgaver, dels ville man hurtigt komme til at indregne et risikotillæg i estimaterne og dels ville der være en naturlig tøven med at nedskrive resttider før end man var helt sikker på, at det ville holde (f.eks. fordi, at man rent faktisk var færdig). Under alle omstændigheder har man herved ødelagt enhver fordel ved at have resttidsestimater (og i tilgift fået unikke ulemper oveni).

Det kan selvfølgelig være, at jeg tager fejl - måske er det i virkeligheden en hel anden synd, som man her vil sanktionere med at udstille synden (og dermed også synderen) offentligt. Under alle omstændigheder noget, som man skal tænke sig godt om, inden man gør. Hvis jeg på den anden side har ret, så har jeg kun en ting at sige, og det er:
FY!

onsdag den 10. oktober 2007

Det, som ikke var der...

For the world is changing: I feel it in the water, I feel it in the earth, and I smell it in the air.

Engang imellem er det vigtigste det, som ikke er der. Og sådan var det, efter min mening, med JAOO i år. I år var der megen snak om, hvad det vil sige at være en professionel udvikler, og hvad det vil sige at have en profession. Der var til gengæld ikke meget snak om tekniske finurligheder - det som om, at vi har fundet ud af det.

Erich Gamma nævnte det selv i sit foredrag - at han var blevet kontaktet med kommentaren om, at han ikke længere snakkede om "the hard stuff" - han ville godt medgive, at han snakkede mere om proces end om teknik, omend han nu nok ville mene, at det ikke var mindre "hard stuff" af den grund.

Gamma var ikke alene - bevares, .NET folkene havde vist en skøn dag med deres nye "legetøj" LINQ, og alle de, som interesserede sig for Ruby, havde vist stadig mere behov for at diskutere værktøj end proces. Men generelt var tekniksnakken blevet mere eller mindre væk.

Hvorfor mon det? Den ene del af forklaringen er sikkert, at vi er fragmenterede - der er efterhånden så mange forskellige fornuftige forslag til værktøjer, frameworks og teknologier, at man kan blive helt svimmel. Skal persistens være JDBC, Hibernate, JPA eller lign.? Skal webservices laves med Axis, JSON eller XFire - og skal stilen være RPC, SOA eller måske endda RESTful? Hvad med unittest? IDE? Buildtool? Webframework? Chancen for at finde to udviklere, som er enige, er efterhånden ganske lille.

Men den anden del af forklaringen er, at de forskellige alternativer faktisk efterhånden er blevet ganske udemærkede. Kigger man på funktionaliteten, så kan de faktisk alle stort set alt, bare på en lidt forskellig måde - og valget bliver ofte mere et spørgsmål om tradition eller smag. Teknikken er, med andre ord, ikke så interessant i sig selv længere.

Nogle vil sikkert mene, at det skyldes at det nuværende procedurale (eller, mere generelt, imparative) programmeringsparadigme, eksemplificeret med f.eks. Java og C#, er ved at løbe tør for damp. Vi har nået så langt som vi kan komme, er påstanden, og hvis vi skal videre, så skal vi seriøst have skeen over i den anden hånd.

Et alternativ er mere målrettet valg af sprog - og udnyttelsen af muligheden for at blande flere sprog, så man bruger det sprog som aktuelt er bedst til lejligheden. Det være sig fulde sprog på eksisterende platforme, som f.eks. Python implementationen Jython, eller sprog i sig selv, som f.eks. Ruby. Men det kunne også være mere domænespecifikke sprog, som kunne være sprog opfundet til lejligheden, f.eks. for at gøre beskrivelsen mere forståelig for dem som kender domænet - eller det kunne være gamle kendinge, som f.eks. SQL eller Ant's buildfiler. Personligt har jeg svært ved at se det nyskabende i det, men der er mange kloge folk, som siger mange kloge ord om det... (og husk, at gode ideer kan implementeres dårligt).

Et andet godt bud på, hvor fornyelse kunne komme fra, er fra de funktionelle (eller, mere generelt, deklarative) sprog. Synspunktet er, at eksisterende sprog i høj grad kommer til at håndtere flerkerne processorer og den deraf følgende høje grad af parallelitet, eksplicit som en udvidelse. Derimod vil funktionelle sprog i langt højere grad kunne håndtere det implicit. Det er lidt forskellen på at bygge læhegn, eller at bygge vindmøller, som svar på forandringens vinde.

Et af de funktionelle sprog, som man lige nu bør holde øje med, er Erlang. Sproget har - i modsætning til mange alternativer - allerede en god ballast i kraft af, at det dels allerede har været anvendt i praksis (det blev oprindeligt udviklet af Ericsson), dels har været OpenSource allerede før årtusind skiftet. Det har allerede bevist, at det virker.

Men vi er der ikke endnu, og der er gode chancer for, at fremtiden bliver noget, som vi slet ikke har fantasi til at forstille os i dag. Min pointe er, at vi for tiden mest er afventende, og at det kan være forvarslet til opbrud.

PS: Citatet i indledningen er store ord, og den angivelige ophavsmand vil helt sikkert føle sig misbrugt i en for ham, så flygtig og foranderlig sammenhæng, som programudvikling er for tiden. Jeg er nu ret sikker på, at når vi om ikke så frygteligt mange år kigger tilbage, så vil vi mene, at verden er blevet forandret. Bonuspoint til dem, som kan regne ud, hvor citatet stammer fra, og hvem som angiveligt skulle have sagt det!

mandag den 8. oktober 2007

Brændviddeforkortning ved intern fokus

Hvis du er fotonørd, så kender du helt sikkert brændvidden på alle dine linser. Men vidste du, at brændvidden på dine linser måske kun gælder ved fokusering på uendeligt?

Det gjorde jeg faktisk ikke, men den er god nok. Der er en formel for optik, som siger, at man kan fokusere tættere på ved enten at øge afstanden imellem filmplanen og linsen - eller ved at reducerer brændvidden (det første holder indtil en afstand på 4 x brændvidden, idet afstanden imellem linsen og filmplanet herefter vil forøges mere end afstanden imellem linsen og det som skal i fokus - i dette punkt danner man i øvrigt en projektion i 1:1 forstørrelse).

Hvis man har en linse med intern fokus, betyder det, at frontelementet ikke ændrer placering i forhold til filmplanet (linsen har altid samme længde). Men det betyder på den anden side, at linsen for at kunne fokusere, må reducere brændvidden.

I Nikons "bogstavskode" hedder linser med intern fokus noget med IF, og hvis man tager en linse som f.eks. AF-S VR Micro-Nikkor 105mm f/2.8G IF-ED, så realiserer den en 1:1 forstørrelse på ca. 31 cm afstand. En 105mm linse burde have en 1:1 forstørrelse på 42 cm afstand, og vi kan derfor udlede at brændvidden på den afstand er reduceret til ca. 78mm.

Brændvidde reduktionen er med andre ord prisen for at have intern fokus.

Der er flere udemærkede kilder, men den jeg fandt mest nyttig, var Ricardo Pollini's Introduction to close-up photography.

søndag den 7. oktober 2007

Alternativ demosaic proces

I den uendelige og nærmest religiøse diskussion for og imod at skyde sine billeder i RAW (sensornært format) eller i f.eks. JPEG (slutanvendelsesnært format), har et af argumenterne for RAW altid været, at hvis der nu kommer en ny og bedre teknik på markedet til fortolkning af sensoroutput, så vil kun allerede eksistererende billeder i RAW format kunne drage nytte af det.

Fascinerede tanke - at tage ens gamle billeder frem og gøre dem (teknisk set) endnu bedre.

Det eneste problem for det argument har bare været, at der ikke rigtigt har været nogen alternative processer til fortolkning af sensoroutputtet (den såkaldte demosaic proces) - dvs. ikke før nu.

Planning poker

For at kunne planlægge indhold, skal man kende omfang - og det gælder også for scrum, selvom om iterationerne er så korte, så man kan holde ud at sprinte igennem dem. Et af de foretrukne værktøjer til at anslå omfang af opgaver, når man bruger scrum som metode, er planning poker.

Det er der efter min mening en række gode grunde til:
  • der er gode chancer for at få vendt alle relevante sten ("none of us is as smart as all of us")
  • fremgangsmåden er lightweight - input er en "story" som kompakt beskrives et ønske, og så de fakta, som deltagerne spørger ind til, for at kunne danne sig en mening.
  • vurderingen sker af dem, som skal udføre opgaven.
  • der satses på konsensus.
  • indbygget i metoden er hensyntagen usikkerheden stiger med resultatets størrelse.
Men der er også en række fælder:

Sammenfaldende interesser?

I det agile manifest slår man fast, at man foretrækker samarbejde med kunden fremfor kontraktforhandlinger (er jeg den eneste, som hæfter mig ved, at ordet kollaboration, som jo både på dansk og engelsk kan betyde samarbejde med fjenden, står lige ved siden af ordet kunde i manifestet?). Vi tror mao. på, at vi har fælles interesser, og så virker metoden da også bedst.

Men har vi fælles interesser? Product owner har jo en interesse i, at få så meget som muligt lavet, og er han menneske som os andre, så vil han nemt kunne fristes til at underspille omfanget af opgaven, for derved at få teamet til at love mere end det ellers ville. Tilsvarende vil et team, som tidligere er blevet udsat for opgaver, som har vist sig at være mere komplicerede end antaget under planlægningen, begynde at indregne risikotillæg i deres vurderinger.

Specielt kritisk bliver det, hvis man bruger vurderingsmetoden i et fastpris scenarie (og derfor mener jeg at man skal være meget forsigtig med at blande de to...), men effekten vil allerede opstå, hvor der ikke er fælles ejerskab af vurderingen ... hvis product owner efterfølgende kan slippe afsted med at sige "Jamen team, I lovede..." eller endnu værre, hvis teamets performance alene bliver målt på dets evne til at opfylde vurderingerne.

Diskussionen er specielt relevant, når man estimerer i fysiske tidsenheder (det være sig såvel kalender- eller, mere typisk, mande-dage), og et forslag har derfor været at estimere i story points i stedet - story point er meget lig function points i deres tilgang, i det at begge forsøger at estimere kompleksitet uden også at estimere effektivitet. Der findes også også argumenter imod at bruge storypoints.

Manglende konsensus

En stor fordel ved metoden er, at alle bliver hørt, og at der er enighed om vurderingen. Hvis det da er tilfældet...

For det er dels vigtigt, at hele teamet deltager i vurderingen, hvis hele teamet senere skal kunne forventes at bakke op om resultatet. En planning poker seance er med andre ord et glimrende tidspunkt til at skille pigs fra chickens - hvis der er nogen i teamet, som mener sig ude at stand til at deltage, så er der stor chance for, at de i virkeligheden er kyllinger i grise-kostumer....

Den anden fælde er, at man stopper diskussionen inden der er konsensus. Det er dræbende for det fælles fodslag, hvis deltagerne sidder tilbage med følelsen af "nu blev det godt nok 5 dage, men jeg tror nu mere på 8 dage...!"

For meget konsensus (eller af de forkerte årsager) kan nu også være af det onde.

Ovendreven tro på nøjagtigheden

I virkeligheden, så kan man jo skrive denne advarsel om stort set hvad som helst - at være sig begrænsninger bevidst er jo altid en god ting. Metoden har allerede indbygget en stillingtagen til usikkerheden i den kraftige progression, som der findes i kortenes talrække. Når man læser beskrivelsen hos ophavsmanden, så er det tydeligt, at han forventer at resultatet er en af disse diskrete værdier (man stopper ikke førend der er konsensus om en af disse).

Et alternativ, som jeg har set praktiseret, er at stoppe når spredningen er kommet under et vist niveau (vores tommelfingerregel er maks. tre på hinanden følgende diskrete værdier), og så tage et passende gennemsnit. Fordelen er, at man ikke bruger langt til på at få de sidste decimaler diskuteret på plads (det flytter næppe meget, og det kan tage lang tid), men ulempen er dels, at man kan opnå en distance til resultatet, og dels, at resultatet præsenteres med en nøjagtighed som det ikke kan bære.

Et eksempel: Vores regel vil acceptere flg. stemmer:
8, 13, 13, 20, 20, 20,
og det naive resultat vil være 15,7 dage (eller måske mere reelt 15 2/3). Dels signalerer decimalerne times nøjagtigt i noget , hvor inputtet var mere end hele dage (der er en uge mellem 8 og 13 dage, og længere imellem 13 og 20 dage), dels ligger det omkring 4 dage under halvdelen af gætterne!

En anden vinkel på det er, at hvis bare en enkelt havde taget et kort, som lå lige ved siden af, så ville det kunne flytte gennemsnittet en dag i hver retning. Et mere reelt resultat havde altså været godt tre uger, eller omkring 16 dage. Har man brug for at kende resultatet mere præcist, så har man enten specificeret storien for grovkornet, eller også er man i gang med at detajlplanlægge.

En godt checkpoint er at spørge alle deltagerne, om de vil kunne acceptere resultatet (igen med specielt fokus på dem, som lægger længst væk). Hvis man gør der, og en af de folk som har vendt f.eks. "20" i virkeligheden vaklede imellem det og så "40", så vil det komme frem!

Hvad snakker vi om?

Når man vurderer på et så uformelt grundlag, som en story og diskussion med udgangspunkt i nogle afklarende spørgsmål, så er det vigtigt at man er enige om, hvad det er, at man vurderer.

Den første fælde er, at de forskellige deltagere i diskussionen løb har dannet sig et forskelligt billede af, hvad løsningen går ud på. Der har sikkert været en livlig diskussion af alternativer og afgrænsninger, og hvis ikke der gøres et grundigt arbejde af moderator med sikre fælles fodslag dels i hovederne på deltagerne og dels som forudsætning for vurderingens validitet efterfølgende, så risikerer man nemt at få svar på noget andet end det, som man spørger om.

Tilsvarende er det vigtigt, at man er enige om, at man kun vurderer gruppens egen indsats. Hvis det er en forudsætning at andre end teamet bidrager, så er det netop en forudsætning - disse andre må selv komme med deres eget bud på, hvad deres del vil andrage, hvis der er relevant. At bede teamet om også at tage dette med, er at tage dem som gidsler på noget, som de dels ikke har forudsætninger for, og dels næppe vil kunne føle ansvar for efterfølgende.

Det stiller også krav om, at teamet består af generalizing specialists - hvis der er for stort spænd i kompetancerne (f.eks. fordi at der er flere, som ikke kan programmere, og opgaverne indeholder betydelige programmeringselementer), så kan det betyde, at vurderingen bliver rent gætværk, simpelthen fordi at folk mangler forudsætningerne for at mene noget fornuftigt. Alternativet med, at lade dele af teamet erklære sig inhabile, er heller ikke godt, dels af hensyn til det fælles ejerskab, dels fordi at man så risikerer at miste et vigtigt input. Under alle omstændigheder, så er det at have et team af generalizing specialists identificeret som en af de afgørende faktorer for at have højt ydende team, så hvis situationen opstår, så skal man overveje om teamet er korrekt sammensat.

Er det så ikke bare noget bras?

Jeg kan ikke fortænke noget, hvis de nu sidder og spørger sig selv, om metoden er noget bras? I så fald, så læs lige om fordelene i indledningen igen - det er et glimrende værktøj, men man skal være sig dets begrænsninger bevist.

Personligt mener jeg, at der er det bedste værktøj til vurdering af opgaver inden sprintplanlægning i et velfungerede scrumteam. Det forudsætter dog stor modenhed fra alle parter - både fra teamet og fra dets omgivende interessenter.

(Opdateret 3. nov. 2007: Der er kommet en fortsættelse med titlen Mere om Planning Poker)

lørdag den 6. oktober 2007

Edderkop

Jeg havde mit kamera med i haven i dag, og her er hvad jeg fandt.



Specielt køn kan man vel ikke ligefrem kalde den, men alligevel lidt fascinerede. I hvertfald når den ikke kravler rundt i nakken på en...

tirsdag den 2. oktober 2007

Versionsstyring

(Opdateret 4. februar 2008: Der er kommet en opfølgning om branches)

Indledning

Så vidt jeg husker, så er versionsstyring danske oversættelse af revision control. Man undgår normal ordet version og det er sikkert for at skelne det i forhold til software configuration management, som jo er det at styre forskellige versioner af software - og typisk endda i forskellige konfigurationer. Revision control er det, som hjælper os med at kontrollere de små skridt, som tilsammen udgør den rejse, som configuration management kontrollerer.

Jeg vil her skrive lidt om værktøjer til versionsstyring. Jeg vil ikke skrive om, hvorfor - det antager jeg, at vi er enige om.

At det ikke altid har været en selvfølgelighed med versionsstyring, oplevede jeg på egen krop for efterhånden nogle år siden. Jeg sad som "schweizerkniv" (projektleder, arkitekt, udvikler, 2nd level supporter og underviser i en og samme person) på et produkt, som havde været længe undervejs. Faktisk havde der allerede været to andre personer på dette før mig og begge var forlængst over alle bjerge. Jeg spurgte derfor ofte mig selv om, hvordan en given del af programkoden kunne have været opstået. Derfor gik jeg til min chef og bad om et versionsstyringsværktøj.

"Hvorfor det?" lød svaret, "du er da alene på projektet". Ja, men nogle gange, så har man brug for at kunne gå tilbage til en tidligere version. "Jamen, kan du ikke bare gemme en kopi et sted på din harddisk?". Jo, men det ville være rart at kunne gå længere tilbage. "Hvad med at gemme flere kopier...?". Her gav jeg så op.

Nu får jeg min tidligere chef til at fremtræde lettere naiv, og det er uretfærdigt, for han var alt andet. Og man kan ikke ligefrem sige, at jeg præsenterede ham for det, der på nydansk hedder en god business-case. Jeg kan ikke fortænke ham i at se store umiddelbare udgifter, og kun magre og usikre gevinster langt ude i fremtiden. Jeg skulle - set i bagklogskabens tydelige skær - have forberedt mig bedre.

Men tiderne har heldigvis ændret sig, og i dag er versionsstyringsværktøjer allestedsnærværende - hvis man har glemt hvorfor, så kan man kigge i indledningen til denne artikel, for en god og dejlig kort introduktion (artiklen er i øvrigt også god at blive klog af, idet den sammenligner fire rimeligt almindelige versionsstyringsværktøjer).

Men selvom versionsstyring er blevet så udbredt, at det nærmest falder i et med tapetet, så er der stadig nogle overvejelser, som man skal gøre sig. Der er flere grundlæggende forskellige tilgange, med hver deres fordele og ulemper.

Granularitet

Det første man skal gøre sig klart er, hvad der er en grundlæggende enhed for versionsstyringen. Nogle værktøjer versionsstyrer filer (f.eks. CVS), mens andre værktøjer versionsstyrer hele arkivet (f.eks. Subversion).

Hvis ændringer kun er helt uafhængige skridt i en fil ad gangen, så betyder denne skelnen ikke noget, men når ændringer begynder at spænde over flere filer ad gangen, så vil det være en fordel at kunne håndtere ændringerne samlet (i såkaldte change sets).

Værktøjer, som versionstyrer hele arkivet, vil naturligt kunne tilbyde atomare (dvs. "alt eller intet") ændringer, og ændringerne vil være samlet naturligt. I filbaserede værktøjer, vil kan kunne opleve at ændringer kun sker halvt, hvis der er problemer undervejs, og man kan efterfølgende kun gætte sig til sammenhængen ud fra f.eks. tid og kommentar til ændringen (nyere versioner af CVS forsøger at lappe på dette ved at give et unikt "commitid" til alle filer, som sendes til CVS i samme kommando).

Atomare ændringer er specielt vigtigt, hvis man ønsker at håndhæve forretningsregler vha. f.eks. precommit-triggere - det kan ikke hjælpe noget, at man har fået opdateret de to første filer i et change set, hvis man under behandlingen er den tredje fil opdager, at hele ændringen skulle have været afvist.

Bemærk også, at selvom understøttelse af change sets er en stor hjælp til change management, så er det ikke nok. Ændringer vil tit opstå ad flere omgange, og den fulde beskrivelse af ændringen vil derfor være det samlede antal skridt.

Låsning vs. fletning

Den anden store skillelinje er i metoden til at undgå konflikter ved samtidige ændringer (helt uden versionsstyring vil det være den ændring, som gemmes sidst, der vinder...).

Den ene metode er den klassiske låsningssematik: Man kan kun fortage en ændring, når man forud har fået en eksklusiv ret til dette. Dette tvinger ændringerne til at ske serielt i forhold til hinanden, idet en ændring ikke kan starte førend den forgående er afsluttet. Ændringskonflikter vil derfor ikke eksistere. Ulempen er, at man med låsen kan komme til at blokere for andre, og der er de klassiske eksempler på deadlocks og låse som ikke bliver frigivet rettidigt (f.eks. pga. ferier). Låsning fungerer bedst, når der er høj granularitet, lavt overlap og kort låsningstid.

Den anden metode er fletning: Enhver kan foretage ændringer - til gengæld vil man efterfølgende kunne konstatere, når en ændring kommer til at konflikte med en anden ændring - og ansvaret for at løse konflikten påhviler den som kom sidst.

Den typiske måde at løse konflikten på, vil være fletning, som kan ske mere eller mindre automatiseret: hvis en ændring er foretaget i den øverste 1/3 af en fil, og en anden ændringen i den nederste 1/3, så vil en automatisk fletning typisk lade begge ændringerne ske, idet de ikke overlapper. Dette kan selvsagt medføre et resultat, som er absurd eller direkte forkert - i praksis sker det dog yderst sjældent, og hvis der er en passende stringent fortolkning - f.eks. fordi det, som er flettet, er kildetekst til et program - så vil det ofte være åbenlyst, når dette sker.

Fordelen er, at man aldrig bliver stoppet undervejs - medmindre at man rent faktisk render ind i en konflikt.

Ulempen ved fletning er, at det ikke er alt som umiddelbart lader sig flette. Ved billedfiler vil det f.eks. sjældent være indlysende, hvordan to resultater skal kombineres (nogle billedformater indeholder originalen uændret samt en liste af efterfølgende operationer, og i så fald vil man måske kunne flette - men det er absolut specieltilfælde).

Et andet eksempel er typiske tekstbehandlingsdokumenter. MS-Word dokumenter lader sig trods alt manuelt flette i Word, så der kan man slippe omkring det med en vis egen-indsats. OpenOffice's ODF format lader sig heller ikke umiddelbart flette: ODF dokumenter er en zip'pet samling af XML-dokumenter - zip-filer lader sig i praksis kun flette ved at flette indholdet, og XML-dokumenter er godt nok tekstfiler, men jeg mangler stadig at se en god flettealgoritme til XML-dokumenter (hint: tekstbaserede flettealgoritmer er som oftest liniebaserede, og det er XML ikke - derimod er XML hierarkisk i opbygningen, så det hjælper heller ikke at "normalisere" dokumentet).

Central vs. decentral

Den tredje store forskel imellem implementationerne er opstået relativt fornyligt, nemlig decentrale systemer.

Førhen var det altid sådan, at der var et centralt "opbevaringssted" (repository). De fleste værktøjer tillod en eller flere arbejdskopier, men der var altid et sted, hvor man dels kunne finde originalen, dels havde en autoritativ kilde til historikken.

I den centrale løsning vil man hente de seneste opdateringer fra det centrale repository (hvor andre tidligere har sendt deres ændringer hen), og samtidig er det her, at man selv sender sine ændringer hen, så andre også kan få glæde af dem. Der er altså et fast centralt holdepunkt og en lang række satellitter rundt om dette.

Nu er der så kommet decentrale eller distribuerede løsninger til, hvor enhver kopi som udgangspunkt er lige så god som alle andre kopier.

I den decentrale løsning vil man kunne hente ændringer et vilkårligt andet sted fra (hvis dette medfører konflikter vil man selv skulle løse dette) og tilsvarende vil man kunne sende sine ændringer vilkårlige steder hen (inden man kan gøre dette, så vil man selv skulle løse eventuelle konflikter). Der er altså ingen fast rollefordeling. Hvor den centrale løsning nærmest er et hjul med eger, så er den decentrale løsning nærmere et netværk - og vel at bemærke ikke et fast netværk, men derimod mere ad hoc baseret.

Det er oplagt, at modellen med et centralt repository lader sig realisere i den decentrale model (hvis alle er enige om, at lade en knude være "master"). Man kan også forstille sig et hierarki i flere niveauer, hvilket kunne bruges til at modellere states, som f.eks. "under udvikling", "under kvalitetssikring" og "produktionsmodent".

Samtidigt er en decentral udgave af den centrale model langt mindre sårbar. Hvis den centrale knude falder ud - permanent eller midlertidigt - så kan de tilbageværende knuder reorganisere sig og køre videre fra det punkt, som svarer til deres kollektive viden om tilstanden inden udfaldet.

Eller med andre ord: den decentrale model "...gives you plenty of rope to swing with - and plenty of rope to hang yourself!".

Afsluttende bemærkninger

Det lyder indlysende, men det er faktisk vigtigt at kende sin implementation godt.

Et eksempel er, at det med CVS er nemt at finde ud af, hvor slettede filer oprindeligt lå - man laver bare en søgning på den del af serverens filsystem, hvor repository ligger, og når man finder filen i en "Attic"-folder, så ser man, hvor denne folder er placeret.

Et andet eksempel er, at CVS er case-sensitiv/in-sensitiv afhængigt at det underliggende filsystem. Arbejder man med forskellige filsystemer på hhv. server og klient, så vil det være en god ide, at have en klippefast konvention for case.

Et tredje eksempel er, at man i CVS kan slette eller flytte filer permanent inkl. historik, ved at manipulere filsystemet på repository direkte (det ødelægger til gengæld godt og grundigt muligheder for at reproducere tidligere versioner (forstået i videste forstand) ud fra reposity...!)

Et fjerde eksempel er, at Subversion i fsfs formatet for repository gemmer hele changesettet i en enkelt fil - det er altså ikke muligt at committe en ændring, som samlet set er større end den største filstørrelse på det underliggende filsystem, også selvom de enkelte ændringer ikke overstiger den.

Et femte eksempel er, at Subversion i working copy gemmer en kopi svarende til repositoryversionen til sammenligning (det gør dels at netværkstrafikken bliver minimeret, idet der kan kommunikeres med deltaer, dels at ændringsdetekteringen bliver mere robust, men også at pladsforbruget bliver fordoblet).

Hvordan finder man ud af det? Som så meget andet ved at få praktiske erfaringer. Så der er ikke andet for end at komme i gang med et eksperimentere, vel?

mandag den 1. oktober 2007

Seam carving del II

Jeg skrev tidligere om teknikken til at skalere billeder, som hed Seam Carving. Det lader til, at jeg ikke var den eneste, som var fascineret, for der er sket en hel del. Denne artikel om Seam Carving indholder bl.a. link til en flash applikation, så man kan prøve at seam carve sine egne billeder - og et link til et plugin til GIMP.

Hvis du synes, at teknikken forvrænger essentielle dele af dit billede, som f.eks. ansigter, så kan du beskytte dem, ved at "male" dem med positiv energi. Samtidig kan man få dele at billedet til at forsvinde hurtigts muligt, ved at "male" det med negativ energi. Se videoen i min første blog om emnet for en illustration.

Her er et lille tilfældigt valgt eksempel:

som efter en gang seam carving til 75% vidde og 90% bredde bliver til flg. (thumbnails blev en anelse opskaleret i forbindelse med opload, så kig på originalerne):


Bemærk også at seam carving kan bruges til at udvide billeder, hvor det mindst kan ses.

lørdag den 29. september 2007

Snotforkælet...

Prøv lige at kaste et blik på denne blog.

Der er to andre interessante observationer, som jeg også gerne vil byde ind med:
  • Nutidens pensionister har ikke betalt ind til deres egen pension via de mange penge, som de har betalt i skat i tidens løb. Faktisk har de kun betalt omkring 1/4-del af de nødvendige penge. Grunden til at forretningen løber rundt nu er dels, at fortidens pensionister var færre, billigere og levede kortere (og sådan bliver det ikke ved med at være), samt at kagen som vi deler i dag er væsentligt større end dengang (fair nok, men det gør ikke påstanden om, at de nu lever af egne "opsparede" penge mere rigtig...).
  • Den såkaldte "danske model" sikrer ikke de svage på arbejdsmarkedet. Faktisk er den skruet sammen på en måde, så de ca. 3/4 som sidder på flæsket er i stand til at holde den resterende 1/4 ude, så de ikke trykker lønner. Når arbejdsløsheden stiger eller falder, så er det stort set et spørgsmål om, at den marginaliserede 1/4 er arbejdsløse i længere eller kortere perioder (se f.eks. de såkaldte vismandsrapporter - og specielt rapporten fra juni 1988). Ikke særligt solidarisk.
Man hytter sig selv og sine...

Svamp

Jeg har fået svamp! Ja, ikke den slags svamp - en der vokser ude i haven. Vi fandt den faktisk allerede for et par dage siden, men nu havde vi tid til at kigge ordentlig på den.

Umiddelbart ser den ret uskyldig ud, men da jeg gik min svampenøgle (Politikkens visuelle svampebog) igennem, da havnede jeg på Snehvid fluesvamp.

Om den står der flg.:
En af vore få dødeligt giftige svampe. Giftstoffet er en cellegift som ødelægger lever og nyre.
Nå, da! Jeg er nu ikke sikker på, at det er en fluesvamp, for den voksede ikke som forventet i nærheden af træer, den lugtede faktisk ikke sødligt-vammel men derimod mere af champignon, og så kunne jeg ikke finde de hatskæl, som man ellers skulle forvente.

Svampebogen forudsætter med flg. passus om forvekslingsmuligheder:
Bliver forvekslet med champignoner, men disse har farvede (først lyserøde siden brune) lameller, og mange af dem vokser ofte på åbent land uden træer i nærheden. Fluesvampen vokser altid i nærheden af træer. Unge eksemplarer af champignoner kan have hvide lameller og i så fald skal man lade dem stå, indtil man er så øvet, så man uden tøven kan kende dem fra hinanden.
Jeg er derfor ret sikker på, at det er en champignon, som jeg her har fundet. Men lamellerne var hvide, og kald mig bare en tøsedreng, for jeg følger svampebogens råd og smider den ud.

...jeg vil dog godt indrømme, at jeg er lidt skuffet - det kunne have været sjovt, hvis der havde været en dødeligt giftig svamp i min have!

fredag den 28. september 2007

Nomen est omen

I vores branche elsker vi, når navnet siger noget om indholdet. Sigende navne kalder vi det, og det gør der muligt at danne sig et overblik uden at skulle gennemgå alle detajler.

Men hvad med det modsatte? Vildledende navne må de vel kaldes. Det morsomme er her, at når et navn er vildledende, så er det som oftest ikke direkte absurd, men siger derimod noget om, hvad indholdet burde have været. Et par hurtige eksempler:
  • Hjemmelavet marmelade fra supermarkedet
  • Reje ost (OK, der er rejer i, men ikke så mange som man skulle tro)
  • Socialistisk Arbejder Parti
  • Den Tyske Demokratiske Republik.
... og find selv på flere.

Nu er der kommet en ny til listen: Microsoft Permissive License (Ms-PL). Microsoft har sendt licensen til review hos OSI - og foreløbigt fået den besked tilbage, at enten gør de licensen permissive eller også finder de på et andet navn (se f.eks. her eller her eller her).

Hvad synes jeg så? Jo, jeg kan jo dels godt lide, når der er rav i den, og så synes jeg faktisk at det er fint at der er folk med rimelige principper, som også står fast på dem.

PS: Lyder "Microsoft Limited Permissive License (Ms-LPL)" ikke som et bedre navn? Synd at det allerede er taget.

torsdag den 27. september 2007

Detailplaner og scrum

I denne uge havde jeg den store fornøjelse at deltage i JAOO konferencen. Det er svært at finde et foredrag på konferencen, hvor man ikke går der derfra med noget at tænke over.

Et af de mange foredrag som jeg hørte, var om scrum (jeg tror at det var Hubert Smiths Planning in Large Companies), og der var der på en af slidene et billede af tavlen fra et sprintplanlægningsmøde. Tavlen var relativt velordnet, med store sedler i en farve til de stories som teamet havde taget ind i sprintet - og under hver story-seddel, en søjle med fine sedler i en anden farve, med de aktiviteter som teamet havde fundet frem til. Så langt, så godt.

Men så var det, at alle deltagere i teamet, ud for hver seddel, havde noteret, hvor lang tid de regnede med at skulle bruge på de enkelte opgaver i dage - og disse tider var, med initialer, overført til sedlerne. Det undrede mig, for i det scrumteam, hvor jeg p.t. deltager, er vi gået væk fra have tider og initialer på opgaverne. Jeg var ikke den eneste som undrede mig, for et af spørgsmålene fra salen var netop til disse tider.

Svaret var, at det var et forsøg på at sikre, at der var en nogenlunde ensartet belastning på alle deltagere i teamet - eller med andre ord en slags ressource leveling. Det er klart at man bør undgå en al for stor forskel imellem opgavernes karakter og teamets kompetencer, så intentionen er god nok (vi har også været præcis der).

Der var flere grunde til, at vi gik væk fra det:
  • Når opgaverne allerede er estimeret på storyniveau, så tilføjer det umiddelbart ikke nævneværdig værdi at nedbryde dette estimat på delopgaver. Der kan være en fordel i at kunne måle fremdriften, men det introducerer et administrativt overhead. Hvad værre er, så åbner det en breche overfor andre om, hvorvidt det giver vil give mening at gøre en story halvt eller 3/4-dele færdig for at kunne klemme en anden story ind - and it ain't over 'til the fat lady sings!
  • Hvis man under sprintplanlægningen allerede fordeler opgaver på folk, så er der en kedelig tendens til, at denne plan hænger ved - det bliver med andre ord også de folk, som kommer til at lave opgaverne. Man kan sige, at forskellen på papiret ikke er stor, men rent mentalt så er man ikke et team længere, hvis der på forhånd er dine og mine opgaver - den største fordel ved at team går fløjten, hvis opgaverne ikke er "vores opgaver"!
Efter min mening, så er der også andre udfordringer ved at forsøge på at lave ressource leveling, som nok ikke umiddelbart ødelægger sprintet, men som man alligevel skal have for øje:
  • Man kan nemt i forsøget på millimeterretfærdighed komme til at overse de dynamiske effekter. Det kan godt være, at der er ligeligt med opgaver til alle, men hjælper ikke noget, hvis der er nogle, som kun har opgaver som naturligt ligger først ... eller til sidst. I et godt team vil teamet arbejde udenom udfordringen, men værdien af forsøget på ressource leveling er gået fløjten.
  • Den anden fælde er, at man begynder at tilpasse opgavesammensætningen til teamet kompetencer og ikke omvendt. Teamet skal kunne levere det som giver værdi, og ikke det som det tilfældigvis er bedst til. Det tager selvfølgelig tid at få et godt team op at stå, så for en tid kan det give mening at lade opgaverne tilpasse sig teamet i nogen udstrækning - og på samme måde er det jo ideelt, hvis teamet kan opsøge opgaver, som passer til kompetanceprofilen. Det er bare vigtigt, at der ikke bliver byttet om på årsag og virkning.
Nu kunne man så sikkert godt forledes til at tro, at jeg taler for, at man helt skal ignorere, i hvor høj grad de enkelte deltager kan byde ind i et sprint - eller for at man helt ignorerer opgavesammensætningen. Det gør jeg så langt fra. Det er et vigtigt input til planlægningen at vide, hvordan teamet er sammensat - og det er naivt at ignorere effekten af f.eks. ferier og uddannelse.

Det som er vigtigt er, at teamet kan tro på at planen er realistisk, og hvis det indebærer, at teamet under sprintplanlægning vurderer på delopgaver og mulige ressourcer til dette, så er det helt fint med mig. Det som jeg hæver en solid pegefinger overfor er, dels at give det mere vægt end som input til en "mavefornemmelse" og dels at tage detailplanen med ud fra sprintplanlægningsmødet. Detailplaner er nok nyttige, men også yderst farlige, og skal derfor holdes i meget kort snor - ellers risikerer man at ødelægge mere end man gavner.

søndag den 23. september 2007

Kolonnebaserede databaser

Der er kommet en blog, som lover at snakke om databaseteknologi og innovation. Det lyder lovende, selvom det indtil videre hovedsageligt har været en platform at promovere et nystartet firma, hvis eksistensberettigelse er at de vil implementere en kolonnebaseret database (column database).

Jeg holder nu øje med den, for når man samler visionære og velformulerede folk, så vil der ofte falde noget af, som man kan blive klogere af. For mig var det da også her, at jeg første gang hørte begrebet "kolonnebaserede databaser".

Og hvad er en kolonnebaseret database? Egentlig er det i udgangspunktet meget simpelt: det er almindeligt for databasesystemer at lagre tuplerne i en relation som fortløbende rækker i en tabel - en kolonnebaseret database derimod vil lagre attributterne hver for sig i hver sin tabel, og så genskabe tuplerne ved attributterne i en tupel alle har samme position i de respektive tabeller.

Den første iagttagelse man kan gøre sig, er at det ikke ligefrem er noget stort. Hvordan man fysisk organiserer sin storagestruktur er vel en implementationsdetajle, som ingen databruger i princippet bør bekymre sig om, på linje med f.eks. indekser og matrialiserede views - og alle eksisterende relationelle databaser ville da også kunne tilbyde kolonnebaseret storagestruktur uden at skulle ændre funktionalitet udadtil.

Interessant er det alligevel, fordi der i hvertfald i teorien, burde være nogle solide performancegevinster at hente i en række almindelige brugsmønstre. Det ser umiddelbart ud til, at gevinsterne er størst for databaser, hvor læsninger er meget mere hyppige end opdateringer (hvad dels er tilfældet for mange databaser, men selv i opdateringstunge databaser er der ofte relativt statiske hjørner af schemaet).

I praksis så har tabeller en tendens til at knobskyde voldsomt over tid (og jo større datamængderne er, jo mere modstand er der imod at refaktorere, så der er ofte tale om en ond spiral...). Men for at føje spot til skade, så er der folk som insisterer på at skrive select * from ... i andet end ad hoc queries - og de burde indkaldes til en kammeratlig samtale med kodepolitiet, og i gentagelsestilfælde fratages deres kodelicens! Ydermere så ser man ofte mapningsværktøjer (f.eks. ORM-værktøjer), som insisterer på altid at læse hele tuplen.

Imod tåbelige brugere eller værktøjer, er kolonnebaserede databaser også magtesløse, men de kan give en umiddelbar gevinst ved dels, at man under dannelse af udtrækket (join og restriktion), og dels i realiseringen af selve resultatet (selektionen) ikke behøver at læse fulde records indeholdende alle felterne i hver tupel, men kan nøjes med at læse de attributter, som er relevante. Det er tilsvarende en queryoptimization, hvor man nøjes med at læse i indekses, hvis man kan finde et som indeholder alle de ønskede felter, i stedet for at læse i tabellen - også selvom den orden som indekset implicerer ikke er relevant.

En anden oplagt fordel med at opdele i kolonner er, at hver tabel har sit eget simple domæne, og at der derfor er væsentlig mindre spredning i værdierne. Indholdet lader sig derfor nemmere komprimere, og med læsehastigheden på eksterne lagringsmedier som en flaskehals, så vil det kunne være en fordel (der er langt mindre spredning i f.eks. folks efternavne end der i en fuld adresse).

Hvis man ydermere kan antage noget som orden i ens domæne eller såmænd bare i det typiske brugsmønster, så kan man sortere data efter dette. Dette vil give langt større muligheder for komprimering - i stedet for at liste alle som hedder "Nielsen" enkeltvist, så kan man nøjes med notere sig, hvor mange der er af dem, hvis man har data sorteret efter efternavn. Selv hvis man først sorterer efter by og derefter efter efternavn, så vil der stadig være mange med samme efternavn i hver by.

På den anden side, så vil kendte implementationer af relationelle databaser i dag allerede støtte flere typiske brugsmønstre med f.eks. indekser og matrialiserede views. Den store fordel ved at være kolonnebaseret vil muligvis kunne høstes ved, at man kan afvikle sine queries direkte på de komprimerede data, så man helt undgår overheadet med at skulle dekomprimere førend resultatet skal realiseres. At kunne arbejde direkte på komprimerede data kan også medføre mere effektiv håndtering af queries, f.eks. fordi at en cache af komprimerede data kan indholde større mængde af data end en tilsvarende for ukomprimerede data.

Så - for at summere op - selvom kolonnebaserede databaser ikke ved første øjekast ser ud til at være noget stort, så sker der interessante ting ved at dreje ens synsvinkel på lagringen af data 90 grader. Specielt i betragtning af, hvor ofte query-optimering i praksis går ud på at eliminere full tablescans...

torsdag den 20. september 2007

lorem ipsum

Hvis man har arbejdet med layout - det være sig GUI eller f.eks. på papir - så er der meget stor sandsynlighed for, at man har mødt noget, som ligner flg. tekst:
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Det ligner latin, og så ikke helt alligevel - og sandsynligvis så er det ment som en vrøvletekst, så man kan vurdere layout, som f.eks. valg af skrifttyper, ombydning el.lign., uden at blive forstyrret af indhold. Teksten har været en del af vores branche fra første gang, hvor vi begyndte at bekymre os om layout (alle der ved, hvad en leporelloliste er, rækker hånden op...!).

Men faktisk går rødderne sandsynligvis længere tilbage. En trykker lavede i år 1500 (eller der omkring) et ark med eksempler på skrifttyper med denne tekst, og noget tyder på, at han er blevet inspireret af ingen ringere end Cicero. Cicero skrev en menneskealder eller to efter Kristi fødsel et essay om "Godt og ondt" og i det siger han bl.a.:
Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, ...
Nu skal jeg ikke foregive at kunne latin, så jeg vil straks indrømme, at jeg har kigget forskellige kilder, og tør derfor godt vove det ene øje, når jeg nu påstår at det kan oversættes med:
Der er ingen som elsker eller søger eller ønsker smerte for smertens egen skyld...
Nu er Cicero jo ikke en person, som man bare sådan lige skal affeje, men der er nu nogen, som mener, at her tager han fejl. Personlig sidder jeg og overvejer hvorfor man dengang for 500 år siden ikke har valgt sekvensen ved siden af, som snakker om glæde? Måske var det en godt skjult kommentar om, hvad han mente om kunder - og i så fald, så er der jo intet nyt under solen...

onsdag den 19. september 2007

Billeder på nettet

Det er underligt, som udviklingen kommer i spring. I lang tid kan et område stå stille, og så pludselig, så sker der tigerspring, som vender op og ned på alt hvad man har ellers har taget for givet. Og et spring kommer sjældent alene.

Grafik eller billeder på nettet har egentlig i lang tid været statiske klumper, der kunne bruges som illustration - som små malerier med smukke guldrammer, som vi kunne hænge på vores hjemmesider. Men de har også været temmeligt besværlige, for de har en normal størrelse (og det er som om, at den sjældent helt passer). Man kan selvfølgelig skalere billeder (så passer de til gengæld oftest kun på den ene led...). Sådan er det bare, ikk'?

Ja, sådan troede jeg at det var, indtil jeg så denne videopræsentation af en teknik, som hedder Seam carving.

Grundtanken er, at man finder den sti igennem billedet, som bidrager mindst til det (der er næsten altid noget blå himmel eller en ensfarvet væg), og så fjerner man en række pixels der. Eller sætter en ny række ind der. For det er der det mindst kan ses. Kunsten er "bare" at finde den sti.

Det er oplagt, at der er en del fotografer, som vil få et veritabelt føl på tværs, når de ser hvad man kan gøre med deres billeder. Specielt de purister, som mener, at billeder er objektive og at enhver form for efterbehandling er manipulation grænsende til forfalskning. Jeg venter bare på ramaskriget!

Seam carving er et forslag til at løse skaleringsproblemerne, men der er jo grænser for hvor meget man kan forstørre eller formindske. Eller er der?

Prøv så at tage et kig på teknologien PhotoSynth, som foreligger i demoform med ophav hos MicroSoft og University of Washington (der er tre gode links videre fra artiklen).

PhotoSynth er vel nærmest panoramaer på sterioder! Man tager en samling af mere eller mindre relaterede billeder og så finder man overlap. Kombiner det med metoder som gør, at man kan blænde fra et billede og over i et andet. Det gør at man kan se oversigtbillleder, og når man vil kigge nærmere på detajler, så "zoome ind" ved at skifte til et andet billede, som er taget med et mere snævert udsnit. Eller navigere til den ene side ved at skifte over til et andet billede som overlapper til den side. Og så videre.

Jeg kan huske den gamle tanke om et netværk bundet sammen af hyperlinks (jeg husker specielt HyperCard) - det her er en visual realisering af samme vision - visionen om hvordan man kan gå på opdagelse og fortabe sig i detajlerne ved at gå ud af en vilkårlig tangent - og pludselig opdage at man er kommet et helt andet sted hen end der, hvor man startede.

Tænk sig at turistbilleder på den måde pludselig kan blive værdifulde...

lørdag den 15. september 2007

God unittest?

Det er ikke så frygtelig lang tid siden, at alle talte om unittest, men ingen lavede dem. Nu er det som om, at der ikke rigtigt er nogen som taler om dem længere, men alle laver dem. Er det udtryk for, at unittests generelt har nået en modenhed, som gør, at der ikke er mere at sige om dem? Nok desværre ikke. Men hvad er det så for diskussioner som er blevet væk?

Det første gode spørgsmål, som man kan stille sig selv er, hvor stor en unit til en unittest? Der kan der siges meget klogt om, men svaret på det må være, at det er så meget som det giver mening at teste selvstændigt.

Hvor meget?

Det er oplagt, at kompleksiteten af de små enheder, er væsentligt mindre end større helheder, og at kompleksiteten stiger voldsomt selv ved små forøgelser at størrelsen. Det er derfor en god ide at starte i det små, og verificere de enkelte dele inden man går videre og verificere at man kan koble dem sammen i større og større strukturer og systemer. Ved at benytte sig af, at man kan antage, at delene allerede fungerer, så er det muligt at hæve abstraktionsniveauet på testen af helet, så man ikke så hurtigt bliver indfanget af den stigende kompleksitet. Alligevel er det oplagt, at der hurtigt bliver tale om størrelser, som det ikke giver mening at teste selvstændigt - programmer afhænger simpelthen er for mange faktorer som kun dårligt lader sig kontrollere.

Med andre ord vil det give mening at have test på integrationsniveau som unittests - hvis bare man holder for øje, at det skal kunne testes selvstændigt.

Men hvor små enheder skal man så starte med at teste? Hvis man har valgt en objekt-orienteret tilgang til at strukturere ens program, så giver svaret næsten sig selv - det er objektet og dets metoder.

Min kode kan ikke unittestes...

Er de objekter, som vi opbygger vores programmer så tilstrækkeligt uafhængige til at vi kan teste dem selvstændigt? Desværre kun alt for sjældent og det skyldes som oftest at programmet trods alle gode intentioner er endt med at have en uklar ansvarsfordeling og for funktionaliteten efterhånden er blevet godt og grundigt sammenfiltret. Og som om det ikke er rigeligt med udfordringer, så er nogle programmer er nok opbygget af klasser med metoder, men uden at være spor objekt-orienterede i deres struktur - der er passive data i nogle klasser og tilstandsløs funktionalitet i andre .

Er man endda så uheldig at man står med en større mængde eksisterende kode, som aldrig rigtigt at blevet unittestet for alvor, så vil man ofte opdage at det er opbygget på en måde, som er direkte fjentlig overfor lade sig teste selvstændigt (inden man giver op, så er der dog god hjælp at hente f.eks. i Michael Feathers bog Working Efficiently with Legacy Code - her er modsvar til alle de undskyldninger som jeg i tidens løb har set for at man ikke kan unitteste, samt en lang række undskyldninger som jeg ikke havde fantasi til... læs den inden du igen siger, at du har kode som ikke kan unittestestes!).

Hvis vi vil unitteste, så tvinger det os med andre ord til at skrive kode, som kan fungere selvstændigt. Vi bliver altså nødt til at overveje ansvarsområder, interfaces, afkobling af afhængigheder (f.eks. vha. dependency injection). Og vi bliver nødt til at læse programkoden for at kunne skrive testen. Og det er faktisk her, at mange folk mener at den egentlige værdi af en unittest ligger: At den tvinger os dels til at skrive god koden, for kode der ikke kan testes er som oftest dårlig kode - og til at reviewe vores egen kode, når vi skriver testen.

Selve testen

Unittest stiller ikke kun krav til den kode, som skal testes - en god test opstår ikke uden videre (som mange har lært på hårde måde, og som alt for mange desværre stadig har til gode at indse).

Det første og helt indlysende krav, som man kan stille til en unittest er såmænd, at den tester noget. Jeg har set eksempler på unittest som godt nok huskede at kalde noget programkode, men derefter glemte at antage noget om effekten (bevares, helt uden værdi er det ikke, for man har da i det mindste fået testet, at koden kan formå at returnere normalt efter at være blevet kaldt...).

Et andet, og måske knapt så indlysende, krav er, at testen alene skal kunne svare på om der er en fejl eller ej. Hvis der er en fejl af den type, som man tester for, så skal testen kunne fejle. Og hvis den ikke er der, så må den ikke fejle. Uanset hvor mange gange man kalder den. Jeg har set unittest, som testede webservices ved at kalde en anden server - sjovt nok, så fejlede den hver gang at der var netværksproblemer, hvilket hver gang satte grå hår i hovedet på den stakkel som ikke kunne se, hvordan hans rettelse kunne have påvirket webservicen. Jeg har også set unittest, som baserede sig på at gemme hardkodede værdier i en fælles database - med den effekt, at man kun kunne køre en instans af testen - den stakkel som kom som nummer 2 ville se testen fejle uforklarligt.

Oplevelser som mine har sandsynligvis været ophav til flg. tommelfingerregler om unittests fra Micheal Feathers hånd: En unittest
  • må ikke bruge en database
  • må ikke bruge netværk
  • må ikke bruge filsystemet
  • skal kunne afvikles samtidigt
  • må ikke krave manuel konfiguration
Et yderligere krav (som i øvrigt bliver nemmere at opfylde, hvis man overholder ovenstående) er, at unittest skal kunne afvikles hurtigt. Her tænkes på, at testens afviklingstid ikke skal måles i sekunder, men derimod i millisekunder - jeg arbejder for tiden på et projekt med kun omkring 45% coverage og der er alligevel over 2500 tests. Det kommer hurtigt til at løbe op, hvis ikke man passer på.

Ingen af kravene er dog endegyldige - jeg har haft stor værdi af unittests, som kaldte de udtræk fra databasen, som programmet brugte - databaseschemaer er ikke en statisk størrelse over tid, og de er ofte ganske løst koblet til programmet. At opdage at tæppet er blevet trukket væk under en af en databaseændring, er mere værd end det overhead, som det introducerer i kørselstid hhv. den usikkerhed om resultatet, som det introducerer at være afhængig af at databaserserveren er altid kørende og velfungerende.

Pointen om at undgå databaseadgang er dog god nok. I stedet for at inline databasekode i forretningslogikken, hvorved man ikke kan teste sin kode uden at stable et større fixture på benene i databasen, så bør man afkoble sin forretningslogik fra databasetilgangen og teste de to ting adskilt.

Et eksempel: I stedet for at have en hel postnummertabel i databasen som en del af forudsætningen for en test af validering af adresselister, så lav en metode til at finde postnumre i databasen postnummertabel, test denne - og stub den så iøvrigt af i logikken til validering af adresser (ved f.eks. at lade stubben have et memory baseret map...). Programkoden er blevet nemmere at læse og forstå, det bliver nemmere at finde og rette evt. fejl, og testen kører en størrelsesorden eller to hurtigere! Der er kun fordele...

Kvalitetssikring af test

Er der så hjælp til at få gode unittest. Ja, da.

Et af det mest oplagte - og heldigvis også mest udbredte - værktøjer, er coveragemålinger. I stedet for at tro, at man rammer de tiltænkte dele af programkoden, så kan man prøve det, og efterfølgende se at man rent faktisk gør det (eller måske mere realistisk - at man ikke rammer det man troede). De simple udgaver måler linecoverage, og det er da også et godt udgangspunkt. Men det kan være misvisende, og derfor er et bedre mål, det som ofte kaldes branchcoverage. Branchcoverage måler ikke bare, at man rammer alle linjer, men også at man får afprøvet alle mulige veje igennem programkoden - eller med andre ord, at man kommer forbi alle beslutningspunkter.

Aktivt at bruge coveragemålinger når man udvikler en unittest, er de første gange en ganske lærerig oplevelse. Man mærker hurtigt, at man som udvikler kun er vant til at tænke i positive normaltilfælde (ja, som konstruktør i videste forstand, for jeg vil godt tage analytikere og designere med i båden, selvom de ikke skriver så mange unittest som os andre...) - man mangler næsten altid at tænke på fejlhåndtering og undtagelser.

Man kan ikke snakke om coveragemålinger uden også at snakke om coverage procenter. Hvor stor en coverage skal man have for at det er godt nok? 50%? 90%? 100%? Tja, som udgangspunkt er mere bedre, men der er et par solide forbehold:
  • Der er tale om en stigende omkostning og et faldende udbytte (der er en faldende grænseværdi). Man skal med andre ord gøre sig klart, hvor meget man vil betale for de ekstra procenter (og man laver dette for at finde eller undgå fejl - hvor sandsynlig er det at der gemmer sig en ekstra fejl i det sidste procentpoint?). Eller sat på spidsen: Kan det virkelig betale sig at jagte den sidste toString(), som kun bruges til debugning?
  • Ikke alle procentpoint er lige meget værd. En tommelfingerregel siger, at 20/80 reglen også gælder for fejl i programkode, og derfor vil jeg hellere have høj dækning på de 20% af koden som har stort fejlpotentiale end høj dækning i resten. Hvis 40% coverage dækker over 100% dækning på de farlige 20% af kodebasen og 25% dækning af resten, så er det langt bedre end 0% dækning af den kritiske del og 50% dækning af det trivielle.
  • Det er ikke nok, at ramme en kodelinje - man skal også bruge det til noget (se ovenfor).
  • Generel coverage har - specielt med dårlig opdelt og afkoblet kode - en tendens til at overvurdere effekten, da der også bliver talt "collaterals" med. Eller sagt på en anden måde, det var langt fra alle mine point i dart som kan tilskrives evne og omtanke - mange point er bare heldige forbiere!
Jager man coverage uden at tage stilling til risiko og effekt, så risikerer man at få testet det trivielle grundigt, og slet ikke det vanskelige. Hånden på hjertet, så vil der nok være en tendens til at bruge tid på de lavhængende frugter, hvis der ikke er anden motivation for at prioritere anderledes.

Synes man stadig ikke, at coverage er høj nok, så bør man kaste et blik på Guantanamo: Al kode er skyldig indtil testet uskyldig - og skyldig kode slettes! Så kan man hurtigt få coverage op. Når man nærlæser værktøjet beskrivelse, så opdager man, at det trods alt ikke er så slemt - al utestet kode antages at være kandidat til at blive slettet, så der genereres et parallelt sourcetræ, som kun indeholder testet kode - så kan man selv vurdere, om man tør erstatte sin "rigtige" programkode, og i hvilket omfang.

Folkene bag Guantanamo har faktisk en anden interessant tanke: Instrumenter produktionskoden, og slet efterfølgende de dele af programmet som ingen bruger... det vil nok kræve nogle rimelig lightweight instrumenteringer - men hvis måleperioden er lang nok, så kan man nøjes med en sandsynlighedsbaseret måling. Specielt hvis det kun skal bruges som inspirationsgrundlag (mit aktuelle projekt har "mørk kode" - kode, som kun skal bruges, hvis uheldet er ude - sådan en kode vil (forhåbentlig) aldrig blive kaldt i praksis, men er stadig yderst relevant at teste og at have med i kodebasen).

Et tilsvarende ekstremt værktøj er AshCroft: Der er stadig i høj grad tale om work-in-progress, men den nuværende version bruger en Java Security manager til at sikre, at man ikke kalder kode i mere end den ene klasse, som man ønsker at teste (plus de nødvendige stubbe). Så kan man lære det!

I en anden boldgade ligger værktøjer Jester. Tanken bag Jester er, at forsøge at teste om unittesten rent faktisk tester noget. Jester vil derfor mutere koden som testes, så der med vilje introduceres fejl. F.eks. vil den ændre if-sætninger (ved f.eks. at skrive not foran betingelsen) i den forventning, at en god unittest vil fange det som en fejl - fanger unittesten det ikke, så rapporterer Jester det som en fejl i unittesten!

Bliver vi klogere?

De fleste lærer heldigvis af deres fejl - men der er en hurtigere (og efter min mening mere behagelig) måde, og det er at lære af andres erfaringer.

Jeg har ovenfor henvist til Michael Feather bog Working Efficiently with Legacy Code - den kommer med mine varmeste anbefalinger. Han adresserer på glimrende vis alle de udfordringerne der kan være at få unittest op og stå i forbindelse med eksisterende kode, både egen og andres.

Står man som Moses foran det Røde hav, og ikke aner, hvad man skal gøre, så er en god introduktion bogen Pragmatic Unittesting - det er som alle bøger i Pragmatic Programmer serien nærmest at sammenligne med Pixie-bøger, men en gang imellem er det meget rart at få en nemt læst bog imellem hænderne, som klart tager stilling til, hvad der er vigtigt og hvad der kan ignoreres i første omgang. Har man prøvet at skrive mere end en håndfuld unittests, så er udbyttet af bogen nok temmeligt ringe (men på den anden side, den er, som tidligere sagt, meget nemt læst...).

Har man brug for noget med mere kød på (og der står jeg selv nu), så vil jeg tro at bogen xUnit Test Patterns: Refactoring Test Code ville være værd at kigge på. Det står højt på listen over bøger, som jeg skal have kigget nærmere på.