Das Hamster-Modell als Buch: http://www-is.informatik.uni-oldenburg.de/~dibo/hamster

D. Boles

Das Hamster-Modell - Java spielend gelernt

Zusammenfassung

In diesem Artikel wird das Hamster-Modell vorgestellt, ein einfaches aber mächtiges Modell zum spielerischen Erlernen der imperativen, objektorientierten und parallelen Programmierung. Das Hamster-Modell orientiert sich dabei an den Konzepten und der Syntax der Programmiersprache Java.

1 Programmieren lernen

Programmieranfänger leiden häufig darunter, daß sie beim Programmieren ihre normale Gedankenwelt verlassen und in eher technisch-orientierten Kategorien denken müssen, die ihnen von den Programmiersprachen vorgegeben werden. Gerade am Anfang strömen häufig so viele Neuigkeiten inhaltlicher und methodischer Art auf sie ein, daß sie leicht das Wesentliche der Programmierung, nämlich das Lösen von Problemen, aus den Augen verlieren und sich in syntaktischen und technischen Einzelheiten verirren. Der "Kampf" mit dem Compiler bekommt somit höhere Priorität als der Programmentwurf an sich und kann frühzeitig zur Frustration führen.

Das Hamster-Modell ist mit dem Ziel entwickelt worden, dieses Problem zu lösen. Mit dem Hamster-Modell wird dem Programmieranfänger ein einfaches aber mächtiges Modell zur Verfügung gestellt, mit dessen Hilfe er Grundkonzepte der Programmierung auf spielerische Art und Weise erlernen kann. Der Programmierer steuert einen virtuellen Hamster durch eine virtuelle Landschaft und läßt ihn bestimmte Aufgaben lösen. Die Anzahl der gleichzeitig zu berücksichtigenden Einzelheiten wird im Hamster-Modell stark eingeschränkt und nach und nach erweitert.

Mit einer ähnlichen Motivation wurde in den 70er und 80er Jahren die Schildkröten-Graphik der Programmiersprache LOGO entwickelt bzw. erprobt [Ros83,Men85]. Problem der Sprache LOGO ist jedoch, daß sie sich - wenn überhaupt - nur im Ausbildungssektor nicht aber beispielsweise im industriellen Bereich durchsetzen konnte. Dem "Mutterspracheneffekt" kommt jedoch auch beim Programmieranfänger eine wichtige Bedeutung zu: Die Muttersprache beherrscht man wesentlich besser als jede später erlernte Sprache. Aus diesem Grund wurde für das Hamster-Modell keine neue Programmiersprache entwickelt. Vielmehr wurde das Modell in die Konzepte und die Syntax der Programmiersprache Java [AG96] eingebettet. Die Sprache Java, die auch als Sprache des Internet bezeichnet wird, ist eine (relativ) einfache Sprache, die viele wichtige Programmierkonzepte enthält und sich - insbesondere im Zusammenhang mit dem rapiden Wachstum des Internet - auch im industriellen Bereich immer mehr durchzusetzen scheint.

2 Das Hamster-Modell

Das Hamster-Modell wurde in einer einfachen Version zu Beginn der 80er Jahre in der GMD entwickelt [Opp83]. Zielsprache war damals die imperative Programmiersprache ELAN [KL83,KL85]. Wir haben das imperative Hamster-Modell an die Programmiersprache Java angepaßt und um Konzepte der objektorientierten und parallelen Programmierung erweitert.

2.1 Grundlagen

"Es war einmal ein Hamster, der lebte einsam und verlassen in seinem Hamster-Territorium." Mit diesem Satz beginnt die Einführung in die Entwicklung von Hamster-Programmen. Das Hamster-Territorium - die Welt, in der ein Hamster-Programmierer operiert - wird dabei durch eine gekachelte Ebene repräsentiert. Auf den Kacheln können Weizenkörner liegen. Kacheln können auch durch Mauern blockiert sein. Auf einer Kachel steht der Hamster, der eine der Blickrichtungen Nord, Ost, Süd oder West einnimmt und prinzipiell beliebig viele Körner in seinen Backen aufbewahren kann.

Der Hamster besitzt die Fähigkeit, Befehle auszuführen. Er kennt die folgenden vier Befehle:

Bekommt der Hamster den Befehl, nach vorne zu gehen, obwohl er vor einer Mauer steht, so stirbt er. Dasselbe gilt für den Fall, daß er auf einer Kachel ein Korn aufnehmen soll, auf der keines liegt, oder daß er ein Korn ablegen soll, er aber keines in seinen Backen hat. Um derartige Situationen überprüfen zu können, kennt der Hamster drei Test-Befehle: Den Lernenden werden nun Hamster-Aufgaben gestellt, die sie mit Hilfe dieser Grundbefehle und inkrementell eingeführten Java-Programmierkonstrukten lösen sollen. Beispiel: In einem rechteckigen geschlossenen Raum unbekannter Größe ohne innere Mauern sind wahllos eine unbekannte Anzahl an Körnern verstreut. Der Hamster, der sich zu Anfang mit Blickrichtung Ost in der linken unteren Ecke befindet, soll alle Körner aufsammeln und dann anhalten.

2.2 Imperative Programmierung

Im ersten Teil des Hamster-Modells werden Sprachkonzepte imperativer Programmiersprachen eingeführt. Deshalb wird dieser Teil im weiteren auch als imperatives Hamster-Modell bezeichnet. Konkret handelt es sich bei den Konzepten um Anweisungen, Prozeduren, Kontrollstrukturen, den Programmentwurf an sich, Variablen und Ausdrücke, Funktionen und Parameter sowie die Rekursion, die in dieser Reihenfolge inkrementell eingeführt werden, so daß der Hamster nach und nach immer komplexere Probleme lösen kann.

Anweisungen und Programme: Zunächst werden die Lernenden mit den Begriffen Anweisung und Programm vertraut gemacht. Hierzu werden Hamster-Territorien jeweils fest vorgegeben und dann spezielle Aufgaben gestellt, die sich nur explizit auf das vorgegebene Territorium beziehen.

Prozeduren: Die Lernenden merken schnell, daß es recht umständlich ist, beispielsweise jedes Mal die Anweisungsfolge links_um(); links_um(); links_um(); angeben zu müssen, um den Hamster um 90 Grad nach rechts zu drehen. Über die Definition (parameterloser) Prozeduren und boolscher Funktionen wird ihnen die Möglichkeit eröffnet, neue Befehle und Test-Befehle zu vereinbaren: void rechts_um() { links_um(); links_um(); links_um(); }

Kontrollstrukturen: Durch die Einführung von Kontrollstrukturen (if-, while- und do-Anweisung) wird es möglich, Hamster-Programme zu entwickeln, die Lösungen eines Problems für verschiedene Hamster-Territorien darstellen. Das folgende Hamster-Programm löst bspw. die in Abschnitt 2.1 gestellte Aufgabe:

void main() {

ernte_eine_reihe_und_laufe_zurueck();

while (weitere_reihe_existiert()) {

gehe_eine_reihe_nach_oben();

ernte_eine_reihe_und_laufe_zurueck();

}

}

void ernte_eine_reihe_und_laufe_zurueck() {

ernte_eine_reihe(); kehrt(); laufe_zurueck(); kehrt();

}

boolean weitere_reihe_existiert() {

links_um();

if (vorn_frei()) { rechts_um(); return true; }

else { rechts_um(); return false; }

}

void ernte_eine_reihe() {

ernte_alle_koerner();

while (vorn_frei()) { vor(); ernte_alle_koerner(); }

}

void gehe_eine_reihe_nach_oben() { links_um(); vor(); rechts_um(); }

void laufe_zurueck() { while (vorn_frei()) vor(); }

void ernte_alle_koerner() { while (korn_da()) nimm(); }

void rechts_um() { kehrt(); links_um(); }

void kehrt() { links_um(); links_um(); }

Programmentwurf: Nach der Einführung der Kontrollstrukturen werden die Lernenden mit dem Begriff des Algorithmus und dem Problemlöseprozeß konfrontiert: Gegeben ein Problem, wie komme ich zu einem (Hamster-)Programm, das dieses Problem korrekt löst? Durch die Bearbeitung vieler Hamster-Probleme erarbeiten sich die Lernenden die Konzepte des Top-Down-Programmentwurfs.

Variablen und Ausdrücke: Um sich Dinge bzw. Situationen merken zu können, bekommt der Hamster ein Gedächtnis, repräsentiert durch Variablen. Gleichzeitig lernt er rechnen. Er muß beispielsweise die Körner im Territorium aufsammeln und die Anzahl in Form einer Binärzahl kodiert (1 = Korn, 0 = kein Korn) wieder ablegen. Typen sind im Hamster-Modell zunächst auf die Typen int, boolean und float beschränkt.

Funktionen und Parameter: Über die Definition von Prozeduren konnten dem Hamster neue Befehle beigebracht werden. Diese Lernfähigkeit des Hamsters wird nun durch die Einführung von Parametern bzw. Rückgabewerten erweitert. Ebenfalls wird das Lokalitätsprinzip von Variablen eingeführt.

Rekursion: Hamster-Programme sind außerordentlich gut geeignet, das Prinzip der Rekursion zu erläutern bzw. den Umgang mit rekursiven Funktionen zu erlernen. Beispiel:

