mandag den 16. november 2009

Områdeviden

I forhold til databaser, så er jeg typen, som gerne vil udtrykke så meget viden om det domæne, som data omhandler, i databasen. Som minimum helt banalt identitet (og her tænker jeg ikke på kunstige nøgler) og referentiel integritet; og i virkeligheden vil jeg gerne sige meget mere, men som oftest understøtter databasesystemerne det kun i ringe udstrækning. Men lidt har også ret.

Jeg vil gerne have, at databasesystemet hjælper mig med at holde orden i data, så programmerne ikke behøver at gøre det. På den måde bliver programmerne - efter min mening - sikrere og mere koncise.

I modsætning her til står det synspunkt, at databasen sådan set bare er en stor spand, hvor man kan hælde semistrukturerede data i, og det med mindst muligt besvær. Integritetsregler er mest af alt i vejen, og i øvrigt så koster de vist også performance.

Når man opfatter databasen på den måde, så giver det sig selv, at det bliver programmernes ansvar selv at sikre sig, at der er orden i data. Det lægger en større byrde på omhu og på kvalitetssikring.

Selvom jeg har valgt side, så har begge synsvinkler faktisk hver i sær sin rimelighed. Er strukturen i rivende udvikling og/eller er skemaet til at overskue, så er det sandt, at integritetsregler mest af alt er i vejen. Men når kompleksiteten stiger, og når det er vigtigt at have konsistente data, så er det ofte nødvendigt at have databasesystemet som kustoden, som dels kan hjælpe med at vise vej, og dels kan afvise de værste unoder.

Kort sagt, så hjælper integriteretreglerne med fastholde viden om domænet.

I forhold til programmeringssprog, så er jeg typen, som har det bedst med sprog, som har en statisk typestruktur. Statisk typecheck gør det muligt at udtrykke ens forståelse af domænet præcist, og advarer en tidligt, hvis man - populært sagt - prøver at blande pærer og bananer.

I modsætning hertil står programmeringssprog med en dynamisk typestruktur. Hvis domæneforståelsen er under udvikling, og man i har tilstrækkeligt overblik og udviser fornøden omhu, så er statisk typecheck mest af alt en spændetrøje på kreativiteten.

Jeg kunne fortsætte, men i virkeligheden så vil jeg blive ganske skuffet, hvis I ikke allerede har gættet, at min pointe er, at der er tale en interessant parallel: integritetsregler i en database er en måde at udtrykke forretningsforståelse på, og det er typesystemet i et programmeringssprog også.

Min holdning burde også være klar: jeg vil hellere lade compileren sikre konsistensen, end at jeg vil bruge tid på at skrive og vedligeholde unittest, som i bund og grund kun gør det samme.

Alligevel må jeg erkende, at det kan blive belastende hele tiden at skulle bekræfte compileren i, at man godt kan huske, hvad der er pærer og hvad der der bananer. Rigtigt slemt bliver det, når man har noget kode, hvor man egentlig i bund og grund er lige glad med, om det er den ene eller den anden konkrete type - man tager bare imod pærer og giver pærer videre ... og viser de sig på et tidspunkt i virkeligheden at være bananer, så gør det ikke noget, bare man kan få og give dem videre uden at det bliver blandet sammen.

Tag f.eks. følgende lille stump Scala kode:
class Bowl {
def getAFruit = new Pear
def add(fruit: Pear) = "Added "+fruit.toString
}

case class Pear
case class Banana

object Mixer {
def mix(aBowl: Bowl, anotherBowl: Bowl) = {
val fruit = aBowl getAFruit;
anotherBowl add(fruit)
}
}

Her er tale om skåle til een slags frugt, og en mixer, som tager et stykke frugt fra den slags skåle og lægger det over i en anden skål af samme slags. Og
grundlæggende set, så er mixeren faktisk lige glad med frugter - var det ikke lige fordi, at jeg havde kaldt metoder og variable noget frugtagtigt, så kunne det faktisk være hvad som helst.

