Die Codequalität bezieht sich auf die Robustheit des Codes, die über die Frage hinausgeht, ob er einfach nur läuft und die gewünschte Funktion erfüllt oder nicht. Qualitativ hochwertiger Code zeichnet sich durch seine Effizienz, Wartbarkeit, Lesbarkeit und Wiederverwendbarkeit aus, wohingegen Code von geringer Qualität spröde, schwer zu analysieren ist und dazu neigt, im Laufe der Zeit technische Schulden anzuhäufen.
Hohe Codierungsstandards sind für den Softwareentwicklungsprozess das, was angemessenes Vorhandensein und „sauberes Arbeiten“ für den Betrieb einer Großküche bedeuten. Praktiken, die die Qualität Ihres Codes verbessern, können kurzfristig zu einer besseren Funktionalität führen. Langfristig sind die wichtigsten Vorteile jedoch weniger Probleme, schnellerer Fortschritt und geringere Wartung.
Die langfristigen Vorteile von hochwertigerem Code können für Programmierer manchmal schwierig zu vermitteln, wenn das Management nicht mit den Feinheiten des Softwareentwicklungszyklus vertraut ist. Das Gleichgewicht zwischen den ganzheitlichen Vorteilen von optimalem Code und dem unmittelbaren Druck der Geschäftsprioritäten erfordert oft komplexe Kompromisse. In einer Studie aus dem Jahr 2022 mit 39 proprietären Produktionscodebasen wurde jedoch unter anderem Folgendes behauptet: 1
Technische Schulden aufgrund überhastet geschriebenen Codes verschwenden bis zu 42 % der Arbeitszeit von Entwicklern.
Minderwertiger Code führt zu 15-mal mehr Fehlern als hochwertiger Code.
Die Behebung von Problemen in minderwertigem Code benötigt im Durchschnitt 124 % mehr Zeit als die Behebung von Problemen in hochwertigem Code.
Qualitativ hochwertigerer Code erhöht das Verständnis, Refaktorisieren, Debuggen und das Hinzufügen neuer Funktionen zu einer Codebasis. Klarer, konsistenter und gut geschriebener Code erleichtert die Koordination zwischen den Entwicklungsteams und reduziert die Komplexität und Komplikationen von Codeänderungen. Es sorgt nicht nur für eine starke Softwarequalität, sondern auch für ein starkes Entwickler- und Nutzererlebnis.
Ob ein Codeabschnitt kompiliert wird und seinen Zweck zur Laufzeit erfolgreich ausführt, reicht nicht aus, um seine Gesamtqualität zu bestimmen. Das Schreiben von Code ist nicht wie das Lösen eines Kreuzworträtsels, bei dem es nur einen einzigen Weg gibt, die Aufgabe richtig zu lösen: Oft gibt es unzählige Lösungen für ein gegebenes Programmierproblem. Funktionalität stellt daher das Kriterium für akzeptablen Code dar. Der Wert eines qualitativ hochwertigen Codes zeigt sich in seinen sekundären Auswirkungen auf den ihn umgebenden Kontext.
Erhalten Sie kuratierte Einblicke in die wichtigsten – und faszinierendsten – KI-Neuheiten. Abonnieren Sie unseren wöchentlichen Think-Newsletter. Weitere Informationen in der IBM Datenschutzerklärung.
Hochwertiger Code ist ein relativ abstraktes Konzept. Die Gesamtqualität eines Codestücks wird ebenso sehr dadurch definiert, wie es erstellt wird und wie es mit der größeren Codebasis interagiert, in dem es existiert, wie durch einen bestimmten Satz diskreter, objektiver Codequalitätsmetriken (obwohl es viele solcher Metriken gibt).
Zu den allgemeinen Merkmalen von qualitativ hochwertigem Code gehören:
Lesbarkeit: Codelesbarkeit ist für Wartung, Debugging und Koordination zwischen Teams und Zeit unerlässlich. Ist Ihr Code auch für andere Teammitglieder leicht verständlich? Kann ein anderer Programmierer, der in einigen Jahren arbeitet, Ihren Code korrekt interpretieren, ohne dass Sie selbst zur Verfügung stehen, um Kontext zu liefern?
Wartbarkeit: Die Komplexität des Codes korreliert oft umgekehrt mit seiner Wartbarkeit. Ist Ihr Code leicht testbar, sodass Ihr Team ihn effizient auf Sicherheitslücken und Optimierungsmöglichkeiten auswerten kann? Ist es robust genug, um neue Funktionen hinzuzufügen, ohne die Kernfunktionalität zu beeinträchtigen, oder ist es zu fragil, um Anpassungen ohne größere Umstrukturierungen vorzunehmen? Die Priorisierung von wartbarem Code kann zwar im Vorfeld zusätzlichen Aufwand bedeuten, spart aber in der Zukunft viel Zeit und Energie.
Effizienz: Gut geschriebener Code kann die Latenz und den Ressourcenverbrauch eines Systems verringern. Zum Beispiel können sorgfältig ausgewählte Datenstrukturen die Anzahl der für eine bestimmte Funktion erforderlichen CPU-Operationen minimieren. Durchdachte Strategien für das Daten-Caching reduzieren kostspielige I/O-Vorgänge (Eingabe/Ausgabe), indem redundante Datenbankabfragen und Netzwerkanfragen eliminiert werden, während gleichzeitig ungenutzter Speicher umgehend freigegeben wird und unnötiges Aufblähen von RAM vermieden wird.
Zuverlässigkeit: Weniger Fehler und Strukturen, die gegenüber Codeänderungen robust sind, bedeuten weniger häufige Ausfälle und Ausfallzeit. Zuverlässigkeit ist eine wesentliche Voraussetzung für die Benutzerfreundlichkeit und das Vertrauen der Benutzer sowie für den Zustand der kritischen Systeme, auf die Ihr Unternehmen angewiesen ist.
In einem Artikel, der 2023 in der Harvard Data Science Review erschien, schlugen Forscher der Calvin University, des Amherst College und der Columbia University ein präskriptives Framework für guten Code vor: „Die vier C’s“²
Korrektheit: Der Code tut, was er tun soll. Die Autoren hoben zwei Folgerungen aus dieser offensichtlichen Einbeziehung hervor: „Erstens ist Korrektheit ein notwendiges, aber nicht hinreichendes Metriken für guten Code.“ Zweitens unterstützen und fördern die anderen Ziele die Korrektheit.“
Klarheit: Jeder, der den Code liest und schreibt, kann erkennen, wofür er gedacht ist, und intuitiv bei Bedarf Änderungen vornehmen.
Eindämmung: Vermeiden Sie Zersiedelung, Redundanz und unnötige Abhängigkeiten. Eine ordnungsgemäße Eindämmung umfasst unter anderem die Verwendung von Funktionen, um wiederverwendbaren Code zu enthalten, und die Aufbewahrung von Code, der in Dateien oder Projekten in einem Modul oder Paket verwendet wird.
Konsistenz: Eine Codebasis sollte die interne Konsistenz von Stil, Namenskonventionen, Kommentaren, Einrückungen und anderen Praktiken wahren.
Da die moderne Softwareentwicklung zunehmend von agentische Codierung Assistenten wie IBM Bob gesteuert wird, sind Containment und Konsistenz besonders nützlich, um die Effizienz und Genauigkeit automatisierter Werkzeuge zu maximieren. Nichtsdestotrotz kann die Fähigkeit von Plattformen der nächsten Generation wie IBM Bob, Möglichkeiten zur KI-Refaktorierung in Echtzeit zu erkennen, den Aufwand reduzieren, der erforderlich ist, um dieses Maß an stilistischer Disziplin durchzusetzen.
Obwohl jede Programmiersprache und jeder Anwendungsfall ihre eigenen spezifischen Nuancen und granularen Überlegungen hat, gibt es einige universelle Best Practices für Qualitätscode in jedem Szenario.
Ein Ansatz zur Konzeption hoher Codequalität besteht darin, sie einfach als Code zu denken, der möglichst viele Merkmale schlechten Codes vermeidet – die später in diesem Artikel erkundet werden.
Für einen normativeren Ansatz beschreibt das bereits erwähnte Harvard Data Science Review (HDSR) Papier eine Reihe von Richtlinien zur Sicherstellung der Codequalität. Obwohl diese Richtlinien vordergründig für die Bedürfnisse von Data Scientist optimiert sind, sind die meisten von ihnen in jeder Codierung anwendbar.
Starke Namenskonventionen sind für die Lesbarkeit und Konsistenz des Codes unerlässlich. Die Autoren schlagen folgende Vorgehensweisen vor:
Die Länge der Namen sollte proportional zu ihrem Umfang sein. Je größer der Abstand – sei es zeitlich, in Codezeilen oder organisatorischer Struktur – zwischen der ursprünglichen Definition eines Begriffs und seiner Verwendung ist, desto wichtiger ist es, dass sein Name seine Rolle klar kommuniziert.
Behalten Sie die Abkürzungen im Blick. Kurze oder sogar nur einbuchstabige Variablennamen können zwar helfen, den Code übersichtlicher zu gestalten, aber sie können auch für Personen, die mit dem Projekt weniger vertraut sind, unverständlich werden. Die Pflege einer Art „Glossar“ mildert diesen Kompromiss.
Verwenden Sie konsequent Großschreibung. Es ist außerdem ratsam, Fälle zu vermeiden, in denen sich zwei Namen ausschließlich durch ihre Groß- und Kleinschreibung unterscheiden.
Vermeiden Sie unauffällige Namen. Sie erhöhen die Schwierigkeit der Codeinterpretation erheblich.
Wählen Sie Dateibenennungskonventionen, die ein natürliches Sortieren ermöglichen. Zum Beispiel können Sie den ISO 8601-Standard für Datum und Uhrzeit übernehmen oder Nummern mit 0en auffüllen, um sicherzustellen, dass alle die gleiche Anzahl an Ziffern haben.
Klare und konsistente Benennungskonventionen können auch dazu beitragen, die Eingabe von KI-Codierung-Assistenten zu vereinfachen und die Genauigkeit ihrer Ausgabe zu erhöhen. Anstatt beispielsweise einen Agenten aufzufordern, bestimmte Arten von Variablen zu untersuchen oder alle Dateien aus einem bestimmten Datumsbereich zu erkunden – was erfordern würde, dass Ihr KI-Agent aus dem Kontext probabilistisch ableitet , welche Variablen oder Dateien die Kriterien erfüllen – können Sie einen Agenten explizit auffordern, alle Dateien zu erkunden, die mit einer bestimmten Zahl beginnen, oder alle Variablen mit einem bestimmten Namen.
Neben der Festlegung verbindlicher Namenskonventionen sollte ein umfassender Styleguide idealerweise auch Formatierungselemente wie die Verwendung von Leerzeichen und Einrückungen, Kommentare und Datentypen sowie „Codierungsdialekte“ standardisieren. Eine breite Palette bewährter Stilanleitungen für verschiedene Programmiersprachen ist auf GitHub zu finden, wie zum Beispiel in dieser kuratierten Liste.
Ein Styleguide ist auch eine unschätzbare Referenz für einen KI-Codierungsassistenten, der als Kontext für bestimmte Aufgaben oder sogar als Teil des Systemprompts Ihres KI-Agenten dient.
Die Nutzung von Toolkit und Bibliotheken ist ein natürlicher Vorteil für Code-Wiederverwendbarkeit und Effizienz, da sie hilft, Workflow und Ausgabe in verschiedenen Teams zu standardisieren und die Code-Erstellung breit zu beschleunigen. Sie sind besonders nützlich, wenn der Code die Interaktion mit komplexen Drittsystemen vermitteln oder wiederkehrende, „gelöste“ Probleme bewältigen muss.
Eine übermäßige Abhängigkeit von Toolkit kann jedoch zu unnötiger Aufblähung und externen Abhängigkeiten führen, wodurch die Robustheit und Wartbarkeit des Codes verringert wird. Sie neigen außerdem dazu, die zugrundeliegende Logik des Codes zu abstrahieren, was seine Lesbarkeit verringert. Die Autoren des HDSR formulieren das ideale Gleichgewicht in einfachen Worten: „Wir wollen, dass unser Toolkit so einfach wie möglich ist, aber nicht einfacher.“
Wenn Sie häufig dieselben Codeblöcke kopieren, einfügen und bearbeiten, könnte eine Funktion, die den wiederholten Code an einer Stelle zusammenfasst, hilfreicher sein. Die Parameter dieser Funktion können die Elemente widerspiegeln, die sich von Instanz zu Instanz ändern. Das beschönigt den Code und vereinfacht die Wartung, da man alle Instanzen dieser Funktion in einem einzigen Schritt und Ort anpassen kann (anstatt jedes einzelne Duplikat eines Codeblocks einzeln anzupassen).
Konsistenzprüfungen sind automatisierte Validierungen, die Verify, ob potenzielle Daten oder Systemzustände mit vordefinierten logischen Regeln und Konventionen übereinstimmen. Sie helfen dabei, unvorhergesehene Konflikte und Widersprüche im Code zu vermeiden und zu berücksichtigen. Diese automatisierten Tests sind typischerweise eine standardisierte, kritische Komponente von CI/CD-Pipelines (kontinuierliche Integration/kontinuierliche Bereitstellung).
Das ist ein typisches Beispiel dafür, wie wichtig die Testbarkeit von Code ist. Es ist schwierig oder unmöglich, Unit-Tests zu entwerfen, die jede Funktion erschöpfend validieren, wenn Ihr Code zu komplex ist oder zu viele eng gekoppelte Abhängigkeiten enthält.
Versionskontrollsysteme fördern die Konsistenz, die Qualitätskontrolle, die Koordination und die reviews-Prozesse zwischen den Teams. Wenn Sie KI-gestützte Codierungs-Frameworks verwenden – insbesondere solche, die Ihren Code autonom anpassen können – stellen Sie sicher, dass Sie eine Möglichkeit haben, unerwünschte oder ungünstige Änderungen leicht rückgängig zu machen. IBM Bob zum Beispiel versioniert Ihre Arbeitsflächendateien automatisch als Checkpoints , um eine einfache Rückführung von Codeänderungen bei Bedarf zu ermöglichen.
Generell lässt sich sagen, dass schlechter Code schwer lesbar und wartbar, anfällig für Änderungen und neue Funktionen, ineffizient und unzuverlässig ist. Es hat häufig unnötige Funktionen, bei denen verschiedene Module miteinander verflochten sind und jede Änderung an einem Modul zusätzlichen Aufwand erfordert, um das andere nicht zu beeinträchtigen. Es fehlt eine angemessene Dokumentation und er ist schlecht organisiert, ohne kohärente, logische Struktur, ein Zustand, der oft als "Spaghetti-Code"bezeichnet wird.
Schlechter Code ist oft nicht nur das Ergebnis schlechter Codierungsfähigkeiten, sondern auch von schlechten Anreizen und einer Organisationsstruktur: Überaggressives Priorisieren von Funktion-Launchs auf Kosten der Codequalität führt in der Regel zu schnelleren Markteintrittszeiten, aber zu größeren zukünftigen Komplikationen und technischen Schulden.
Man sollte sich vor Augen halten, dass schlechter Code oft funktioniert – zumindest vorübergehend. Wenn dies nicht der Fall wäre, würden sich die technischen Schulden nicht anhäufen, denn unbestreitbar fehlerhaften Code müssten behoben werden. Refactoring: Improving the Design of Existing Code, das wegweisende Buch von Martin Fowler und Kent Beck, das erstmals 1999 erschien (und seitdem viele Male aktualisiert wurde), verwendete daher den Begriff Code Smells, um schlechten Code zu beschreiben. Sie sind normalerweise keine Fehler und verhindern nicht automatisch die Funktionsfähigkeit eines Programms, aber sie weisen auf Designschwächen und Codequalitätsprobleme hin, die die Entwicklung verlangsamen oder in Zukunft Fehler verursachen könnten.
Die Liste der Code-Smells von Fowler und Beck, vor denen man sich hüten sollte, enthält Beispiele wie:
Lange Funktion (lange Methode): Eine Methode mit zu vielen Codezeilen.
Große Klasse: Eine Klasse, die versucht, zu viel zu tun, zu viele Variablen enthält und daher keinen Zusammenhalt aufweist.
Primitive Obsession: Verwendung primitiver Datentypen anstelle spezialisierter kleiner Objekte.
Mysteriöser Name: Funktionen oder Variablen sind schlecht benannt und verbergen ihre eigentliche Absicht.
Datenklumpen: Gruppen von Variablen, die häufig und überall zusammen auftreten.
Faule Elemente: Klassen oder Funktionen, die zu wenig bewirken, um zu existieren.
Lange Parameterliste: Funktionen, die zu viele Argumente erfordern, um korrekt zu funktionieren.
Shotgun-Operation: Eine Änderung erfordert die gleichzeitige Änderung vieler verstreuter Module (was im Wesentlichen das Gegenteil einer großen Klasse ist).
Duplizierter Code: Identische oder sehr ähnliche Codestrukturen an mehreren Stellen.
Eine umfassende Liste der Code-Gerüche, komplett mit Erklärungen, Beispielen und Zitaten, finden Sie hier. Ihr Vorhandensein ist in der Regel ein Zeichen dafür, dass eine Refaktorisierung erforderlich ist. Ein umfassendes, organisationsweites Verständnis dieser Probleme und der daraus resultierenden Komplikationen ist hilfreich, um ein gemeinsames Verständnis von Qualitätsstandards in den Entwicklungsteams zu etablieren.
Die Messung der Codequalität sollte stets sowohl eine qualitative als auch eine quantitative Bewertung umfassen. Objektive Metriken wie die zyklomatische Komplexität können zwar nützlich sein, aber ohne den richtigen Kontext können sie auch irreführend sein.
Zum Beispiel könnte Ihr Team eine automatisierte Suite schreiben und Ihr Code könnte in einer Reihe von Unit-Tests eine Codeabdeckung von 100% erreichen. Wenn es der Testsuite jedoch an einigen der aussagekräftigen Aussagen mangelt, die erforderlich sind, um wirklich zu bestätigen, dass Ihr Code vollständig wie gewünscht funktioniert, kann das falsche Vertrauen, das sich aus dieser Testabdeckung ergibt, mehr schaden als nutzen.
Ebenso sollte eine robuste Reviews-Struktur sowohl eine manuelle Code-Reviews als auch eine KI-Code-Reviews beinhalten. Ein modernes agentisches Codierungstool wie IBM Bob kann umfangreiche statische Codeanalysen und Refaktorisierungen in Echtzeit durchführen, profitiert jedoch stark von benutzerdefinierten Regeln und benutzerdefinierten Modi, die die spezifischen Bedürfnisse und Absichten des Entwicklers widerspiegeln. Der Mensch ist nicht erschöpfend und die KI nicht unfehlbar, aber die gegenseitige Unterstützung ist der sicherste Weg, um sicherzustellen, dass alle potenziellen Probleme mit dem richtigen Kontext untersucht wurden.
Denken Sie immer daran, dass die Codequalität vom Kontext abhängt. Stellen Sie sich vor, ein Programmierer in Ihrem Team hat einen eloquenten, effizienten, fehlerfrei artikulierten Algorithmus oder Codeblock geschrieben, der seine beabsichtigte Funktion sauber erfüllt. Wenn das Problem effektiv mit einer standardmäßigen, integrierten Bibliotheksfunktion hätte gelöst werden können, mit der jeder bereits vertraut ist, stellt dieser elegante Code eigentlich ein Qualitätsproblem dar, da er unnötige Komplexität und mentalen Mehraufwand mit sich bringt.
Beschleunigen Sie die Softwarebereitstellung mit Bob, Ihrem KI-Partner für sichere, absichtsorientierte Entwicklung.
Optimieren Sie die Softwareentwicklung mit vertrauenswürdigen KI-gestützten Tools, die den Zeitaufwand für das Schreiben von Code, Debuggen, Code-Refactoring oder Codevervollständigung minimieren und mehr Raum für Innovation schaffen.
Erfinden Sie kritische Workflows und Abläufe neu, indem Sie KI einsetzen, um Erfahrungen, Entscheidungsfindung in Echtzeit und den geschäftlichen Nutzen zu maximieren.
1. „ Code rot: Die geschäftlichen Auswirkungen der Codequalität – eine quantitative Studie von 39 proprietären Produktionscodebasen“, Proceedings of the International Konferenz on Technical Debt (abgerufen über die Association for Computing Machinery Digital Library), 16. August 2022
2. „Förderung besserer Codierungspraktiken für Data Scientists“, Harvard Data Science Review, 27. Juli 2023