Ihr Code kann riechen! Wie man es repariert
EIN Codegeruch ist ein Teil des Codes oder eines allgemeinen Codierungsmusters, das so aussieht, als könnte dies auf ein tieferes Problem in der Gesamtstruktur und im Design einer Codebase hinweisen.
Stellen Sie sich einen Codegeruch als ein Zeichen vor, das darauf hindeutet, dass ein Codeabschnitt überarbeitet werden sollte. Es ist nicht so, dass der Code fehlerhaft oder nicht funktionsfähig ist - oft läuft der stinkende Code einwandfrei -, aber stinkender Code ist oft schwer zu warten und zu erweitern, was zu technischen Problemen führen kann (insbesondere bei größeren Projekten)..
In diesem Artikel werden 10 der häufigsten Code-Gerüche hervorgehoben, worauf zu achten ist und wie man sie desodoriert. Wenn Sie ein neuer Programmierer sind Wie man das Programmieren ohne all den Stress lernt Wie man das Programmieren ohne all den Stress lernt Vielleicht haben Sie sich entschieden, das Programmieren zu beginnen, ob für eine Karriere oder nur als Hobby. Großartig! Aber vielleicht fangen Sie an, sich überfordert zu fühlen. Nicht so toll. Hier finden Sie Hilfe, um Ihre Reise zu erleichtern. Lesen Sie mehr, vermeiden Sie diese und Ihr Code wird spürbar besser!
1. Enge Kupplung
Das Problem
Enge Kopplung ist, wenn zwei Objekte so stark von den Daten und / oder Funktionen eines anderen abhängig sind, dass das Ändern eines Objekts das Ändern des anderen erfordert. Wenn zwei Objekte zu eng miteinander gekoppelt sind, kann das Ändern von Code ein Alptraum sein, und es ist wahrscheinlicher, dass bei jeder Änderung Fehler auftreten.
Zum Beispiel:
Klasse Worker Fahrrad Fahrrad = neues Fahrrad (); public void commute () bike.drive ();
In diesem Fall sind Worker und Bike eng miteinander verbunden. Was wäre, wenn Sie eines Tages für Ihr Pendeln ein Auto anstatt eines Fahrrads fahren wollten? Sie müssen in die Worker-Klasse gehen und den gesamten Code für das Fahrrad durch den Code für das Auto ersetzen. Es ist unordentlich und fehleranfällig.
Die Lösung
Sie können die Kopplung lösen, indem Sie eine Abstraktionsebene hinzufügen. In diesem Fall möchte die Worker-Klasse nicht nur Fahrräder fahren, sondern auch Autos und möglicherweise Lastwagen, möglicherweise sogar Roller. Das sind alles Fahrzeuge, nicht wahr? Erstellen Sie also eine Fahrzeugschnittstelle, mit der Sie verschiedene Fahrzeugtypen nach Belieben einfügen und ersetzen können:
Klasse Worker Fahrzeug Fahrzeug; public void changeVehicle (Fahrzeug v) Fahrzeug = v; public void commute () vehicle.drive (); Schnittstelle Vehicle void drive (); Klasse Fahrrad implementiert Fahrzeug public void drive () Klasse Fahrzeug implementiert Fahrzeug public void drive ()
2. Gottesgegenstände
Das Problem
Ein Gott-Objekt ist eine massive Klasse / Modul, die zu viele Variablen und Funktionen enthält. Es “weiß zu viel” und “macht zu viel,” Das ist aus zwei Gründen problematisch. Erstens sind andere Klassen / Module für die Daten zu stark abhängig (enge Kopplung). Zweitens wird die Gesamtstruktur des Programms matschig, da sich alles an derselben Stelle befindet.
Die Lösung
Nehmen Sie ein Gottobjekt, trennen Sie seine Daten und Funktionen nach den Problemen, die es zu lösen gibt, und verwandeln Sie diese Gruppierungen in Objekte. Wenn Sie ein Gottobjekt haben, ist es möglicherweise besser, wenn Sie aus vielen kleineren Objekten bestehen.
Angenommen, Sie haben eine monströse Benutzerklasse:
Klasse Benutzer public String Benutzername; öffentliches String-Passwort; öffentliche String-Adresse; öffentliche String-Postleitzahl; public int age;… public String getUsername () return username; public void setUsername (String u) Benutzername = u;
Sie können es in eine Komposition der folgenden konvertieren:
Klasse Benutzer Berechtigungsnachweise; Profilprofil;… Klasse Berechtigungsnachweise public String Benutzername; public String password;… public String getUsername () Benutzername zurückgeben; public void setUsername (String u) Benutzername = u;
Wenn Sie das nächste Mal Anmeldeprozeduren ändern müssen, müssen Sie nicht durch eine umfangreiche Benutzerklasse crawlen, da die Credentials-Klasse leichter zu verwalten ist!
3. Lange Funktionen
Das Problem
Eine lange Funktion ist genau das, was sie sich anhört: eine zu lange gewachsene Funktion. Es gibt zwar keine spezifische Anzahl für die Anzahl der Codezeilen “zu lang” Für eine Funktion ist dies eines der Dinge, bei denen Sie es kennen, wenn Sie es sehen. Es ist eine ziemlich engere Version des God-Objekt-Problems - eine lange Funktion hat zu viele Verantwortlichkeiten.
Die Lösung
Lange Funktionen sollten in viele Unterfunktionen unterteilt werden, wobei jede Unterfunktion dazu bestimmt ist, eine einzelne Aufgabe oder ein Problem zu behandeln. Im Idealfall wird aus der ursprünglichen langen Funktion eine Liste von Unterfunktionsaufrufen, die den Code sauberer und lesbarer machen.
4. Übermäßige Parameter
Das Problem
Eine Funktion (oder ein Klassenkonstruktor), die zu viele Parameter erfordert, ist aus zwei Gründen problematisch. Erstens macht es den Code weniger lesbar und erschwert den Test. Zweitens, und was noch wichtiger ist, kann dies darauf hinweisen, dass der Zweck der Funktion zu vieldeutig ist und versucht, zu viele Verantwortlichkeiten zu bewältigen.
Die Lösung
Während “zu viele” Da es für eine Parameterliste subjektiv ist, empfehlen wir, auf Funktionen zu achten, die mehr als 3 Parameter haben. Sicher, manchmal macht es Sinn, eine einzige Funktion mit 5 oder sogar 6 Parametern zu haben, aber nur, wenn es einen wirklich guten Grund dafür gibt.
Meistens gibt es keine, und der Code wäre besser, diese Funktion in zwei oder mehr verschiedene Funktionen aufzuteilen. nicht so wie “Lange Funktionen” Code-Geruch, dieser kann nicht durch das Ersetzen von Code durch Unterfunktionen gelöst werden. Die Funktion selbst muss in separate Funktionen aufgeteilt werden, die unterschiedliche Verantwortlichkeiten abdecken.
5. schlecht benannte Bezeichner
Das Problem
Ein-oder Zwei-Buchstaben-Variablennamen. Nicht-beschreibende Funktionsnamen. Übermäßig verzierte Klassennamen. Markieren von Variablennamen mit ihrem Typ (z. B. b_isCounted für eine boolesche Variable). Und am schlimmsten ist das Mischen verschiedener Namensschemata in einer einzigen Codebasis. All dies führt zu schwer lesbarem, schwer verständlichem und zu wartendem Code.
Die Lösung
Die Auswahl guter Namen für Variablen, Funktionen und Klassen ist eine schwer erlernte Fähigkeit. Wenn Sie sich einem bestehenden Projekt anschließen, durchforsten Sie es und sehen Sie, wie vorhandene Bezeichner benannt werden. Wenn es einen Style Guide gibt, merken Sie sich diesen und halten Sie sich daran. Erwägen Sie bei neuen Projekten, Ihren eigenen Style Guide zu erstellen, und halten Sie sich daran.
Im Allgemeinen sollten Variablennamen kurz, aber beschreibend sein. Funktionsnamen sollten in der Regel mindestens ein Verb haben, und es sollte sofort ersichtlich sein, was die Funktion nur aus ihrem Namen bewirkt. Vermeiden Sie jedoch, dass Sie zu viele Wörter blockieren. Gleiches gilt für Klassennamen.
6. Magische Zahlen
Das Problem
Sie stöbern durch einen Code, den (hoffentlich) jemand anderes geschrieben hat, und Sie erkennen hartcodierte Zahlen. Vielleicht sind sie Teil eines if-Statements oder vielleicht Teil arkaner Berechnungen, die nicht sinnvoll erscheinen. Sie müssen die Funktion ändern, aber Sie können einfach nicht verstehen, was die Zahlen bedeuten. Stichwortkopf kratzt.
Die Lösung
Beim Schreiben von Code werden diese sogenannten “magische Zahlen” sollte unter allen Umständen vermieden werden. Festcodierte Zahlen sind zu dem Zeitpunkt sinnvoll, zu dem sie geschrieben werden. Sie können jedoch schnell die Bedeutung verlieren, insbesondere wenn jemand anderes versucht, Ihren Code zu erhalten.
Eine Lösung besteht darin, Kommentare zu hinterlassen, die die Zahl erklären, aber die bessere Option ist die Umwandlung von Zahlen in konstante Variablen (für Berechnungen) oder Aufzählungen (für bedingte Anweisungen und Schalteranweisungen). Durch die Benennung von magischen Zahlen wird der Code auf einen Blick unendlich lesbarer und weniger anfällig für fehlerhafte Änderungen.
7. Deep Nesting
Das Problem
Es gibt zwei Hauptmöglichkeiten, um tief verschachtelten Code zu erhalten: Schleifen und bedingte Anweisungen. Tiefverschachtelter Code ist nicht immer schlecht, kann jedoch problematisch sein, da er schwer zu analysieren ist (insbesondere, wenn Variablen nicht gut benannt sind), und dass sie sogar noch schwieriger zu ändern ist.
Die Lösung
Wenn Sie feststellen, dass Sie eine doppelte, dreifache oder sogar vierfache for-Schleife schreiben, versucht Ihr Code möglicherweise, zu weit außerhalb von sich selbst zu sein, um Daten zu finden. Geben Sie stattdessen die Möglichkeit an, die Daten über einen Funktionsaufruf für das Objekt oder das Modul anzufordern, das die Daten enthält.
Andererseits sind tief verschachtelte Bedingungsanweisungen oft ein Zeichen dafür, dass Sie versuchen, zu viel Logik in einer einzelnen Funktion oder Klasse zu behandeln. Tatsächlich neigen tiefe Verschachtelungen und lange Funktionen dazu, Hand in Hand zu gehen. Wenn Ihr Code über umfangreiche switch-Anweisungen oder verschachtelte if-then-else-Anweisungen verfügt, können Sie stattdessen ein Zustandsmaschinen- oder Strategiemuster implementieren.
Tiefe Schachtelung ist besonders bei unerfahrenen Spielprogrammierern weit verbreitet. 5 Freie Spielentwicklungssoftware-Tools zum Erstellen eigener Spiele 5 Kostenlose Spieleentwicklungssoftware-Tools zum Erstellen eigener Spiele Hier sind die besten kostenlosen Spieleentwicklungssoftware und -werkzeuge, mit denen Sie Ihr Traumspiel erstellen können heute. Weiterlesen !
8. Nicht behandelte Ausnahmen
Das Problem
Ausnahmen sind mächtig, werden aber leicht missbraucht. Faule Programmierer, die falsch-werfen-Anweisungen verwenden, können das Debuggen exponentiell erschweren, wenn nicht unmöglich. Zum Beispiel das Ignorieren oder Begraben gefangener Ausnahmen.
Die Lösung
Anstatt gefangene Ausnahmen zu ignorieren oder zu begraben, sollten Sie mindestens die Stack-Ablaufverfolgung der Ausnahme ausdrucken, sodass Debugger etwas zu tun haben. Wenn Ihr Programm ohne Fehler ausfällt, ist dies ein Rezept für zukünftige Kopfschmerzen, garantiert! Ziehen Sie auch bestimmte Ausnahmen gegenüber allgemeinen Ausnahmen vor. Weitere Informationen finden Sie in unserem Artikel zum richtigen Umgang mit Ausnahmen. Wie man Java-Ausnahmen richtig behandelt. Wie man Java-Ausnahmen richtig behandelt. In diesem Artikel erfahren Sie, was Java-Ausnahmen sind, warum sie wichtig sind und wie Verwenden Sie sie und vermeiden Sie häufige Fehler. Weiterlesen .
9. Doppelter Code
Das Problem
Sie führen dieselbe exakte Logik in mehreren nicht zusammenhängenden Bereichen Ihres Programms aus. Später stellen Sie fest, dass Sie diese Logik ändern müssen, erinnern Sie sich jedoch nicht an die Orte, an denen Sie sie implementiert haben. Am Ende ändern Sie nur 5 von 8 Stellen, was zu fehlerhaften und inkonsistenten Verhaltensweisen führt.
Die Lösung
Doppelter Code ist ein Hauptkandidat, um in eine Funktion umgewandelt zu werden. Angenommen, Sie entwickeln eine Chat-Anwendung und schreiben Folgendes:
String queryUsername = getSomeUsername (); boolean isUserOnline = false; for (String Benutzername: onlineUsers) if (Benutzername.equals (queryUsername)) isUserOnline = true; if (isUserOnline) …
An anderer Stelle im Code stellen Sie fest, dass Sie dasselbe tun müssen “Ist dieser Benutzer online??” prüfen. Anstatt die Schleife zu kopieren, können Sie sie in eine Funktion ziehen:
public boolean isUserOnline (String queryUsername) für (String Benutzername: OnlineUsers) if (Benutzername.equals (queryUsername)) return true; falsch zurückgeben;
Jetzt können Sie überall in Ihrem Code die isUserOnline () - Prüfung verwenden. Wenn Sie diese Logik jemals ändern müssen, können Sie die Methode anpassen und sie wird überall angewendet, wo sie aufgerufen wird.
10. Fehlende Kommentare
Das Problem
Der Code enthält keinerlei Kommentare. Keine Dokumentationsblöcke für Funktionen, keine Verwendungsübersichten für Klassen, keine Erklärungen zu Algorithmen usw. Man könnte argumentieren, dass gut geschriebener Code keine Kommentare benötigt, aber die Wahrheit ist, dass selbst der bestgeschriebene Code noch mehr mentale Energie erfordert verstehe als Englisch.
Die Lösung
Das Ziel einer einfach zu wartenden Codebase sollte Code sein, der so gut geschrieben ist, dass er nicht funktioniert brauchen Kommentare, hat sie aber immer noch. Achten Sie beim Schreiben von Kommentaren auf Kommentare, die erklären Warum Ein Code-Snippet existiert statt zu erklären Was es tut Kommentare sind gut für die Seele und den Verstand. Vernachlässige sie nicht.
Wie schreibe ich Code, der nicht riecht?
So offensichtlich es erscheinen mag, entstehen die meisten Codegerüche aus einem Missverständnis oder einer Vernachlässigung guter Programmierprinzipien und -muster. 10 Grundlegende Programmiergrundsätze Jeder Programmierer muss befolgen 10 Grundlegende Programmiergrundsätze Jeder Programmierer muss befolgen Schreiben Sie immer Code, der von jedem Programmierer gepflegt werden kann Arbeiten Sie an Ihrer Software. Zu diesem Zweck finden Sie hier einige Programmierprinzipien, die Ihnen beim Aufräumen helfen. Weiterlesen . Zum Beispiel eliminiert eine solide Einhaltung des DRY-Prinzips die meisten Code-Duplizierungen, während die Beherrschung des Single-Responsibility-Prinzips es nahezu unmöglich macht, monströse Gottobjekte zu schaffen.
Wir empfehlen auch, unseren Artikel zum Erstellen von Cleaner-Code zu lesen. 10 Tipps zum Schreiben von Cleaner & Better Code 10 Tipps zum Schreiben von Cleaner & Better Code Das Schreiben von sauberem Code ist zwar einfacher als er tatsächlich ist, aber die Vorteile sind es wert. So können Sie heute saubereren Code schreiben. Lesen Sie mehr, was eine praktischere Seite der Programmierung darstellt. Wenn Sie Ihren eigenen Code nicht lesen und auf einen Blick verstehen können, wie wird es dann noch jemandem geben? Sauberer Code ist geruchloser Code.
Womit kämpfen Sie am meisten, wenn es um das Programmieren geht? Teilen Sie uns unten in den Kommentaren mit!
Bild-Gutschrift: SIphotography / Depositphotos
Erfahren Sie mehr über: Programmierung.