Nov 132012
 

Nach einem ersten Anlauf, der leider etwas ungenau geplant war, hatte ich heute die Möglichkeit, eine Doppelstunde zur Einführung in das Konzept der Vererbung in der objektorientierten Programmierung ein zweites mal besser vorstrukturiert durchzuführen.

Das Möbelplaner-Projekt wurde die letzten Jahre von Hamburger Informatik-Lehrer/innen und Didaktiker/innen, unter anderem von meinem Kollegen Uwe Debacher als möglicher Anwendungskontext für den Themenbereich „Objektorientierte Programmierung“ im Rahmenplan der Studienstufe in Hamburg in Java entwickelt.

Das Projekt ist für die IDE (integrierte Entwicklungsumgebung) BlueJ konzipiert und besteht aus einer Klasse „Leinwand“, die die anspruchsvolleren Aufgaben der grafischen Darstellung im Hintergrund übernimmt, und aus den Klassen „Stuhl“ und „Tisch“, die sich auf die Leinwand zeichnen lassen. Mit diesem Projekt arbeiten wir den Großteil des Semesters und bauen die Funktionalitäten Schritt für Schritt aus.

Grafik übernommen von http://www.debacher.de/wiki/BlueJ

Als Einstieg in das Thema „Vererbung“ wählte ich ein UML-Diagramm (eine standardisierte Beschreibungssprache) der beiden Klassen „Stuhl“ und „Tisch“, um die Attribute und Methoden wirkungsvoll im Vergleich gegenüberzustellen. Genauer wurde UML an dieser Stelle nicht thematisiert, dies werde ich im laufe der nächsten Wochen genauer tun.

eigene Grafik

In Hinblick auf Wartbarkeit und Übersichtlichkeit von Software diskutierten wir die Nachteile von Code-Dopplungen. An einem vorbereiteten Beispiel „Schrank“ mit erbenden Klassen „Kleiderschrank“ und „Küchenschrank“ habe ich daraufhin das Konzept in Java gezeigt, wie sich Objekte erzeugen lassen und Attribute wie Methoden von „Schrank“ auf die beiden Spezialfälle übertragen lassen, indem diese mit dem Schlüsselwort „extends“ als Unterklassen von Schrank definiert werden. (siehe weiter unten „Schrank.zip“ für das vollständige Java-Projekt) Hierbei habe ich extra-Zeit verwendet auf die Klassifizierung von Compiler-Fehlern und dabei auch das Thema Sichtbarkeit von Attributen und Methoden im Kurs diskutiert: Die zu vererbenden Elemente müssen als „public“ oder besser als „protected“ umgeschrieben werden, damit die erbenden Klassen auf diese zugreifen können.

Die Klasse Schrank mit den erbenden Unterklassen Kleiderschrank und Kuechenschrank, eigene Grafik

„Schrank“ und „Kleiderschrank“ sowie „Kuechenschrank“ als UML-Diagramm, eigene Grafik

Die Aufgabenstellung war nun, für das eigene Möbelplaner-Projekt die Klassen Stuhl und Tisch (und möglicherweise weitere Klassen) von einer generalisierenden Oberklasse „Moebelstueck“ erben zu lassen, um den Quellcode zu reduzieren und das Erzeugen neuer Möbel-Klassen zu erleichtern.

Hierzu hatte ich in unserem schulinternen Server-System mit iServ mehrere Hilfestellungen in Form von Quellcode als pdf je Klasse in verschiedenen Entwicklungsstufen mit einer Beschreibung des aktuellen Schrittes zur Verfügung gestellt, aber erst, nachdem alle etwa 20 Minuten eigenständig am arbeiten waren, um diejenigen zu unterstützen, die große Schwierigkeiten mit der Aufgabe hatten.

Das Hilfesystem mit schrittweisen Versionen der erbenden und vererbenden Klassen.

Etwa 20 Minuten vor Schluss habe ich einen Schüler, der gut in der Zeit lag sein Zwischenergebnis präsentieren lassen, um an diesem die Konfliktstelle zu diskutieren, die mir beim ersten Versuch im Parallelkurs den Rahmen gesprengt hatte. Die Methode „gibAktuelleFigur()“ erzeugt über einen GeneralPath eine zweidimensionale grafische Darstellung der betreffenden Klasse. Wenn nun sämtliche Methoden aus „Stuhl“ und „Tisch“ generalisiert werden, so muss auch die Methode „gibAktuelleFigur()“ in Moebelstueck enthalten sein, da sie von anderen Methoden benötigt wird, die exakt gleich sind in „Stuhl“ und „Tisch“. Dies hatte der Schüler selbst als „unschön“ gelöst erkannt, dass er einfach wie beim Stuhl einen Shape erzeugen ließ, obwohl ein Möbelstück gar keine direkte Form haben kann. Daran anknüpfend zeigte ich den Schüler/innen an der Schülerlösung, wie eine abstrakte Methode in einer dann abstrakt deklarierten Klasse eingefügt wird, die die Implementierung der Methode dann den Unterklassen überlässt. Dies rundete das heutige Thema ab und wurde gegen Ende der Stunde noch von einer Sicherungsphase mit individuellem Forumsbeitrag abgeschlossen.

