No IDE: A New Experience

Last week, we were attending a small conference that also included some one-day workshops. I chose to dig a little bit into Node.js. The workshop was held by Golo Roden.

I must admit I’ve had prejudices against JavaScript. And so I chose this topic to gain new insights. Now I know a lot more about JavaScript, have more questions and I really wonder:

Is it possible to conduct large complicated projects without an IDE?

I started developing software more than a decade ago with Smalltalk. For those of you who do not know Smalltalk: There is no separation of the IDE and the product. You don’t even work with files. Have a look yourself: http://www.pharo-project.org/home. – The non-existence of files in the Smalltalk IDE will give you an impression of how I feel with files. About ten years ago I had my first encounter with a different language based on files: Java. – Wow, that was strange at first.

To you this may seem weird. Programming without files? – To me it has been the other way around.

And last Thursday I’ve been attending my first workshop without even an IDE. Only an editor and a command line. – And it worked well for me. At least I was able to type in all the code (or should I say text?) Golo showed on the screen and made only few typos. I was really happy to have a quite sophisticated editor capable of JavaScript: syntax highlighting, able to show brace coherence.

But: I really wonder whether this will scale.

  • How will this work with more than ten files?
  • How will you do refactorings?
  • How can you see relations?

To me one aspect – if not the most important one – of programming is to be able to navigate my code. I definitely do want to see the implementation of a method or function I call. I want to be able to find the potential callers of a function. All this typing is so distracting from the product I’m about to build.

  • I have to know what is already defined to be able to use it.
  • It’s a pain (and slow) to look it up by reading potentially concerned files or documentation.
  • I have to remember the filenames where stuff is defined.
  • I have to track everything inside my head – in detail!

Is this really a professional working style? – What do you think?

 Instead I’d like to be able
  • to see an overview of my code
  • to see the big picture

This is even hard in today’s IDEs. But closer than just an editor.

P.S.: Some googling pointed me to obviously working IDEs for JavaScript with more than syntax highlighting.

How we ran our Legacy Code Retreat

Preparation:

The Content:

The Organization:

We had the great opportunity to use our employer’s facilities. Everything is available there, except for food. So the only thing left to do was to get some food. We have chosen our local bakery for breakfast, got fruit at the supermarket and hired a caterer for lunch.
What we learned: Don’t buy too much food. – We did. For the bakery we discovered that three pieces per participant are sufficient, and two pieces of fruit. We made an effort to offer food of excellent quality, and many participants rewarded this with small remarks about how much they enjoyed it.
We had coffee prepared for every break. During the setting up, we could count on the earlycomers’ aid in carrying stuff around. It is our general experience that participants of those kinds of events are always very helpful.

The iterations:

In gerenal the format worked well. The first iteration served as warm-up. We stretched the second iteration to another 45 minutes to give the participants the chance to play around more. The restriction-based iterations have been sort of confusing for some of the participants. Their feedback indicates that the codebase is not very suitable for applying the proposed patterns. We should have given a little bit more guidance there and clearly explain that the restrictions are not exercises to be completed but rather propositions to serve as a mental guide for the modifications to be done and to play around with.

A Great Surprise:

The biggest surprise we’ve experienced was that one of the participants (Hayati Ayguen) came up with doing the golden master and the automated comparison via a bash-script (see below)! Great!

Summary:

This won’t be the last legacy code retreat in Germany. Be prepared to see more of them in the future. Feel free to contact us for help when you want to run your own.

Bash Scripts and related Code:

createGoldenMaster.sh

#!/bin/bash

for s in `seq 1 $1`; do
  ./a.out $s >erg$s
done

compareWithGoldenMaster.sh

#!/bin/bash

totalerrs=0
for s in `seq 1 10`; do
  ./a.out $s >current
  errs=`diff erg$s current |wc -l`
  echo "vergleich $s hat " $errs "unterschiede"
  totalerrs=$[ $totalerrs + $errs ]
done

if [ $totalerrs -eq 0 ]; then
  echo all OK.
else 
  echo ERROR!
fi

GameRunner.cpp

#include <stdlib.h>
#include "Game.h"

static bool notAWinner;

int main( int argc, char * argv[] )
{
    if ( argc != 2 )
    {
        cerr << "usage: " << argv[0] << " <seed>" << endl
             << "  seed should integer " << endl;
        return 10;
    }
    int seed = atoi( argv[1] );
    cout << "seed is " << seed << endl;
    srand( seed );

	Game aGame;

	aGame.add("Chet");
	aGame.add("Pat");
	aGame.add("Sue");

	do
	{
		aGame.roll(rand() % 5 + 1);

		if (rand() % 9 == 7)
		{
			notAWinner = aGame.wrongAnswer();
		}
		else
		{
			notAWinner = aGame.wasCorrectlyAnswered();
		}
	} while (notAWinner);

}

