torsdag den 25. juni 2009

Galileo er her!

Så skete det, Galileo er frigivet ... hent den før din nabo.

(for jer, som ikke lige er java-udviklere af Eclipse overbevisningen, så er der altså tale om en ny version af et udviklingsmiljø)

onsdag den 24. juni 2009

Du er, hvad du spiser...

Når man kommer sydpå ad motorvejen gennem Gudenådalen ved Randers, så møder man på vej op ad den sydlige skrænt et ekstra spor med en usædvanligt "80 km/t"-angivelse. Jeg har oplevet at køre med folk, som har spurgt, hvad det nu var for noget, og som har kigget lettere uforstående på mig, når jeg har sagt, at det er da et krybespor - eller mao. et vigespor til trafik, som ikke har kræfterne til at holde farten op ad bakken. Og jeg kan sådan set godt forstå denne undren, for det er godt nok lang tid siden, at jeg sidst har oplevet, at det er blevet benyttet - men det var rigtigt godt at have tilbage i de tider, hvor jeg var en lille knægt.

Nu skal dette indlæg ikke være en tur ad barndommens gade; den første del-pointe, som jeg vil hen til er, at der er sket meget med biler og motorer siden dengang: i min fornuftigt prissatte lille Skoda stationcar har jeg nok mere overskud op ad den bakke nu, end min bedstefar dengang havde i sin Ford Escort sportsmodel med registerkarburator! Der er tale om to vidt forskellige biler - min er fremstillet med langt højere præcision, og har derfor en langt højere effektivitet. Faktisk tror jeg slet ikke, at min bil ville kunne klare at køre særligt længe på det brændstof, som man kunne få dengang, hvis den overhovedet ville køre ... og det er i virkeligheden min egentlige pointe: når "maskinen" bliver høj-effektiv, så skal "brændstoffet" være i topkvalitet.

Nu skal dette indlæg heller ikke handle om biler, men derimod om scrum, product owners og backlogs. Det er bare en observation, som er så intuitivt rigtig, at jeg lige ville gå omvejen, inden jeg kommer til den (hold godt fast, nu kommer der et par sætninger med langt imellem punktummerne): hvis man tager et led i den værdikæde, som udgår softwareudvikling ud, nemlig implementationsdelen, og man toptuner den til at blive en højtydende kodeskrivningsmaskine ved at f.eks. bruge scrum (og hvis man virkelig får scrum til at fungere), så bliver det pludseligt tydeligt, at maskinens effektivitet afhænger af, og er begrænset af, kvaliteten af det input, som den bliver givet. Hvis opgaven med at levere klare opgaver (som man i scrum-regi uddelegerer ansvaret for til product owner - uden at han dermed behøver at være udførende) fejler, så man kun får halvgåede eller middelmådig opgaver ind, så vil resultatet af at køre dem igennem en højeffektiv maskine, justeret over tid til med hårfin tolerance at eliminere ethvert spild, i bedste fald være halvgået eller middelmådigt ... og på længere sigt slide maskinen ned.

Jeg ville her gerne kunne sige, at det er noget, som jeg selv har fundet på, men det er det ikke helt - hvis jeg kan læse indenad, så er det faktisk en af pointerne i, hvad Carsten Jakobsen og Jeff Sutherland siger i et paper kaldet "Scrum and CMMI – Going from Good to Great: are you ready-ready to be done-done?", som de vil præsentere på Agile2009 konferencen. Hvor jeg kun har min mavefornemmelse at have synspunktet i, så henviser de til en lang række praktiske observationer - og i øvrigt har de også andre gode pointer undervejs.

Så hvis du, kære proces-ejer, står med en lyst til at køre hele skidtet en tur til mekanikeren, så tag lige at overvej, om det måske i stedet for kunne være kvaliteten af inputtet, der har et (ahem!) "forbedringspotentiale"? I så fald, så få en god snak med den, som er indsat som product owner, om hvor vigtig en rolle han spiller, og om ikke det kunne gøres bare lidt bedre? Det er både billigere, og det virker bedre. Du er, hvad du spiser...!

