Kategorien
Allgemein

Perl ausprobieren

Immer mal wieder frage ich mich, was ein einfacher Perl-Ausdruck denn nun wirklich macht. Da kommt der eingebaute Debugger genau richtig.

Für einfache Ausdrucke und Versuche ist es natürlich am einfachsten einen Perl-Einzeiler zu benutzen. Also

perl -e 'print "Hallo Weltn"'

Für Ausdrucke, die aber auf Variablen zur Laufzeit angewiesen ist, kann es recht müßig sein die History der Shell zu nutzen, oder eine Datei zu öffnen und dort  zu experimentieren.

Debugger to the rescue

Da bietet sich dann an den Debugger zu benutzen. Aber ich will ja eigentlich keine Datei entwanzen. Das Programm für den Debugger muss aber auch gar nicht gross sein. Eine einfache 0 tut es da auch. Mit perl -d -e 0 gelangt man mit dem folgenden Ausdruck in seine persönliche Perl Spielwiese:

user@rechner:~$ perl -d -e 0
Loading DB routines from perl5db.pl version 1.28
Editor support available.

Enter h or `h h' for help, or `man perldebug' for more help.

main::(-e:1):    0
  DB<1> $a="hallo"

  DB<2> print "$a weltn"
hallo welt

Wie man sieht, kann man im Debugger Variablen setzen und auf diese im nächsten Ausdruck zugreifen.

Mit dem üblichen Debugger Befehl x – Untersuche (eXamine) diesen Ausdruck/diese Variable – können wunderbar auch geschachtelte Datenstruckturen anschaulich dargestellt werden.

  DB<3> @a=qw(hallo welt)

  DB<4> x @a
0  'hallo'
1  'welt'
  DB<5> x @a
0  ARRAY(0x8404d64)
   0  'hallo'
   1  'welt'
  DB<6>

Macht man einen Fehler, so gibt der Debugger eine Fehlermeldung aus und man hat wieder einen neuen Versuch.

  DB<6> $a[a)
syntax error at (eval 11)[/usr/share/perl/5.8/perl5db.pl:628] line 2, near "a)"
Missing right curly or square bracket at (eval 11)[/usr/share/perl/5.8/perl5db.pl:628] line 4, at end of line
Kategorien
Allgemein

Immer eins nach dem anderen

Ein kleines Beispiel zeigt, wo die Reihenfolge der Deklaration von Variablen in Java Klassen wichtig ist.

Auf der Tomcat Mailingliste kam heute eine Mail, in der jemand fragte, warum sein Singleton im Tomcat nicht einamlig in der JVM vorhanden war. Die Lösung war wohl, dass er zwei verschiedene Classloader benutzte und daher zwei verschiedene Instanzen.

Ein anderes Problem seines Codes war aber ganz anderer Natur. Der Code sah etwa so aus:

public class Singleton {
    private static Singleton instance = new Singleton();
    private static int counter = 0;

    private Singleton() {
         System.out.println("Counter: " + (++counter));
    }

    public static getInstance() {
        return instance;
    }

    public int getCounter() {
        return counter;
    }
}

Auf den ersten Blick sieht das in Ordnung aus. Der Konstruktor gibt brav ein "Counter: 1" aus und man ahnt nichts böses. Bis dann ein kleiner Testfall mit jUnit aufkreuzt:

public class SingletonTest extends TestCase {
     public void testSingletonCounter() {
          Singleton instance = Singleton.getInstance();
          assertEquals(instance.getCounter(), 1,
              "Es kann nur einen geben");
     }
}

Hier wird dann plötzlich klar, dass intern der counter trotz anderweitiger Ausgabe wieder auf 0 gesetzt wurde. Das liegt daran, dass die Initialisierung der statischen Klassenvariablen der Reihe nach geschieht. Im Konstruktor ist counter also erstmal nicht definiert – implizit also null – und wird dann auf eins inkrementiert. Nach dem Konstruktor wird dann die vermeintlich noch nicht initialsierte Variable auf 0 gesetzt.

Das kann ganz schön ins Auge gehen.