Archive for the 'Agile' Category

Prima lezione del corso di Tecnologia e Applicazioni Internet

Sunday, March 7th, 2010

Summary: first lesson with my new class. Teaching TDD, letting the students get a glimpse of how skilled they are in programming; which is unfortunately not much.

Per il secondo anno insegno Tecnologia e Applicazioni Internet all’Insubria. Il mio obiettivo per questo corso è di insegnare come sviluppare applicazioni web, applicando le pratiche tecniche di Extreme Programming. In particolare, vorrei insegnare Test-Driven Development e i principi di Object-Oriented Design, per come li capisco. Il mio meta-obiettivo per questo corso è fare in modo che lo studente diventi il doppio più bravo a programmare.

Per questo corso uso Java e non Rails. Il motivo di questa scelta è che Rails, per quanto sia una spanna sopra a tutti i web framework in Java, è purtuttavia un framework e in quanto tale è una stampella, una gruccia, che ti permette di stare in piedi ma certo non ti aiuta quando vuoi imparare a camminare da solo, men che meno a correre. Per imparare a camminare da soli bisogna imparare a programmare a oggetti.

In Aula

Per la prima lezione ho spiegato il TDD da solo, senza la complicazione delle servlet. Mi sono sforzato di pensare a un esempio che fosse piccolo a sufficienza per fare una demo di fronte agli studenti, in un pomodoro o poco più. Ho deciso di fare un “calcolatore a riga di comando”, ovvero un programma che presa una stringa come “2 + 3″ come argomento sulla riga di comando, stampi “5.0″ su standard output.

Il primo test che ho scritto:

@Test
public void twoAndThreeIsFive() throws Exception {
	Calculator calculator = new Calculator();
	double result = calculator.add(2, 3);
	assertEquals(5.0, result, EPSILON);
}

Abbastanza semplice da far passare. Ma non era sufficiente, perché dalla riga di comando gli argomenti arrivano come stringhe e non come interi già parsati. Per cui ho scritto un secondo test che ha fatto emergere una classe Parser

@Test
public void willParseTwoAndFive() throws Exception {
	Calculator calculator = new Calculator();
	String result = new Parser(calculator).calculate("2 + 5");
	assertEquals("7.0", result);
}

Perché creare una seconda classe a questo punto? Non sarebbe bastato mettere il metodo “parse” nella classe Calculator? Avrei potuto, però in questo modo il metodo “add” sarebbe diventato un metodo ad uso interno della classe. Come avrei fatto a testarlo? Avrei dovuto buttare via il test su add, oppure tenere add come “public” anche se in realtà serve solo internamente. Oppure usare qualche brutto trucco come dare ad “add” visibilità protected oppure package.

Invece, tenendo il Calculator come classe a sè che si occupa solo di fare conti, mentre Parser si occupa di leggere e scrivere stringhe, posso tenere “add” come metodo pubblico di Calculator. Martin direbbe che ho applicato il “Single Responsibility Principle.” Per me è stato decisivo pensare “se no mi tocca testare un metodo privato”.

Poi non ero ancora soddisfatto. Nel TDD quello che facciamo è sviluppare un isola felice di codice a oggetti, che però a un certo punto si deve scontrare con la realtà procedurale del mondo esterno. In questo caso il “mondo esterno” è il main, che deve creare e invocare i nostri oggetti. Per me è fondamentale che il main non contenga nessuna logica, ma soltanto la creazione di un certo numero di oggetti, collegati insieme. Se faccio restituire il risultato a Parser#calculate, poi al main resta la responsabilità di invocare System.out.println() per stampare.

Il mio obiettivo è ridurre al minimo la logica nel main, in modo che il main, che è per sua natura più difficile da testare unitariamente, sia così semplice da risultare ovviamente corretto. O comunque, per essere sicuro che il main se fallisce, fallisce sempre, e se funziona, funziona sempre. In questo modo posso essere ragionevolmente certo che se il mio main contiene un errore, me ne accorgerò. Gli errori di cablaggio, come li chiama Hevery, sono facili da trovare.