lørdag den 20. juni 2009

Vedligeholdelsesfri dokumentation

Prøv lige at smage på de ord: "Vedligeholdelsesfri dokumentation" - lyder det ikke godt? Smag bare lidt mere på det, mens jeg afslører, at jeg tror at det ca. lige så umuligt som "slanke-chokolade" og "sundt slik".

Bevares, hvis kakao-indholdet i chokolade er højt nok, så skulle det vistnok kræve mere energi at fordøje end man kan optage fra det - og den form for tørret frugt, som kalder sig selv for "sundt slik", er nok heller ikke så slemt (ikke mindst fordi, at man sjældent hører om nogen, som spiser en hel pose af det på en gang!).

På samme måde vil en dokumentation, som beskriver noget, som aldrig ændrer sig, være så godt som vedligeholdelsesfri (helt frit bliver det kun, hvis dets kontekst også er statisk). Og jeg hørte for nyligt om et eksempel, hvor man skulle bruge en adapter til et ældgammelt system, og hvor man pustede støvet af de gulnede ark med dokumentationen systems kommunikationsprotokol, og på rimelig tid ud fra dokumentationen alene lavet en velfungerende nyimplementation af protokollen i et moderne sprog. Men kan vi ikke godt blive enige om, at det så absolut er undtagelsen?

Så, som tommelfingerregel, så koster det at have dokumentation. I øvrigt koster det også at finde den, når man skal bruge den (og jo mere man har, jo sværere kan det blive); og det koster såmænd også at bruge den. Personligt har jeg i hvertfald tit oplevet at bruge længere tid på at læse al den relevante(?) dokumentation, end på rent faktisk at arbejde med ændringen - og det fraregnet tiden med at finde den i første omgang.

Hvad får mig så lige til at skrive det - jo, som Mikis bemærker i indlægget "The cost and benefit of documentation", så har der nok været en tendens til (i bedste fald) kun at kigge på etableringsomkostningerne.

Alligevel så kan vi ikke undvære dokumentation, så kunsten er at have præcis den rette mængde - og her slår Mikis et slag for begrebet "behovsdreven dokumentation" - tesen er, at det først er, når vi har brug for dokumentationen, at vi reelt kan vurdere, om den er indsatsen værd, og hvilken form den bør have.

Her tror jeg virkelig, at Mikis har fat i den lange ende, for det svarer meget godt til YAGNI holdningen fra XP, og YAGNI har igen og igen vist sit værd i praksis.

En enkelt bekymring kan jeg dog godt have: det er ikke sikkert, at behovet manifesterer sig tidsnok. Måske går det fint med uformel erfaringsudveksling medens tingene er under udvikling, og derfor er der ikke dokumenteret noget nævneværdig - behovet for dokumentation viser sig måske først, efter at to af de tre, som vidste noget, er rejst, og den trejde er på barsel?

Eller helt generelt, så er der områder med lav risiko og høj konsekvens - og så kan man ikke vente på, at det indtræffer; her vil man lettere kunstigt være nød til at skabe behovet undervejs, lidt på samme måde, som når færdselspolitiet er nød til at lave fartkontroller, for at hjælpe os med at huske fornuften i at køre efter omstændighederne - alternativet ville være at mange af os ville dø, inden vi lærte den rette mængde af moderation.

Det, som jeg vel prøver at sige er, at nogen dokumentation kunne godt være af typen med lav risiko og høj konsekvens, og så kan vi næppe forlade os udelukkende på "behovsdreven dokumentation"?

Læs hans indlæg - det er godt at blive klog af!

torsdag den 18. juni 2009

Billedduet

Jeg vil lige dele to af mine billeder med jer:



Fra Makro



Billeder kan bruges jfr. flg. licens:
Creative Commons License
Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License

onsdag den 17. juni 2009

Aliasing

Hvis man har prøvet at fotografere, så kender man betydningen af skarphed - at de interessante dele af billedet står med klare kanter og overgange. Michael Freeman nævner endda i sin bog "The Photographers Eye", at vi har vænnet os til at søge efter de skarpe dele af et billede, når vi skal afkode, hvad der er vigtigt. Skarphed er mao. ikke bare pedanteri - det er en grundlæggende del af billedet.

Derfor er det vel heller ikke unaturligt, at de af os, som fotograferer digitalt med passion, nok alle har prøvet at tage den helt store digitale lup frem og "pixel-peepe" - eller med andre ord, forstørre billederne op i en så urimelig stor størrelse, at man tydeligt kan se de enkelte billedpunkter - og vi er nok alle blevet skuffet over, at vores nye dyre kamera med det nye og måske endnu dyrere objektiv foran, faktisk er synligt uskarpt. Hvorfor kan det dog ikke gøres bedre, når man nu engang er lykkedes med flyve folk til månen og tilbage igen?

Det korte svar er, at det kan det, men det vil vi ikke ønske os!

Det lange svar er til gengæld temmeligt kompliceret, ja faktisk så kompliceret, at jeg ikke skal prøve at foregive at have forstået det - alligevel vil jeg godt vove det ene øje, og prøve at redegøre for elementerne i det:

Uskarpheden i billedet er nemlig lavet med vilje - man har simpelthen sat en "dugget rude" foran sensoren, nemlig det såkalde anti-alias-filter. Den kan fjernes, og så bliver billedet faktisk helt knivskarpt - se f.eks. MaxMax's (LPD LLC) side om "Hot Rod Visible", hvor de tilbyder at fjerne AA-filteret, og erstatte det med noget optisk neutralt. Effekten er ganske tydelig og meget mærkbar.

Der er dog en pris, og det er Moiré-mønstre (følg linket til Wikipedia for en række glimrende illustrationer). To steder, som alle vel har oplevet, er dels til afslutningsdebatten i TV, hvor en uheldig politiker har fået et jakkesæt med et fint mønster på, som så på TV ender med at give masser af falske farver og meget tydelige striber som flytter sig - og dels på film, hvor hjul på transportmidler der bevæger sig fremad (f.eks. diligencer) tilsyneladende kan rotere baglængs.

MaxMax-folkene viser også et par eksempler på Moiré-mønstre, men nedtoner betydningen af dem - og dette er nok lige lovligt modigt, for dels forekommer Moiré-mønstre meget ofte i virkeligheden (f.eks. vil en murstensvæg digitalt fotograferet på nogen afstand kunne give meget kraftig Morié), og dels så er det vanskeligt at fjerne effekten i efterbehandlingen - der er simpelthen gået for megen information tabt.

Men hvad kommer Morié-mønstre af? Jo, det kommer af en effekt kaldet aliasing: hvis vi bruger nogle begreber fra signalbehandling, så vil frekvenser (faktisk "frekvenskomponenter") i et signal, der ligger over Nyquist-frekvensen (=½ samplefrekvens), fremstå på samme måde som frekvenser, som ligger under (en frekvens f vil fremstå på samme måde, som en frekvens NfN+f hhv. NfN-f, hvor fN er Nyquist-frekvensen, og N er et positivt heltal).

Modtrækket vil typisk være at fjerne de frekvenser, som ligger over Nyquist-frekvensen, i en proces kaldet "anti-aliasing" - i billedbehandling vil det svare til at gøre billedet lige præcist uskarpt nok til, at man kan sample det præcist - og det lige netop det, som anti-alias-filteret før sensoren i kameraet gør. Bemærk, at sløringen inden sampling sker i det analoge domæne, og dermed i praksis med en langt højere opløsning en sensoren - man kan derfor ikke opnå samme resultat efter at man har samplet signalet; de høje frekvenser er da gået tabt.

Så derfor, kære med-digital-foto-entusiaster, skal billederne fra et godt kamera faktisk være en lille smule uskarpe; de er meget pænere på den måde!

tirsdag den 16. juni 2009

Kapløbet er startet

Så er kapløbet om de gode jordbær startet! I løbet af den sidste uges tid har jeg fået samlet en halv snes, hvilket måske ikke er så imponerende, men det er altså i skarp konkurrence med de "jordbærtyve", som ikke har noget imod at spise den modne del af et halvmodent bær.

 

Jeg måtte også konstatere, at ikke alle jordbærtyvene har vinger - de to allerflotteste blev plukket af en, som jeg kender, og han viste mig endda, hvor den grønne rest var kastet hen, da jeg undrede mig.

Hvis du undrer dig over, hvorfor dine jordbær stadig er grønne, så har det vist noget med sorten at gøre, for det er indtil videre kun det ene bed, som er modnet - resten kommer nok senere.

lørdag den 13. juni 2009

Vandkunst

Jeg havde en rigtig god dag i dag, hvor jeg gik turen fra Tangkrogen til Ballehage og tilbage igen med min familie. Vejret havde selvfølgelig en stor betydning, men det store scoop var udstillingen Sculpture by the Sea - og den kan varmt anbefales!

Som udgangspunkt er kulturdelen nok ikke så børnevenligt (med hvalhelikopteren ved hotellet, som en mærkbar undtagelse), men børn har som regel intet imod en gå-tur langs standkanten og i skoven, hvis bare man sætter tempoet passende lavt, og tager sig tid til at stoppe for at soppe eller (uh!) købe en is undervejs.

Og så alligevel, for selvom langt det meste var udstyret med "må ikke berøres"-skilte, så var der rigtigt mange finurligt underfundige skulpturer imellem, som havde en legende form for humor, som alligevel talte til børnene: hvem ville for eksempel ikke blive fascineret af en kæmpenål og tråd, som syr en rift i en bakke sammen?

Vi kom noget spontant afsted (som er den politisk korrekte omskrivning af, at det var et uplanlagt tilfælde), og lad mig derfor give et par gode råd:
  • Start turen ved Tangkrogen. Kommer man i bil, er der gode parkeringsmuligheder, og mange busser holder i umiddelbar nærhed. En del af de bedste skulpturer står også der.

  • Det er en lang tur, så hvis vejret er til det, så pak et tæppe, en rulle mariekiks og en termokande med kold saft el.lign. til en mini-picnic. Der skulle være masser af muligheder for at slå sig ned undervejs, og om ikke andet, så er der jo altid godt ved Ballehage.

  • De har tænkt over det, da de lagde ruten - følg den! Det meste af vejen følger man bare strandkanten, men omkring kajakklubben/Varna er der tydelige pile, som sender en op ad trappen, og der er også nogle skulpturer der - og man kommer ned på stranden igen umiddelbart efter Varna. Tilsvarende kommer man op på skrænten ved Ballehage, når man skal hjemover, og der er også nogle fine skulpturer ved stien der (samt gode kik ned på nogle af dem man har passeret).

  • Husk kamera! Jeg fik det ikke med, så jeg fik ingen billeder, og det gør I så heller ikke. Det ærgrer mig så meget, at jeg overvejer at tage tilbage igen, for at få rettet op på det.

  • Og så til sidst: husk solcreme, hvis ikke dine børn også skal grine af din røde næse, når I kommer hjem :-)
Der er rigtigt mange, som går turen, men selvom der er mange mennesker, så er det jo spredt ud over mange kilometer strand, og der var aldrig optræk til trængsel. Og der er tydeligvis mange, som møder hinanden undervejs, så husk at kigge efter andet end skulpturerne.

Stor ros til Aros og Århus Kommune!

torsdag den 11. juni 2009

Kvalitet er sikkerhedsventilen

Kender I det, at noget som man sådan set godt har vidst i lang tid, pludselig bliver sat på ord på en måde, så man kommer til at tænke over det igen. Det skete for mig med flg. udsagn:
"[...] most customers and managers still believe that if they want something badly enough and pressure developers enough to do it, that it will happen. They don’t understand that the pressure valve is quality and long term product sustainability and viability."

Jeg har læst det i indlægget Ken Schwaber on "Flaccid Scrum - A New Pandemic?" på Jeff Sutherlands blog. Der er også mange andre fine betragtninger, så aflæg ham et besøg.

"Kvalitet er sikkerhedsventilen" siger Jeff og/eller Ken (jeg har ikke lige gennemskuet hvem...) - jeg kommer til at tænke på dengang, hvor jeg legede med dampmaskiner som barn: De havde (mindst!) to sikkerhedsventiler, fandt jeg ud af, for selvfølgelig kørte vi dem til grænsen. Men når vi havde kørt dem så hårdt, at sikkerhedsventilen blev aktiveret, så hev vi straks brænderen ud, for det ville ellers være rent spild. Dels fordi at vi ikke kunne få den til at køre hurtigere uanset, men sandelig også fordi at det skar ned på den samlede kørselstid - al den dejlige damp, som kunne være brugt godt, fes jo bare ud igennem sikkerhedsventilen til ingen verdens nytte!

Og sådan er det vel også med udvikling: Der kommer et punkt, hvor mere pres nok medfører mere aktivitet, men ikke bedre resultater - ja, faktisk ender med at være kontraproduktivt; vi når simpelthen ikke så langt, som vi ellers ville have kunnet.

Analogien med dampmaskinerne har dog en åbenlys mangel: Med dampmaskiner kan man tydeligt se, når grænsen er nået, men hvordan ser man det i en udviklingssituation? Hvordan måler man, at man i virkeligheden er ved at lukke damp ud?

onsdag den 10. juni 2009

Kombinatorisk test eksplosion

Martin Fowler skriver om hvorvidt dynamiske typecheck skulle være mere udbredt i Ruby i sin bliki-post DynamicTypeCheck - det mener han ikke er tilfældet, og giver en statistik over en række Ruby-projekter som begrundelse.

I denne statistik lister han også antal liniers testkode hhv. antal liniers programkode, og han holder dem selv op imod hinanden. Jeg tillod mig derfor at lave et lille krydsplot af dem:



Jeg kan være den første til at indrømme, at der er alt for få datapunkter til at kunne sige noget autoritativt, men jeg hæfter mig alligevel ved at antallet af nødvendige liniers test per kodelinie vokser - man skulle vel have forventet en form for ligefrem proportionalitet, eller med andre ord et konstant antal testlinier per kodelinie.

Man kunne fristes til at stille spørgsmålet, om ikke fraværet af statiske typecheck gør, at man bliver nødt til at teste alle mulige kombinationer, og derfor at behovet for test vokser geometrisk.

Men som sagt, så er datagrundlaget nok lige tyndt nok til andet end at undres og formulere denne hypotese...

lørdag den 6. juni 2009

Mere sjov med SP...

Jeg kunne selvfølgelig ikke lade være med at lege videre med scenariet i Sjov med SP - men lad mig lige starte med to undskyldninger:
  1. Det har ikke så meget med SP at gøre, men mere med Scala og scala-fortolkeren (det er fordi, at det første kun er en undskyldning for at tale om det sidste!)
  2. Jeg har sidste gang fået regnet afgiften, og ikke efter-afgift-provenuet.
Med det af vejen, så tilbage til mine kode-skriblerier: Man kan jo nemt indse, at der er tale om en konstruktion, som er meget populær indenfor skatte- og afgiftsystemet: Der er forskellige afgiftsatser på forskellige dele af et beløb. Vi ser der bl.a. med registreringsafgiften, og med personbeskatning (bundfradrag, mellem og topskat).

Funktionerne, som jeg er kommet frem til, har flg. signatur: et beløb, en liste af satstrin som tupler med sats og længde på satstrinnet, og så til sidst en sats for "resten". Man kunne formulere satsen for "resten" i listen af satstrin ved et angive det som et sidste satstrin med en meget stor længde; koden vil så blive kortere, men det virkede forkert - jeg gik derfor efter det lidt mere omstændige, men mere eksplicitte.

Nå, nok snak, lad os se noget kode! Først en rekursiv løsning baseret på pattern-matching:
   1:def calcsteps(amountleft: Double, steps: List[(Double,Int)], infrate: Double): Double = 
2: steps match {
3: case (rate, range)::tail =>
4: if (amountleft < range)
5: amountleft*rate
6: else
7: range*rate + calcsteps(amountleft-range, tail, infrate)
8: case Nil =>
9: amountleft * infrate
10: }
Princippet er, at linie 3-7 håndterer første satstrin i listen: kan det rumme hele beløbet, så er vi færdige - ellers regnes dette satstrins bidrag, og funktion kaldes rekursivt i linie 7 med resten af beløbet og resten af satstrinene. Linie 8-9 håndterer, når der ikke er flere satstrin, dvs. "resten".

Men det kan (selvfølgelig?) også gøres på andre måder, f.eks. vha. en "fold-left" operation på satstrin-listen:
   1:def calcstep(status: (Double, Double), step: (Double, Int)):(Double, Double) = {
2: val (amountLeft, resultSoFar) = status
3: val (rate, limit) = step
4: if (amountLeft < limit)
5: (0, resultSoFar + amountLeft*rate)
6: else
7: (amountLeft-limit, resultSoFar + limit*rate)
8:}
9:
10:def calc( amount: Double, steps: List[(Double, Int)], infrate: Double) : Double = {
11: val (amountLeft, resultSoFar) = ((amount, 0.0) /: steps) (calcstep)
12: resultSoFar + infrate * amountLeft
13:}
En "fold-left"-operation består i at kalde en funktion med en initialværdi og første element i listen, og gentage kaldet af samme funktion med hhv. resultatet af foregående kald og næste element i listen indtil hele listen er løbet igennem.

Funktionen, som bliver kaldt for hvert trin, er defineret i linie 1-8, og ligner sjovt nok temmeligt meget det, som er vist det rekursive eksempel. Bemærk at tuplerne status og step "pakkes" ud vha. patternmatching i ln. 2 og 3.

Selve foldningen sker i linie 11; for dem, som ikke er vant til syntaksen, så er det "/:"-operatoren, som er en fold-left - tuplen foran er initialværdien, og efter den står listen - dette efterfølges af den funktion, som man ønsker at folde med ... jeg indrømmer, at det virker kryptisk ved første øjekast, men man vender sig foruroligende hurtigt til det!

Hvad er så bedst? Tjo, umiddelbart så vil jeg foretrække den rekursive løsning, og det simpelthen fordi, at den er meget nemmere at forklare - når vi skriver kode, så kommunikerer vi nok en smule "hvordan" til compileren, men i langt højere grad "hvad" med mennesker - både os selv nu og andre senere. Derfor er kode, som er kort og overskuelig, så langt at foretrække.

Men den anden løsning er nu ikke uden fordele:
  • I modsætning til den rekursive løsning, som får en kaldstack med en dybde propertionalt med længden af satslisten, så vil foldningen have en stackdybde, som ikke varierer med inputtet.
  • Trinnet er eksplicit og kan kvalitetssikres separat
  • En folding terminerer naturligt, mens en rekursion skal have (mindst) et termineringstilfælde
Problemet med den dybe kaldstak for den rekursive løsning ville (afhængigt af compilers implementation) kunne forsvinde, hvis den blev formuleret "tail-recursive". Her er en lille udfordring:
  1. Hvorfor er funktionen ikke tail-recursive?
  2. Hvordan kan man formulere den tail-recursive?
  3. Hvorfor ville det (måske) kunne gøre en forskel?

torsdag den 4. juni 2009

Kald ved rette navn

For snart et års tid siden, da bad jeg om navngivne parametre i Java - det venter jeg sådan set stadig på, men stor er min glæde, da jeg i dag opdager, at det er stærkt på vej i Scala ... det sprog bliver bare bedre og bedre!

Det er dog først til version 2.8, som man sammen med et plugin til Eclipse prøver at time med den koordinerede release af Eclipse til sommer.