Ændrer man skålen til at give og tage bananer i stedet, så virker mixeren stadig. Men prøver man at lave om på skålen, så den giver bananer og tager imod pærer, så brokker compileren sig, som den skal - så der er i virkeligheden et typecheck omme bagved - vi bliver bare hjulpet af typeinferensen til at glemme det for et øjeblik. Og sådan bør det også være - det ligner for mig nærmest noget af det gode fra begge verdener.

...og så for at lige at forgribe evt. kommentarer: Ja, det kunne modelleres mere præcist, f.eks. med anonyme typer - men det er helt anden snak.

tirsdag den 27. oktober 2009

Om kontorer

Prøv at læse ComputerWorld i dag - de har en artikel med titlen "Sådan indretter du det bedste it-kontor" (nej, ingen præcise links, for det kan danske dagblade ikke lide) - man skal godt nok igennem de første par sider for at komme igennem de fleste almindeligheder, men så kommer der også et par fine pointer.

En pointe er, at store kontorer gør det nemt at finde sammen for at samarbejde. Forudsat selvfølgelig, at man kan finde ud af at samarbejde i forvejen, for ellers begynder man bare at gå hinanden på nerverne, og i værste fald udarter der sig en "tyssekultur" (hvor er det dog et fedt ord!). Det er sandt - jeg har siddet i store kontorer, hvor vi kunne sidde hele projektet, og være os selv, sammen, og det var rigtigt godt. Men jeg har også siddet i kontorlandskab, hvor vi var adskillige projektet fordelt over flere forskellige afdelinger, og det var en pest.

En anden pointe er, at der ikke kun er brug for samarbejde, men også brug for plads til individuelt arbejde. Ja, tak! Her er man knapt så klar i spyttet, og svinger sig højest op til at mumle noget om plads til hjemmearbejdspladser. Det er efter min mening ikke godt nok - hjemmearbejde er efter min mening ikke ideelt; både fordi, at det er et skråplan at invitere arbejdet alt for permanent indenfor, der hvor man helst skulle have en helle - men også fordi at det simpelthen er for upraktisk. Ja, bevares, ikke et eneste ondt ord herfra om den fleksibilitet, som hjemmearbejdspladser giver - tvært imod - det er bare ikke løsningen på behovet for rum til individualitet. Der må kunne laves noget, som er bedre, og gerne noget, som man kan føle er ens eget, på samme måde, som kontorstolen og bordet er det i storrummet. Jeg tror snildt at en gruppe af mennesker vil kunne dele sådan et sted, bare det ikke bliver alt for mange.

En tredje pointe er, at der er behov for "projektrum" - det er ikke helt klart, om det skal tages bogstaveligt, og forstås som en ekstra lokale til projektet (hvilket absolut giver mening), eller om det mere er et spørgsmål om projektet også skal kunne rummes. Vigtigt er det i hvert fald med vægplads til alt hvad projektet behøver - opslagstavler, grafer, plakater, oversigter og fælles bøger: alt det, som ofte bliver ofret i storrummene for at få stoppet de sidste par personer ind, og for at lave plads til store vinduer med dagslys. Forstå det dog: vi har brug for vægplads! ... og det inkluderer også pladsen umiddelbart foran væggen - der kan ikke lige stå et skrivebord eller sidde en ekstra person med ryggen til; og heller ikke selvom han er ekstern konsulent, og kun er der tre dage om ugen.

Så storrumskontorer - ja, tak, for det er på mange måder en genial ide - men husk at der stadig skal være plads til at være individuel ... og aldrig på bekostning af vægpladsen og rummet til spontane møder (ellers samles vi på gangen eller foran kaffeautomaten - eller endnu værre, holder helt op med at mødes!).

søndag den 11. oktober 2009

Hvad kan vi nå...?

Der er vist et ordsprog siger siger, at hvis man prøver at jage to fugle, så får man ingen af dem. Jeg vil her prøve at tale om to ting, som begge har noget at gøre med hvor meget man kan nå (som nogle kalder det effektivitet eller velocity eller noget helt tredje...), og så håber jeg, at de er så beslægtede, at jeg får ram på i hvert fald noget af det.