Allora ho applicato il principio “Tell, don’t Ask,” e ho passato l’OutputStream come collaboratore alla Parser#calculate.

@Test
public void willParseTwoAndFive() throws Exception {
	Calculator calculator = new Calculator();
	OutputStream stream = new ByteArrayOutputStream();
	new Parser(calculator, stream).calculate("2 + 5");
	assertEquals("7.0\n", stream.toString());
}

In questo modo è come se dicessi a Parser, “questa è la tua stringa da calcolare, questo è lo stream dove devi scrivere il risultato, adesso arrangiati, non ne voglio sapere nulla.”

Un pattern che si può riconoscere in questo design è una versione embrionale di collecting parameter. In generale cerco di evitare di avere metodi che restituiscono dati. Di solito è più efficace dire agli oggetti di fare cose, piuttosto che chiedere dati. Questo è il principio “tell, don’t ask“.

Possiamo anche vedere l’oggetto Parser come un adapter: adatta l’interfaccia del Calculator, basata su numeri, alle necessità di main, che lavora con stringhe.

Tutto ciò, beninteso, non significa che per programmare bisogna ad ogni piè sospinto cercare nel manualone dei pattern uno o più pattern da ficcare dentro al nostro codice. Al contrario, quello che ho fatto io è stato di scrivere il codice che mi sembrava più appropriato per risolvere il mio problema, e poi, ragionandoci sopra, ho riconosciuto dei pattern in quello che avevo scritto.

In laboratorio

La seconda parte della lezione si è svolta in laboratorio. Ho proposto un semplice esercizio, di scrivere un programma che concatena le righe di due file a una a una, un po’ come fa il comando paste(1) di Unix. Ho visto subito che per la maggior parte degli studenti questo esercizio era troppo difficile, per cui sono subito passato a suggerire come primo test una versione semplificata del problema.

@Test
public void pasteLinesFromArrays() throws Exception {
	List a = Arrays.asList("aa", "bb");
	List b = Arrays.asList("xx", "zz");
	List result = new ArrayList();

	Concatenator concatenator = new Concatenator();
	concatenator.concatenate(result, a, b);

	assertEquals(Arrays.asList("aaxx", "bbzz"), result);
}

I miei studenti sono al terzo anno di Informatica triennale. Nel nostro corso di laurea, il linguaggio di programmazione di riferimento è Java. Purtroppo, ho dovuto osservare che per la grande maggioranza dei miei circa 40 studenti, scrivere il codice che fa passare questo esercizio è un problema difficile. E nessuno (mi pare) è stato in grado di estendere il codice per fare passare anche il secondo test:

@Test
public void listsCanBeOfDifferentLength() throws Exception {
	List a = Arrays.asList("a");
	List b = Arrays.asList("b", "c");
	List result = new ArrayList();

	Concatenator concatenator = new Concatenator();
	concatenator.concatenate(result, a, b);

	assertEquals(Arrays.asList("ab", "c"), result);
}

Non so che cosa pensare. Questi esercizi mi sembrano di un livello di difficoltà paragonabile al famoso “problema” FizzBuzz, che viene usato nei colloqui di lavoro per scremare quelli che non sanno programmare per niente da quelli che forse sono capaci di fare qualcosa. Al terzo anno mi aspetterei qualche cosa di più. Sto cercando di ricordare me stesso al terzo anno di università. Sono sicuro che sarei riuscito a risolvere questo problema.

Ma non importa. Venerdì prossimo continuerò con esercizi di questo tipo. Piano piano miglioreremo. Sono sicuro che, alla fine del corso, gli studenti che avranno continuato a frequentare raggiungeranno l’obiettivo di diventare (almeno) il doppio più bravi a programmare.

Next speaking engagements

Thursday, February 25th, 2010

I’m happy to say that the Birthday Greetings Kata session that I did with Antonio at XP Days Benelux was selected for a second run at the Mini XP Day! I hope to see you in Eindhoven, The Netherlands, on April 26.

My other speaking engagement is a Coaching Workshop, co-organized with Simone Casciaroli, that will happen at Better Software in Firenze, 5-6 May. Simone and I were going to present this at the Agile Day 2009, but Simone was hit by flu and could not come.

