<!DOCTYPE article PUBLIC "-//NLM//DTD JATS (Z39.96) Journal Archiving and Interchange DTD v1.0 20120330//EN" "JATS-archivearticle1.dtd">
<article xmlns:xlink="http://www.w3.org/1999/xlink">
  <front>
    <journal-meta />
    <article-meta>
      <title-group>
        <article-title>Zur Einsch a¨tzung von Programmierfa¨ higkeiten - Jedem Programmieranfa¨ nger u¨ber die Schultern schauen</article-title>
      </title-group>
      <contrib-group>
        <contrib contrib-type="author">
          <string-name>Bastian Schulten</string-name>
          <email>b.schulten@ostfalia.de</email>
        </contrib>
        <contrib contrib-type="author">
          <string-name>Frank Ho¨ppner</string-name>
        </contrib>
      </contrib-group>
      <abstract>
        <p>Am besten kann man den Kenntnisstand und die Fa¨higkeiten eines Studierenden in einer Programmierveranstaltung einscha¨tzen, wenn man ihm wa¨hrend des Programmierens u¨ber die Schulter schaut. Man erkennt, ob systematisch vorgegangen wird, welche Sprachkonstrukte sicher sitzen oder nicht, wieviel Trial &amp; Error im Spiel ist, etc. Da die Anzahl der Teilnehmer die der Betreuer aber um ein Vielfaches u¨bersteigt, ist eine solche direkte Beobachtung schwer mo¨glich. Wir beschreiben vorbereitende Arbeiten und erste Teilergebnisse fu¨r die Erprobung eines Werkzeugs, das eine nachtra¨gliche Analyse der Entstehung einer Lo¨sung erlaubt, um u¨ber (manuelle oder semiautomatische) Auswertungen Ru¨ckschlu¨sse auf Wissenslu¨cken und damit hilfreiche Aufgaben oder sinnvolle Stoff-Wiederholungen zu erlangen. Die Bewertung von Programmierfa¨higkeiten ist mu¨hsam und aufwendig, weil eine Vielzahl von Aspekten zu beru¨cksichtigen ist. Als harte Fakten muss das Endprodukt natu¨rlich die geforderte Funktionalita¨t erfu¨llen, was durch Unit-Tests sehr gut bewerkstelligt werden kann. Die Funktionalita¨t mag als alleiniges Kriterium einer finalen Abgabe oder eines Abschlussprojektes geeignet sein, aber im Laufe des Semesters - in der Zeit, in der ein Studierender noch lernt, noch Fehler machen darf - ist es mo¨glicherweise nicht das einzige und informativste Kriterium. Gerade bei großen Studierendengruppen wird oftmals eine Bearbeitung von Aufgaben in Zweiergruppen angeboten. Um die Relevanz der Bearbeitung von Aufgaben zu betonen, werden Programmieraufgaben oft als Teilleistungen ausgeschrieben. Das kann wiederum schwa¨chere Studierende dazu verleiten, sich sta¨rkeren anzuschließen, um sich die Teilleistungen auf jeden Fall zu sichern. Im schlimmsten Fall fu¨hrt das dazu, dass die schwa¨cheren Studierenden die Erstellung der Aufgaben weitestmo¨glich anderen u¨berlassen, um kein Risiko einzugehen. Dabei berauben sie sich selbst der wichtigen Praxis. Kriterien fu¨r die Abnahme einer Aufgabe sind oft Funktionalita¨t und Form, wie es bspw. durch JUnit und Checkstyle automatisiert gepru¨ft werden kann. So hilfreich diese Werkzeuge sind, sie tragen bewusst auch zu einer Begradigung oder Normierung der Lo¨sungen bei, so dass sich die Abgaben mehr a¨hneln, als es der Kenntnisstand der Studierenden vermuten ließe: Ob die Lo¨sung in einem Zug runterprogrammiert oder das Ende einer langen Trial &amp; Error Odyssee darstellt, kann man dem Quelltext am Ende meist nicht mehr ansehen. Wenn ein Kommilitone zum Schluss geholfen hat, helfen danach weder Checkstyle</p>
      </abstract>
    </article-meta>
  </front>
  <body>
    <sec id="sec-1">
      <title>Einleitung</title>
      <p>noch JUnit dabei, den Studierenden das no¨tige Feedback u¨ber den eigenen Leistungsstand
zuru¨ckzuspiegeln.</p>
      <p>Unsere Hypothese ist, dass man den Kenntnisstand eines Studierenden am besten
beurteilen kann, indem man ihm zuschaut: Wie geht er die Lo¨sung an? Hat er einen Plan oder
hangelt er sich von Fehlermeldung zu Fehlermeldung? Folgt er blind den Vorschla¨gen
der Entwicklungsumgebung? Wa¨hlt er eine sinnvolle Reihenfolge der Lo¨sung von
Teilproblemen? Diese Beobachtung verbietet sich im Regelfall aus Aufwandsgru¨nden
(abgesehen von Pru¨fungssituationen). Diese Arbeit ist ein erster, vorla¨ufiger Schritt hin zu
einem toolgestu¨tzten u¨ber die Schulter schauen. Die Grundidee ist die Aufzeichnung der
Entstehungsgeschichte eines Programms, so dass eine nachgelagerte Beurteilung der
Herangehensweise mo¨glich ist.
2
2.1</p>
    </sec>
    <sec id="sec-2">
      <title>Verwandte Arbeiten</title>
      <sec id="sec-2-1">
        <title>Evolution eines (Quell-) Textes</title>
        <p>Angeregt zu diesem Ansatz haben Arbeiten u¨ber die Beurteilung der Fa¨higkeiten von
angehenden Schriftstellern: Gab es einen Entwurf? Wieviele U¨ berarbeitungen gab es? Wurde
der Text in einem Stu¨ck geschrieben oder musste sta¨ndig vor und zuru¨ckgesprungen
werden? (Vgl. [Ma87, PR96]) Als Unterstu¨tzung fu¨r eine solche Beurteilung wurden in diesen
Disziplinen diverse Editoren geschaffen, die jeden Tastendruck bei der Entstehung eines
Aufsatzes dokumentieren (zum Beispiel3 ScriptLog), um diese Fragen im Nachhinein zur
Beurteilung heranziehen zu ko¨nnen. In den letzten Jahren gab es aber auch im
SoftwareEngineering versta¨rkt Bestrebungen, die Zwischensta¨nde aus Versionsverwaltungen (wie
SVN, CVS) automatisch zu analysieren, um den wahren Umfang von A¨ nderungen in
Code-Repositories abzuscha¨tzen [CCP07], Bug-Tracking Eintra¨ge und Change-Log
Eintra¨ge miteinander zu verknu¨pfen [BB09] oder die Entwicklung einer Codebasis u¨ber der
Zeit zu visualisieren [Ha13]. Eine noch feiner granulierte Analyse der Entstehung eines
Programms erscheint fu¨r industrielle Anwendungen weniger sinnvoll, ko¨nnte im Bereich
der Programmierausbildung – analog zu der Beurteilung von Autoren – aber ein bisher
unausgescho¨pftes Potential bergen.
2.2</p>
      </sec>
      <sec id="sec-2-2">
        <title>Programmversta¨ndnis</title>
        <p>Ebenfalls relevant ist die Disziplin des Program Understanding [WY96], bei der es u.a.
darum geht, die Anweisungen eines Programms den verschiedenen Teilzielen des Autors
zuzuordnen4, um so ihre Bedeutung fu¨r die Gesamtlo¨sung zu verstehen. Die Vorstellung
ist, dass der Entwickler einen Plan zur Umsetzung verfolgt, der aus verschiedenen
Teilpla¨nen besteht. Die Rekonstruktion des urspru¨nglichen Plans anhand des Quelltexts kann
3 Siehe bspw. http://www.writingpro.eu/logging_programs.php
4 z.B. besteht das Teilziel, einen Za¨hler zu implementieren, aus den Schritten Deklaration, Initialisierung und</p>
        <p>Inkrementierung, die jeweils an der richtigen Stelle (vor/innerhalb einer Schleife) stehen mu¨ssen.
auf Grundlage einer manuell gepflegten Hierarchie von Pla¨nen/Aktionen inkl.
zahlreicher Nebenbedingungen gelingen [QYW98]. Diese Aktionen repra¨sentieren das Wissen
von Programmierern (Erfahrung, gute Programmierpraxis), das aber bei
ProgrammierAnfa¨ngern meist erst noch entwickelt werden muss. Insofern ist der Erfolg dieser
Techniken bei Programmierlaboren fraglich. Andere Arbeiten verzichten auf ein tieferes
Versta¨ndnis und prognostizieren auf Basis von einfachen Kennzahlen der statischen
Analyse (Anzahl Blo¨cke, Schleifen, ...) z.B. die Art des implementierten Sortier-Algorithmus
[TMK08].
2.3</p>
      </sec>
      <sec id="sec-2-3">
        <title>Versta¨ndnisprobleme von Programmieranfa¨ngern</title>
        <p>In der Literatur sind viele Fehlkonzepte von Programmieranfa¨ngern dokumentiert [BA01,
KP10]. Wir listen einige typische Probleme von Programmieranfa¨ngern auf, die vor allem
aber auch aus der eigenen Erfahrung im Bereich der Java-Programmierausbildung bekannt
sind:
1.
2.
3.
4.
5.</p>
        <p>Richtung der Zuweisung: Wird die Anweisung a=b; als Zuweisung von links nach
rechts, rechts nach links, oder als Vergleich aufgefasst?
Ausfu¨hrungsreihenfolge von Anweisungen der for-Schleife: Falsche Vorstellungen
u¨ber den Zeitpunkt, zu dem die Bestandteile der Anweisung ausgefu¨hrt werden,
provozieren ein Trial &amp; Error Vorgehen.</p>
        <p>Statische Elemente: Wurde zuerst dem prozeduralen Paradigma gefolgt (Java:
statische Methoden und Attribute), fa¨llt es den Studierenden beim Wechsel zum
objektorientierten Paradigma oft schwer, diesen statischen Elementen zu entsagen.
Eine ungebrochene Verwendung des Schlu¨sselwortes static ist ein Indiz, dass das
no¨tige Versta¨ndnis noch nicht erworben wurde.</p>
        <p>Copy &amp; Paste Bann: Meistens wissen die Studierenden, dass sie Copy &amp; Paste nicht
verwenden sollen, machen es aber dennoch.</p>
        <p>Test-Handling: Wird das Potential ggf. bereitgestellter Tests genutzt? Stellen die
Studierenden sicher, dass sie bei der fortwa¨hrenden Erweiterung ihrer Lo¨sung keine
gru¨nen Testfa¨lle mehr verlieren?
Weitsicht: Eine Aufgabe mittlerer Gro¨ße, fu¨r die JUnit-Tests vorliegen, ist
typischerweise in Form von Interfaces vorspezifiziert. Die Studierenden kennen also
ein Spektrum an Klassen und Methoden, die sie implementieren mu¨ssen. Wie gehen
Studierende diese Aufgabe an? Erkennen sie, was aufeinander aufbaut, und fangen
am Ende der Abha¨ngigkeitskette an? u.v.a.m.
3</p>
      </sec>
    </sec>
    <sec id="sec-3">
      <title>Eine Beispielsituation</title>
      <p>Zur Illustration einer typischen Labor-Situation betrachten wir die stark vereinfachte
MiniAufgabe aus Abb. 1, die einem Studenten zu einem Zeitpunkt gestellt wird, zu dem
Objekte eingefu¨hrt wurden. Davor wurde Java nur prozedural behandelt (statische Attribute,
statische Methoden). Daher bereitet es einigen Studierenden erfahrungsgema¨ß
Schwierigkeiten, sich vom Schlu¨sselwort static loszusagen, wenn sie die Konzepte dahinter noch
nicht verstanden haben. Ist das Konzept angekommen, ist die Aufgabe trivial und ein
entsprechender Test (analog zum Inhalt von main()) besta¨tigt das richtige Ergebnis 5.
Aufgabe: Ein X soll eine ganze Zahl
speichern, die u¨ber get() abgefragt und
u¨ber set(int) neu gesetzt werden kann.</p>
      <p>In der main()-Methode legen Sie zwei
X-Objekte an, setzen ihren Wert auf 2
bzw. 3, addieren den einen zum
anderen Wert und geben die Summe auf dem
Bildschirm aus.</p>
      <p>1 public class X f
2 public static void main(String [] args ) f
3 X x1 = new X();
4 X x2 = new X();
5 x1. set (2);
6 x2. set (3);
7 x1.add(x2);
8 System.out . println (x1. get ());
9 g
10 g</p>
      <p>Abb. 1: Ein sehr einfaches Beispielproblem.
1 public class X f
2 static int i ;
3 static int get () f return i ; g
4 static void set ( int ai ) f i=ai ; g
5 static void add(X x) f i+=x.i ; g
6
7
8
9
10
11
12
13
14 g
15 g</p>
      <p>Beginnt der Student aber wie gewohnt mit statischen Attributen, zeigt Abb. 2 einen
mo¨glichen Zwischenstand, der aber natu¨rlich das falsche Ergebnis (na¨mlich 6) liefert.
Durch die Ausgabe oder den Unit-Test weiß der Student, dass etwas nicht stimmt, aber
was unternimmt er? Ein (leider) typisches Verhalten von Studierenden ist es, sich hier
(unreflektiert) Ratschla¨ge von der Entwicklungsumgebung zu holen. Eclipse macht mehrere
Vorschla¨ge. Einer ist change access to static fu¨r die Zeilen 10-13 aus Abb. 1. Folgt der
Student konsistent diesem Vorschlag (er ko¨nnte potentiell auch inkonsistent
verschiedenen Vorschla¨gen folgen), fu¨hrt ihn der Weg zu Abb. 3. Eine letzte verbleibende Warnung
gibt es dort fu¨r Zeile 8: the value of local variable x1 is not used. Diese Meldung sollte ihm
zu denken geben (Wie kann ich zwei Zahlen addieren, wenn eine davon gar nicht benutzt
wird?), resultiert aber mo¨glicherweise nur in einem Ru¨ckbau aller bisher vorgenommenen
A¨ nderungen. Der zweite Ratschlag, den Eclipse beim Stand von Abb. 2 macht, ist remove
static modifier of set(). Folgt er wieder konsistent demselben Vorschlag bei allen
Warnungen, fu¨hrt ihn dies zu der richtigen Lo¨sung, ohne sich seinem eigenen Versta¨ndnisproblem
je gestellt zu haben.</p>
      <p>Die erhaltene Version liefert das gewu¨nschte Ergebnis, ein etwaiger Unit-Test ebenso. Vom
Endergebnis her ist es nicht von der Lo¨sung eines Studenten, der die Problematik
durchdrungen hat, zu unterscheiden. Die wichtige Information u¨ber die Programmierfa¨higkeit
tra¨gt der Weg zum Ziel, der u¨blicherweise nicht bekannt ist.
4
4.1</p>
    </sec>
    <sec id="sec-4">
      <title>L o¨sungsvorschlag</title>
      <sec id="sec-4-1">
        <title>Ansatz</title>
        <p>Als Lo¨sungsansatz fu¨r das skizzierte Problem wird hier eine Beobachtung der
Studierenden wa¨hrend der Programmentwicklung vorgeschlagen. Die Erprobung im Rahmen einer
gro¨ßeren Studierendengruppe steht noch bevor, bisher wurden nur im kleineren Rahmen
Entstehungsprotokolle erhoben. Die (geplanten) Elemente sind im Einzelnen:</p>
        <p>Automatische Protokollierung der Entstehungsgeschichte der Lo¨sung durch ein
PlugIn in der Entwicklungsumgebung. Dies ermo¨glicht eine Playback-Funktion, so dass die
Entstehungsgeschichte im Nachhinein (zusammen mit dem Student oder nur durch den
Betreuer) betrachtet werden kann. Das Replay muss nicht in Echtzeit erfolgen und ist
damit zeitsparend, aber das eigentliche Ziel ist eine (semi-) automatische Analyse der
Aufzeichnungen.</p>
        <p>Eine klare Kommunikation an die Studierenden, dass die aufgezeichneten Informationen
in keiner Weise fu¨r die Bewertung herangezogen werden, dafu¨r gibt es Klausuren und/oder
gesonderte Aufgaben/Projekte. Das Ziel ist es, Versta¨ndnisprobleme oder Schwa¨chen
direkt und zielgerichtet im Labor oder der begleitenden Veranstaltung ansprechen zu ko¨nnen,
bevor es zu einer Klausur oder einem finalen Abschlussprojekt kommt. Dieses Ziel sollte
im Sinne der Studierenden sein, so dass sie sich freiwillig fu¨r eine Teilnahme entscheiden.
Die Protokollierung wird nicht zur Pflicht erhoben (ist abschaltbar).</p>
        <p>Im Idealfall liefern Indikatoren, die aus den Protokollen abgeleitet wurden, dem Betreuer
ein Indiz u¨ber problematische Abschnitte der Lo¨sung, so dass eine gemeinsame Reflektion
gezielt angestoßen werden kann (und nicht erst nach Versta¨ndnisproblemen gesucht
werden muss). Ha¨ufig auftretende Probleme ko¨nnen dem Dozenten helfen, in der begleitenden
Vorlesung problematischen Stoff zu wiederholen und Hinweise auf weitere Aufgaben (in
der gleichen Richtung) zu liefern.
4.2</p>
      </sec>
      <sec id="sec-4-2">
        <title>Verarbeitung</title>
        <p>Die einfachste Form der Verarbeitung der Protokolle ist der Einsatz einer
PlaybackFunktion. Sie ermo¨glicht die schrittweise Rekonstruktion, ist aber weiterhin zeitintensiv.
Fu¨r die automatische Auswertung wird nach jeder A¨nderung (mit Hilfe der Java Compiler
API) der aktuelle Quelltext und/oder der Syntaxbaum erzeugt, um Unterschiede in
Quelltextzeilen und/oder Knoten des Syntaxbaums zu identifizieren. Der Vorteil der lu¨ckenlosen
Protokollierung ist, dass sich die Quelltexte bzw. Syntaxba¨ume von Schritt zu Schritt nur
minimal unterscheiden und somit eine Beurteilung der (Art der) A¨ nderung erleichtert wird
(vgl. ChangeDistiller [Fl07]). Quelltextzeilen und/oder Syntaxbaum-Knoten
verschiedener Evolutionsschritte werden einander zugeordnet und mit A¨ nderungsza¨hlern
ausgestattet. Dabei liefert die Analyse auf Basis des Syntaxbaums klare Vorteile: (1) Die A¨ nderung
kann pra¨ziser lokalisiert werden (z.B. Abbruchbedingung einer for-Schleife), (2)
Formatierungen oder Kommentare beeinflussen zwar die Position im Quelltext, aber nicht die
Lage des Baumknotens.</p>
        <p>Außerdem ko¨nnen die einzelnen A¨ nderungsereignisse zu abstrakteren Aktionen gebu¨ndelt
werden, etwa Bearbeitung der Methode f(), die in der Zeit verortet werden (Beginn / Ende
der Bearbeitung). Entsprechende Zeitra¨ume lassen sich fu¨r die Erfu¨llung einzelner Tests
oder die Compilierfa¨higkeit von Klassen generieren.
4.3</p>
      </sec>
      <sec id="sec-4-3">
        <title>Pra¨sentation und Nutzung</title>
        <p>Sind die Protokolle verarbeitet, ko¨nnen sie auf verschiedene Weise aufbereitet werden, um
Einblicke in den Kenntnisstand Einzelner oder der Gruppe zu geben:
1:public class X f
1: private int value ;
1: public int get () f
1: return value ;
1: g
2: public void set ( int value ) f
1: this . value = value ;
1: g
1: public void add(X x) f
1: this . value += x. get ();
1: g
1: public static void main(String [] args ) f
1: X x1 = new X();
1: X x2 = new X();
1: x1. set (2);
1: x2. set (3);
1: x1.add(x2);
1: System.out . println (x1. get ());
1: g
1:g
1:public class X f
3: int i ;
4: void set ( int ai ) f
1: i = ai ;
1: g
3: int get () f
1: return i ;
1: g
3: void add(X x) f
3: i += x. i ;
1: g
1: public static void main(String [] args ) f
1: X x1 = new X();
1: X x2 = new X();
3: x1. set (2);
3: x2. set (3);
3: x1.add(x2);
3: System.out . println (x1. get ());
1: g
1:g
Abb. 4: Lo¨sung eines Studenten mit den no¨tigen
Kenntnissen.</p>
        <p>Abb. 5: Lo¨sung bei static-Schwierigkeiten.
(gelb: mind. 2x, orange: mind. 3x modifiziert)</p>
        <p>Indikatoren – In ersten Tests hat sich der Eindruck ergeben, dass die Anzahl der
compilierbaren Zwischenschritte ein Indikator fu¨r den Reifegrad der Programmierfa¨higkeit sein
ko¨nnte. Wer noch unsicher ist, wird sich von compilierbarem Zwischenstand zu
compilierbarem Zwischenstand bewegen – sei es, weil sich nur kleine Schritte zugetraut werden,
oder weil den Fehlermarkierungen am Editor sehr viel Aufmerksamkeit gezollt wird. Je
gro¨ßer die eigene Sicherheit und je weiter die Gedanken schon vorauseilen, desto eher
werden spontan weitere Aspekte beru¨cksichtigt, noch bevor die letzte Anweisungen
syntaktisch korrekt aufgeschrieben wurde. Viele weitere Indikatoren sind denkbar, wie etwa
die Lokalita¨t von A¨ nderungen (Fokus bei der Bearbeitung).</p>
        <p>HeatMap – Versta¨ndnisprobleme (wie die Probleme 1-3 des Abschnitts 2.3) fu¨hren
dazu, dass die Studierenden fu¨r eine funktionierende Lo¨sung (Unit-Tests erfu¨llt) bestimmte
Stellen wieder und wieder anfassen, bis es richtig la¨uft. Die A¨ nderungsha¨ufigkeit kann im
Code farbcodiert dargestellt werden, so dass Regionen hoher A¨ nderungen sofort als Hot
Spot erkannt werden ko¨nnen. Damit sind die Stellen, die schwer gefallen sind, leicht zu
erkennen. Fu¨r die vom finalen Quelltext her nicht unterscheidbaren Beispiello¨sungen aus
Kap. 3 ergibt sich (bei der aktuell zeilenbasierten A¨ nderungsza¨hlung) ein klarer
Unterschied in Abb. 4-5. (Erfolgt die A¨ nderungsza¨hlung und Farbcodierung nicht zeilenweise
sondern pro Syntaxbaum-Element wird noch deutlicher markiert, dass es eine große
Unsicherheit bei den Modifikatoren gab.)</p>
        <p>Bearbeitungsmuster – Die A¨ nderungshistorie kann verku¨rzt durch die Darstellung der
Zeitintervalle, in denen bestimmte Methoden bearbeitet oder Tests erfu¨llt wurden,
visualisiert werden (vgl. Abb. 6). Diese kompakte Darstellung erlaubt die Beurteilung von
Problemen 5 und 6 aus Abs. 2.3. Mit Methoden der Sequenzanalyse (z.B. [PHB12])
ko¨nnen die Entstehungshistorien aller Studierenden nach Gruppen unterschiedlicher
Vorgehensweisen untersucht werden. Sind historische Protokolle verfu¨gbar, wa¨re auch eine
Art Ratgeber-Funktion denkbar, die Anfa¨ngern Tipps gibt, um welche Dinge sie sich als
Na¨chstes ku¨mmern ko¨nnten.</p>
        <p>Konstruktor(en)</p>
        <p>Methode f()
Methode g()</p>
        <p>Test 3
Test 2
Test 1
Zeit
Abb. 6: Zeitleiste mit Zeitintervallen der Bearbeitung (hell) und Testerfu¨llung (dunkel). Vertikale
Linien zeigen compilierbare Zusta¨nde an.
5</p>
      </sec>
    </sec>
    <sec id="sec-5">
      <title>Fazit und Ausblick</title>
      <p>Die Entstehungsgeschichte der Lo¨sung zu einer Programmieraufgabe ist fu¨r den
Dozenten eine wertvolle Hilfe zur Beurteilung des Kenntnisstands des Autors. Die Erfassung
der Historie in Form eines (persistenten) Protokolls erlaubt verschiedene Auswertungen
(wie HeatMap, Bearbeitungssequenzen, ...), die rasch wertvolle Hinweise auf Defizite
des Autors liefern ko¨ nnen, aber auch eine Beurteilung des Fortschritts der Gruppe
insgesamt ermo¨ glichen. Bisher handelt es sich um vorla¨ufige Untersuchungen im kleinen
Rahmen; ob und wie weit sich der Ansatz zu einem nu¨ tzlichen Werkzeug im Alltag der
Programmierausbildung ausbauen la¨sst, soll im bevorstehenden Semester erprobt werden.
Mo¨ glicherweise sind dazu andere als die bisher u¨ blichen Aufgabentypen angezeigt, bspw.
vorgegebene, fehlerhafte Quelltexte, die korrigiert werden sollen. Eine solche Korrektur ist
i.a. einfacher als die Konstruktion einer komplett eigensta¨ndigen Lo¨ sung und hatte
vielleicht deswegen bisher wenig Wert, aber die Mo¨ glichkeit zur Beobachtung bei der
Fehlersuche kann aufzeigen, wo im Quelltext ein Student eine mo¨ gliche Ursache gesehen hat
und damit wertvolle Einblicke in das Versta¨ndnis liefern.</p>
      <p>Literaturverzeichnis
[BA01]
[BB09]
[CCP07]
[Fl07]
[Ha13]
[KP10]
[Ma87]</p>
      <p>Ben-Ari, M: Constructivism in computer science education. Journal of Computers in
Mathematics and Science, 20:45–73, 2001.</p>
      <p>Bachmann, Adrian; Bernstein, Abraham: Data retrieval, processing and linking for
software process data analysis. University of Zurich, Technical Report, (December), 2009.
Canfora, Gerardo; Cerulo, Luigi; Penta, Massimiliano Di: Identifying Changed Source
Code Lines from Version Repositories. International Workshop on Mining Software
Repositories, S. 14, Mai 2007.</p>
      <p>Fluri, Beat; Wu¨ rsch, Michael; Pinzger, Martin; Gall, Harald C.: Change Distilling : Tree
Differencing for Fine- Grained Source Code Change Extraction. IEEE Trans. on
Software Engineering, 33(11):725–743, 2007.</p>
      <p>Hanjalic, A: ClonEvol: Visualizing software evolution with code clones. Software
Visualization (VISSOFT), S. 1–4, 2013.</p>
      <p>Kaczmarczyk, LC; Petrick, ER: Identifying student misconceptions of programming.
Proceedings Computer Science Education, S. 107–111, 2010.</p>
      <p>Matsuhashi, Ann: Revising the plan and altering the text. In: Writing in real time:
Modelling production processes. S. 197–223, 1987.
[PR96]</p>
      <p>Piolat, Annie; Roussey, Jean-Yves: Students’ drafting strategies and text quality.
Learning and Instruction, 6(2):111–129, Juni 1996.</p>
    </sec>
  </body>
  <back>
    <ref-list>
      <ref id="ref1">
        <mixed-citation>
          <string-name>
            <surname>Woods</surname>
            , Steven; Yang,
            <given-names>Q:</given-names>
          </string-name>
          <article-title>The program understanding problem: analysis and a heuristic approach</article-title>
          .
          <source>In: 18th Int. Conf. Software Engineering</source>
          .
          <year>1996</year>
          .
        </mixed-citation>
      </ref>
    </ref-list>
  </back>
</article>