Nachtrag: aktualisierte Fassung des Programms ist am Ende des Beitrags
Das mit dem Verstehen ist ja schön und gut, aber bei Sprachen – Programmiersprachen wie anderen – reicht es nicht, wenn man die grammatischen Kategorien kennt, man muss die Sprache auch anwenden können. In Bayern lernen die Schüler in Informatik in der 10. Klasse Gymnasium (im naturwissenschaftlich-technologischen Zweig) die Grundprinzipien es objektorientierten Modellierens und Programmierens. Mit den Prinzipien haben sie auch wenig Schwierigkeiten; Klassendiagramme kriegen sie einigermaßen hin – aber das Umsetzen der Diagramme in Programmcode macht vielen mehr Probleme.
Also habe ich mir vorgenommen, im nächsten Durchgang mehr zu pauken. Eine Doppelstunde nur Klassendiagramme implementieren. Und dann nochmal, wenn es nötig ist. Das kriegt man nämlich nur durch Übung rein. – Ob ich das dann wirklich so mache, hängt natürlich von der konkreten Klasse ab. Aber ich habe mir schon etwas vorbereitet, und zwar den Java-Klassendiagramm-Implementierungs-Aufgaben-Generator. So sieht er aus:
Wenn man auf den weißen Knopf kriegt, erzeugt und speichert das Programm zwei Textdateien. Die eine ist ein Klassendiagramm für eine zufällig erstellte Klasse, mit 1 zufällig ausgewählten Attribut, einem Standardkonstruktor und je einer getter- und setter-Methode für das Attribut:
|-------------------- | Raumschiff |-------------------- | alter: int |-------------------- | Raumschiff() | getAlter(): int | setAlter(int): void |--------------------
Wenn man sparsam mit den Leerzeilen ist, kann man das in sechs kurzen Zeilen programmieren. Wenn die Schülerin das getan hat, importiert sie die zweite Datei, die das Programm erzeugt hat, in ihr Projekt. Diese Datei enthält den Code für eine weitere Java-Klasse, und zwar eine Testklasse, die überprüft, ob die Klasse auch semantisch richtig implementiert worden ist, also ob die Methoden auch das tun, was sie sollen, und ob das Attribut da ist, und ob die Datentypen und die Schreibung exakt mit dem Klassendiagramm übereinstimmen. Die Testklasse sieht so aus, auch wenn die Schülerin sich den Code nie anschauen muss:
import static org.junit.Assert.*;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class RaumschiffTest {
Raumschiff testObject;
public RaumschiffTest() {
}
@Before
public void setUp() {
testObject = new Raumschiff();
}
@After
public void tearDown() {
testObject=null;
}
@Test
public void attributeUeberpruefen() {
testObject.alter = 8;
}
@Test
public void setAlterTest() {
testObject.setAlter(40);
assertEquals(40, testObject.alter);
testObject.setAlter(11);
assertEquals(11, testObject.alter);
testObject.setAlter(31);
assertEquals(31, testObject.alter);
}
@Test
public void getAlterTest() {
testObject.alter = -5;
assertEquals(-5, testObject.getAlter());
testObject.alter = 64;
assertEquals(64, testObject.getAlter());
testObject.alter = -17;
assertEquals(-17, testObject.getAlter());
}
}
Mit einem Mausklick startet man den Test, und herauskommt eine Anzeige, welche Tests bestanden wurde:
Dazu muss die von der Schülerin erstellte Klasse erst existieren, und zwar grammatisch fehlerfrei. Die Tests überprüfen nur, ob das Programm auch das tut, was es soll, nicht ob es überhaupt läuft – das sagt einem schon der Compiler eine Stufe zuvor.
Man kann sich auch Klassen mit zwei, drei oder vier Attributen erzeugen lassen. Wenn die Attribute nicht als private
markiert sind, werden die Attribute überprüft und die getter/setter-Methoden anhand dieser Attribute überprüft – ansonsten wird die getter-Methode anhand der setter-Methode auf Richtigkeit getestet, und umgekehrt. Man auch auswählen, dass ein zweiter Konstruktor mit zu den Attributen passenden Argumenten erzeugt werden soll. Außerdem kann man noch ankreuzen, ob die neuen Objekte der Klasse bestimmte Startwerte für die Attribute haben sollen, die dann im Konstruktor festgelegt werden. Dann heißt es unter dem Klassendiagramm:
Der Wert des Attributs 'alter' soll am Anfang sein: 32
Die Werte für die Attribute werden ebenfalls zufällig ausgewählt. Attribute können vorerst nur vom Typ String, boolean, char, double, int
sein. Die Testklasse wird jeweils unter Berücksichtigung all dieser Entscheidungen erstellt.
Das könnte man jetzt ausweiten und die Schüler selber Klassenbezeichner und Attribute auswählen lassen. Oder mit Referenzattributen arbeiten, dass also – für den Anfang – zwei Klassendiagramme erstellt werden, wobei das eine ein Referenz auf das zweite enthält.
Wen es stört, dass das so eine Art Liegestützen für Java sind, also eher sinnlose, wiederholende Übungen, der kann sich vielleicht daran erfreuen, dass die Schüler so an den Umgang mit Testklassen und Testverfahren herangeführt werden.
- Download des .jar-Archivs. Vorsicht: Erzeugt im selben Verzeichnis die Textdateien im Format
<Klasse>Test.java
und<Klasse>Diagramm.txt
und überschreibt vorhandene Dateien mit gleichem Namen ohne Rückfrage.- Erste Bugs gefunden, verbesserte Version von 2017-08-06, 19:50 Uhr
- Neue Version vom 2017-08-07, 09:00 Uhr, etwas aufgeräumt im Code und assertEquals bei double verbessert
- Neue Version vom 2017-08-31: Code aufgeräumt, die Varianten bei privaten Attributen etwas eingeschränkt, und jetzt kann man auch noch optional eine zufällige Methode schreiben lassen, die kein Getter oder Setter ist. Im Moment sind das aber nur
istGerade, verdoppeln, hoch3
undbetrag
, das wäre aber leicht zu erweitern. Hintergrund: Jetzt gibt es doch für jeden Pseudo-Datentyp eine eigene Klasse (und damit Postleitzahlen im Bereich 10000-99999 statt mit beliebigen int-Werten), und für jede Pseudo-Methode ebenfalls (die für ihren eigenen Testcode verantwortlich ist). - Neue Version vom 2017-09-02. Nach außen unverändert, aber viel innen umbenannt und neu gebastelt, unter anderem zusätzliche Pseudo-Methoden.
- Neue Version vom 2018-10-21. Postleitzahlen funktionieren jetzt als String.
Schreibe einen Kommentar