void laufe_bis_zur_wand_und_zurueck() {

if (vorn_frei()) { vor(); laufe_bis_zur_wand_und_zurueck(); vor(); }

else { links_um(); links_um(); }

}

Eine komplexe Aufgabe, die rekursiv relativ einfach lösbar ist, ist die, daß sich der Hamster in einem Labyrinth befindet, in dem er ein Korn suchen soll.

2.3 Objektorientierte Programmierung

Aufbauend auf dem imperativen Hamster-Modell werden im objektorientierten Hamster-Modell inkrementell die objektorientierten (Java-)Programmierkonzepte Objekte, Klassen, Arrays, Vererbung, Polymorphismus und dynamisches Binden sowie Zugriffsrechte eingeführt.

Objekte: Im imperativen Hamster-Modell gibt es genau einen (namenlosen) Hamster, der die ihm gegebenen Befehle durchführt. Im objektorientierten Hamster-Modell wird dem Programmierer nun die Möglichkeit eingeräumt, mehrere Hamster gleichzeitig zu steuern. Hamster sind dabei benamte Objekte:

  if (paul.vorn_frei()) paul.vor();

while (willi.korn_da()) willi.nimm();

Klassen: Hamster müssen aus Klassen erzeugt werden, in denen die Befehle, die sie ausführen können, zu definieren sind. Was im imperativen Hamster-Modell Prozeduren bzw. Funktionen waren, sind nun Methoden, die die Befehle bilden, die die Hamster verstehen. Das Gedächtnis eines Hamster wird durch die Instanzvariablen seiner Klasse repräsentiert. Zusätzlich zu Hamster-Klassen können auch "normale" Klassen wie Listen oder Stacks definiert und benutzt werden.

Arrays: Arrays sind in Java Objekte und werden deshalb - zusammen mit der for-Schleife - erst an dieser Stelle eingeführt. Über Arrays kann ein Hamster sein Gedächtnis erweitern, um beispielsweise ein Abbild des Hamster-Territoriums (Matrix mit Körnern und Mauern) abzuspeichern.

Vererbung: Das Prinzip der Vererbung läßt sich ganz hervorragend anhand des Hamster-Modells erläutern: Hamster vererben die "erlernten" Befehle an ihre Nachfahren. So wie in Java alle Klassen automatisch von der Klasse Object abgeleitet sind, sind alle Hamster-Klassen von der Klasse Hamster abgeleitet, in der die sieben Grundbefehle definiert sind.

Polymorphismus und dynamisches Binden: Auf dem Prinzip der Vererbung aufbauend, wird das Polymorphismus-Prinzip eingeführt: Hamster-Kinder erben die durch ihre Vorfahren erlernten Befehle, können diese aber beispielsweise optimieren.

Zugriffsrechte: Unter dem Motto "Die Hamster werden eitel" werden die Lernenden anschließend mit den Zugriffsrechten vertraut gemacht. Während bisher prinzipiell beliebig von außen auf die Eigenschaften eines Hamsters zugegriffen werden konnte, hat nun ein Hamster über die Verwendung der Schlüsselwörter public, private und protected die Möglichkeit, bestimmte Eigenschaften öffentlich bekannt zu machen bzw. gegenüber Fremden zu verbergen.

  public class VaterHamster {

protected void ernte() { while (korn_da()) nimm(); }

public void ernte_eine_reihe() {

ernte();

while (vorn_frei()) { vor(); ernte(); }

}

}

public class KindHamster extends VaterHamster {

private int gesammelte_koerner;

protected void ernte() {

while (korn_da()) { nimm(); gesammelte_koerner++; }

}

public KindHamster() { gesammelte_koerner = 0; }

public int wieviel_koerner() { return gesammelte_koerner; }

}

void main() {

KindHamster paul = new KindHamster();

paul.ernte_eine_reihe(); paul.links_um();

while (paul.wieviele_koerner() < 10) {

paul.ernte_eine_reihe(); paul.links_um();

}

}

2.4 Parallele Programmierung

Der dritte Teil des Hamster-Modells führt aufbauend auf dem imperativen und dem objektorientierten Hamster-Modell die parallelen (Java-)Programmierkonzepte Threads, Kommunikation zwischen Threads, Synchronisation und Scheduling ein.

Threads: Während die Hamster im objektorientierten Hamster-Modell in einem Hauptprogramm quasi durch den Programmierer gesteuert wurden, werden sie nun selbständig.

  public class MeinHamster implements Runnable {

protected void ernte() { while (this.korn_da()) this.nimm(); }

public void run() {

while (this.vorn_frei()) { this.vor(); this.ernte(); }

this.links_um();

...

}

}

void main() {

MeinHamster paul = new MeinHamster();

MeinHamster willi = new MeinHamster();

new Thread(paul).start();

new Thread(willi).start();

}