Report of the first run of the OCP kata

Tuesday, February 23rd, 2010

Two weeks ago we had our first meeting of the Milano Coding Dojo. It was great fun, and I was honored to see Giordano had prepared such a good presentation mentioning, among other things, the “OCP Kata” of my earlier blog post. The “Open Closed Principle” says that we should be able to add new feature by adding code, not by changing existing code (with an exception made for the place where the objects are created; after all, for the new class to be used, it must be instantiated somewhere.) The OCP Kata is a set of rules, to be used in a training session, that force us to apply the OCP.

So this was not only the first test-drive of this Dojo, but also of the OCP Kata. How did it go?

We worked randori-style on the Yathzee kata. My impressions follow.

On the OCP Kata rules

The OCP Kata was an influence only for the first test (forced us to use an explicit factory) and the second test (forced us to apply the OCP). After that, the OCP rules did not fire, as the problem was naturally easy to be solved in OCP style. After all, it was the implementation of a series of scoring rules for the Yathzee game. Once you have the scoring rules machinery in place, everything else can be completed just by adding a new class (and modifying the factory).

One class, many uses

We must always keep an eye on the design. The complexity of the code kept going up, until we worked hard at removing duplication. The OCP rules do not produce a good design by themselves. Early in the kata, the rule for “twos” was the same as the rule for “threes” with 3 in place of 2. The solution was to create a SingleNumberRule that takes the number in the constructor. We avoided making two classes, when a single class could be used in different context with different configuration.

The driving force was removing duplication.

More duplication

Later, we had a lot of duplication between the “pair” rule, and the “double pair” rule. The code that looks for a pair is needed in both rules. An old-school OO programmer would have made the two rules derive from a common, abstract base class. The abstract base class would be a repository for shared methods. Modern OO programmers know to use inheritance only as a last resort. So what could we do to remove duplication without inheritance? One key observation was that most of that duplicated code was looking heavily into the array of rolls. When you have code that uses heavily a data structure, it’s a good idea to move both data structure and code in an object.

The natural name for that object is “hand”, so we created a Hand class that wraps the array of die rolls. The duplicated code disappeared.

The driving forces were removing duplication and avoiding direct access to data.

Finding abstractions

The code in the Hand class was still not good enough. It was full of loops. There was no flash of insight here, we just applied a few “extract method”s that moved each loop in its own little method. Once we did that, we realized that some loops depended on another one that counts the occurrences of each number in the hand. For instance, the occurrences in the hand (1, 1, 3, 3, 4) are (2, 0, 2, 1, 0, 0). This is a key abstraction in this domain.

The other abstraction that is needed to implement the pair rule is “find me the highest pair”, which is just max{i | occurrences(i) ≥ 2}. (It is not enough to score *any* pair. It must be the highest pair, if more are present.)

To implement the “double pair” rule, we need a way to say “find the second highest pair”. One way to say this is that if the highest pair is, say, 4, we must look for the highest pair that is less then 4. The method we need is

    public int highestPairLessThen(int n) {
       return max{i | occurrences(i) ≥ 2 && i < n};
    }

Now the two pairs rule was easy to implement:

    public int highestPair() {
      return highestPairLessThen(7);
    }

    public int secondHighestPair() {
      return highestPairLessThen(highestPair());
    }

The solution here was to find the right abstractions, and implement complex things in terms of simple things. It’s a bit of functional programming in the small.

Conclusions

The goal of good design is to have simple building blocks that can be combined together to create complex things. When we are at the object-talking-to-other-objects level, the OCP principles guides us to invent object abstractions. When we are in the small, within-the-object level, it’s good to apply some mathematical thinking. It’s not deep, difficult mathematics. It’s just a game of finding the right definitions, and using them to express complex things in terms of simpler things.

Update: cleaned up HTML, added headings

Niente Shore né Larsen

Saturday, February 6th, 2010

Summary: the Shore + Larsen course due in Milan this month is cancelled due to not enough attendance. Too bad.

