1 Punkte von GN⁺ 2024-03-01 | 1 Kommentare | Auf WhatsApp teilen

Was tun, wenn man eine bestehende C++-Codebasis übernimmt?

  • Beim Start in einem neuen Job, beim Teamwechsel oder nachdem ein erfahrener Kollege gegangen ist, übernimmt man plötzlich eine große C++-Codebasis mit komplexer und eigenwilliger Struktur.
  • Bugs müssen behoben und neue Funktionen hinzugefügt werden, aber die Codebasis kann weder ignoriert noch abgeschafft werden. Sie ist für diejenigen wichtig, die das Gehalt bezahlen – also ist sie auch für dich wichtig.

Erster Schritt: Den Code lokal zum Laufen bringen

  • Den Code und das Build-System nur minimal ändern, um es lokal lauffähig zu machen. Noch keine groß angelegte Refaktorierung.

Unnötiges entfernen

  • Alles entfernen, was nicht absolut notwendig ist, um die Funktionen bereitzustellen, die das Unternehmen oder das Open-Source-Projekt bewirbt und verkauft.

Das Projekt ins 21. Jahrhundert holen

  • CI (Continuous Integration), Linter, Fuzzing, automatische Formatierung usw. hinzufügen.

Schrittweise Verbesserung des Codes

  • Kleine, schrittweise Änderungen am Code vornehmen. Das wiederholt tun, bis das Projekt in Bezug auf Sicherheit, Developer Experience, Korrektheit und Performance in einen akzeptablen Zustand gebracht ist.

Teilweise Neuschreibung in einer speichersicheren Sprache erwägen

  • Wenn möglich, in Erwägung ziehen, Teile des Codes in einer speichersicheren Sprache neu zu schreiben.

Unterstützte Plattformen festlegen

  • Im README die offiziell unterstützten <Architektur>-<Betriebssystem>-Paare angeben, zum Beispiel x86_64-linux oder aarch64-darwin.

Builds auf Maschinen zum Laufen bringen

  • Sicherstellen, dass auf allen unterstützten Plattformen zuverlässig und konsistent gebaut werden kann.

Tests auf Maschinen erfolgreich durchlaufen lassen

  • Falls es keine Tests gibt, vor Codeänderungen Tests schreiben, sie erfolgreich durchlaufen lassen und dann zurückkommen.

Im README beschreiben, wie man die Anwendung baut und testet

  • Die Build- und Testbefehle so einfach machen, dass auch Nicht-Spezialisten ihnen leicht folgen können.

Low-Hanging Fruits finden, um Build- und Testgeschwindigkeit zu erhöhen

  • Einfache Wege finden, um Build- und Testgeschwindigkeit ohne Änderungen am Build-System zu verbessern.

Unnötigen Code entfernen

  • Compiler-Warnungen und Linter verwenden, um ungenutzten Code zu finden und zu entfernen.

Linter

  • Sich nicht übermäßig an Linter-Regeln festbeißen, sondern ein paar grundlegende hinzufügen und in den Entwicklungszyklus integrieren.

Code-Formatierung

  • Zum passenden Zeitpunkt den Stil einmalig auf die gesamte Codebasis anwenden und die Konfiguration committen.

Sanitizer

  • Sanitizer verwenden, um echte Bugs und Speicherlecks zu erkennen und zu beheben.

CI-Pipeline hinzufügen

  • Alle eingerichteten guten Praktiken (Linter, Code-Formatierung, Tests usw.) automatisieren und für jede Änderung produktionsreife Binärdateien erzeugen.

Schrittweise Verbesserung des Codes

  • Sich auf konkrete Ziele wie Sicherheit, Korrektheit und Performance konzentrieren und subjektive Maßstäbe wie „sauberer Code“ vermeiden.

Neuschreiben in einer speichersicheren Sprache?

  • Das ist derzeit laufende Arbeit und mit vielen Vorbehalten verbunden. Nur tun, wenn es einen klaren Grund dafür gibt.

Fazit

  • Bietet einen konkreten, schrittweisen Plan, um aus einer komplexen Legacy-C++-Codebasis herauszukommen.

Anhang: Abhängigkeitsmanagement

  • In C++ gibt es kein einheitliches Abhängigkeitsmanagement, und meist werden System-Paketmanager verwendet. Das ist jedoch keine gute Idee.
  • Die Meinung des Autors zum Abhängigkeitsmanagement ist, Git-Submodule und das Kompilieren aus dem Quellcode zu verwenden.

Meinung von GN⁺

  • Dieser Artikel bietet Nachwuchs-Softwareingenieuren, die eine C++-Codebasis übernommen haben, einen nützlichen Schritt-für-Schritt-Leitfaden.
  • Der Umgang mit Legacy-Code ist für viele Entwickler eine häufige Herausforderung, und dieser Artikel gibt dafür praktische Ratschläge.
  • Dass im Verbesserungsprozess der Codebasis die Bedeutung von Tests betont wird, spiegelt gute Praktiken der Softwareentwicklung wider.
  • Die Meinung des Autors zum Abhängigkeitsmanagement ist umstritten; in realen Projekten werden moderne Paketmanager wie Conan oder vcpkg jedoch oft erfolgreich eingesetzt.
  • Bei der Einführung von Technologien sollten die Eigenschaften des Projekts und das technische Niveau des Teams berücksichtigt werden, und dieser Artikel kann ein guter Ausgangspunkt für solche Entscheidungen sein.

1 Kommentare

 
GN⁺ 2024-03-01
Hacker-News-Kommentare
  • In einigen Hacker-News-Kommentaren werden Ratschläge dazu gegeben, was man tun sollte, wenn man ein C++-Projekt übernimmt:

    • Reproduzierbare Builds: Es wird empfohlen, die Build-Umgebung mit Tools wie Docker zu kapseln, damit Werkzeuge und Abhängigkeiten klar definiert und reproduzierbar sind.
    • Sauber mit der Option -Wall bauen: Warnungen beheben, um Probleme im Code zu korrigieren; in seltenen Fällen kann man Warnungen auch ignorieren, nachdem man sie verstanden hat.
    • Es wird vorgeschlagen, frühe Tests mit Tools wie Valgrind durchzuführen, um Lese-/Schreibfehler zu untersuchen.
    • Refactoring sollte anfangs auf einen lokal begrenzten Bereich beschränkt bleiben, und größere Redesigns sollte man vermeiden, bevor man die Gesamtstruktur verstanden hat.
  • Andere Kommentare argumentieren, dass es wichtig ist, zuerst CI, Linting und Auto-Formatting einzuführen:

    • Bevor unnötige Teile aus dem Code entfernt werden, sollte man verstehen, wie das Programm funktioniert; statische Analysewerkzeuge können Einblicke geben, an welchen Stellen Arbeit nötig ist.
  • Ein Nutzer schlägt vor, in ein neues Team oder zu einem anderen Unternehmen zu wechseln.

  • Es gibt auch Kommentare, die die Bedeutung von Werkzeugen und Techniken zum Verständnis des Codes hervorheben:

    • Wichtig seien der Einsatz von Tools zur Indizierung der Codebasis, das Erstellen von UML-Sequenzdiagrammen sowie das Anfertigen von Notizen, als würde man den Code jemand anderem beibringen.
  • Ein Kommentar gibt Ratschläge dazu, wie man ein Projekt modernisieren kann, etwa durch das Hinzufügen von CI, Lintern, Fuzzing und Auto-Formatting:

    • Mit CI soll sichergestellt werden, dass das Projekt auch anderswo gebaut werden kann; Compiler-Warnungen und statische Analysierer helfen dabei, Probleme im Code zu erkennen.
    • Für wichtige Codeteile sollten Unit-Tests eingerichtet werden, um zu prüfen, ob der Code die vorgesehenen Aufgaben korrekt ausführt.
    • Auto-Formatting habe eine geringere Priorität; empfohlen wird, dem Stil des ursprünglichen Maintainers zu folgen.
  • Ein weiterer Kommentar kritisiert den Rat, Teile in einer speichersicheren Sprache neu zu schreiben:

    • Es sei schwierig, die dafür nötigen Ressourcen zu bekommen, zusätzliches Wissen über eine weitere Sprache neben C++ sei erforderlich, und das Testing könne komplexer werden.
  • Es gibt auch einen Kommentar, der behauptet, dass die Nutzung von git-Submodulen und das Kompilieren aus dem Quellcode Paketmanagern überlegen seien:

    • Dabei wird angemerkt, dass es seltsam sei, solche Kritik zu äußern, bevor man Tools wie vcpkg überhaupt ausprobiert hat.

Diese Kommentare bieten verschiedene Ansätze und Ratschläge für den Umgang mit einem übernommenen C++-Projekt und zeigen unterschiedliche Ansichten zu Projektmanagement, Codeverständnis, Refactoring und Modernisierungsstrategien.