Objektorientierte Programmierung
LVA 185.162, VL 2.0, 2009 W

Hinweise zur Beurteilung der 5. Übungsaufgabe

Einleitung:

Auch die vorläufige Beurteilung der 5. Aufgabe (reguläre Abgabe) ist für viele Gruppen eher schlecht ausgefallen. Diese Seite soll die häufigsten und wichtigsten Fehler, die dabei gemacht wurden, aufzeigen, Hinweise zur empfohlenen Lösung geben, wahrscheinliche Gründe für das Zustandekommen der Fehler erklären und das Beurteilungsschema kurz erläutern.

Die Aufgabe ist so aufgebaut, dass Generizität sehr überlegt eingesetzt werden muss, um alle vorgegebenen Testfälle ohne Warnungen durch den Compiler lösen zu können. Ein Hintergedanke dabei war, dass Sie mehrere Lösungsvarianten durchprobieren und dabei auf verschiedene Anwendungsmöglichkeiten der Generizität und deren Grenzen stoßen sollten. Nur recht wenigen Gruppen ist es gelungen, die Aufgabe tatsächlich in allen Details richtig zu lösen.

Häufigste Fehler:

Empfohlene Lösung:

In allen guten Lösungsvarianten hat Reducible einen Typparameter (für den Typ des Arguments von reduce) mit oder ohne Schranke, und Component sieht ungefähr so aus:
public abstract class Component extends Reducible<Component>
{ ... }
Auf anderen Ansätzen kann man kaum sinnvoll aufbauen.

Es ist gar nicht schwer, die empfohlene Lösung hinsichtlich der Typparameter auf AccTree zu verstehen:

public class AccTree<A extends Reducible<A>, B extends A> ...
implements Reducible<AccTree<A,B>>
{
    ...
    public A reduced()
    {
        Iter<B> i = ...;
        A r = i.next();
        while (i.hasNext()) ...;
        return r;
    }
    ...
}
Der Typparameter A kann demnach für Component als Untertyp von Reducible<Component> stehen, und B für einen Untertyp davon wie z.B. Component, Device und Job. Für den 2. Testfall eignen sich daher Instanzen von AccTree<Component,Device> und AccTree<Component,Job>, für den 3. Testfall Instanzen von AccTree<Component,Component>. Wir können als Ersetzung von A und B aber auch AccTree<X,Y> als Untertyp von Reducible<AccTree<X,Y>> verwenden. Diese relativ einfache Lösung kommt ohne Wildcard-Typen aus.

Wenn wir statt zwei nur einen Typparameter verwenden wollen, dann müssen wir notgedrungen eine Entsprechung zu B verwenden. Beispielsweise könnten wir AccTree so definieren:

public class AccTree<T extends Reducible<? super T>> ...
T entspricht tatsächlich B, da ? (der Typparameter von Reducible) implizit A entspricht und T ein Untertyp von ? ist. Der einzige Unterschied zur obigen Lösung besteht darin, dass A implizit ist und daher in der Implementierung von reduced nicht anstelle eines Typs verwendet werden kann. Wir haben dadurch aber keine Möglichkeit, den Ergebnis-Typ von reduced richtig auszudrücken. Zusätzlich liefert reduce in Component nicht genug Information, um T als Ergebnis-Typ verwenden zu können. Wenn wir diesen Ansatz weiterverfolgen, stoßen wir auf die Probleme, die unter Häufigste Fehler angerissen sind. Eine (wenn auch nicht verallgemeinerbare) Lösung besteht darin, dass reduce die Kosten einfach nur aufaddiert und die Summe in this speichert; dann braucht reduced nicht das Ergebnis der Aufrufe von reduce zurückgeben, sondern nur das Ergebnis eines Aufrufs von get mit dem gewünschten Ergebnis-Typ T.

Die meisten Gruppen haben richtig erkannt, dass man mit einem einfachen Typparameter nicht auskommt und daher einen Wildcard-Typ verwenden muss. Leider haben nur mehr wenige Gruppen den letzten Schritt von Wildcard-Typen zur oben gezeigten Lösung mit zwei Typparametern geschafft, obwohl der Unterschied zwischen diesen Lösungsvarianten klein ist und kaum etwas am gesamten Programm verändert. Offensichtlich wurden auch die Hinweise per Mail nicht richtig verstanden.

Fehlerursachen:

Die tatsächlichen Ursachen für die häufigsten Fehler können nur vermutet werden. Folgendes dürfte eine Rolle gespielt haben:
Vertrauen auf Andeutungen und Ähnlichkeiten:
Als StudentIn entwickelt man sehr bald ein Gefühl dafür, aus welchen groben Andeutungen und Ähnlichkeiten zwischen Aufgabenstellungen man die gewünschte Struktur der Lösung ablesen kann. Der Hinweis auf die Verwendung von Typ-Wildcards war sicher wichtig, um einen großen Teil der Gruppen auf die richtige Fährte zu bringen. Verstärkend kommt hinzu, dass es auch in den letzten Jahren ähnliche Aufgaben gegeben hat, in denen eine sehr ähnliche Verwendung von Typ-Wildcards zur Lösung der Aufgabe notwendig war. In diesem Jahr haben auch mehr Gruppen eine annähernd richtige Lösung geschafft als in früheren Jahren. Kleine Unterschiede in der Aufgabe können aber große Unterschiede in der Lösung verursachen. Leider war es in diesem Jahr so, dass die optimale Lösung doch ohne Typ-Wildcards auskommt und sich sicher einige Guppen wegen der Hinweise nicht getraut haben, die optimale Lösung abzuliefern. Der später per Mail gekommene Hinweis auf eine sehr gute Lösung war vielleicht etwas zu spät.
Vertrauen auf (scheinbar) Bekanntes:
Mit Generizität waren viele StudentInnen noch nicht vertraut, andere Konstrukte wie Typumwandlungen waren aber vorher schon bekannt. Natürlich wurde versucht, aufgetretene Probleme mit bekannten Mitteln (beispielsweise Typumwandlungen) zu lösen. Diese Mittel haben sich jedoch als äusserst widerspenstig erwiesen, vor allem weil Typumwandlungen im Zusammenhang mit Generizität neue, bisher nicht gekannte negative Eigenschaften entwickelten. Trotzdem hat man sich eher darauf verlassen als auf die unbekannte Generizität, und man hat gar nicht versucht, Probleme über Generizität zu lösen. Tatsächlich ist der Umgang mit Generizität aber viel einfacher als mit sehr unsicheren Typumwandlungen. Diese Einsicht hat sich aber noch nicht verfestigt.
Vertrauen auf die magische Lösung:
Typ-Wildcards dürften bei einigen StudentInnen den Eindruck erweckt haben, eine magische Lösung für alle Zwecke darzustellen, in denen normale Typen bzw. Typparameter nicht mehr ausreichen. In dieser Vorstellung kann es keine Lösung geben, die noch magischer als die magische Lösung ist und auch funktioniert, wo die magische Lösung versagt. Es wurde daher gleich gar nicht nach einer einfachen Lösung gesucht.
Ursachen nicht gesucht oder gefunden:
In dieser Aufgabe kann man eine gute Lösung nur finden, indem man schrittweise vorgeht: Sobald man nach der Lösung eines Teilproblems auf Schwierigkeiten stößt, muss man die Ursachen dafür finden und beseitigen bevor man das nächste Teilproblem angeht. Vermutlich wollten viele sich nicht die Zeit für eine eingehende Analyse der Ursachen eines Problems nehmen und haben beim Auftreten von Schwierigkeiten einfach eine andere Variante gesucht, ohne die Ursachen zu kennen. Mit dieser Vorgehensweise ist man aber wahrscheinlich bald im Kreis gelaufen und immer wieder auf annähernd dieselben Schwierigkeiten gestoßen, ohne sich einer echten Lösung zu nähern. Wahrscheinlich hätte es in diesem Fall viel Zeit gespart, der Ursache für das Problem auf den Grund zu gehen.
Konzentration auf eine Sache:
Für viele verlorene Punkte waren gar nicht Probleme im Zusammenhang mit Generizität verantwortlich, sondern beispielsweise ein schlampiger Umgang mit Zusicherungen oder Sichtbarkeit. Der Hauptgrund dürfte darin liegen, dass man sich ganz auf eine Sache, nämlich Generizität konzentriert und dabei andere für die Beurteilung relevante Aspekte übersehen hat.
Generizität gar nicht verstanden:
Von einigen Gruppen ist Generizität offensichtlich noch gar nicht (nicht einmal im Ansatz) verstanden worden. Unter diesen Voraussetzungen ist die Aufgabe einfach nicht lösbar.

Beurteilungsschema

Für ein abgegebenes Programm, das sich übersetzen lässt, gibt es 100 Punkte. Davon werden für Fehler im Programm Punkte abgezogen:
Complang
Puntigam
   Kontakt
   Research
   Lehre
      OOP
      Typsysteme
      EP2
      FOOP
      Prog.spr.
      frühere Lehre
         LVAs 2017 W
         LVAs 2017 S
         LVAs 2016 W
         LVAs 2016 S
         LVAs 2015 W
         LVAs 2015 S
         LVAs 2014 W
         LVAs 2014 S
         LVAs 2013 W
         LVAs 2013 S
         LVAs 2012 W
         LVAs 2012 S
         LVAs 2011 W
         LVAs 2011 S
         LVAs 2010 W
         LVAs 2010 S
         LVAs 2009 W
            OOP
               1. Aufgabe
               2. Aufgabe
               3. Aufgabe
               4. Aufgabe
               5. Aufgabe
                  Beurteilung
               6. Aufgabe
               7. Aufgabe
               8. Aufgabe
               9. Aufgabe
               Cacao
            Typsysteme
         LVAs 2009 S
         LVAs 2008 W
         LVAs 2008 S
         LVAs 2007 W
         LVAs 2007 S
         LVAs 2006 W
         LVAs 2006 S
         LVAs 2005 W
         LVAs 2005 S
         LVAs 2004 W
         LVAs 2004 S
         LVAs 2003 W
   Links
Sitemap
Kontakt
Fakultät für Informatik
Technische Universität Wien
Anfang | HTML 4.01 | Datenschutzerklärung | letzte Änderung: 2009-12-02 (Puntigam)