Kommunikation: Die Hamster merken bald, daß sich bestimmte Probleme viel besser kooperativ lösen lassen. Dazu müssen sie miteinander kommunizieren. Der Nachrichtenaustausch kann dabei über gemeinsame Variablen (static-Variablen) oder über den Aufruf spezieller Kommunikationsmethoden ("per Zuruf") erfolgen.

Synchronisation: An speziellen Beispielen wird gezeigt, daß eine unkoordinierte Zusammenarbeit der Hamster in bestimmten Situationen zu Fehlern führen kann. Über die Java-Eigenschaften der Synchronisation werden die Hamster mit entsprechenden Mechanismen zur Verhinderung solcher Situationen vertraut gemacht.

Scheduling: Eine optimale Koordination läßt sich manchmal nur dann erreichen, wenn nicht alle Hamster gleichberechtigt sind, sondern bestimmte Hamster mehr Rechte bzw. mehr Macht haben als andere. Zu diesem Zweck werden die Java-Scheduling-Konstrukte priority, start, stop, yield, suspend und resume eingeführt.

3 Implementierung und Erfahrungen

Für das Hamster-Modell (zur Zeit nur für den imperativen Teil) ist eine graphisch-interaktive Programmierumgebung in Java implementiert worden, in der Hamster-Programme erstellt und ausgeführt werden können. Die Programmierumgebung stellt über ein Laufzeitsystem die Grundbefehle zur Verfügung. Hamster-Programme sind selbst auf dem Laufzeitsystem aufbauende Java-Programme, so daß sie auf den gesamten Java-Sprachschatz zugreifen können.

Zur Zeit entwickeln wir ein sogenanntes "virtuelles Hamster-Programmier-Labor". Diese Anwendung unterstützt die Erstellung und Ausführung von Hamster-Programmen im Internet. Darüber hinaus sind Online-Hilfen, viele Hamster-Aufgaben und Musterlösungen integriert. Des weiteren können Hamster-Programmierer über eine spezielle Workbench sowohl Probleme und Erfahrungen als auch Hamster-Programme und -Klassen austauschen bzw. sogar kooperativ ent-wickeln.

Im Wintersemester 1996/97 wurde an der Universität Oldenburg im Studiengang Diplom-Informatik zum ersten Mal Java als Programmiersprache für Erstsemester gelehrt. Dabei wurde das Hamster-Modell eingesetzt. Es hat sich gezeigt, daß es insbesondere für Programmieranfänger eine gute Grundlage zum Erlernen allgemeiner Programmierkonzepte bietet und dabei gleichzeitig in die Konzepte und Syntax von Java einführt. Beim Hamster-Modell steht nicht so sehr das "learning-by-listening" im Vordergrund, wie es sonst im universitären Bereich üblich ist, sondern das "learning-by-doing". Motiviert durch das optische Feedback bei der Ausführung von Hamster-Programmen in der graphisch-interaktiven Programmierumgebung haben die Studierenden nicht nur vorgegebene Aufgaben bearbeitet sondern sich immer wieder selbst Aufgaben ausgedacht und entsprechende Hamster-Programme entwickelt. Das Hamster-Modell stellt damit auch eine Lösung für das bekannte Anfängerproblem dar, daß Anfänger zwar gerne programmieren üben wollen, ihnen aber keine passenden Aufgaben einfallen.

Allerdings haben die Erfahrungen gezeigt, daß das Hamster-Modell nicht isoliert eingesetzt werden sollte. Einige Studierende hatten nach ein paar Wochen doch Probleme der Art: Das ist also Programmierung, wir hatten uns da was ganz anderes drunter vorgestellt. Es sollten also parallel zu Hamster-Problemen auch "reale Probleme" bearbeitet und gelöst und mit Hilfe von Java implementiert werden.

Literatur

[AG96] K. Arnold und J. Gosling: Java - Die Programmiersprache, Addison-Wesley, 1996.

[KL83] L. Klingen und J. Liedtke: Programmieren mit ELAN, Teubner Verlag, 1983.

[KL85] L. Klingen und J. Liedtke: ELAN in 100 Beispielen, Teubner Verlag, 1985.

[Men85] K. Menzel: LOGO in 100 Beispielen, Teubner Verlag, 1985.

[Opp83] L. Oppor: Das Hamstermodell, GMD St. Augustin, Interner Bericht, 1983.

[Ros83] P. Ross: LOGO programming, Addison-Wesley, 1983.

Autor:

Dipl-Inform. Boles, Dietrich
Universität Oldenburg, Fachbereich Informatik, Escherweg 2
D-26121 Oldenburg
Tel.: 0441/9722-212 , Fax: 0441/9722-202
e-mail: boles@informatik.uni-oldenburg.de