5 einfach zu lesende Code-Regeln

Sie fragen sich: "Wie schreibe ich sauber und verständlich?" Wie kann man schnell den Code eines anderen herausfinden? "

Beachten Sie die folgenden Regeln und wenden Sie sie an!

In diesem Artikel werden die Grundregeln für die Benennung von Variablen und Funktionen, syntaktische Einrückungen und ein umfangreiches Refactoring-Thema nicht erläutert. Wir betrachten 5 einfache Regeln, um den Code zu vereinfachen und die Belastung des Gehirns während des Entwicklungsprozesses zu verringern.

Betrachten Sie den Prozess der Wahrnehmung von Daten, um die beschriebenen Regeln mit dem Wahrnehmungsprozess zu korrelieren, und bestimmen Sie die Kriterien für einen einfachen Code.

Der vereinfachte Wahrnehmungsprozess besteht aus folgenden Schritten:

  1. Die über die Rezeptoren empfangenen Daten stimmen mit früheren Erfahrungen überein.
  2. Wenn es keine Korrelation gibt, ist dies Rauschen. Das Geräusch ist schnell vergessen. Wenn es etwas gibt, auf das man sich beziehen kann, wird die Tatsache erkannt.
  3. Wenn die Tatsache wichtig ist - wir erinnern uns, verallgemeinern oder handeln zum Beispiel, sagen oder tippen wir den Code.
  4. Um die Menge der gespeicherten und analysierten Informationen zu reduzieren, wird eine Verallgemeinerung verwendet.
  5. Nach der Zusammenfassung werden die Informationen erneut korreliert und analysiert (Schritt 1).


Wissenschaftler teilen das Gedächtnis in kurzfristige und langfristige. Das Kurzzeitgedächtnis hat ein geringes Volumen, aber Informationen werden sofort extrahiert und gespeichert. Das Kurzzeitgedächtnis ist der Gehirn-Cache. Es kann 7 + -2 Wörter, Zahlen, Objekte speichern. Das Langzeitgedächtnis hat ein größeres Volumen, erfordert jedoch mehr Energie (Aufwand) zum Speichern und Abrufen von Informationen als das Kurzzeitgedächtnis.

Schlussfolgerungen:

  • Je weniger Elemente, desto weniger Energie wird verbraucht.
  • es ist erforderlich, die Anzahl der wahrgenommenen Elemente auf 9 zu reduzieren,
  • Verwenden Sie das Langzeitgedächtnis so wenig wie möglich: verallgemeinern oder vergessen.

Wir fahren mit der Beschreibung der Regeln fort.

Regel 1. Wir verwenden die Aussage in den Bedingungen, um das "nicht" loszuwerden.

Durch Entfernen des Operators "nicht" wird die Anzahl der zu analysierenden Elemente verringert. Außerdem wird in vielen Programmiersprachen ein "!" Für den Negationsoperator verwendet. Dieses Zeichen kann beim Lesen des Codes leicht übersprungen werden.

Vergleichen Sie:

if (!entity.IsImportAvaible) { // 1 } else { // 2 } 

Nachher:

 if (entity.IsImportAvaible) { // 2 } else { // 1 } 

Regel 2. Verringerung der Verschachtelung.

Während der Codeanalyse muss jede Verschachtelungsebene im Speicher gehalten werden. Reduzieren Sie die Anzahl der Ebenen - reduzieren Sie die Kraftstoffkosten.

Überlegen Sie, wie Sie die Anzahl der Verschachtelungsebenen verringern können.

1) Rücklaufkontrolle. Wir schneiden einige Fälle ab und konzentrieren uns auf die verbleibenden.

 if (conributor != null) { // } 

Konvertieren in

 if(contributor == null) { return; } // 

oder

 while( 1) { if( 2) { break; } // } 

oder

 for(; 1;) { if( 2) { continue; } // } 

Ein erweitertes Beispiel finden Sie in Regel 5. Beachten Sie das Auslösen einer Ausnahme.

2) Isolierung der Methode. Der Name der Funktion ist das Ergebnis der Verallgemeinerung.

 if( ) { foreach(var sender in senders) { sender.Send(message); } } 

in

 if( ) { SendAll(senders, message); } void SendAll(IEnumerable<Sender> senders, string message) { foreach(var sender in senders) { sender.Send(message); } } 

3) Kombinationsbedingungen.

 if (contributor == null) { if (accessMngr == null) { // } } 

in

 if (contributor == null && accessMngr == null) { // } 

4) Variablen entfernen und in semantische Blöcke unterteilen. Infolgedessen können Blöcke unabhängig voneinander geändert werden, und vor allem ist das Lesen und Verstehen eines solchen Codes viel einfacher. Ein Block - eine Funktionalität. Ein häufiger Fall ist eine Suche mit Verarbeitung. Der Code muss in separate semantische Blöcke unterteilt werden: Elementsuche, Verarbeitung.

 for (int i=0;i<array.length;i++) { if (array[i] == findItem) { // array[i] break; } } 

in

 for(int i=0;i<array.length;i++) { if(array[i] == findItem) { foundItem =array[i]; break; } } if (foundItem != null) { // foundItem } 

Regel 3. Wir werden Indexer und Aufrufe über Eigenschaften los.

Indexer - Der Vorgang des Zugriffs auf ein Element eines Arrays am Index arr [index].

Bei der Wahrnehmung des Codes arbeitet das Gehirn mit den Symbolen [] als Begrenzer und dem Indexer als Ausdruck.

 function updateActiveColumnsSetting(fieldsGroups) { var result = {}; for (var i = 0; i < fieldsGroups.length; i++) { var fields = fieldsGroups[i].fields; for (var j = 0; j < fields.length; j++) { if (!result[fieldsGroups[i].groupName]) { result[fieldsGroups[j].groupName] = {}; } result[fieldsGroups[i].groupName][fields[j].field] = createColumnAttributes(j, fields[j].isActive); } } return JSON.stringify(result); } 

Ein Indexer ist ein Ort häufiger Fehler. Aufgrund kurzer Indexnamen ist es sehr einfach, I, j oder k zu verwechseln.

Im obigen Beispiel in der Zeile result [fieldsGroups [j] .groupName] = {}; Fehler gemacht:
j wird anstelle von i verwendet.

Um herauszufinden, wo genau der i-te Wert verwendet wird, müssen Sie:

1) Markieren Sie eine Array-Variable visuell

 function updateActiveColumnsSetting(fieldsGroups) { var result = {}; for (var i = 0; i < fieldsGroups.length; i++) { var fields = fieldsGroups[i].fields; for (var j = 0; j < fields.length; j++) { if (!result[fieldsGroups[i].groupName]) { result[fieldsGroups[j].groupName] = {}; } result[fieldsGroups[i].groupName][fields[j].field] = createColumnAttributes(j, fields[j].isActive); } } return JSON.stringify(result); } 

2) jedes Vorkommen auf die Verwendung des gewünschten Indexers I, j, i-1, j-1 usw. zu analysieren, wobei die Verwendungsorte der Indexer und bereits identifizierte Referenzen in der Wahrnehmung zu berücksichtigen sind.
Durch Hervorheben des Indexers in einer Variablen reduzieren wir die Anzahl gefährlicher Stellen und können das Gehirn leicht verwenden, um die Variable wahrzunehmen, ohne dass es auswendig gelernt werden muss.

Nach der Verarbeitung:

 function updateActiveColumnsSetting(fieldsGroups) { var columnsGroups = {}; for (var i = 0; i < fieldsGroups.length; i++) { var fieldsGroup = fieldsGroups[i]; var groupName = fieldsGroup.groupName; var columnsGroup = columnsGroups[groupName]; if (!columnsGroup) { columnsGroup = columnsGroups[groupName] = {}; } var fields = fieldsGroup.fields; for (var j = 0; j < fields.length; j++) { var fieldInfo = fields[j]; columnsGroup[fieldInfo.field] = createColumnAttributes(j, field.isActive); } } return columnsGroups; } 

Die visuelle Auswahl ist viel einfacher, und moderne Entwicklungsumgebungen und Editoren helfen dabei, Teilzeichenfolgen in verschiedenen Teilen des Codes hervorzuheben.

 function updateActiveColumnsSetting(fieldsGroups) { var columnsGroups = {}; for (var i = 0; i < fieldsGroups.length; i++) { var fieldsGroup = fieldsGroups[i]; var groupName = fieldsGroup.groupName; var columnsGroup = columnsGroups[groupName]; if (!columnsGroup) { columnsGroup = columnsGroups[groupName] = {}; } var fields = fieldsGroup.fields; for (var j = 0; j < fields.length; j++) { var fieldInfo = fields[j]; columnsGroup[fieldInfo.field] = createColumnAttributes(j, field.isActive); } } return columnsGroups; } 

Regel 4. Gruppieren Sie die Blöcke nach der Bedeutung.

Wir nutzen den psychologischen Effekt der Wahrnehmung - „den Effekt der Nähe“: eng beieinander liegende Figuren in der Wahrnehmung werden kombiniert. Um den Code für die Analyse und Verallgemeinerung im Wahrnehmungsprozess vorzubereiten und die Menge der im Speicher gespeicherten Informationen zu verringern, können Sie eine Zeile nebeneinander anordnen, die durch Bedeutung vereint oder in ihrer Funktionalität geschlossen ist, und sie durch eine leere Zeile teilen.

An:

 foreach(var abcFactInfo in abcFactInfos) { var currentFact = abcInfoManager.GetFact(abcFactInfo); var percentage = GetPercentage(summaryFact, currentFact); abcInfoManager.SetPercentage(abcFactInfo, percentage); accumPercentage += percentage; abcInfoManager.SetAccumulatedPercentage(abcFactInfo, accumPercentage); var category = GetAbcCategory(accumPercentage, categoryDictionary); abcInfoManager.SetCategory(abcFactInfo, category); } 

Nachher:

 foreach (var abcFactInfo in abcFactInfos) { var currentFact = abcInfoManager.GetFact (abcFactInfo); var percentage = GetPercentage(summaryFact, currentFact); accumPercentage += percentage; var category = GetAbcCategory(accumPercentage, categoryDictionary); abcInfoManager.SetPercentage(abcFactInfo, percentage); abcInfoManager.SetAccumulatedPercentage(abcFactInfo, accumPercentage); abcInfoManager.SetCategory(abcFactInfo, category); } 

Im oberen Beispiel gibt es 7 Blöcke, in den unteren 3: Werte abrufen, in einer Schleife akkumulieren, Manager-Eigenschaften festlegen.

Einrückung ist gut, um Orte zu identifizieren, die es wert sind, beachtet zu werden. Also die Zeilen

 accumPercentage += percentage; var category = GetAbcCategory(accumPercentage, categoryDictionary); 

Zusätzlich zu den vorherigen Berechnungen akkumulieren sie Werte in der Variablen accumulatedPercentage. Um die Unterschiede hervorzuheben, wird der Code eingerückt.

Ein besonderer Anwendungsfall für eine Regel besteht darin, lokale Variablen so nahe wie möglich am Verwendungsort zu deklarieren.

Regel 5. Nach dem Grundsatz der Eindeutigkeit der Verantwortung.

Dies ist das erste SOLID-Prinzip in OOP, kann jedoch zusätzlich zu Klassen auf Projekte, Module, Funktionen, Codeblöcke, Projektteams oder einzelne Entwickler angewendet werden. Auf die Frage, wer oder was für diesen Bereich verantwortlich ist, ist sofort klar, wer oder was. Eine Verbindung ist immer einfach. Jede Klasse wird auf ein Konzept, eine Phrase oder eine Metapher verallgemeinert. Infolgedessen ist der Wahrnehmungsprozess, der weniger zu merken ist, einfacher und effizienter.

Abschließend ein umfassendes Beispiel:

 private PartnerState GetPartnerStateForUpdate( PartnerActivityInfo partner, Dictionary<int, PartnerState> currentStates, Dictionary<int, PartnerState> prevStates) { PartnerState updatingState; if (prevStates.ContainsKey(partner.id)) { if (currentStates.ContainsKey(partner.id)) { var prevState = prevStates[partner.id]; updatingState = currentStates[partner.id]; // 1 } else { // 2 } } else if (currentStates.ContainsKey(partner.id)) { updatingState = currentStates[partner.id]; } else { throw new Exception(string.Format("  {0}         {1}", partner.id, month)); } return updatingState; } 

Nach dem Ersetzen der ContainsKe-Indexer, dem Invertieren der Verzweigung, dem Auswählen der Methode und dem Reduzieren der Verschachtelungsebenen stellte sich Folgendes heraus:

 private PartnerState GetPartnerStateForUpdate( PartnerActivityInfo partner, Dictionary<int, PartnerState> currentStates, Dictionary<int, PartnerState> prevStates) { PartnerState currentState = null; PartnerState prevState = null; prevStates.TryGetValue(partner.id, out prevState); currentStates.TryGetValue(partner.id, out currentState); currentState = CombineStates(currentState, prevState); return currentState; } private PartnerState CombineStates( PartnerState currentState, PartnerState prevState) { if (currentState == null && prevState == null) { throw new Exception(string.Format( "  {0}         {1}" , partner.id, month)); } if (currentState == null) { // 1 } else if (prevState != null) { // } return currentState; } 

Die erste Funktion ist dafür verantwortlich, Zustände aus Wörterbüchern zu erhalten, die zweite dafür, sie zu einem neuen zu kombinieren.

Die vorgestellten Regeln sind einfach, bieten jedoch in Kombination ein leistungsstarkes Tool zur Vereinfachung des Codes und zur Reduzierung der Speicherlast während des Entwicklungsprozesses. Sie werden ihnen nicht immer folgen können, aber wenn Sie feststellen, dass Sie den Code nicht verstehen, ist es am einfachsten, mit ihnen zu beginnen. Sie haben dem Autor in den schwierigsten Fällen wiederholt geholfen.

Source: https://habr.com/ru/post/de436160/


All Articles