Che peccato! XP Labs mi ha scritto che i corsi di James Shore e Diana Larsen che avrebbero dovuto esserci questo mese, sono stati annullati per il numero insufficiente di iscritti. Sarebbe stata un’occasione unica per noi della zona di Milano di imparare da questi autori. Io sono un grande fan del manuale di Shore e Warden.

Mi sono allora iscritto ai i corsi di Rebecca Wirfs-Brock, che saranno in marzo. Spero proprio che si riesca a raggiungere il numero! Gli autori di Growing Object-Oriented Software citano Rebecca come l’originatrice dello stile di design che prediligono.

The OCP kata

Tuesday, January 12th, 2010

Read the first chapter of the Patterns book, it’s all there, where it says “favor composition over inheritance”,

said Jacopo. We were chatting about the Open/Closed Principle, and how I read about it in Meyer in 1991, yet it didn’t “click” for me back then.

Now I see how the OCP is key to writing code that can be changed easily, which is the chief technical goal of an agile team. I wondered, is there a way to teach and learn the OCP? Is there a kata to learn OCP?

It’s unfortunate that most common coding katas result in “single-object-oriented programming”. The famous bowling score example by Robert Martin, for instance, is usually solved by creating *one* object. This might be fine for learning how to write simple code. It’s not so good for learning how to do object-oriented design.

So I invented this little exercise to practice and learn OCP.

Take any coding problem. The bowling score, the string evaluator, the supermarket checkout, you name it. Then follow these instructions.

0. Write the first failing test. Then write a factory that returns an object, or an aggregate of objects, that make the test pass.

The factory should be limited to creating objects and linking them together. No conditionals allowed.

1. Write the next failing test.

2. Can you make it pass by changing the factory and/or creating a new class and nothing else? If yes, great! Go back to 1. If not, refactor until you can.

The refactoring should bring the system to a state where it’s possible to implement the next test just by changing the aggregate of objects that is returned by the factory. Be careful not to implement new functionality; the current test should still fail.

For instance, take the bowling score problem. The first test is

  @Test public void gutterGame() throws Exception {
    BowlingGame game = new BowlingGameFactory().create();
    for (int i=0; i<20; i++) {
      game.roll(0);
    }
    assertEquals(0, game.score());
  }

The code to make this pass is

  class BowlingGameFactory {
    public BowlingGame create() {
      return new BowlingGame();
    }
  }

  class BowlingGame {
    public void roll(int n) {}
    public int score() {
      return 0;
    }
  }

Nothing strange here. Now the second test is

  @Test public void allOnesGame() throws Exception {
    BowlingGame game = new BowlingGameFactory().create();
    for (int i=0; i<20; i++) {
      game.roll(1);
    }
    assertEquals(20, game.score());
  }

The simplest code that makes both tests pass would be to change BowlingGame to accumulate rolls in a variable. But our rules stop us from doing that; we must find a way to implement the new functionality with a new object. I think about it for a few minutes, and all I can think of is to delegate to another object the accumulation of rolls. I will call this role “Rolls”. Cool! This forces me to invent a new design idea. But I must be careful not to add new functionality, so I will just write a Rolls object that always returns 0.

  interface Rolls {
    void add(int n);
    int sum();
  }

  class BowlingGame {
    private final Rolls rolls;

    public BowlingGame(Rolls rolls) {
      this.rolls = rolls;
    }

    public void roll(int n) {
      rolls.add(n);
    }

    public int score() {
      return rolls.sum();
    }
  }

  class BowlingGameFactory {
    public BowlingGame create() {
      Rolls zero = new Rolls() {
        public void add(int n) {}
        public int sum() { return 0; }
      };
      return new BowlingGame(zero);
    }
  }

This passes the first test, and still fails the second. In order to pass the second test, all I have to do is provide a real implementation of Rolls and change the factory.

  class Accumulator implements Rolls {
    void add(int n) { ... }
    int sum() { ... }
  }

  class BowlingGameFactory {
    public BowlingGame create() {
      return new BowlingGame(new Accumulator());
    }
  }

