Wie finde ich Quellcode, der eine bestimmte Funktion implementiert hat? [geschlossen]

14

Ich habe mich gefragt, welche Techniken es gibt, um herauszufinden, welcher Code eine bestimmte Funktion in einer Desktop-Anwendung implementiert.

Ich bin ein Junior-Entwickler, der nur über professionelle Programmiererfahrung im Bereich Web-Programmierung verfügt. Im Web ist das einfacher. Sie "inspizieren" beispielsweise eine Schaltfläche mit den Browser-Tools und können sehen, was getan wird, wenn Sie darauf klicken. Vorausgesetzt, Sie haben den vollständigen Quellcode, können Sie die Hierarchie der Aufrufe aufschlüsseln.

Aber wie macht man das in Desktop-Anwendungen? Zumindest ohne in die volle Codebasis eintauchen zu müssen?

py_script
quelle
6
Anstatt den Code zu lesen, können Sie manchmal einen Debugger verwenden. Wie das funktioniert (und wie benutzerfreundlich das für Sie ist), hängt von der verwendeten Sprache, dem verwendeten Debugger und der verwendeten Debugger-Oberfläche ab. In jedem Fall ist die Verwendung eines Debuggers eine Kunst, die man lernen muss - aber wenn man sie erst einmal gelernt hat, ist sie ein sehr mächtiges Werkzeug. Ich sollte irgendwann lernen, selbst eins zu benutzen.
Amon
Und wo soll ich die Haltepunkte einrichten?
py_script
Die Einrichtung des Haltepunkts hängt vollständig von Ihrer Anwendung und ihrer Organisation ab.
2
Mit neuen objektorientierten Systemen wie Backbone.js und Templates, die immer beliebter werden, kann es tatsächlich etwas schwierig sein, zu "inspizieren", wo und wie Web-Interfaces erstellt wurden.
NoBugs
1
@jeffo Wenn Sie zum Beispiel Datei-> In einer Anwendung öffnen (sagen wir LibreOffice's Writer), wie können Sie herausfinden, welche Aufrufsequenz dahinter steckt?
py_script

Antworten:

21

Rückverfolgung

Bei der Rückverfolgung wird ein Endpunkt zu einem Ereignis gesucht, das mit der Funktion verknüpft ist (siehe unten). Dort wird ein Haltepunkt in den Debugger eingefügt. Die Funktion wird ausgelöst und wenn der Debugger stoppt. Der Aufrufstapel wird überprüft, um den Aufrufpfad zurückzuverfolgen. Während Sie den Call-Stack hinaufgehen, können Sie sich Notizen zu variablen Zuständen machen oder neue Haltepunkte setzen, um das Ereignis erneut zu untersuchen.

Die Funktion wird erneut ausgelöst und der Debugger stoppt an den neuen Haltepunkten. Sie können dann die Rückverfolgung wiederholen oder die Vorwärtsverfolgung durchführen, bis das Ziel gefunden wurde.

Für und Wider

  • Es ist immer einfacher, den Call-Stack zu durchlaufen und zu sehen, wie Sie irgendwo hingekommen sind.
  • Es kann Millionen von Bedingungen geben, die erfüllt sein müssen, bevor ein Endpunkt erreicht wird. Wenn Sie den Endpunkt bereits kennen, haben Sie sich viel Arbeit erspart.
  • Wenn die Funktion fehlerhaft ist. Möglicherweise erreichen Sie den Endpunkt nie, und es kann Zeitverschwendung sein, herauszufinden, warum.

Endpunkterkennung

Um ein Feature zu debuggen, muss man wissen, wo im Quellcode das endgültige Ziel erreicht wird. Nur von diesem Punkt aus können Sie zurückverfolgen, um zu sehen, wie der Code dorthin gelangt ist . Ein Beispiel; Um zu verstehen, wie das Rückgängigmachen ausgeführt wird. Sie wissen, wo im Code Dinge rückgängig gemacht werden, aber Sie wissen nicht, wie die Dinge dahin kommen . Dies wäre ein Kandidat für das Zurückverfolgen, um herauszufinden, wie die Funktion funktioniert.

Vorwärtsverfolgung

Die Vorwärtsverfolgung lokalisiert einen Startpunkt für ein Ereignis, das mit einer Funktion verknüpft ist (siehe unten). Dort werden Protokollmeldungen in den Quellcode eingefügt oder Haltepunkte gesetzt. Dieser Vorgang wird wiederholt, wenn Sie sich weiter vom Startpunkt entfernen , bis Sie das Ziel für das Feature gefunden haben.

Für und Wider

  • Dies ist der einfachste Ausgangspunkt, um ein Feature zu finden.
  • Die Komplexität des Codes verringert die Wirksamkeit der Vorwärtsverfolgung. Je mehr Bedingungen im Code enthalten sind, desto größer ist die Chance, dass Sie in die falsche Richtung gehen.
  • Die Vorwärtsverfolgung führt häufig dazu, dass Haltepunkte festgelegt werden, die durch nicht verwandte Ereignisse ausgelöst werden. Unterbrechen Sie den Debugging-Prozess und stören Sie Ihre Suche.

Starten Sie die Punktermittlung

Sie können Schlüsselwörter, Benutzeroberflächen-IDs (Schaltflächen-IDs, Fensternamen) oder einfach zu findende Ereignis-Listener für die Funktion verwenden. Sie können beispielsweise mit der Schaltfläche beginnen, die zum Auslösen einer Rückgängig- Funktion verwendet wird.

Prozess der Eliminierung

Sie können sich dies als den Mittelpunkt im Vergleich zu den Start- und Endpunktpositionen vorstellen. Sie führen einen Prozess der Beseitigung , wenn Sie bereits ein Stück Code wissen , verwendet in einem Feature, aber es ist weder der Anfang oder das Ende des Features.

Die Richtung, die Sie vom Mittelpunkt aus einschlagen, hängt von der Anzahl der Ein- und Ausgänge ab. Wenn der Codeabschnitt an vielen Stellen verwendet wird, kann das Zurückverfolgen von dieser Position aus sehr zeitaufwändig sein, da alle überprüft werden müssen. Anschließend verwenden Sie einen Eliminierungsprozess, um diese Liste zu reduzieren. Alternativ können Sie von diesem Punkt aus eine Vorwärtsverfolgung durchführen. Wenn sich der Codeabschnitt jedoch an vielen Stellen verzweigt, kann dies ebenfalls ein Problem sein.

Sie müssen die Positionsrichtungen reduzieren, indem Sie Pfaden nicht folgen, die für das Feature eindeutig nicht ausgeführt würden. Bewegen Sie sich über diesen Code hinaus und platzieren Sie Haltepunkte nur dort, wo es wahrscheinlich mit der Funktion zusammenhängt.

Das Debuggen in der Mitte erfordert häufig erweiterte IDE-Funktionen. Die Fähigkeit, Codehierarchie und Abhängigkeiten zu sehen. Ohne diese Werkzeuge ist es schwierig zu tun.

Für und Wider

  • Mittelpunkte sind oft das erste Stückchen Code , das erscheint in den Kopf , wenn Sie die Funktion denken. Sie sagen sich: "Ah, das muss XXXX verwenden, um zu arbeiten."
  • Mittelpunkte können Startpunkte am einfachsten aufdecken .
  • Mittelpunkte können eine einfache Möglichkeit sein, den Pfad zu einem Feature zu ermitteln, wenn sie durch Synchronisation oder Threading-Änderungen verloren gehen.
  • Mittelpunkte können Sie zu Code führen, mit dem Sie nicht vertraut sind. Es kostet Sie Zeit zu lernen, was los ist.
Reactgular
quelle
Danke Matthew, tolle Annäherung. Aber wie findest du einen Startpunkt (sorry, wenn es allen außer mir klar ist)?
py_script
@py_script Mit welcher Programmiersprache haben Sie Probleme?
Reactgular
Es geht nicht um ein spezifisches Problem ich habe, aber mein Haupt Desktop - Programmiersprache ist Java, können mit ihm so gehen
py_script
11

Angenommen, die Funktion ist an ein UI-Ding gebunden, wie z. B. einen Button oder ein Menü, und das, was ich normalerweise mache, folgt (sehr mühsam, aber es funktioniert). Hierbei wird der Quellcode durchsucht und kein Debugger verwendet .

  1. Suchen Sie auf der Schaltfläche nach dem (hoffentlich eindeutigen) Text, z. B. "Super Feature X3".
  2. Das ist wahrscheinlich in einer Datei mit einer Konstanten, z SUPER_BUTTON_3 = "Super Feature X3". Denken Sie zum späteren Nachschlagen an diesen Dateinamen.
  3. Möglicherweise gibt es eine weitere Abstraktionsebene (von sogar zwei). Suchen Sie weiter, um den "echten" String zu erhalten, der vom Button verwendet wird. Beachten Sie, wie dies für die Zukunft getan wird.
  4. Suchen Sie nun nach dieser Konstante. Hoffentlich hast du jetzt den Button gefunden. Vielleicht verbinden sie dort den ActionListener. (Ich nehme Java-ese hier, YMMV, aber das Konzept gilt immer noch)
  5. Wenn nötig, suchen Sie auf diesem Button und Sie werden irgendwann herausfinden, wo er mit einem Listener verbunden wird.
  6. Vielleicht leitet dieser Listener wirklich zu anderen Listenern weiter (die "echte" Funktionalität), basierend auf der Konstante, wenn ja, folgen Sie dieser if / else- oder case-Anweisung. HINWEIS : Wenn es eine zentrale Dispatch-Funktion gibt, können Sie hier Haltepunkte einrichten .
  7. Schließlich sollten Sie am tatsächlichen Code sein.

Wie @amon bemerkte, ist manchmal ein Debugger einfacher ...

user949300
quelle
Interessant ... zum Glück sind solche Namen normalerweise im Code fest
codiert
3
  • Wenn Sie einen verwandten Code finden, können Sie mit Ihrer Versionsverwaltungssoftware das gesamte Commit oder die Commits in der Nähe anzeigen, die es hinzugefügt haben. Das sollte Ihnen alles zeigen, was zur Implementierung dieser Funktion erforderlich war.

  • Eine einfache Möglichkeit, einen Ausgangspunkt zu finden, besteht darin, in Ihrer Codebasis nach dem Text auf der Schaltfläche zu suchen.

  • Häufig fügen die Benutzer in ihren Commit-Nachrichten eine Issue-ID aus ihrem Issue-Tracker ein. Wenn Sie ein Problem finden, das die Funktionsanforderung beschreibt, können Sie nach Commits mit dieser Problem-ID suchen.

Michael Burge
quelle
Das ist ein kluger Ansatz, aber ich denke, er funktioniert nur in Unternehmensumgebungen. Was ist, wenn Sie nur einen Tarball haben?
py_script