HS-Flensburg-PLTP / jlint

Other
0 stars 0 forks source link

Fortgeschrittene Vorschläge für Methodennamen #331

Closed jan-christiansen closed 1 year ago

jan-christiansen commented 1 year ago

In diesem Issue soll einmal beispielhaft eine Regel implementiert werden, die mithilfe eines wahrscheinlichkeitsbasierten Ansatzes Vorschläge für die Verbesserung von Bezeichnern macht. Im konkreten Fall sollen Vorschläge für Methodennamen gemacht werden. Der Ansatz soll die Technik unter https://code2vec.org einsetzen. Dazu muss erst einmal erarbeitet werden, wie das trainierte neuronale Netz unter https://github.com/tech-srl/code2vec verwendet werden kann. Die Struktur der Regel ist ähnlich zur Regel, welche die Sprache eines Bezeichners überprüft. Mit einem Shell-Kommando wird für eine Methode das neuronale Netz ausgewertet und liefert Vorschläge inklusive Wahrscheinlichkeit des Vorschlages. Als Eingabe verlangt das neuronale Netz allerdings die Definition der Methode. Es muss also erarbeitet werden, welche Form dieses Argument genau haben muss.

jan-christiansen commented 1 year ago

Hier sind noch ein paar Beispiele aus den Laboraufgaben, um den Ansatz später zu evaluieren.

Im besten Fall würde die Regel für die Methoden containsHelp und isNull bessere Namen vorschlagen.

static <T> boolean containsHelp(final T current, final T value) {
    return value == null && current == null || current != null && current.equals(value);
}
static <T> boolean isNull(T temp, T value) {
    return temp != null && temp.equals(value) || temp == null && value == null;
}

Auch für die Methoden helpcountNodes und add sollte die Regel im besten Fall bessere Namen vorschlagen.

public int countNodes() {
    return helpcountNodes(root);
}

public int helpcountNodes(final BinTreeNode root) {
    if (root == null) {
        return 0;
    } else {
        return 1 + helpcountNodes(root.right) + helpcountNodes(root.left);
    }
}
private int count(final BinTreeNode check) {
    if (check == null) {
        return 0;
    } else {
        return 1 + count(check.left) + count(check.right);
    }
}

private void add(final List<Integer> list, final BinTreeNode node) {
    if (node != null) {
        if (node.right != null) {
            add(list, node.right);
        }
        list.add(0, node.value);
        if (node.left != null) {
            add(list, node.left);
        }
    }
}
jan-christiansen commented 1 year ago

Viele der Methodennamen in den Aufgaben sind vorgegeben. Für diese Namen sollte die Regel keine Alternativen vorschlagen. Daher muss es eine Whitelist geben, die angibt, welche Methodennamen gar nicht erst kontrolliert werden. Diese Whitelist ist insbesondere wichtig, da die Regel ansonsten für falsch implementierte Methoden neue Namen vorschlagen würde, obwohl die Implementierung einfach korrigiert werden sollte. Das führt vermutlich schnell zu Verwirrung.

jokogr25 commented 1 year ago

Fragen: Umgang wenn Name in Vorschlägen vorkommt add(list, BinTreeNode) -> wird zu add Umbenennung der Methode, um Einfluss zu nehmen?

Problem(e) bei rekursiven Methoden

jokogr25 commented 1 year ago

Varianten der Beispiel-Methoden in code2vec testen

jokogr25 commented 1 year ago

code2seq

Averodas commented 1 year ago
static <T> boolean containsHelp(final T current, final T value) {
    return value == null && current == null || current != null && current.equals(value);
}

code2vec:

Original name:  contains|help
        (0.337449) predicted: ['equal']
        (0.222097) predicted: ['eq']
        (0.152269) predicted: ['are', 'equal']
        (0.130073) predicted: ['is', 'equal']
        (0.056747) predicted: ['equals']
        (0.045972) predicted: ['safe', 'equals']
        (0.027768) predicted: ['matches']
        (0.013918) predicted: ['same', 'as']
        (0.007310) predicted: ['is', 'current']
        (0.006396) predicted: ['compare', 'values']

code2seq:

Original name:  contains|help
Predicted:      ['is', 'equal']
Averodas commented 1 year ago
static <T> boolean isNull(T temp, T value) {
    return temp != null && temp.equals(value) || temp == null && value == null;
}

code2vec:

Original name:  is|null
        (0.179465) predicted: ['safe', 'equals']
        (0.169058) predicted: ['equals']
        (0.147519) predicted: ['eq']
        (0.137217) predicted: ['equal']
        (0.106244) predicted: ['null', 'safe', 'equals']
        (0.091403) predicted: ['are', 'equal']
        (0.066828) predicted: ['is', 'equal']
        (0.062435) predicted: ['same']
        (0.022597) predicted: ['compare', 'values']
        (0.017234) predicted: ['is', 'identical']

code2seq:

Original name:  is|null
Predicted:      ['equals']
Averodas commented 1 year ago
public int helpcountNodes(final BinTreeNode root) {
    if (root == null) {
        return 0;
    } else {
        return 1 + helpcountNodes(root.right) + helpcountNodes(root.left);
    }
}

code2vec:

Original name:  helpcount|nodes
        (0.189534) predicted: ['get', 'image', 'path']
        (0.162416) predicted: ['get', 'descripcion', 'justificante']
        (0.113696) predicted: ['get', 'waiting', 'consumer', 'count']
        (0.087972) predicted: ['get', 'tipo', 'tramite']
        (0.084806) predicted: ['has', 'native', 'allocation']
        (0.084696) predicted: ['splay']
        (0.077957) predicted: ['convert', 'id']
        (0.074889) predicted: ['valid', 'type']
        (0.070948) predicted: ['get', 'start', 'sequence', 'number']
        (0.053086) predicted: ['uid']

code2seq:

Original name:  helpcount|nodes
Predicted:      ['nodes']
Averodas commented 1 year ago
private void add(final List<Integer> list, final BinTreeNode node) {
    if (node != null) {
        if (node.right != null) {
            add(list, node.right);
        }
        list.add(0, node.value);
        if (node.left != null) {
            add(list, node.left);
        }
    }
}

code2vec:

Original name:  add
        (0.722491) predicted: ['add']
        (0.078461) predicted: ['add', 'all']
        (0.052235) predicted: ['add', 'to', 'list']
        (0.040259) predicted: ['add', 'int']
        (0.034390) predicted: ['add', 'child', 'nodes']
        (0.017696) predicted: ['add', 'objects']
        (0.014537) predicted: ['add', 'if', 'not', 'null']
        (0.013726) predicted: ['to', 'list']
        (0.013132) predicted: ['populate', 'list']
        (0.013072) predicted: ['append', 'list']

code2seq:

Original name:  add
Predicted:      ['add']
Averodas commented 1 year ago

Momentan werden beide Netze folgendermaßen benutzt:
Ein Befehl lädt das Modell und versetzt es in den predict-Modus. Das laden des Models dauert etwa 40 Sekunden auf meinem Rechner. Das Ende des Ladens wird durch eine Ausgabe auf stdout angezeigt. Jetzt kann die Input.Java Datei im Hauptverzeichnis geändert werden und mit einem beliebigen Tastendruck in dem Terminal wird der Java-Code in dieser evaluiert. Die Auswertung des Codes dauert etwa eine Sekunde.

Das Ergebnis der Auswertung wird wieder in stdout geschrieben. Danach kann die Input.Java erneut verändert werden um den nächsten Code zu evaluieren.

jokogr25 commented 1 year ago

Implementation der Regel momentan hier: #340