mandag den 30. juni 2008

Indre klasser

I, mine faste læsere, kender mig godt nok til at vide, at det ikke er samfundskritik, som overskriften lægger op til. I stedet vil jeg filosofere lidt over den syntaktiske finurlig med dette navn, som jeg har stiftet bekendskab med i programmeringssproget Java.

Det, som har inspireret mig, er et indlæg på Michael Feathers' blog: Are Nested Classes Really a Good Idea? Jeg kan godt afsløre her, at det synes han ikke, men han er fornuftig nok til at mene, at det mest er et spørgsmål om stil. Indlægget er ikke længere end, at jeg vil opfordre til, at man selv læser det.

Langt hen ad vejen er jeg enig med Michael Feathers - når de indre klasser har tyngde nok til at være "rigtige" klasser, så er det ofte sådan, at det er bedre at gøre dem til det - altså rigtige klasser for sig selv. Indre klasser er ... ja, ikke sådan direkte forkerte, bare akavede - de ødelægger ofte rytmen i programmet.

Når jeg koder, så skriver jeg ofte og gerne indre klasser. Det sker, når jeg under kodningen ser et skift i abstraktionsniveauet, eller måske identificerer jeg et afvigende ansvarsområde; det er de her små urenheder, som måske - måske ikke - er starten til udkrystalisering ... og det er her, at jeg ofte bruger indre klasser. Man kan mene, at jeg her lige så godt kunne have lavet en rigtig klasse fra starten af, men det meget hurtigere - og på sin vis også langt mere uforpligtende - lige at lave en indre klasse.

På det tidspunkt, hvor jeg kan mærke, at nu har koden fundet et naturlig leje, så er der en tendens til, at jeg løber de indre klasser igennem. De indre klasser, som har tyngde og substans, vil jeg som tommelfingerregel forfremme til "rigtige" klasser - og for de øvrige vil jeg ofte overveje, om ikke der findes alternativer, som lige så vel kan kommunikere den "lille" indre klasses struktur og hensigt. Det er sjældent, at jeg committer kode med indre klasser, som bare er klasser (i modsætning til closure-agtige indre klasser, men det kommer jeg til).

Måske er min fremgangsmåde opstået fordi, at jeg kommet til Java via Pascal - jeg husker stadig smerten ved ikke at kunne lave lokale funktioner og procedurer: Jeg følte, at jeg blev tvunget til at gøre klassen ujævn i sin natur, og jeg havde svært ved at leve med, at jeg ikke kunne begrænse scope for en metode til en sub-kontekst. I virkeligheden, så har det vist sig, at jeg kan komme langt med at dele klassen op i interface og implementation (og understrege dette med bevidst brug af synlighed) - og hvor det ikke er nok, så er det ofte fordi, at jeg prøver at gøre for meget på en gang.

Det, som normalt får mig til at tøve en kende, er, når den indre klasser er meget tæt koblet til den ydre klasse, og måske endda nært forbundet til implementationen af den. Tit er det bare dovenskab eller manglende klarhed i ansvarfordelingen - men tit er det også ubehaget ved at forurene pakkens interface med noget alt for detajleret og måske internt af natur; for den oprindelige ydre klasse var ment til at skulle bruges for andre udefra, mens den indre klasse mere var en service for den oprindelige yde klasse. Løsningen er den samme, som for metoder i klasser: man erklærer kun det, som er del af interfacet for public (en lille sidebemærkning: lige så vel som klasser har et interface, så har pakker det også - og ofte drevet af de samme overvejelser; og når Java får et eksplicit modulbegrebet, så får vi endnu et niveau, at definere interfaces på ... men det er en anden historie).

Javas "far", James Gosling, skrev for nyligt under titlen Closures bl.a. flg.:
In the early days of Java the lack of closures was pretty painful, and so inner classes were born: an uncomfortable compromise that attempted to avoid a number of hard issues.
Indre klasser er mao. noget, som ikke engang dets ophav vil kendes ved!

Closures er (eller måske rettere: har indtil for nyligt været) meget omdiskuteret i Java kredse, og det er vel netop det sted, hvor jeg selv anvender indre klasser mest eksplicit, nemlig når jeg gerne vil skille det generelle fra det specifikke. Man kan selvfølgelig prøve med template method og nedarvning, men personligt, så fortrækker jeg ofte noget, som i stedet bruger komposition (og derfor mere ligner strategy): I den generiske del erklæres et indre interface, og når det generiske skal anvendes, så bliver interface som oftest implemeteret ved en indre klasse hos anvenderen.

Closures vil da gøre dette nemmere, og den typiske indvending imod closures, nemlig at de ofte er anonyme, er, på samme måde som ved anonyme indre klasser, selvvalgt - og vel også i bund og grund et spørgsmål om stil. Men netop her er smerten ikke så stor, for indre klasser løser faktisk den del rimeligt OK - der findes værre dele af Java. Synes jeg.

Så, for lige at vende tilbage, og svare på spørgsmålet i Michael Feathers' overskrift: Nej, indre klasser er ikke ligefrem nogen genial ide - men på den anden side heller ikke nogen udpræget dårlig ide ... hvis bare man bruger den med omtanke og omhu. Og det kan man jo sige om så meget!

søndag den 15. juni 2008

Multiple specialer

Rasmus bloggede for en uges tid siden under titlen "Hvad gør et team crossfunctional?" om nogle af de udfordringer, som er forbundet med at skulle skulle nedmande, set ud fra de erfaringer som han har gjort sig med et konkret scrumteam (et team, som jeg indtil i år også var med i, så jeg bærer noget af skylden...). Det udartede sig til en godmodig meningsudveksling imellem Rasmus og mig om begreberne "cross functional" og "generalizing specialist" - begreber, som jeg gerne vil tale mere om her:

Lad os tage "cross functional" først, for det er på mange måder den nemmeste. Wikipedia skriver i artiklen "Cross functional teams" bl.a. flg.:
In business, a cross-functional team is a group of people with different functional expertise working toward a common goal.[...]

Cross-functional teams often function as self-directed teams responding to broad, but not specific directives. Decision-making within a team may depend on consensus, but often is led by a manager/coach/team leader.

A non-business, yet good example of cross-functional teams are music bands, where each element plays a different instrument (or has a different role).
Cross-functional er altså en egenskab ved en gruppe af mennesker - et team - og siger derfor ikke andet om medlemmerne i teamet, end at de kommer fra en forskellig baggrund.

Som det ses, så kommer Wikipedia også kort ind på den typiske beslutningsstruktur i et cross functional team, dog uden at uddybe det nærmere. Umiddelbart kan jeg dog ikke se nogen direkte sammenhæng - et team kan godt være cross functional uden at være konsensusbaseret; og omvendt, så kan et team godt være konsensusbaseret uden at være cross functional - når man måske nok ser en sammenhæng, så skyldes det efter min mening snarere, at de omstændigheder, som gør at man vil foretrække et cross functional team, også vil gøre, at man vil foretrække at gøre teamet selvbestemmende.

Umiddelbart ser det ud til, at den bedste kilde til det andet begreb - generalizing specilist - er Scott W. Ambler (han er i hvertfald ikke selv ked af at tage æren som ophavsmand); se f.eks. her: Generalizing Specialists: Improving Your IT Career Skills. Han skriver flg. om emnet:
A generalizing specialist is more than just a generalist. A generalist is a jack-of-all-trades but a master of none, whereas a generalizing specialist is a jack-of-all-trades and master of a few.
...og fortsætter:
Similarly, a generalizing specialist is more than just a specialist. A specialist is narrowly focused on a single topic, making them very effective at that topic but not at others. Specialists will often be blind to the issues which other specialists focus on [...]
En generalizing specialist er med Scott ord altså mere en "både og" end en "enten eller"; en person, som formår at kombinere det bedste fra generalisten og specialisten - og han understreger senere, at man helst ikke er specialist på bare et enkelt område, men gerne på adskillige - hvis bare man har dybden; dybden er vigtigere end bredden, for hvis man mangler dybde, så er man i bedste fald kun en generalist. Han anerkender dog, at dette ikke sker ad sig selv, og et ekspertise er noget, som kommer med erfaringen.

Det nærmeste Wikipedia har om emnet, er artiklen om versatilister - det er efter min mening ikke helt det samme, men trods alt så ens, at Scott anderkender begrebet som et synomym til generalizing specialist - og at Wikipedia linker til Scotts artikel.

Generalizing specialist er mao. en egenskab ved personen, og ikke ved teamet.

Generalizing specialist og cross functional teams er altså to forskellige begreber. Men begreberne er alligevel forbundne, for som Scott selv fremhæver, så det lige så god en ide at kunne spænde over flere specialer for et team, som for en person; på mange måder er det den samme ide, bare på to forskellige niveauer.

Begreberne er også fælles om at fokusere på kombinationen af specialer som det bærende element; hvis ikke, så er det bare den store middelmådighed, og det er ikke målet med nogen af dem. Og Rasmus' bekymring ved nedmanden er vel præcis den, at når opgaverne skal fordeles over stadig færre , så risikerer det at blive udvandet så meget, at muligheden for at specialisere sig går fløjten.

Det er svært at tale om scrum uden også at have en mening om generalizing specialist og cross functional teams som begreber. En oplagt grund er, at scrum fokuserer på opnå excellens, og det opnår man ikke uden at involvere specialister, men personligt mener jeg, at der en anden, og vigtigere grund: Grundtanken i scrum er, at et team som får lov at samarbejde om at løse sine opgaver på en regelmæssig måde, over tid vil lære at blive bedre og bedre til det.

Det vigtige er at altså teamet og regelmæssigheden - men hvor blev så det med cross functional og generalizing specialist egentlig af? De er der stadig, men årsager som er mere indirekte. Jeg kan umiddelbart se to:

For det første, så er det en forudsætning for at kunne lære som team, at man kan samarbejde. Det er ikke nok at trække opgaverne fra en fælles liste - eller for sags skyld, klistre dem op på en tale, og stå og snakke om dem en gang om dagen - hvis en person altid løser "de grønne opgaver" og en anden person altid løser "de røde opgaver". Det er ikke samarbejde, det er samtidigt arbejde! Cross functional er altså ikke nok for et team (det er vel end ikke et team, idet det "fælles" mål bare er kombinationen af en række individuelle mål). En generalizing specialist en umiddelbar fordel i forhold til at samarbejde, i det han allerede er vant til at spænde over flere specialer, og dermed allerede i sig selv er brobygger, og han vil derfor virke fremmende på samarbejdet i teamet.

For det andet, så er det en forudsætning for at kunne opnå en regelmæssighed, at teamet skal kunne tilpasse sig en vis variation i opgaverne - og det opnår man dels ved at have en vis bredde ved at være cross functional - men også ved at have en vis intern fleksibilitet, hvorved generalizing specialists igen bliver vigtige. Et team, som kun består at specialister, vil kæmpe for at tilpasse opgaverne til teamets profil - et team af generalizing specialists vil i højere grad tilpasse sig opgaverne karakter og lære at løse dem godt.

Fleksibiliteten er derfor vigtig. Man kan med en vis ret sige, at det bedste værktøj ikke altid er det mest specialicerede værktøj, men måske snarere det værktøj, som man har ved hånden. Jeg har prøvet at lodde med et stearinlys, og jeg har da også (gys!) lavet "mesterskruer" med batteriet på min skruemaskine.

Men på den anden side, så skal man passe på - fleksibiliteten har en pris. Man skal overveje, hvad der er ved at ske, hvis man igen og igen står med værktøj, som ikke passer til opgaven - loddekolber er bedre end stearinlys; og hvis man endelig falder for at lave "mesterskruer", så er en hammer bedre (endnu bedre er det selvfølgelig at have materialer, som passer til opgaven!). De forhåndenværende søms princip er altid en nødløsning; en næstbedst i bedste fald - og vil derfor aldrig give så godt et resultat, som at gøre det rigtigt. Det er på samme måde med et team - selvom opgaverne skal kunne ramme skævt i forhold til teamet uden at det er en ulykke i sig selv, og selvom et godt team kan klare næsten hvad som helst, så er det vigtigere at have det rette sammensætning af teamet end at klare sig med hvad man nu engang har.

Cross functional teams bestående af generalizing specialists kan være overraskende robuste og brede, men må ikke forveksles med forveksles med et hold af generalister, også selvom det ved første øjekast kan være nemt at overse forskellene. Resultaterne (og teamet) vil lide under det!

Afslutningsvist - og i nogen grad "off-topic"- så er der endnu en fordel i kunne spænde over flere specialer, som person eller som team, som egentlig ikke har noget med ovenstående at gøre (og som vel også er noget overset i sammenhængen): De innovative og kreative løsninger kommer sjældent indenfor et enkelt speciale; specialer kan være meget konserverende, og specialister kan være meget konservative - ofte kommer det fra brydningsfeltet imellem flere specialer - og et aktuelt eksempel kunne være neuroøkonomi. Men det er en helt anden snak.

onsdag den 11. juni 2008

Ligustersværmer

Fra Makro
I går aftes var jeg lige en tur ude i vores have, og der falder mit blik på en af de opbindingspæle, som vi har stående bl.a. ved vores nyplantede frugttræer - og så fik jeg mig noget af en overraskelse, for der sad et stort insekt. Altså ikke "stor" på den måde, hvor en skovmyre er "stor" set i forhold til en havemyre, men bare stor!

Jeg måtte derfor ind og hente mit kamera og har da også fået et par billeder (i slutningen af albummet "Makro" er der en fem billeder - se linket under billedet).

Ud fra billederne og en gennemsøgning af nettet, så har jeg besluttet mig for, at det nok er en af vores almindelige aftensværmere, nemlig en ligustersværmer (sphinx ligustri). Det var godt, at jeg havde billederne at støtte mig til, for jeg har aldrig set sådan en før, og uden billederne havde jeg nok gættet på en anden og mere sjælden art.

Ligustersværmeren er en af de største danske sommerfugle. Jeg nænnede ikke at forstyrre den, selvom jeg meget gerne ville have set den sværme, så vi må nøjes med billeder af den med vingerne foldet pænt sammen som her - men selv sådan synes jeg, at den er imponerende; pælen, som den sidder på, er ca. 45 mm i diameter.

Turen på nettet var også en tur tilbage til "barndommens gade", for ligustersværmerens store, flotte og meget karakteristiske larve husker jeg tydeligt, at vi som børn gik og fandt i genboens ligusterhæk. Der står i et katalog over skadedyr på nettet, at skaderne fra ligusterlarverne meget begrænset, så hvis man skulle finde en, så var anbefalingen at kalde på børnene og i øvrigt at passe godt på den! Hvis I overrasker mig ud på sensommeren med hovedet i busken, så ved I nu hvorfor.

søndag den 1. juni 2008

Er syntaktisk sukker tomme kalorier?

Jeg havde i denne uge fornøjelsen af, sammen med Rasmus, at deltage i et gå-hjem-møde om "C# 3.0 og LINQ" arrangeret af Niels Ladegaard Beck fra Trifork. I forbindelse med gennemgangen af nye features i C# 3.0 lød det på et tidspunkt som om, at Niels nærmest undskyldte, at der nok mest var tale om "syntaktisk sukker". Det fik mig til at sidde og tænke over, om hvorfor syntaktisk sukker nærmest er blevet et skældsord, og på om det er rimeligt?

Lad os starte med at prøve på at definere begrebet "syntaktisk sukker". Her er et godt bud:
Syntactic sugar gives the programmer an alternative way of coding that is often more practical, more conducive to a better programming style, or more natural to read. However, it does not typically affect the expressiveness of the formalism or permit the language to do something new.
(kilde: Wikipedia: Syntatic sugar).

Syntaktisk sukker er altså en anden, og måske mere bekvem, måde at sige det samme på. Hvis man kan sige noget nyt, så er det per definition ikke syntaktisk sukker. Og så er det, at asketer og purister siger fra - en måde at gøre tingene på, det må da være mere end rigeligt, vil de mene!

Men hvad er det så lige, at formålet med et programmeringssprog egentlig er? Ja, vel indlysende nok, at være medie for en instruktion til en computer, men vel mindst lige så indlysende, at gøre det på en human og forståelig måde.

Hvis man har prøvet at være i en situation, hvor man er normsættende, så har man sikkert også på et tidspunkt hørt sig selv sige: "Du skal ikke gøre, som jeg gør - du skal gøre, som jeg siger!" Med computere er problemet lidt omvendt, og havde man kunnet tale til dem, så ville man sikkert kunne høre sig selv sige: "Du skal ikke gøre, som jeg siger - du skal gøre, som jeg mener!" På samme måde, så har man, når man har prøvet at forklare noget til andre, sikkert også hørt sig selv sige: "...lad mig prøve at forklare det på en anden måde".

Et godt sprog skal derfor dels kunne give utvetydige instruktioner, men samtidig formidle en præcis forklaring af hensigten. En præcis forklaring uden unødige omsvøb er en god forklaring - også selvom den måske ikke lige overholder den gængse opfattelse af formalia og regler for, hvad der er den rette tone. Syntaktisk sukker er derfor et spørgsmål om forklaringsevne, og ikke et spørgsmål om udsagnskraft. Syntaktisk sukker giver os muligheden for at formulere os på mere end en måde, og derfor muligheden for at vælge den mest hensigtsmæssige.

Syntaktisk sukker behøver derfor ikke at være et spørgsmål om bekvemmelighed eller dovenskab (i en sidebemærkning vil jeg så mene, at de to vigtigste menneskelige egenskaber er nysgerrighed og dovenskab, så ikke et ondt ord om dovenskab - vi havde aldrig opdaget hjulet, hvis ikke vi var nysgerrige, og vi havde aldrig fået det udnyttet, hvis ikke vi var dovne!) - syntaktisk sukker er i mindst lige så høj grad et spørgsmål om, at kunne udtrykke det, som man mener. Når man skriver programmer, så formidler man forståelse af en fremgangsmåde - dels til computeren, men også til mennesker, både ens fremtidige jeg, men også alle andre, som bliver konfronteret med ens kreation. Jo mere præcist at man er i stand til at udtrykke sig, jo bedre bliver meningen formidlet.

Eller for at sætte det på spidsen: Computeren skal nok forstå, hvad du siger - men kan du selv og andre forstå, hvad du mener?

Niels fra gå-hjem-mødet i indledning vil sikkert være enig med mig i ovenstående, for hans foredrag var i høj grad et eksempel på, hvordan man med de nye ting i C# 3.0 og LINQ kunne skære ned på formalia, og dermed øge læseligheden.

Et oplagt eksempel, hvad mange vil kalde syntaktisk sukker, er Type inference (hvordan oversætter man i øvrigt"type inference" til dansk?). Ortodokse tilhængere af statisk type check vil sikkert bruge begrebet nedsættende, i det de argumenterer for, at den reducerede formalisme forringer sprogets evne til i kraft af sin opbygning at medvirke til at undgå fejl. Det er da også muligt at komme på eksempler, hvor det er tilfældet. Men den anden fløj i debatten vil mene, at det som oftest i stedet tvinger os til at gentage det indlysende grænsende til det absurde. Ved at fylde teksten op med unødvendige trivialiteter, så fjerner man opmærksomheden fra det væsentlige - eller men andre ord, ved at gøre det nemt at finde fejl i formalia, så gør man det sværere at se fejl i logikken. Jeg hælder nok mest til det sidste synspunkt - og er det sandt, så er det da at smide barnet ud med badevandet!

Hvis du er med så langt, så vil du sikkert have fornemmet, at mit holdning til spørgsmålet i overskriften er, at syntaktisk sukker ikke nødvendigvis er tomme kalorier - og måske endda som oftest det modsatte. Det er så her, at jeg bliver nødt til at padle baglæns, for mit argument står og falder med at syntaktisk sukker kan gøre det nemmere at formidle overblik og hensigt. Men engang imellem, så er der udelukkende tale om bekvemmelighed og dovenskab - og desværre på måde, som gør det sværere at få overblik eller forstå hensigten. Oftest er der tale om et tveægget sværd - det, som kan give fornuft, kan også misbruges. Ikke alt sukker er godt sukker - og nogen steder er selv lidt sukker for meget sukker!

Et eksempel på det tveæggede sværd kunne være operator overloading. Det er oplagt, at man her har muligheden for på en kompakt måde hurtigt at formidle overblik og indsigt. Men det kommer med en betydelig risiko for at blive misforstået (eller, hvis det kommer i de forkerte hænder, at blive direkte vildledt!).

Et andet eksempel stod gå-hjem-mødet for, nemlig C# 3.0 extension methods. Her var der tale om adskillige løftede øjenbryn, og en af deltagerne slog hovedet på sømmet med en bemærkning om, at det ville gøre det meget vanskeligt at finde ud af, hvor funktionaliteten stammede fra uden understøttelse fra ens IDE (og her vil jeg så tilføje, at det altid er en Beck'sk "stank", når ting bliver så komplicerede, at man bliver afhængig af værktøjer til at hjælpe en med at håndtere kompleksiteten - her skal man altid spørge sig selv, om kompleksiteten er iboende eller tilfældig!). Jeg tror, at alle kunne se meget af det gode, som extension methods ville gøre muligt, men jeg er også overbevist om, at vi var adskillige, som havde et dårligt deja vu - sikkert forårsaget af konkrete oplevelser med f.eks. operator overloading.

Til slut vil jeg lige svare på mit spørgsmål til mig selv i indledningen: Jeg tror, at syntaktisk sukker som begreb har et dårligt rygte på grund af alt for mange eksempler på dårlig implementering. Men et princip kan sagtens være godt, selvom der findes eksempler på dårlig anvendelse - og derfor vil jeg også mene, at det dårlige rygte er uretfærdigt. Eksemplerne på dårlig anvendelse skal dog mane til forsigtighed, og vi skal vælge vores leverandør af sukker med omhu, og tilsvarende selv være bevidst om faren ved overdreven eller forkert brug af sukker.

(en lille og helt urelateret regi-bemærkning: Jeg startede med at skrive dette på en smuk sommerdag, og jeg lå derfor ude i skyggen under det store æbletræ i vores have - jeg kunne derfor have skrevet en lovsang om den frihed, som de såkaldt trådløse teknologier giver os ... men jeg nåede kun halvvejs, førend det væltede op med advarsler i stærkt stigende streghed om, at nu var der altså snart ikke mere strøm på batteriet! Jeg endte derfor med at sidde indenfor i lummerheden bundet til en stikkontakt - jeg glæder mig til den dag, hvor energiforsyningen også reelt bliver trådløs!)