Den første er den erkendelse, som vi vel alle kender, at når man skal koncentrere sig, så skal man have ro. Det er derfor, at der er stille på bibliotekets læsesal, og det er derfor, at vi som studerende lukkede os inde på vores værelser, når vi skulle have noget fra hånden. Jeg ynder selv at bruge metaforen, at vi bygger mentale korthuse - med den prøver jeg dels at ramme det faktum, at man ikke kan bygge et korthus halvhjertet: det kræver fuld koncentration - men også at det hele kan ramle sammen selv ved små udefra kommende forstyrrelser: en tilfældig vind fra en dør som bliver åbent, eller en uforsigtig person, som lige snitter bordet, hvor korthuset står på ... der skal ikke meget til.

Jeg har tidligere blogget lidt om ready-ready, hvor jeg dengang hæftede mig ved det faktum, at ting skulle være i orden og helt klar, inden man gik i gang. Men jeg har også haft lejlighed høre Carsten fortælle om sin artikel, og han pegede også på, at det var vigtigt at kunne gøre det færdig, som man var gået i gang med. Eller med andre ord, at det ikke var nok, at alle opgaver var klar - det var også vigtigt, at der ikke blev skiftet hest i vadestedet flere gange undervejs.

Der er en erkendelse, som andre også er kommet frem til: i denne artikel fra Coding Horror fortælles om den dramatiske nedgang i opgaveløsningsevnen der kommer, når man prøver at multitaske - og i denne artikel fra Software Nation diskuteres begrebet "flow", og det faktum at flow-stilstanden kan brydes på et øjeblik, men som tommelfingerregel tager i omegnen af et helt kvarter at skabe - der skal mao. ikke mange forstyrrelser til på en dag førend megen god tid er blevet tabt.

Derfor ser man også tit, at folk med behov for at koncentrere sig prøver at skabe lommer af ro i løbet af dagen, f.eks. ved at møde tidligt, blive sent eller ved at tage hovedtelefoner på. Nogle kan også formå at komme i en zen-lignende trance, som gør at de virker distræte og tabt for omverdenen.

Ud fra ovenstående er det oplagt, at jo mere ro, jo bedre, men det er desværre ikke så simpelt. Meget af det, som vi i dag går og laver, er blevet så kompliceret, at det kræver andres hjælp - en hjælp, som vi har brug for, for ikke at få brudt vores flow, men som samtidig gør, at vi bliver nød til at bryde andres flow.

At diskutere hvad, der vil være den rette balance, er bestemt også interessant, men faktisk vil jeg ikke gå længere her, end til at konstatere, at ro og kontinuitet hhv. forstyrrelser og afbrydelser er en betydelig faktor i forståelsen af, hvor meget man kan nå.

Det er vel en af grundene til, at man ser mange gå væk fra at estimere i timer, for ingen timer er ens: et timeestimat indeholder både et gæt på opgavens kompleksitet og et gæt på den forventede produktivitet. En bedre måde at estimere på vil være, at fokusere på kompleksitet og effektivitet som to forskellige størrelser.

Kompleksitet kan man måle i idealtimer (hvor lang tid skal en uforstyrret udvikler bruge), og derefter lave en forholdsmæssig reduktion for, hvad forstyrrelser betyder - en tommelfingerregel siger, at der kan leveres 6 effektive timer på en 7½ times arbejdsdag, men det afhænger meget af forstyrrelsernes karakter og omfang, så det kan til tider være væsentligt mindre (i parentes skal bemærkes, at denne størrelse godt kan blive selvrefererende, for i virkeligheden vil det feedback som kommer i kraft af vundne erfaringer gøre, at man efter nogen tid ikke længere arbejder med "idealtimer", men derimod med "den slags timer, som der er seks af på en dag med de sædvanlige forstyrrelser" ... men det er en anden snak).

Andre går skridtet videre, og frigør helt kompleksitet fra fysisk eller virtuel tid, for vi har alle forskellige forudsætninger (og forskellighed kendetegner netop et godt team, for så kan man supplere hinanden). Forskelligheden betyder f.eks., at det er helt naturligt, at jeg kan se på en opgave og tænke "10 dage", mens mine kollegaer tænker "2 dage" hhv. "5 dage" - og vi kan alle have ret, hver for sig. Derfor vil man ofte i stedet prøve at estimere i relative størrelser af sammenlignelige opgaver - det være sig "storypoints" eller "gummibamser" eller hvad man nu finder på - pointen er, at ved at frigøre sig fra noget, som a priori har en fast betydning, så kan man i stedet blive enige om en fælles relativ reference.

Godt - hvis vi nu lige for argumentet skyld lige antager, at der er helt styr på det med vurdere, hvor lang tid noget tager, så er der faktisk endnu en usikkerhed, som jeg tit oplever at man overser: nemlig hvor meget tid, som rent faktisk står til rådighed.

Det mentale trylletrick som oftest laves, er at antage at alle er der fuld tid, medmindre at de holder fri eller er på heldags kursus el.lign ... og det er faktisk ofte på langt sigt og i det store og hele et meget godt gæt (som så også er regnet ind i antagelsen om en 6 effektive timer på en dag). Men det er et gæt, på samme måde som vi ovenfor gættede på produktiviteten.

I og med at det er et gæt, så er det faktisk interessant at måle på den på samme måde som fremdrift måles. Skyldes den faktiske fremdrift f.eks. høj produktivitet kombineret med korte dage og sygdom, eller er det lav produktivitet med lange dage og en helt usædvanlig sygdomsfri periode?

Har man let adgang til løbende registrering af timeforbrug, så kan det derfor være interessant at plotte en kurve over et "faktisk effort burndown" plottet op imod det "planlagte effort burndown", som jo findes på alle burndowncharts. Og hvis adgangen til faktisk forbrug ikke er så let, så er det såmænd også meget fint bare at tage totalen med i de jævnlige revurderinger (f.eks. ifm. retrospektiv). For på samme måde, som det er interessant at diskutere, hvor megen "kompleksitet", som man nåede i forhold til planen, så er det også ganske interessant at diskutere, hvor god planen var. Er niveauet stabilt, så bliver der ikke så meget at snakke om, men ændrer det sig, så kan det være, at der er forhold som kræver opmærksomhed.

Opsummerende, så kan man sige, at spørgsmålet om, hvad man kan nå afhænger af (mindst) tre faktorer:
  1. Opgavens omfang (kompleksitet)
  2. Vilkårene for dens løsning (effektivitet, eller kompleksitet i forhold til forbrugt tid)
  3. Ressourceudnyttelse (efficiens, eller forbrugt tid i forhold til planlagt tid)
Om muligt, så bør man opsamle erfaringer for alle tre faktorer - for kender man dem ikke, så er det yderst vanskeligt at sige noget om, hvad man kan nå. Ved at skille faktorerne ad i stedet for at betragte dem samlet, så vil man dels opnå en mindre samlet variation i gættene, men også en større forståelse for, hvorfor gættene lander, hvor de gør.

mandag den 21. september 2009

15 skridt

Bussen går et stykke fra, hvor vi bor, og derfor har vi efterhånden fået en hel lille tradition med at deles om tage min kones cykel der hen, og så lade den stå ved stoppestedet til, når vi kommer hjem igen.

I dag da jeg kom med bussen, da kunne jeg så konstatere, at nogen havde brugt cykelkurven som affaldsspand: der lå en halv pølse og noget sammenkrøllet pølsepapir i den - de glade givere havde i øvrigt ikke været særligt gode til at ramme, for der lå lige så meget på jorden omkring cyklen.

Og så er det, at man spørger sig selv: hvorfor? Den nærmeste skraldespand var stort set tom, og lå kun femten skridt væk - jeg ved det, for jeg talte dem, da jeg gik derhen med affaldet.

Gad vide, om det er nogen, som trænger meget til briller, men ikke har råd på grund af finanskrisen? Eller måske kom jeg helt uforvarende til at ødelægge en fremtidig installationskunstners allerførste værk?

onsdag den 16. september 2009

Tegnsætsudfordringer

Jeg har lige for nyligt skrevet som at bruge curl til test af ikke-trivielle C#-webservices - hvis man er usædvanligt skarpøjet, så vil man kunne have set, at jeg har lavet en potentiel tegnsætsfejl - men man kan ikke se det mere, for jeg har rettet eksemplet til; jeg vil gerne forklare her, hvor i den bestod:

XML-dokumentet sagde jo selv, at det var skrevet i UTF-8 tegnsættet - men faktisk var det endda skrevet i den delmængde, som også er kendt som US-ASCII. Hvis man kigger på headeren til content-type, som findes i scriptet, så kan man se, at mime-typen er sat til "text/xml". At burde derfor være idel lykke, ikke sandt?

Nej, så langt fra, for hvis man nærlæser RFC3023, så kan man i afsnit 3.1 se, at der på det stærkeste anbefales at angive et tegnsæt til typen text/xml - og hvis man ikke gør det, så skal indholdet fortolket som værende US-ASCII! Mit eksempel går derfor kun godt, fordi at det tilfældigvis holdt sig indenfor US-ASCII, men i samme øjeblik at man f.eks. prøver at skrive "ÆØÅæøå", så bryder det sammen på subtil vis.

Løsningen er derfor at ændre mime-typen til "text/xml;charset=utf-8".

Spørg lige om det var svært at finde, når man opdager problemet i en integrationstest, hvor webservicen som sagt er skrevet i C#, men hvor den skriver data ned i en Oracle-database, hvor det så senere læses af en server, som er skrevet i C++, som sender det over en socket-baseret legacy-protokol for at havne i MFC/C++ baseret klient?

tirsdag den 8. september 2009

C# Webservice og curl

For nyligt blev jeg bedt om at hjælpe på et projekt, hvor man havde brug for at udvide nogle webservices, som var skrevet i C#. Ja, det er ikke just min boldgade, men hvor svært kan det være? Og det er faktisk gået over al forventning.

At kalde det for webservices er måske lidt en tilsnigelse, for der er i vid udstrækning tale om et remote procedure call, også selvom det er pakket fint ind - der bruges godt nok plusord som "SOAP", "WSDL" og "Document Literal" (i en helt egenartig variation - bravo Microsoft!), men reelt skriver man en metode, og så bruger man værktøjer til at generere "det ind imellem".

Kigger man på den WSDL, som kommer ud af det, så bliver man ikke imponeret. At man har felter med en datatype, som kan være Null, betyder ikke at feltet skal være optionelt - jeg kiggede bl.a. på en webservice til at sende SMS'er, og der måtte man ifølge service definitionen selv om, om man ville angive telefonnummer og besked!

Kan man sluge den kamel (og det er noget af kamel at sluge for en person som jeg, der er til stærkt typede sprog), så må man sige, at det er ganske nemt. Og muligheden for at kalde den autogenerede metode via POST af en tilsvarende autogenereret formular, er tilnærmelsesvist genialt. Hvor er det dog nemt at få en hurtig test af det, som man lige har flikket sammen.

Men så var det, at jeg pludselig rendte ind i flg. besked på testsiden:
The test form is only available for methods with primitive types or arrays of primitive types as parameters.
...mand, og nu gik det ellers lige så godt med mine små "Hello, world!" eksperimenter.

Den sad jeg så lidt og grublede over. Det kunne da ikke være sandt, at man ikke kunne teste sådan en webservice på andre måder end ved at lave en hel ny klient til den?

Så var det, at jeg faldt over cURL. Hmm. Sammen med afvisningen på testsiden var der jo et eksempeldokument - mon ikke det kunne lade sig gøre, at kalde webservicen direkte via cURL?

Dokumentet kunne f.eks. være dette:
   1:<?xml version="1.0" encoding="utf-8"?>
2:<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
3: <soap:Body>
4: <TestData xmlns="http://test.example.org/ws">
5: <Id>Alfa</Id>
6: <list>
7: <item>
8: <field>NAME</field>
9: <oldValue>gammelt navn</oldValue>
10: <newValue>nyt navn</newValue>
11: </item>
12: <item>
13: <field>CITY</field>
14: <oldValue>Gammelby</oldValue>
15: <newValue>Nyborg</newValue>
16: </item>
17: </list>
18: </TestData>
19: </soap:Body>
20:</soap:Envelope>

Og cURL kan kaldes på flg. måde:
   1:#!/bin/bash
2:curl -H "SOAPAction: \"http://test.example.org/ws/TestData\"" \
3: -H "Content-Type: text/xml;charset=utf-8" \
4: -d @testdata.xml \
5: http://localhost/TestWebService/TestWebService.asmx?op=TestData

De to "-H" sætter headers på, og "-d" refererer til filen med ovenstående xml-dokument (som er body i beskeden). Sværere er det såmænd ikke.

Yeah!

onsdag den 2. september 2009

Demo

Da jeg tidligere skrev om Kniberg scrum checkliste faldt der pludselig nogle brikker på plads for mig - og jeg vil gerne dele nogle af dem med jer her, men lov mig til gengæld, at tilgive mig på forhånd, hvis der i virkeligheden er tale om, at jeg er den sidste til at indse det indlysende!

Og hvad er det så, som er gået op for mig? Jo, at demo er vigtigt for et godt scrum.

Tit springes demo over, og vel som oftest fordi at det er en noget kunstig affære - en ceremoni, som der står i teoribøgerne, at man skal lave (som f.eks. førnævnte checkliste)- og så laver man det. Sådan har mange af de demoer, som jeg har deltaget i på diverse teams i hvert fald været, og er der noget, som vi ikke har tid til i en agil verden, så er det ceremoni!

Vi har også prøvet at efterrationalisere over det, og som oftest har det været noget med, at vi med demoen markerede, at vi var færdige - eller med andre ord en slags sejrsdans over sprintet. Hmm - hvis ikke man har styr på sit done-kriterium, så vil ikke nok så mange demoer hjælpe en ... og hvem har ikke oplevet en demo af noget, som i virkeligheden viste sig at være foilware? Nej, jeg mener ikke, at det er derfor.

Et andet argument var, at nu havde vi arbejdet på så mange forskellige ting i løbet af sprintet, at det var godt, at vi fik lejlighed til at vise det frem for hinanden. Hmm i anden - der er forhåbentlig kun et team, og det har forhåbentlig allerede arbejde sammen imod samme mål i et helt sprint ... så hvad er der lige at vise hinanden? Næh, det kan heller ikke være derfor.

Lad os i stedet kigge på nogle af de andre elementer i scrum:

Vi har for det første en Product Owner (ja, altså en rigtig en, som skal leve - eller dø! - med det, som vi laver, og ikke sådan en "produkt-stråmand", som man desværre alt for tit ser i stedet for), fordi at vi hele tiden vil lave de ting, som er til størst nytte.

Vi har for det andet retrospectives, fordi at vi hele tiden vil forsøge at gøre det bare lidt bedre (og fordi at vi ved, at gør man det hele tiden lidt bedre, så bliver det meget bedre på langt sigt!).

Hvad er demoen så? Jo, det er det sted, hvor vi som team får direkte feedback fra dem, som skal leve af og med resultatet af vores arbejde. Hvis Product Owner er en rigtig Product Owner, så er han helt essentiel for, at demoen giver værdi: for temaet skal opleve, hvor han griner og hvor han græder. Men det skal ikke kun være begrænset til Product Owner selv - der må meget gerne være andre slutbrugere til stede - de som også skal leve af, og med, det som temaet har frembragt.

Som et naturligt resultat af en demo vil hele teamet have en forståelse af, hvad som virkede godt, og hvad, som virkede mindre godt - og det er en viden, som teamet kan tage med direkte med tilbage i dets arbejde på løbende at forbedre processen.

Demo skal derfor falde rimeligt kort efter sprintets afslutning, og gerne inden retrospektiv, for en god demo vil danne et godt udgangspunkt for diskussionen på retrospektivet.

Teamet vil, når det har mødt brugerne, også naturligt få en bedre forståelse for baggrunden for de ønsker, som det fremover skal arbejde med realisere, og vil derfor være væsentligt bedre rustet til dette.

Demo har også en anden værdi - for i scrum fokuserer man hele tiden på, at levere noget, som gør en synlig forskel ... og hvordan kan man vise noget frem, som ikke gør en synlig forskel? Demoen er dermed en indikator af, om Product Owner og temaet tilsammen evner at fokusere på det rette ... falder det svært eller unaturligt at lave en demo efter et sprint, så spørg jer selv, om det er det rette, som man har brugt tiden på?

Endelig er der jo det faktum, at der ikke er noget mere motiverende end at vide, at man har gjort en positiv forskel - og det gælder også for et scrumteam.