Is Your Team Busy Producing Legacy Code?

Jag sprang över en artikel (sälj för en bok) med titeln: Is Your Team Busy Producing Legacy Code? Upphovsmannen Gil Broza pekar på precis de områden som jag själv brinner för – hur man faktiskt lever (eller överlever) med sin kodbas. I kort skulle jag sammanfatta det Gil skriver så här:

Du är inte agil om du inte jobbar proffesionellt med kod. Undvik skriva legacy kod genom TDD, refactoring och Clean Code.

Andra kallar det Software Craftmanship.

Vi hjälper våra kunder öva dessa fördigheter med Coding Dojos. Vi tror att vi lyckas bättre med plattformsspecifika övningar som inte bara övar ett visst moment eller färdighet, utan också visar på att det går att använda “i riktiga problem, för att skriva riktig produktionskod”. Att sitta med enkla plattformsoberoende övningar har givetvis sin plats – man fokuserar på principen, att få in tankesättet genom att ta bort komplexiteten från t ex stela och stora API:er. Men stannar man där – i små enkla problem – har vi sett att det är också där tillämpandet fastnar. Klivet till “verkligheten” blir för stort från övningsexemplets förenklade och säkra sandlåda till den grymma verklighetens omständigheter.

Snabbspårskurs i TDD

Den 3-6 december går JDays av stapeln för första gången i Göteborg. De första dagarna består av föreläsningar (som till viss del väljs av besökarna) och sista dagen är kurser (som ingår i priset). Jag kommer hålla en av heldagskurserna och den beskrivs så här:

Software Craftsmanship stands on the notion that “code is written by humans, for humans” and realizes that the developers themselves are the first users of the code they produce. They’ll read it several times during the code’s lifetime – and the time it takes to read and understand the code, is heavily affected by how “clean” that piece of code is.

Test-driven development offers more than just simple validation of correctness. By focusing on the test first, a developer must imagine how the system and/or it’s APIs will be used, which may help in crafting interfaces and APIs that are easy to understand and digest – thus being a great help in writing actual clean code.

In this hands-on crash course attendees will learn and master the basics of TDD. The theory behind TDD will be explained and intertwined with exercises. Focus is on practicing TDD – i.e. writing code – so that the participant is ready to start doing TDD in real life projects the following day. During the day, various topics related to Software Craftmanship and Clean Code will be explained and discussed.

Attendees should be comfortable with the Java programming language and bring a laptop with Eclipse (or similar IDE) installed.

Väl mött! :-)

When Fluent API:s help

Through my work, I often run across an API pattern that looks like this: it consists of the API definition itself and some definition of how to consume the API. An example:

Three typical options

If you look at the get method in this API, one typically has three options on defining it’s behaviour (or contract):

  • return a BillingPeriod object
  • return null if there’s nothing to return
  • throw an exception if there’s nothing to return

From what I’ve seen, returning null is common as well as throwing an exception. Every now and then (way too often according to the bug tracker) the usage of API on either of these patterns fail – the consumer of simply forgets to check with the boolean method before calling the getCurrentOrNextPeriod().

I really really really think that putting “null” in source code should be frowned upon and only used in very rare circumstances. The problem with returning null is that you have to check if you received a null reference instead of a reference pointing to an actual object. Throwing an exception may be a “safer” way saying “HEY you really shouldn’t proceed now since you asked me to get something that I can’t provide, and you shouldn’t have asked me for stuff I don’t have in the first place and so you probably may do other harmful stuff if I don’t interrupt you now right away”.

A fourth option

A fourth option would be to return a Nullable – a pattern suggested by Uncle Bob and others. This is simply a reference that you can ask: “do you point to an actual object, or will you give me a null reference back?”
which would let us rewrite the API to:


But, while this surely adds information saying “there may not be a BillingPeriod – you should check first”, it still relies on the programmer to call the hasValue() method before getValue().

Wait, there’s a fifth option!

But, there’s also a fifth option. With a more “fluent” API one may enforce a completely fail safe usage pattern:

which would make a consumer look like this:

This would force the consuming programmer to use the API properly and in a safe way.

Yes, it requires some more code from the programmer that provides the API, but it’s not that much and it does reduce errors in the consuming programmer’s code! And bugs that are discovered “late” (when the API is used (in production)) are always much more expensive than bugs discovered “early” (when the API is produced).

CITCON 2012 i Budapest

I helgen kom jag äntligen iväg på CITCON (uttalas kit-kon) eller Continuous Integration and Testing Conference. Det är en årlig konferens som i år arrangeras på fyra kontinenter. Formatet är open space och de enda fasta förutbestämda punkterna är när sessioner börjar presenteras, vilka rum som finns och tider för sessioner och pauser – allt annat avgörs på plats av de som deltar. “Come prepared” skickades ut i ett mail och det märktes att en del kom väldigt förberedda och hade funderat länge på olika problem eller frågeställningar de ville ventilera. Majoriteten kom dock oförberedd, men det var nog tur – långt fler sessioner föreslogs än det fanns tid att avhandla.