Einige der Antworten auf die erste Fragestellung:

„Die Vererbung ist nützlich für das Software Projekt, weil es übersichtlicher gestaltet ist. Zwar braucht man Zeit um alles zu verstehen, doch nach und nach merkt man, dass es besser und schneller geht, wenn man die Sachen einmal definiert.“

„Es verkürzt das Schreiben um einiges und vereinfacht das Erstellen von Möbelstücken.“

„Die Vererbung ist sehr nützlich,weil man sich so eine Menge Arbeit sparen kann. Man definiert die Sachen die immer gleich sind nur ein einziges Mal. Außerdem wird es auch für den Aussenstehenden viel einfacher verständlich, weil das Skript nicht mehr so lang und kompliziert wirkt.Auch neue Klassen sind dank der Vererbung leichter zu erstellen.“

Die vollständigen Unterlagen zum weiterverwenden gibt es bei Uwe Debacher und soweit hier verwendet auch ausschnittsweise hier:

MoebelAnfang.zip

Schrank.zip

Hilfen-Vererbung.zip

Aug 232012
 

Ich würde gerade gerne mehr schreiben, aber da vieles Material, was ich im Unterricht verwende nicht ausschließlich von mir erstellt ist (was ich auch nicht als primäre Aufgabe von Lehrer/innen sehe) sondern Kompositionen darstellt, kann ich gar nicht so viel publizieren, wie ich gerne würde.

Aber gelegentlich werde ich dies selbstverständlich weiterhin tun.

Gutes Material empfehlen kann ich allerdings:

Für meinen Informatik-Unterricht, beispielsweise den Kurs zu Objektorientierter Programmierung, verwende ich häufig die Materialien von meinem Kollegen Uwe Debacher: www.debacher.de der sein Material ebenfalls unter Creative Commons zur Verfügung stellt und viel mit Wiki-Tutorials arbeitet.

Für Lego Mindstorms benutze ich gelgentlich ein Lehrerhandbuch, welches unters traditionelle Copyright fällt und zu kaufen ist und hier dementsprechend nicht veröffentlicht wird. Zudem hat Uwe Debacher auch hier einiges veröffentlicht und ich habe auch eigenes Material bereits auf diesen Blog gestellt, das ich wiederverwende und weiterentwickle. Viele Aufgaben sind in diesem Bereich projektförmig und lassen sich mit den Schüler/innen auch gut gemeinsam in Ideensammlungen ohne zusätzliches Material entwickeln.

Für den Mathematik-Unterricht in der Vorstufe verwende ich teilweise das Arbeitsheft von Klett „Zum Übergang von der Realschule in die Oberstufe„, das ich auf einer Fachtagung zur Brückenfunktion der Vorstufe in den Hamburger Stadtteilschulen zufällig in die Hände bekam, kaufte und sehr angetan war von dem Aufbau als Selbstlern-Heft mit Selbsttests und Übungsaufgaben zu moderner Mathematik, also auch viel Problemlöse- und Modellierungsaufgaben. In der Schule nutzen wir das Buch „Elemente der Mathematik„, welches ich gerne und gut nutze, allerdings fehlen mir auch noch die Konkurrenz-Vergleiche anderer Mathematik-Schulbücher. Inspirierende für die Mathematik finde ich auch immer wieder die online verfügbaren Aufgaben der Hamburger Behörde zu den zentralen schriftlichen Überprüfungen.

Soweit erstmal zum Unterrichten und den Lizenzen. Fortsetzung folgt…

Apr 272012
 

Heute haben wir uns im Informatik-Fachseminar mit dem Thema Kryptologie in der Sek1 (9. oder 10.Klasse) und einer Umsetzung mit der Programmiersprache Python beschäftigt.

Ziel war heute, ein Programm zur Verschlüsselung von Zeichenketten zu erstellen, das problemorientiert und nicht künstlich nur zum Üben geeignet ist. Als Ansatz nahmen wir eine einfache Verschlüsselung an, die einzelne Zeichen vertauscht, z.B. das erste gegen das dritte, das zweite stehenlässt, das vierte gegen das sechste tauscht usw.
Hierzu gab es einen Vorschlag, der folgendermaßen aussieht:

def drilling(eingabe):
    zaehler = 0
    laenge = len(eingabe)
    ausgabe = ""
    while zaehler < laenge:
        if zaehler % 3 == 0:
            if zaehler+2 < laenge:
                ausgabe = ausgabe + eingabe[zaehler+2]
            else:
                ausgabe = ausgabe + eingabe[zaehler]
        if zaehler % 3 == 1:
            ausgabe = ausgabe + eingabe[zaehler]
        if zaehler % 3 == 2:
            ausgabe = ausgabe + eingabe[zaehler-2]
        zaehler += 1
    print ausgabe     

eingabe = raw_input("Bitte ein Wort eingeben:")
drilling(eingabe)

Wir diskutierten kleinschrittigeres Vorgehen, erst nur ein Tripel vertauschen, um nicht gleich Schleifen und Fallunterscheidungen als Konzepte mit einbeziehen zu müssen. Beispielsweise könnte erst nur der Vertauschvorgang auf Papier modelliert werden, also erst nur Zeichenketten der Länge 3, dann im zweiten Schritt dieses auf Zeichenketten der Länge eines Vielfachen von 3 erweitern und dann auf beliebige Zeichenketten.
Der erste Schritt wäre dann:

# Eine ganz einfache Variante der Drillingsverschluesselung
def drilling(eingabe):
    ausgabe = eingabe[2] + eingabe[1] + eingabe[0]
    print "Das Wort lautet " + eingabe 
    print "Der verschluesselte Text lautet " + ausgabe     

eingabe = raw_input("Bitte ein Wort der Laenge 3 eingeben:")
drilling(eingabe)

Den zweiten Schritt habe ich noch nicht so richtig durchdacht, wünschenswert wäre ein Programm, das weniger Konzepte enthält, aber mehr kann als das erste Programm, also z.B. alle durch 3 teilbaren Zeichenketten-Längen aber weniger Fallunterscheidungen und keine Modulo-Rechnung enthält.

Als weiteren Ansatz diskutierten wir, erst ein anspruchsvolles Programm zu einem Problem vorzulegen und dies analysieren lassen, um dann eine Modifikation oder Variante implementieren zu lassen. Dies könnte allerdings auch abschreckend wirken und zur Entwicklung eines Vokabulars erscheint ein systematischer Ausbau von Konzepten günstiger.

Ich habe noch nicht so viele Erfahrungen mit Python, daher habe ich mich erst einmal auch mit einfachen Aufgaben beschäftigt, z.B. wie eine Liste erstellt wird und was man damit alles machen kann. Dabei habe ich mich an einem Skript von Bernd Grave orientiert: www.uni-math.gwdg.de/bgr/unterricht/informatik/EinfPython.pdf Problemorientiert sind diese Aufgaben allerdings nicht, da es völlig unsinnig erscheint, eine Einkaufsliste mit einem solchen Aufwand zu verwalten. Zum Konzepte von Python kennenlernen ist es allerdings recht schön.

Mein erstes Experiment mit Ausgaben und Fallunterscheidungen (Ich nutze Ubuntu, da ist Python bereits vorinstalliert und als Editor einfach gedit und rufe die Programme dann über die Konsole auf):

Hier meine Listen-Experimente:

# Programm "Listen", angelehnt an Bernd Grave, 
# "Programmieren mit Python - erste Schritte"

# Erzeuge eine Liste und gebe ein Listenelement aus

planeten = ['Sonne','Mond','Sterne']

nummern = range(10)
print 'Listenelemente ausgeben'
print planeten [1]
print nummern [3]

# S.11 "Benutzung von Listen"

einkaufsliste = ['Aepfel','Mangos','Karotten','Bananen']

# Laenge einer Liste ausgeben
print '\n Ich habe', len(einkaufsliste), 'Dinge einzukaufen.'

# Elemente einer Liste ausgeben (interessant ist hier, dass eine 
# Variable "ding" für die Listenelemente erst in der for-Schleife 
# erzeugt wird, ohne näher deklariert zu werden)
print 'Diese Dinge sind:',
for ding in einkaufsliste:
print ding,

# Ein Elemente der Liste hinzufuegen
print '\n ich muss auch Reis einkaufen'
einkaufsliste.append('Reis')
print 'Meine Einkaufsliste ist jetzt', str(einkaufsliste)

# Eine Liste sortieren
print 'Jetzt werde ich meine Einkaufsliste sortieren.'
einkaufsliste.sort()
print 'Die sortierte Einkaufsliste ist', einkaufsliste

Die Ausgabe dieses kleinen Programms auf der Konsole sieht dann folgendermaßen aus: