In diesem Tutorial stellen wir Ihnen neun praktische Techniken zum Schreiben von elegantem und lesbarem Code vor. Wir sprechen nicht über bestimmte Architekturen, Sprachen oder Plattformen. Der Fokus liegt auf dem Schreiben von besserem Code. Lass uns anfangen.
"Das Messen des Programmierfortschritts anhand von Codezeilen gleicht dem Messen des Flugzeugbaus nach Gewicht." - Bill Gates
Wenn Sie Entwickler sind, hat es wahrscheinlich Zeiten gegeben, in denen Sie Code geschrieben haben. Nach einigen Tagen, Wochen oder Monaten haben Sie darauf zurückgesehen und zu sich selbst gesagt: "Was macht dieser Code?" Die Antwort auf diese Frage war möglicherweise "Ich weiß es wirklich nicht!" In diesem Fall können Sie nur den Code von Anfang bis Ende durchgehen und versuchen zu verstehen, was Sie gedacht haben, als Sie ihn geschrieben haben.
Dies geschieht meistens, wenn wir faul sind und nur die neue Funktion implementieren möchten, nach der der Kunde gefragt hat. Wir möchten die Arbeit einfach mit so wenig Aufwand wie möglich erledigen. Und wenn es funktioniert, interessiert uns der Code selbst nicht, da der Client den Code niemals sehen wird hässlich Wahrheit, ganz zu schweigen davon. Recht? Falsch. Heutzutage ist die Zusammenarbeit mit Software die Standardeinstellung, und die Benutzer werden den von Ihnen geschriebenen Code sehen, lesen und prüfen. Auch wenn Ihr Code nicht von Ihren Kollegen geprüft wird, sollten Sie es sich zur Gewohnheit machen, klaren und lesbaren Code zu schreiben. Immer.
Die meiste Zeit arbeiten Sie nicht alleine an einem Projekt. Häufig sehen wir hässlichen Code mit Variablen mit Namen wie ich
, ein
, p
, Profi
, und rqs
. Und wenn es wirklich schlecht wird, ist dieses Muster im gesamten Projekt sichtbar. Wenn Ihnen das bekannt vorkommt, bin ich mir ziemlich sicher, dass Sie sich die Frage gestellt haben: "Wie kann diese Person Code wie diesen schreiben?" Das macht Sie natürlich umso dankbarer, wenn Sie auf klaren, lesbaren und sogar schönen Code stoßen. Klarer und sauberer Code kann in Sekunden gelesen werden und kann Ihnen und Ihren Kollegen viel Zeit sparen. Das sollte Ihre Motivation sein, Qualitätscode zu schreiben.
Wir sind uns alle einig, dass Code leicht verständlich sein sollte. Recht? Das erste Beispiel konzentriert sich auf den Abstand. Schauen wir uns zwei Beispiele an.
Geschlecht zurückgeben == "1"? Gewicht * (Höhe / 10): Gewicht * (Höhe * 10);
if (gender == "1") return weight * (height / 10); else Gewicht zurückgeben * (Höhe * 10);
Obwohl das Ergebnis dieser Beispiele identisch ist, sehen sie recht unterschiedlich aus. Warum sollten Sie mehr Codezeilen verwenden, wenn Sie weniger schreiben können? Lassen Sie uns zwei weitere Beispiele untersuchen.
für (Knoten * Knoten = Liste-> Kopf; Knoten! = NULL; Knoten = Knoten-> Nächste) print (Knoten-> Daten);
Knoten * Knoten = Liste-> Kopf; if (node == NULL) return; while (node-> next! = NULL) Print (node-> data); Knoten = Knoten-> Nächste; if (Knoten! = NULL) Drucken (Knoten-> Daten);
Das Ergebnis dieser Beispiele ist wiederum identisch. Welcher ist besser? Und warum? Bedeuten weniger Codezeilen einen besseren Code? Wir werden diese Frage später in diesem Tutorial noch einmal besprechen.
In der Informatik hört man oft den Satz "Weniger ist mehr". Im Allgemeinen ist es besser, wenn Sie ein Problem in weniger Codezeilen lösen können. Sie benötigen wahrscheinlich weniger Zeit, um eine 200-Zeilen-Klasse zu verstehen als eine 500-Zeilen-Klasse. Stimmt das aber immer? Sehen Sie sich die folgenden Beispiele an.
Reservierung ((! room = FindRoom (room_id))) || ! room-> isOccupied ());
room = FindRoom (room_id); if (room! = NULL) Reservierung (! room-> isOccupied ());
Stimmen Sie nicht zu, dass das zweite Beispiel einfacher zu lesen und zu verstehen ist?? Sie müssen die Lesbarkeit optimieren können. Natürlich könnten Sie dem ersten Beispiel ein paar Kommentare hinzufügen, um das Verständnis zu erleichtern, aber ist es nicht besser, die Kommentare wegzulassen und Code zu schreiben, der leichter zu lesen und zu verstehen ist?
// Bestimmen Sie, wo das Monster entlang der Y-Achse erscheinen soll CGSize winSize = [CCDirector sharedDirector] .winSize; int minY = Monster.contentSize.width / 2; int maxY = winSize.width - monster.contentSize.width / 2; int rangeY = maxY - minY; int actualY = (arc4random ()% rangeY) + minY;
Das Beschreiben von beschreibenden Namen für Dinge wie Variablen und Funktionen ist ein Schlüsselaspekt beim Schreiben von lesbarem Code. Es hilft Ihren Kollegen und sich selbst, den Code schnell zu verstehen. Eine Variable benennen tmp
sagt Ihnen nichts anderes, als dass die Variable aus irgendeinem Grund temporär ist, was nichts anderes als eine fundierte Vermutung ist. Es wird nicht angezeigt, ob die Variable einen Namen, ein Datum usw. enthält.
Ein weiteres gutes Beispiel ist die Benennung einer Methode halt
. Es ist kein schlechter Name an sich, aber das hängt wirklich von der Implementierung der Methode ab. Wenn ein gefährlicher Vorgang ausgeführt wird, der nicht rückgängig gemacht werden kann, möchten Sie ihn möglicherweise umbenennen töten
oder Pause
Wenn der Vorgang fortgesetzt werden kann. Verstehst du die Idee??
Wenn Sie mit einer Variablen für das Gewicht von Kartoffeln arbeiten, warum sollten Sie sie nennen? tmp
? Wenn Sie diesen Code ein paar Tage später erneut aufrufen, können Sie sich nicht mehr an das erinnern tmp
wird für verwendet.
Wir sagen das nicht tmp
ist ein falscher Name für eine Variable, weil es Zeiten gibt, wann tmp
ist als Variablenname durchaus sinnvoll. Schauen Sie sich das folgende Beispiel an tmp
ist überhaupt keine schlechte Wahl.
tmp = first_potato; first_potato = second_potato; second_potato = tmp;
Im obigen Beispiel, tmp
beschreibt, was es tut, es speichert temporär einen Wert. Es wird nicht an eine Funktion oder Methode übergeben und nicht inkrementiert oder geändert. Es hat eine genau definierte Lebensdauer und kein erfahrener Entwickler wird durch den Namen der Variablen abgelehnt. Manchmal ist es jedoch einfach nur Faulheit. Schauen Sie sich das nächste Beispiel an.
NSString * tmp = user.name; tmp + = "" + user.phone_number; tmp + = "" + user.email;… [Vorlage setObject: tmp forKey: @ "user_info"];
Ob tmp
speichert die Informationen des Benutzers, warum nicht benannt Benutzerinformation
? Die korrekte Benennung von Variablen, Funktionen, Methoden, Klassen usw. ist beim Schreiben von lesbarem Code wichtig. Dadurch wird Ihr Code nicht nur lesbarer, Sie sparen auch in Zukunft Zeit.
Wie wir im vorherigen Tipp gesehen haben, ist es wichtig, Namen mit Bedacht zu wählen. Es ist jedoch ebenso wichtig, den Namen, die Sie für Variablen, Funktionen, Methoden usw. verwenden, eine Bedeutung zu verleihen. Dies hilft nicht nur, Verwirrung zu vermeiden, sondern auch den Code, den Sie schreiben, verständlicher zu machen. Einen sinnvollen Namen zu wählen, ist fast wie das Hinzufügen von Metadaten zu einer Variablen oder Methode. Wählen Sie beschreibende Namen und vermeiden Sie generische. Das Wort hinzufügen
, Zum Beispiel ist dies nicht immer ideal, wie Sie im nächsten Beispiel sehen können.
bool addUser (Benutzer u) …
Es ist nicht klar was Nutzer hinzufügen
soll es tun. Fügt es einen Benutzer zu einer Liste von Benutzern, zu einer Datenbank oder zu einer Liste von Personen hinzu, die zu einer Party eingeladen werden? Vergleichen Sie das mit registerUser
oder signupUser
. Das macht mehr Sinn. Recht? Werfen Sie einen Blick auf die folgende Auflistung, um eine bessere Vorstellung davon zu bekommen, was wir fahren.
Wort | Synonyme | tun | machen, durchführen, ausführen, komponieren, hinzufügen | Start | starten, erstellen, beginnen, öffnen | explodieren | detonieren, sprengen, loslegen, platzen |
Viele Programmierer mögen keine langen Namen, weil sie schwer zu merken sind und schwer zu tippen sind. Natürlich sollte ein Name nicht lächerlich lang sein newClassForNavigationControllerNamedFirstViewController
. Diese ist schwer zu merken und macht Ihren Code einfach hässlich und unlesbar.
Wie wir zuvor gesehen haben, sind auch die entgegengesetzten, kurzen Namen nicht gut. Was ist die richtige Größe für einen Variablen- oder Methodennamen? Wie entscheiden Sie sich für die Benennung einer Variablen? len
, Länge
, oder Benutzername_Länge
? Die Antwort hängt vom Kontext und der Entität ab, an die der Name gebunden ist.
Lange Namen sind bei der Verwendung einer modernen IDE (Integrated Development Environment) kein Problem mehr. Die Vervollständigung des Codes hilft Ihnen, Tippfehler zu vermeiden, und er gibt auch Vorschläge, um das Erinnern an Namen zu erleichtern.
Sie können kurze (er) Namen verwenden, wenn die Variable lokal ist. Außerdem wird empfohlen, für lokale Variablen kürzere Namen zu verwenden, damit der Code lesbar bleibt. Schauen Sie sich das folgende Beispiel an.
NSString * link = [[NSString-Zuordnung] initWithFormat: @ "http: // localhost: 8080 / WrittingGoodCode / resources / GoodCode / getGoodCode /% @", idCode]; NSURL * infoCode = [NSURL URLWithString: link];
Boolesche Namen können schwierig zu benennen sein, da sie je nach Art und Weise, wie Sie den Namen lesen oder interpretieren, eine andere Bedeutung haben können. Im nächsten Codeausschnitt, read_password
kann bedeuten, dass das Passwort vom Programm gelesen wurde, es kann jedoch auch bedeuten, dass das Programm das Passwort lesen soll.
BOOL readPassword = YES;
Um dieses Problem zu vermeiden, können Sie den obigen Boolean in umbenennen didReadPassword
um anzuzeigen, dass das Passwort gelesen wurde oder sollteReadPassword
um anzuzeigen, dass das Programm das Passwort lesen muss. Dies ist beispielsweise in Objective-C häufig zu sehen.
Das Hinzufügen von Kommentaren zu Code ist wichtig, aber es ist ebenso wichtig, sie sparsam einzusetzen. Sie sollten verwendet werden, um jemandem zu helfen, Ihren Code zu verstehen. Das Lesen von Kommentaren ist jedoch auch zeitaufwändig. Wenn ein Kommentar keinen großen Wert hinzufügt, wird diese Zeit verschwendet. Das nächste Code-Snippet zeigt, wie nicht Kommentare verwenden.
// Dies geschieht, wenn eine Speicherwarnung empfangen wird - (void) didReceiveMemoryWarning [super didReceiveMemoryWarning]; // Entsorgen Sie alle Ressourcen, die neu erstellt werden können. // Dies validiert die Felder - (BOOL) validateFields
Sind diese Codeausschnitte hilfreich für Sie? Die Antwort lautet wahrscheinlich "Nein". Die Kommentare in den obigen Beispielen fügen keine zusätzlichen Informationen hinzu, zumal die Methodennamen bereits sehr deskriptiv sind. Fügen Sie keine Kommentare hinzu, die das Offensichtliche erklären. Schauen Sie sich das nächste Beispiel an. Ist dies nicht eine viel bessere Verwendung von Kommentaren??
// Geschwindigkeit des Monsters bestimmen int minDuration = 2.0; int maxDuration = 8,0; int rangeDuration = maxDuration - minDuration; int actualDuration = (arc4random ()% rangeDuration) + minDuration;
Kommentare wie diese machen es sehr einfach, schnell und effizient durch eine Codebasis zu navigieren. Es erspart Ihnen das Lesen des Codes und hilft Ihnen, die Logik oder den Algorithmus zu verstehen.
Jede Sprache oder Plattform hat einen (oder mehr) Style Guide und sogar die meisten Unternehmen haben einen. Setzen Sie die geschweiften Klammern einer Objective-C-Methode in eine separate Zeile oder nicht?
- (ungültig) berechneOffset
- (ungültig) berechneOffset
Die Antwort ist, dass es keine Rolle spielt. Es gibt keine richtige Antwort. Natürlich gibt es Style-Guides, die Sie übernehmen können. Wichtig ist, dass Ihr Code stilistisch konsistent ist. Auch wenn sich dies nicht auf die Qualität Ihres Codes auswirkt, wirkt sich dies zweifellos auf die Lesbarkeit aus, und es wird höchstwahrscheinlich die Hölle Ihrer Kollegen oder der Person, die Ihren Code liest, ärgern. Für die meisten Entwickler ist hässlicher Code die schlechteste Art von Code.
Ein häufiger Fehler unter den Entwicklern besteht darin, möglichst viele Funktionen in Funktionen und Methoden zu packen. Das funktioniert, aber es ist unelegant und macht das Debuggen zu einem Schmerz im Nacken. Ihr Leben - und das Ihrer Kollegen - wird sehr viel einfacher, wenn Sie größere Probleme in winzige Bits zerlegen und diese Bits in separaten Funktionen oder Methoden behandeln. Schauen Sie sich das nächste Beispiel an, in dem wir ein Image auf die Festplatte schreiben. Dies scheint eine triviale Aufgabe zu sein, aber es gibt noch viel mehr, wenn Sie es richtig machen wollen.
- (BOOL) saveToImage: (UIImage *) Bild mit Dateiname: (NSString *) Dateiname BOOL Ergebnis = NEIN; NSString * Dokumente = Null; NSArray * pfade = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES); if (paths.count) Dokumente = [Pfade objectAtIndex: 0]; NSString * basePath = [Dokumente stringByAppendingPathComponent: @ "Archiv"]; if (! [[NSFileManager defaultManager] fileExistsAtPath: basePath]) NSError * error = nil; [[NSFileManager defaultManager] createDirectoryAtPath: basePath withIntermediateDirectories: YES-Attribute: keine Fehler: & Fehler]; if (! error) NSString * filePath = [basePath stringByAppendingPathComponent: Dateiname]; result = [UIImageJPEGRepresentation (image, 8.0) writeToFile: filePath atomisch: YES]; else NSLog (@ "Verzeichnis konnte wegen Fehler% @ mit Benutzerinfo% @ nicht erstellt werden.", Fehler, error.userInfo); Ergebnis zurückgeben;
Wenn eine Codeeinheit versucht, zu viel zu tun, landen oft tief verschachtelte Bedingungsanweisungen, viele Fehlerprüfungen und zu komplexe Bedingungsanweisungen. Diese Methode führt drei Schritte aus. Rufen Sie den Pfad des Dokumentenverzeichnisses der Anwendung ab, rufen Sie den Pfad für das Archivverzeichnis ab und erstellen Sie das Verzeichnis, und schreiben Sie das Image auf die Festplatte. Jede Aufgabe kann in eine eigene Methode gestellt werden, wie unten gezeigt.
- (BOOL) saveToImage: (UIImage *) Bild mit Dateiname: (NSString *) fileName NSString * archivesDirectory = [self applicationArchivesDirectory]; if (! archivesDirectory) NEIN zurückgeben; // Pfad erstellen NSString * filePath = [archivesDirectory stringByAppendingPathComponent: Dateiname]; // Image auf Platte schreiben return return [UIImageJPEGRepresentation (image, 8.0) writeToFile: filePath atomisch: YES];
- (NSString *) applicationDocumentsDirectory NSArray * pfade = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES); Pfadangaben zurückschicken? [pfade objectAtIndex: 0]: nil;
- (NSString *) applicationArchivesDirectory NSString * documentsDirectory = [self applicationDocumentsDirectory]; NSString * archivesDirectory = [documentsDirectory stringByAppendingPathComponent: @ "Archives"]; NSFileManager * fm = [NSFileManager defaultManager]; if (! [fm fileExistsAtPath: archivesDirectory]) NSError * error = nil; [fm createDirectoryAtPath: archivesDirectory withIntermediateDirectories: YES-Attribute: keine Fehler: & Fehler]; if (error) NSLog (@ "Verzeichnis kann wegen Fehler% @ mit Benutzerinfo% @ nicht erstellt werden.", Fehler, error.userInfo); Rückkehr Null; return archivesDirectory;
Dies ist viel einfacher zu debuggen und zu warten. Sie können das sogar wiederverwenden applicationDocumentsDirectory
Methode an anderen Stellen des Projekts. Dies ist ein weiterer Vorteil, wenn größere Probleme in überschaubare Teile zerlegt werden. Das Testen von Code wird auch viel einfacher.
In diesem Artikel haben wir uns näher mit dem Schreiben von lesbarem Code befasst, indem wir Namen für Variablen, Funktionen und Methoden weise auswählen, beim Schreiben von Code konsistent sind und komplexe Probleme in überschaubare Abschnitte unterteilen. Wenn Sie Fragen oder Anregungen haben, können Sie unten einen Kommentar hinterlassen.