Thoughts on collections

Yesterday I stumbled upon code like the following:

if (coll != null) {
   for (Item item : coll) {
      // do something
   }
}

This pattern was repeated over and over. I wondered:
“Why on earth can this collection be null at all?” – The succinct answer can be found in the definition of the field:

private Collection<Item> coll;

This field is never initialized during the enclosing object’s instantiation.
Alright, this is not really bad by itself. So I will insert a null test every time I am accessing the field and everything will be fine.

STOP -> Wrong (implicit) question! (“What’s wrong with it?”)

You can of course answer this question, but it would be better to ask: “What’s the use of omitting the initialization?” answer: “Less memory.”

STOP -> I’m asking for a hearing device. Did my opponent really reason about memory? In a programm that is parsing XML via SAX, writes the resulting data into a database, reading it again from there and finally builds a DOM, which is written to the filesystem?

So what is it good for to omit the initialization? – Nothing but unreadable code and possible errors. Therefore collections should always be initialized with an appropriate empty collection.

To me there is no semantical difference between an empty collection and null.
If there is nothing in it, there’s nothing in it. I do not need different “nothings”.

IS there anything left to say? -> “YES!”

Why is the collection declard as Collection and not as an appropriate subtype? – Doesn’t the developer know what he wants?
A quick screening of the code shows: the collection is always created as ArrayList. Then it is obvious to declare the field as List<Item>. After all, List is more powerful than Collection.
Needless to say that a closer look at the code found parts where the field’s null check was omitted…

We then performed the initialization and removed every null check. We avoided changing Collection to List at that time:

private Collection<Item>; coll = new ArrayList<Item>();

And we have been really lucky: There have been a few unittests. We ran them and: NullPointerException when accessing coll! – I was slightly shocked! – rather: I pretended to be.

The cause lay here:

public void setItems(List<Item> items) {
   coll = items;
}

Looks completely innocent, but herewith you can set coll to null. So quickly searching all senders of this method and found (here list is a local variable; please don’t ask for the rest of the method…):

if (list == null || list.isEmpty()) {
   thing.setItems(null);
}

That’s the place where null is creeping back in through the backdoor. The first step was to always initialize list. For a local variable this is trivial. Side effect: less code:

thing.setItems(list);

Similar places were changed accordingly.

I often wonder: “Who the hell needs setters for collection fields?”
Is there an alternative?
Once you know it, it is quite obvious:
The collection-field is an implementation detail, managing a certain number of elements. Probably you want to add or remove elements. The actual process must be controlled by the owner of the collection-field. Therefor:

public void addItem(Item item) {
   coll.add(item);
}

public void removeItem(Item item) {
   coll.remove(item);
}

Of course you only need these methods, if you need to modify the collection this way.

Finally: ACCESS

To protect the above methods (add/remove) from the use of backdoors, mutable access to the collection field is to be prohibited. Your compiler can help:

public List<Item> getColl() {
   return Collections.unmodifiableList(coll);
}

Conclusion:

Collections in objects need protection and care:

  • They must never be(come) null
  • The enclosing object is responsible. All changes must be performed by it

The you’ll get:

  • Straightforward code, because many error-prone situations are impossible (except reflection-calls…)
  • Easier traceability of the changing code locations

I hope my words have been clear-cut, reasonable and entertaining.

Gedanken zur Verwendung von Collections

Gestern bin ich über Code gestolpert wie den folgenden:

if (coll != null) {
   for (Item item : coll) {
      // do something
   }
}

Dieses Pattern hat sich sehr oft wiederholt. Ich fragte mich: “Warum kann diese Collection überhaupt null sein?” – Die lapidare Antwort steht in der Felddefinition:

private Collection<Item> coll;

Das Feld wird auch später im Zuge der Instantiierung nirgendwo initialisiert.
Klar, das ist per se erst mal nicht schlimm. Dann teste ich eben vor jedem Zugriff auf null und alles funktioniert wunderbar.

STOP -> Falsche (implizite) Frage! (“Was ist schlimm daran?”)

Diese Frage kann man natürlich auch beantworten, aber besser ist folgende Frage: “Was bringt das Nicht-Initialisieren?” Antwort: “Weniger Speicherverbrauch.”

STOP -> Ich frage mich, ob ich ein Hörgerät brauche. Hat mein Gegenüber tatsächlich mit dem Speicherplatz argumentiert? In einer Software, die via SAX XML parst und Daten in eine Datenbank schreibt, von dort wieder ausliest und einen DOM baut, der dann als File geschrieben wird?

Was also bringt das Nicht-Initialisieren einer Collection? – Nichts außer unübersichtlichem Code und Fehlermöglichkeiten. Daher sollten Collections immer mit einer geeigneten leeren Collection vorbelegt werden.

Für mich gibt es keinen semantischen Unterschied zwischen einer leeren Collection und null.
Wenn nichts drin ist, ist nichts drin. Ich brauche keine unterschiedlichen “Nichtse”.

Gibt’s da noch mehr zu sagen? -> “JA!”

Wieso ist die Collection eigentlich als Collection deklariert und nicht als geeigneter Subtyp? – Weiß der Entwickler nicht, was er will?
Eine erste Durchsicht des Codes zeigt, dass die Collection immer als ArrayList instanziiert wird. Dann ist es ratsam, das Feld als List<Item> zu deklarieren. Immerhin kann List mehr als Collection.
Ich brauche wohl nicht zu sagen, dass schon beim weiteren Durchforsten des Codes Stellen zu Tage gefördert wurden, in denen das Feld nicht auf null geprüft wurde…

Wir haben also dann die Initialisierung vorgenommen und alle null-Prüfungen entfernt. Auf die Umwandlung von Collection nach List haben wir zunächst verzichtet:

private Collection<Item>; coll = new ArrayList<Item>();

Außerdem waren wir in der glücklichen Situation, dass wir einige UnitTests hatten. Und siehe da: NullPointerException beim Zugriff auf coll! – Ich war leicht geschockt – oder besser: tat so.

Die Ursache lag in folgender Methode:

public void setItems(List<Item> items) {
   coll = items;
}

Sieht harmlos aus, aber hierdurch kann coll auf null gesetzt werden. Also flugs alle Sender auf diese Methode gesucht und dort dann folgendes gefunden (list ist hier eine lokale Variable; fragt bitte nicht nach dem Rest der Methode…):

if (list == null || list.isEmpty()) {
   thing.setItems(null);
}

Hier kommt uns also das null wieder durch die Hintertür rein. Als ersten Verbesserungsschritt sorgen wir also dafür, dass list immer initialisiert ist. Das ist bei einer lokalen Variablen trivial. Und der Code wird kleiner:

thing.setItems(list);

Andere Aufrufer haben wir ähnlich geändert.

Ich frage mich immer wieder: “Wer zum Teufel braucht einen setter auf Collection-Felder?”
Was ist die Alternative?
Die Alternative ist einleuchtend:
Das Collection-Feld ist ein Implementierungsdetail, das eine gewisse Anzahl von Elementen verwaltet. Man möchte ggf. Elemente hinzufügen oder entfernen. Über das tatsächliche Durchführen muss aber der Besitzer dieser Elemente die Kontrolle behalten. Daher:

public void addItem(Item item) {
   coll.add(item);
}

public void removeItem(Item item) {
   coll.remove(item);
}

Die Methoden braucht man natürlich nur, wenn man die Operationen auch benötigt.

Zum Schluss: ZUGRIFF

Damit die beiden oben genannten Methoden (add/remove) auch nicht durch die Hintertür ausgetrickst werden können, darf natürlich nicht die Collection zur Veränderung nach außen gegeben werden. Dies kann (nicht prüfbar) durch Konvention erreicht werden, oder aber (durch den Compiler prüfbar) durch Rückgabe als unveränderbare Collection:

public List<Item> getColl() {
   return Collections.unmodifiableList(coll);
}

Fazit:

Collections in Objekten brauchen Schutz und Zuneigung:

  • Sie dürfen nie null sein oder werden
  • Das umgebende Objekt ist für sie verantwortlich, daher dürfen ändernde Zugriffe ausschließlich nur durch dieses Objekt vorgenommen werden

Dadurch erreicht man:

  • Klaren Code, da zahlreiche Fehlersituationen nicht mehr möglich sind (Reflection-Aufrufe ausgenommen…)
  • Bessere Nachvollziehbarkeit der Modifikationsstellen

Ich hoffe, diese Ausführungen waren verständlich, einleuchtend und unterhaltsam.

P.S.: Ich suche immer noch jemanden, der mich von meiner hier kundgetanen Meinung abbringen will.