And so on. The point here is to think about how to

  1. compose functionality out of existing objects, and
  2. avoid reworking existing code.

Feedback?

Project automation for Confluence plugins

Monday, January 4th, 2010

A while ago our team was working at customizing Confluence for one of our customers. I’d like to share a few tips on how to automate Confluence plugin deployments.

(It should not be necessary to point out that all repetitive operations should be automated. Read all about it in The Pragmatic Programmer and Pragmatic Project Automation.)

Our automation was mostly Bash-based. I think it’s important to write expressive code in any language. When you’re scripting with Bash, the main way to be expressive is to use functions. We keep our scripts in a $(project)/script directory, so that you can invoke them with a minimum of keystrokes. The script we use for installing our plugin on localhost is:

 1  confluence_url=http://localhost:8080
 2  confluence_install=~/confluence-2.9.2-std
 3  admin_password=admin
 4
 5  source src/main/bash/lib.sh || exit 1
 6
 7  quietmvn package || exit 1
 8  plugin_jar=$(ls target/ourplugin-*.jar)
 9  [ -f "$plugin_jar" ] || (echo "no plugin generated"; exit 1)
10  confluence_login
11  confluence_uninstall_plugin
12  confluence_install_plugin

Lines 1-3 set up some variables for future use.

Line 5 loads our library of functions in the current shell process. The “|| exit 1” bit means “if this command fails, then quit immediately”.

The “quietmvn” in line 7 invokes maven with a filter that hides useless warnings. We found that Confluence plugin builds generate a lot of warnings due to dependencies on Atlassian packages that have poorly written “pom.xml” files. This (according to Atlassian) is harmless; but then again, useless warnings are harmful, so we filter them out.

Getting back to line 7, this builds the jar package of our Confluence plugin.

Line 8 defines a $plugin_jar variable with the relative pathname of the plugin jar. The $(foobar) bit is a Bash command that executes the foobar command and returns the text output generated by the command.

Line 9 says “if the plugin file does not exist, then exit with a meaningful error message.” In Bash, the command [ -f foobar ] tests if file “foobar” exists.

Line 10 to 12 are the interesting bit. They invoke three Bash functions that do what their name implies. They depend on the variables we set up in lines 1-3. This allows us to use the same functions for both local and production deployments. And here is our precious Bash library:

 1  cookie_jar=/tmp/confluence-cookies.txt
 2  curl="curl --cookie-jar $cookie_jar --cookie $cookie_jar --output /tmp/curl-output.html"
 3
 4  function confluence_login() {
 5    echo "login to confluence"
 6    $curl -s -S -d os_username=admin -d os_password=$admin_password "$confluence_url/login.action"
 7  }
 8
 9  function confluence_uninstall_plugin() {
10    echo "uninstall plugin"
11    $curl -s -S $confluence_url'/admin/plugins.action?mode=uninstall&pluginKey=ourpluginkey'
12  }
13
14  function confluence_install_plugin() {
15    echo "reinstall plugin ($plugin_jar)"
16    if [ \! -f $plugin_jar ]; then
17      echo "ERROR: $plugin_jar not found"
18      exit 1
19    fi
20    $curl -F file_0=@$plugin_jar\;type=application/octet-stream $confluence_url/admin/uploadplugin.action
21  }
22
23  function quietmvn() {
24      mvn $* | grep -v '\[WARNING\] POM.*Not a v4.0.0 POM'
25  }

The three functions I was talking about use Curl to interact with Confluence as if our script was a web browser. This is not the way to automate installs that Atlassian recommends, which is to use Maven with some Atlassian plugins. We found that the Maven way was not as reliable as using Curl.

And this is all there is to it. It took some time to find the right way to invoke Confluence with Curl, but every minute spent was worth it. This small library of Bash commands allows you to perform installs and uninstalls of any plugin with maximum reliability. It takes away a lot of pain from Confluence plugin development.

Ricerca sales manager in Sourcesense

Tuesday, December 22nd, 2009

Summary: position in Sourcesense for a Sales Manager

Sourcesense sta cercando un commerciale per assunzione. Questa persona si dovrà occupare (fra l’altro) di sviluppare il business per il team Agile. Se pensi di essere in grado di spiegare ai potenziali clienti perché è vantaggioso comprare sviluppo e formazione da un team che è in grado di sviluppare software in incrementi settimanali, con il controllo e la sicurezza che ne conseguono, allora sei la persona giusta per noi!

Lettori di questo blog: se conoscete una persona adatta, per favore diteglielo.

Tutte le informazioni qui:

http://www.sourcesense.com/en/careers/006-sales

XP Day London was, indeed, a blast!

Thursday, December 10th, 2009

It was very, very, inspirational and fun. I ran another session of Birthday Greetings Kata, facilitated an open space on the Hexagonal Architecture. London is a city I love to visit, and the Church House location, is fantastic: just a few steps from Westminster Abbey.

And I had the authors sign my copy of GOOS (I believe every good book should have an acronym… and I don’t like GOOSGBT :-) )

My signed copy of GOOS

Thank you guys! I have a feeling this book will be a good companion in my re-discovery of OOP.

Entity-relationship-oriented programming

Thursday, December 10th, 2009

How I agree with Dafydd Rees when he writes:

Most Java and C# programmers have no idea how to do object-oriented programming.

They’re really doing entity-relationship-oriented programming. Trouble is, they’re in the majority so they form a self-reinforcing group that take for granted knowledge and skills that they don’t even realise that they don’t have.

Aaand… I’m afraid I was in the E-R-oriented camp until not long ago. Now I’m beginning to see how how objects should work.

Back from XP Days Benelux, on to XP Days London

Sunday, November 29th, 2009

Last week I attended the XP Days Benelux. It’s the fourth time I go there, and it’s been a mild shock to realize how often I was there. The first time I went there was because I had the pleasure to meet Pascal, who was kind enough to help us run the first Essap. It was a big bet for us to do something as big as a Summer School. Luckily, we had help from Pascal and Francesco.

I was just starting to get my bearings in the Agile world back in 2006. Pascal came to Essap and taught us about estimating, planning and executing a plan, with his and Vera’s ingenious XP Game. And that was not his only contribution… he was, like, a *real agilist* who had a long tradition and a strong community behind. In 2006 we had just started the Milano XP User Group. It was great to meet someone who had a much bigger experience of working with agility.

There is this peculiar thing about the Benelux Agile community. They are real cosmopolitans. They speak English easily, since their countries speak many different languages and they are used to speak English even among themselves. They really *live* the agile values. I mean, if you want to succeed with agile, you better start living your life with the agile values. The organization of the XP Days reflects this.

For instance, it’s not like in old-school conferences where you send you session proposal and then it’s either rejected or approved. At Xp Days you are supposed to send a first draft, then you receive feedback on your proposal, then you improve your proposal with the feedback. This reflects the value of feedback, and the principle that good things are not done in one shot, but iteratively.

In the room where the plenary sessions were held, the core values of this group of agilists were exposed prominently. See in the first picture here, they are those sheets of papers high up to the right of the projector screen. They are unreadable in the photo, but they were well readable if you were in the room. They were

  • courage,
  • openness,
  • focus,
  • respect,
  • committment.

One other example of agile values in action is the many forms of feedback that are encouraged. For every session, you’re encouraged to write your feedback on a small card for that session. At the closing of each day, people who attended each sessions are asked to tell everybody what they learned (in 60 seconds! The timebox is another agile principle.) When you leave the conference you are asked to write a feedback sheet for the conference in general. “Give the gift of feedback”, is what the organizers say.

So my trail in the world of agile has been very much influenced from the beginning by the Benelux agilists. It’s a great trail to be in :-) Over the years I got to meet many more friends there, and it’s great to meet new ones every year. Some, like Yves, Marc and Willem, continued Pascal’s tradition and came to help us organize Essap in 2008.

My and Antonio’s contribution to the XP Days this year was the session on the Birthday Greetings Kata. Thanks to all participants! We learned a lot of valuable feedback on how to improve this session, and I’m ready for the next stop, which will be in London.