Samstag, 3. Mai 2008

You broke the build

Auf meinem Blog schreibe ich meist über methodische Punkte rund um Scrum und/oder XP. Dabei beziehe ich mich immer auf Erfahrungen, die ich in Verbindung zu diesen Themen mache. Kürzlich hatte ich ein Erfahrung, die sich so gestaltete:

Das Set
Mehrere Entwickler arbeiten an verschiedenen Standorten an einem Software-Entwicklungsprojekt. Es gibt Entwickler, die sich ausschliesslich bei der Implementierung innerhalb eines Layers befinden, z.B. Backend, Business Services oder Web Container. Oft haben die Entwickler layerübergreifend nicht die Einsicht, von wem, wo und zu welchem Zeitpunkt Methoden aufgerufen werden.

Das Problem
Veränderung! Service Interfaces stellen einen Contract dar. Ein Änderung des Contract muss also allen Beteiligten mitgeteilt werden. So gedacht und durchgeführt von einem Entwickler, der an einem Standort die Runde per Zuruf informiert, dass er ein Interface ändern werde. Die Entwickler an anderen Standorten bekommen diese Information nicht. Der besagte Entwickler ändert das Interface und checkt den Code ins Repository ein. Alle Entwickler haben beim nächsten sync mit dem Repository nicht kompilierbaren Code. Der automatisierte Build failed in der Folge und alle Entwickler werden per Email benachrichtigt.

Was ist passiert?
Ein Entwickler hat für geschlagene 3 1/2h das gesamte Entwicklerteam mit seinem Checkin lahm gelegt.

Wie umgeht man das?
Zunächst mal sei gesagt, dass genau dieses Problem oft vorkommt und das Konzept von continuous integration aus den Angeln hebt. Hiermit soll sichgerstellt werden, das alle Veränderungen an der Codebasis, die in das Repository eingecheckt werden, die Lauf- und Funktionstüchtigkeit der Software nicht stören.

Am Beispiel eines bliebigen Interfaces möchte ich zeigen, wie man das Problem umgehen kann.

Die Methode
...
public void doSomething(String a, String b);
...

soll einen neuen Parameter bekommen:

...
public void doSomething(String a, String b, String c);
...

Wenn man das alte Interface verändert, werden alle Zugriffe auf diese Methode nicht kompilierbar sein. Man kann das wie folgt umgehen:

...
/** @deprecated */
public void doSomething(String a, String b);

public void doSomething(String a, String b, String c);
...

Die Implementierungen kann dann so aussehen:

...
/** @deprecated */
public void doSomething(String a, String b) {
// FIXME call doSomething(a,b,c) instead
doSomething(a,b, "fixed (dummy) c value");
}

public void doSomething(String a, String b, String c) {
// do stuff here
}
...


Per FIXME Kommentar kann man allen Entwicklern im Code erkenntlich machen, wie sie die neue Signatur aufrufen sollen. Wenn man das eincheckt wird nach wie vor Kompilierfähigkeit garantiert.

Natürlich muss sichgestellt werden, dass die deprecated Methode irgendwann entfernt wird. Hierfür gibt es Tools, die man im Rahmen der continuous integration laufen lassen kann. Sie raportieren TODO und FIXME Tags im Code

Keine Kommentare: