Probleme mit Codemonkeys

Benutzeravatar
GreenLightning
Neuling
Neuling
Beiträge: 5
Registriert: 20. Apr 2017 16:32

Probleme mit Codemonkeys

Beitrag von GreenLightning » 9. Jul 2017 11:34

Abgesehen von den technischen Problemen mit Codemonkeys finde ich auch die Qualität der Aufgaben noch ... ausbaufähig. Anstelle mich nur zu beschweren, möchte ich hier außerdem konkrete Probleme mit einzelnen Aufgaben aufzeigen, sodass diese behoben werden können. Leider kann ich nicht auf alle Aufgaben gleichzeitig eingehen, da ich ansonsten morgen noch an diesem Post schreiben würde...

In diesem Post geht es um die Aufgabe Graph: findNode. Das sollte man erstmal klar stellen, denn die Beschreibung der Aufgabe hat sowohl "Graph: findNode" also auch "Graph: removeEdge" als Überschrift.

Beginnen wir mit der Aufgabenstellung:

Die Zusammenfassung "In diesem Aufgabenpaket soll eine Methode implementiert werden, welche die zusammenhängenden Teilgraphen eines Graphens bestimmt." finde ich nicht sehr treffend, es geht eher darum herauszufinden, ob man von einem Startknoten ausgehend einen anderen Knoten mit einem gesuchten Datensatz erreichen kann. Dies lässt sich zwar auf das Teilgraphproblem zurückführen, würde aber die Aufgabe komplizierter machen, als sie eigentlich ist.

Die Aufgabenstellung ist zumindest grammatikalisch korrekt (was man von einigen anderen Aufgabenstellungen nicht behaupten kann), ist aber inkonsistent bezüglich der Verwendung von Umlauten. Im ersten Satz des folgenden Zitats wird ein Umlaut benutzt ("zurück"), aber zwei Sätze später wird "koennen" mit "oe" geschrieben: "Sollte eines dieser Argumente null entsprechen, so gibt diese Funktion den Wert null zurück. Ansonsten wird ausgehend vom Startknoten der Graph traversiert. Dabei koennen die ausgehenden Kanten eines Knotens mit Hilfe der Funktion getFanOut() ermittelt werden."

Man könnte mir jetzt natürlich vorwerfen, auf den kleinsten Fehlern herumzuhacken, aber ich versuche nur vollständig zu erklären, was mich an dieser Aufgabe stört. Solche Inkonsistenzen und definitiv die kaputte Überschrift sollten auch beim Korrekturlesen sofort auffallen. Dass diese Fehler immer noch in der Aufgabe stehen, steigert nicht gerade meine Auffassung der Qualität der Plattform. Weiterhin habe ich auch schon Sätze gesehen, die rein grammatikalisch überhaupt keinen Sinn ergeben.

Ein Satz weiter findet man "Die Kanten auf die diese Knoten zeigen wiederum durch getTargetNode()." Ein kleiner Fehler (denn die Knoten zeigen nicht auf die Kanten, sondern die Kanten auf die Knoten), der aber trotzdem zur weiteren Verwirrung des Studenten beiträgt und eigentlich bei einer Qualitätskontrolle der Aufgaben sofort hätte auffallen müssen.

(In der Dokumentation der Methode Node::getFanOut() findet man außerdem "This function returns the edge objects that represent any outgoing edge of the edge, this instance represents.")

Endlich können wir zum wichtigstem Teil der Aufgabe kommen, dem Code. Nach einigem Herumprobieren kommt man vielleicht auf diesen Code, erstmal richtig aussehenden Code:

Code: Alles auswählen

{
    if (startNode == null || data == null) return null;
    ArrayDeque<Node<N, E>> open = new ArrayDeque();
    HashSet<Node<N, E>> visited = new HashSet();
    open.add(startNode);
    visited.add(startNode);
    while (!open.isEmpty()) {
        Node<N, E> node = open.pop();
        if (objectEquals(data, node.getData())) return node;
        for (Edge<N, E> edge: node.getFanOut()) {
            Node<N, E> target = edge.getTargetNode();
            if (!visited.contains(target)) {
                open.add(target);
                visited.add(target);
            }
        }
    }
    return null;
}
Allerdings besteht man damit nur 11 / 13 Tests. Woran scheitern die anderen?

Test 1: "Reference implementation found other result than your implementation."

Tatsächlich liefert der Code ein korrektes Ergebnis, das Problem ist nur, dass es bei diesem Test anscheinend mehrere korrekte Ergebnisse gibt und die Referenzimplementierung eben ein anderes korrektes Ergebnis zurück gibt.

Nachdem man für einige Zeit blöd auf die Aufgabenstellung gestarrt hat, könnte einem Auffallen, dass für die Klasse ArrayDeque nur die Methode push() und nicht add() dokumentiert ist. Der Unterschied ist, dass die eine Methode das Element am Anfang und die andere das Element am Ende der Datenstruktur einfügt. Das erklärt also den Unterschied zwischen unserer Implementierung und der Referenzimplementierung. Nachdem man open.add() nun durch open.push() ersetzt hat, bleibt nur noch ein fehlschlagender Test.

Test 2: "When the startNode argument is not part of the graph, the result is supposed to be null."

Jetzt wird es interessant, was hat diese Fehlermeldung zu bedeuten? In der Aufgabenstellung selbst findet man keinen Hinweis, nur die Dokumentation der zu implementierenden Methode scheint diese Voraussetzung zu erwähnen: "@constraint startNode the input node is well-formed if it is not null and part of the graph". In einem Testat wäre man an dieser Stelle komplett verloren und selbst der beste Programmierer der Welt könnte nur damit Anfangen Methodennamen zu raten. Aber wenn man sich nicht im Testatmodus befindet, bei dem die Aufgaben vorgegeben sind, kann man auf folgende göttliche Eingebung hoffen: "Schau dir die Aufgabe Graph: addSubgraph, Graph: removeNode, Graph: findConnectedSubgraphs oder Graph: addNode an". In diesen Aufgaben ist nämlich die Methode getNodeList() dokumentiert, mit der man die geforderte Zugehörigkeit überprüfen kann, wenn diese Methode trotz fehlender Dokumentation in Graph: findNode erlaubt ist.

Zurück zu „Archiv“