Hur gick det till?

CITCON är en typisk open space-konferens. Ungefär så här i punktform (YMMV):

  • Alla deltagare samlas i ett rum, var och en får en knapp minut att svara på “vad heter du, en värd/arrangör presenterar formatet, reglerna och det schema som finns. Schemat är tomt förutom information om tillgängliga rum och tider då sessioner startar och slutar.
  • En kö bildas med de som vill föreslå en session. Man får bara föreslå en i taget, och ställa sig sist i kön om man vill man föreslå fler.
  • Personen längst fram i kön berättar i en knapp minut vad han/hon vill göra under sessionen, t ex visa ett verktyg, prata om ett problem, testa en kodkata, visa hur man (inte) testade av mobilappar. Personen sätter upp en lapp på schemat med sessionens titel samt sitt namn. Ingen vikt läggs vid var eller när lappen hamnar på schemat – den kommer ändå flyttas väldigt snart.
  • När kön är slut börjar tre aktiviteter: “röstning” och “planering”. Röstningen – dvs att var och en med ett litet streck markerar de sessioner man är intresserad av – behövs för att försöka sätta sessioner med många deltagare i ett rum som rymmer många deltagare. Planeringen är fullt demokratisk/anarkistisk – vem som helst får flytta runt lappar, men man gör klokt i att stämma av med den som satte upp lappen och andra som står vid schemat just då. Sessioner med relaterade ämnen slås ibland ihop. Nästa person kanske plockar isär dem. Allt eftersom tiden lider så stabiliseras processen och del 1 av open space avslutas. (Den tredje aktiviteten var att det serverades olika saker att knapra på och dricka. :-)
  • Genomförande. Schemat är fortfarande föränderligt ända fram tlll att ett pass starttid nås. Nya sessioner kan föreslås, befintliga slås ihop, flyttas, tas bort etc. Detta förekom också men inte i stor utsträckning.
  • En session startas och avslutas av en facilitator (personen vars namn står på lappen). Facilitatorn berättar hur sessionen skall förlöpa och försöker sammanfatta vad som sagts i slutet. Under CITCON var det vanligaste diskussioner av olika slag där ordet var helt fritt. CITCON förordar starkt att någon utpekad/frivillig för anteckningar.
  • Avslutning. Händer inte alltid men på CITCON samlades alla i samma rum där man startade och sammanfattade konferensen, denna gång genom att svara på frågan “what was your a-ha moment?”

Utöver detta finns bara en regel – regeln om två fötter! Om man känner att “här har jag inget att hämta eller tillföra, då skall jag använda mina två fötter och förflytta mig”. Oartigt? Nej för bövelen – det är oansvarigt att bara sitta av tid och kanske ta upp en skön sittplats för någon som verkligen är intresserad och mycket mer konstruktivt att istället söka upp en aktivitet man har något utbyte av.

Var var det?

Budapest, hos Colabs – ett hus vigt åt att hjälpa startups. Mycket vitt med klara accentfärger, bean bags och sköna citat prydde väggarna, t ex “There is no finish line. So love the journey.” (Tyvärr inte en enda whiteboard!)

Vilka sessioner hölls?

Jag stod en hel del ute i korridoren och pratade öga mot öga med enskilda individer. T ex pratade jag oväntat länge med Željko Filipin (jobbar nu för Wikimedia Foundation) om automatiserad testning av webb. Vi behandlade allt möjligt i ett härligt tempo: git, selenium vs web driver i mix med Watir, EC2, Jenkins plugins, Jenkins i molnet, egna seleniumslavar och “i molnet”. Minst 10 gånger svors det över all kostnad IE medför. Cucumber, Rake, Maven. Specification workshops. Jenkins Project Templates …

Does retail need tests?

Douglas Squirrel berättade bakgrunden som var att han kom från konsulting och i huvudsak bank- och finanssektorn – ett område där man inte gärna tar fel på 1 och 1000. Det senaste halvåret har han dock jobbat i retail/e-handel för ett bolag där man inte har ett enda utvecklartest, dvs test som skrivs av utvecklare, körs av utvecklare, för utvecklare. De har en del “metrics” i form av mätvärden som spottas ut i rapporter lite stup i kvarten. Dessa bevakas av diverse folk. Douglas frågeställning var: “why do I need those stinkin’ tests”? Hela sessionen var alltså ett ifrågasättande av enhetstester, integrationstester – kort och gott alla test som inte finns kvar i produktion. Douglas iklädde sig alltså en annan roll (han är pro-test i vanliga fall) under en timme med förhoppningen att få med sig utmärkta argument för att införa test. Det gick sådär – alla kring bordet var väldigt pragmatiska och det enda argumentet som jag tror höll var att “om utvecklarna vill införa det för att känna sig nöjda i arbetet (så det stannar på bolaget) så bör det vara något man accepterar från ledningen”.

Testing newer parts of a test suite more often than older parts

En session jag föreslog var att prata om hur man kan köra bara delar av en testsvit. Målet (för mig) är att köra alla nya tester kontinuerligt (vid push) och gamla tester endast nattligen. Orsaken till detta önskemål är att jag sett att detta är ett mönster som jag sett i det team jag jobbast mest de senaste åren: det som går sönder är det som är rörligt, dvs det vi jobbar med “nu” och där alla detaljar inte utkristalliserats ännu. Så gott som aldrig har något som är äldre än 3 månader gått sönder.
För att fortsätta upprätthålla korta snabba feedback-cykler hade det varit trevligt med ett verktyg som gör denna uppdelning åt mig. Man skulle givetvis kunna dela in alla test i två sviter manuellt, men det skulle ge underhållsbörda som är oönskad (ett verktyg borde klara av att göra denna enkla indelning).
Jetbrains CI-motor har visst stöd för att köra test som fallerar ofta oftare än andra men verkade inte ha precis det jag var ute efter. Olika idéer bollades och intressanta diskussioner fördes iaf med kompetent och erfaret folk, även om resultatet inte blev en nu JUnitRunner (iaf inte ännu …)

Andra sessioner

Det fanns fem tidsslottar men utnyttjade man lagen om två fötter så hade man möjlighet att delta i många fler. Fastnade man i bra diskussioner med folk i korridoren kunde man utan tvekan haft ett enormt utbyte utan att “delta” i en enda planerad session. Jag själv deltog även i sessioner om TDD, valuable metrics, men undvek en hel del om “how to motiviate people”. (Någon föreslog att “if a developer’s commit count is too low too long eventually it should be reflected in the salary” så det var emellanåt stora variationer på nivå i inläggen i debatterna.)
Allt eftersom dyker anteckningar från sessionerna upp på CITCON-wikin, som även har anteckningar kvar från tidigare år. En liten guldklimp med värdefullt material bland nätets alla wikis helt enkelt!

Var det värt att åka?

Absolut! I ett sådant här sammanhang kommer verkligen open space till sin fulla rätt och man är fullständigt slutkörd efter en intensiv dag av argumenterande, lärande, provocerande (för att ifrågasätta “axiom”). De som deltog hade över lag en mycket öppen och vänlig attityd och rent tekniskt var det stor blandning från embedded, webb, “native”, desktop och samma gällande plattformar. De som kom var här för att dela med sig och ta del av andras lärdomar och det var en underbar stämning och mycket inspirerande atmosfär som uppstod.
Jag hade endast två förväntningar som inte infriades: att över hälften av deltagarna skulle vara “seniora”; att vi skulle serveras gulash till lunch. Men det var verkligen av mindre vikt – allt övrigt slog in (över förväntan) och konferensen gav nya erfarenheter och uppslag, befäste en del “jag tror att”. På det hela taget var det sammanfattningsvis nästan “för” informations-, kunskaps- och tankeverksamhetsintensiv. Och, alla kör Jenkins, för allt.

Java Labels

Jag kan inte minnas att jag förut sett etiketter används i Java-kod (utanför böcker och studiematerial från kurser), men idag dök det upp i en del av java.util (ComparableTimSort) efter att jag kollade upp en bugg i Mockito som härstammade från just ändring av Arrays.sort och Collections.sort (gällande @InjectMocks):

    private void mergeLo(int base1, int len1, int base2, int len2) {
        assert len1 > 0 && len2 > 0 && base1 + len1 == base2;

        // Copy first run into temp array
        Object[] a = this.a; // For performance
        Object[] tmp = ensureCapacity(len1);
        System.arraycopy(a, base1, tmp, 0, len1);

        int cursor1 = 0;       // Indexes into tmp array
        int cursor2 = base2;   // Indexes int a
        int dest = base1;      // Indexes int a

        // Move first element of second run and deal with degenerate cases
        a[dest++] = a[cursor2++];
        if (--len2 == 0) {
            System.arraycopy(tmp, cursor1, a, dest, len1);
            return;
        }
        if (len1 == 1) {
            System.arraycopy(a, cursor2, a, dest, len2);
            a[dest + len2] = tmp[cursor1]; // Last elt of run 1 to end of merge
            return;
        }

        int minGallop = this.minGallop;  // Use local variable for performance
    outer:
        while (true) {
            int count1 = 0; // Number of times in a row that first run won
            int count2 = 0; // Number of times in a row that second run won

            /*
             * Do the straightforward thing until (if ever) one run starts
             * winning consistently.
             */
            do {
                assert len1 > 1 && len2 > 0;
                if (((Comparable) a[cursor2]).compareTo(tmp[cursor1]) < 0) {
                    a[dest++] = a[cursor2++];
                    count2++;
                    count1 = 0;
                    if (--len2 == 0)
                        break outer;
                } else {
                    a[dest++] = tmp[cursor1++];
                    count1++;
                    count2 = 0;
                    if (--len1 == 1)
                        break outer;
                }
            } while ((count1 | count2) < minGallop);

Jag trodde först det hängde ihop med kommentaren ovan, men så ovan var jag vid etiketter att jag misstog mig. :-)

Information Radiators – Team Performance

Jag såg en skön bild som fick mig att tänka på agila värden.

Sign“This team has delivered as planned, on time, for the past 24 weeks without slipping dates, and with zero overtime.”

“This team has a current roll of 1023 consecutive fully successful software builds and automated test runs.”

Transparens, överblickbarhet – att skylta med det som är viktigaste aktiviteten för ett team (lyckade mjukvaruleveranser t ex), borde göra att man känner ansvar om skylten visar ett dåligt “resultat”.

Denna form av utåtriktad “information radiator” ger bara rätt effekt under förutsättning att teamet som skylten gäller för, har full kontroll över hela kedjan som ingår i det skylten visar upp, t ex “lyckade byggen”. Om det står någon annan organisation i vägen så kommer teamet inte ta ansvar eftersom det inte KAN ta ansvar. Istället kommer de känna sig utpekade som “dåliga” och känna sig oförtjänt nedtryckta pga omständigheter de inte kan påverka eller göra något åt.

Givetvis är målet att teamet skall känna sig nöjda och viss stolthet över sitt arbete och sin skylt med ett bra “resultat” – en implicit klapp på axeln med orden: Japp, här inne vet de vad de gör och de gör det bra!

Oberoende, självorganiserande team ftw!

resize_with_right_button

I have an issue with my thinkpad’s buttons above the touchpad (the pointer device below keyboard). The issue is that pressing the mouse_button_modifier key (Alt) + middle button  + mouse movements starts scrolling events instead of window resize events.

The default settings work just fine if I plug in an external pointer device, but the touchpad is “misbehaving” and one way to cope with this when there’s no external keyboard or mouse, is to set the gconf key /apps/metacity/general/resize_with_right_button to true.

Raspberry Pi – first runs

One of the main expectations for me on this little device is to use it as a fanless media player. We’ve been using Boxee for quite some time which has a few very good features, all in all accepted by the boss (wife).

This post will be rather technical and list problems encountered and solutions (hopefully) applied in order to get it up and running.

Poor keyboard layout selection
System is configured to use sv_SE.UTF-8 as locale, yet the keyboard is en_* layout.
No solution yet. (Should be easy.)

Monitor/TV resolution not supported out of the box
The native resolution of the family TV, a Sony KDL-40V4220, is 1360×768. This is not available for selection in the xbmc settings menu.
No solution yet.
Status: well, on one of the kids’ newer TV this works just fine but some 15-ish pixels are cut off at each end by the TV(?)

No way to mount NFS shares via menu
All the family’s content is shared over NFS.
No solution yet. (Should be easy.)

Unclear if the remote will work (using LIRC)
I’ve not checked, but this is a must.
No solution yet.

No gigabit
I knew this one, but it’s still bugging me. The move from milliseconds to nanoseconds is just very appealing.
There’ll likely be no solution untill a new board comes out – the chipset/clock on the raspberry pi will not support this high speed I’ve been told.

No DVD playback – no mpeg2 decoding by GPU
According to a thread on the forum, this is because of licensing and the Pi foundation has not invested in this. (And the CPU is not powerful enough.)

Utmaning

Utifrån 12 things killer employees do before noon funderar jag på följande utmaning:

  1. Make a work to-do list the day before
    0 % – ny.
  2. Get a full night’s rest
    50 %.
  3. Avoid hitting snooze
    40 % – två dagar av fem.
  4. Exercise
    0 % – noll dagar av fem (förmiddagar), en dag av sju.
  5. Practice a morning ritual
    50 % – RSS-flöde på spårvagnen in.
  6. Eat breakfast
    100 % klart.
  7. Arrive at the office on time
    20 % – lurigt pga avlämning på förskola som kan vara skakigt, men en dag av fem.
  8. Check in with their boss and/or employees
    80 % – kan vara bättre på detta
  9. Tackle the big projects first
    ? % – oklart.
  10. Avoid morning meetings
    ? % – svårt när man jobbar förmiddagar …
  11. Allot time for following up on messages
    ? %
  12. Take a mid-morning break
    50 % – är ångan uppe hoppar jag mackan/rasten.