Namenskonventionen, zum Beispiel lokale und Parametervariablen [geschlossen]

13

Ich habe mit einem Senior-Entwickler über Kodierungskonventionen gesprochen, die für unsere Projekte (hauptsächlich Java / JEE-Projekte) gelten sollen. Ich stimmte einer von ihm vorgeschlagenen Konvention nicht zu:

Instanzvariablennamen sollten mit "_", lokale Variablen mit "loc" und Methodenparameter mit "par" beginnen, damit sich Ursprung und Gültigkeitsbereich von Variablen leicht identifizieren lassen.

Während er Argumente für das Kurzzeitgedächtnis und die Lesbarkeit vorbrachte, stimmte ich der Tatsache nicht zu, dass es die Lesbarkeit eher verringert. IDEs wie Eclipse-Formatvariablen unterscheiden sich je nach Typ, und dieses Problem würde mit einem guten Klassen- und Methodendesign vermieden.

Haben Sie eine Meinung, Argumente oder Studien, die meinen Standpunkt stützen (oder widersprechen)?

HH
quelle
Sie sagen, dass Sie "der Tatsache, dass es die Lesbarkeit eher verringert", nicht zustimmten. Ich sage nicht, dass Sie falsch liegen, aber welche Beweise haben Sie vorgelegt, um diese Behauptung zu stützen? Nachforschungen, die besagen, dass die Lesbarkeit
beeinträchtigt wird, sind
Ich habe es so gemeint, wie es unübersichtlich ist. Aber ich habe keine anderen Beweise als meine persönliche Meinung
SH
Die Präfixe duplizieren Informationen, die bereits im Code enthalten sind und in einer halbwegs anständigen Umgebung angezeigt werden. Und wie wir alle wissen, können doppelte Informationen inkonsistent werden. DRY sollte Sie darauf hinweisen, die Präfixe nicht zu verwenden.
Julia Hayward

Antworten:

15

Wie Wikipedia zu diesem Thema sagt - Regeln für die Benennung von Java,

Lokale Variablen, Instanzvariablen und Klassenvariablen werden ebenfalls in lowerCamelCase geschrieben. Variablennamen sollten nicht mit einem Unterstrich (_) oder einem Dollarzeichen ($) beginnen, obwohl beide zulässig sind. Bestimmte Kodierungskonventionen besagen, dass Unterstriche verwendet werden sollten, um allen Instanzvariablen ein Präfix zu setzen, um das Lesen und das Programmverständnis zu verbessern.

Nach meiner Erfahrung mit Codierungsstandards sind Instanzvariablennamen, die mit "_" beginnen, nicht sehr gut, wie in den Wikipedia-Standards angegeben.

lokale Variablen mit "loc" und Methodenparameter mit "par", wie Sie sagten, es wäre einfach, einen Variablenursprung und -umfang zu identifizieren, aber es sollte für Sie sein, nicht für die anderen Programmierer, die irgendwann Ihren Code zur Wartung durchgehen .

Gemäß der Clean Code- Spezifikation zu den Methoden sollten diese so kurz sein, wie es für die Lesbarkeit möglich ist, und Variablennamen sollten nicht verinnerlicht werden. Sie sollten für Ihre Operation relevant sein, die Ihre Methode ausführt.

Mitglieder- / Bereichspräfixe, Sie müssen Mitgliedsvariablen auch kein Präfix mehr mit m_ setzen. Ihre Klassen und Funktionen sollten so klein sein, dass Sie sie nicht benötigen. Außerdem sollten Sie eine Bearbeitungsumgebung verwenden, die Elemente hervorhebt oder einfärbt, um sie voneinander zu unterscheiden.

public class Part {
private String m_dsc; // The textual description
void setName(String name) {
m_dsc = name;
}
}

public class Part {
String description;
void setDescription(String description) {
this.description = description;
}
}

Außerdem lernen die Leute schnell, das Präfix (oder Suffix) zu ignorieren, um den bedeutungsvollen Teil des Namens zu sehen. Je mehr wir den Code lesen, desto weniger werden die Präfixe angezeigt. Schließlich werden die Präfixe unsichtbar und ein Marker für älteren Code.

Niranjan Singh
quelle
4

Dies ist eine alte Frage, aber ich werde sie trotzdem hier posten. Ich habe mehr als 20 Jahre Erfahrung in der Programmierung und im Umgang mit dem Code anderer Leute.

Ich denke, dass die Benennung Ihrer Variablen mit einem kurzen Hinweis auf deren Gültigkeitsbereich für die nächste Person (oder für Sie selbst), die sich Ihren Code ansieht, wirklich sehr nützlich ist.

Man sieht sich Code in einer IDE mit hübschen Farben noch nicht an (und ich kann mich nicht erinnern, was die Farben bedeuten, und verschiedene IDE zeigen verschiedene Farben usw.).

Richtig, Methoden sollten kurz genug sein, damit sie nicht mit Tonnen von Variablen und Tonnen von Code geladen werden, sondern sogar mit einer kurzen - wenn Sie sich Code ansehen, der völlig ungewohnt ist, ist es manchmal schwierig zu sagen, ob eine Variable eine Klassenvariable ist, lokal Variable oder Methodenparameter.

Um auf einen Blick unterscheiden zu können, ist es sehr einfach, den Code zu überprüfen, mit dem Sie nicht vertraut sind.

Nehmen Sie dieses Beispiel:

public <T> Page<T> moreLikeThis(MoreLikeThisQuery query, Class<T> clazz) {
    int startRecord = 0;
    ElasticsearchPersistentEntity persistentEntity = getPersistentEntityFor(clazz);
    String indexName = isNotBlank(query.getIndexName()) ? query.getIndexName() : persistentEntity.getIndexName();
    String type = isNotBlank(query.getType()) ? query.getType() : persistentEntity.getIndexType();

    Assert.notNull(indexName, "No 'indexName' defined for MoreLikeThisQuery");
    Assert.notNull(type, "No 'type' defined for MoreLikeThisQuery");
    Assert.notNull(query.getId(), "No document id defined for MoreLikeThisQuery");

    MoreLikeThisRequestBuilder requestBuilder = client.prepareMoreLikeThis(indexName, type, query.getId());

    if (query.getPageable() != null) {
        startRecord = query.getPageable().getPageNumber() * query.getPageable().getPageSize();
        requestBuilder.setSearchSize(query.getPageable().getPageSize());
    }
    requestBuilder.setSearchFrom(startRecord);

    if (isNotEmpty(query.getSearchIndices())) {
        requestBuilder.setSearchIndices(toArray(query.getSearchIndices()));
    }
    if (isNotEmpty(query.getSearchTypes())) {
        requestBuilder.setSearchTypes(toArray(query.getSearchTypes()));
    }
    if (isNotEmpty(query.getFields())) {
        requestBuilder.setField(toArray(query.getFields()));
    }
    if (isNotBlank(query.getRouting())) {
        requestBuilder.setRouting(query.getRouting());
    }
    if (query.getPercentTermsToMatch() != null) {
        requestBuilder.setPercentTermsToMatch(query.getPercentTermsToMatch());
    }
    if (query.getMinTermFreq() != null) {
        requestBuilder.setMinTermFreq(query.getMinTermFreq());
    }
    if (query.getMaxQueryTerms() != null) {
        requestBuilder.maxQueryTerms(query.getMaxQueryTerms());
    }
    if (isNotEmpty(query.getStopWords())) {
        requestBuilder.setStopWords(toArray(query.getStopWords()));
    }
    if (query.getMinDocFreq() != null) {
        requestBuilder.setMinDocFreq(query.getMinDocFreq());
    }
    if (query.getMaxDocFreq() != null) {
        requestBuilder.setMaxDocFreq(query.getMaxDocFreq());
    }
    if (query.getMinWordLen() != null) {
        requestBuilder.setMinWordLen(query.getMinWordLen());
    }
    if (query.getMaxWordLen() != null) {
        requestBuilder.setMaxWordLen(query.getMaxWordLen());
    }
    if (query.getBoostTerms() != null) {
        requestBuilder.setBoostTerms(query.getBoostTerms());
    }

    SearchResponse response = requestBuilder.execute().actionGet();
    return resultsMapper.mapResults(response, clazz, query.getPageable());
}

Nehmen Sie sich jetzt die Zeit und schauen Sie sich den Code an (extrahiert aus ElasticsearchTemplate aus dem Projekt spring-data-elasticsearch - der Code, den ich gerade durchgesehen habe und der mich dazu veranlasste, in Google nach den Aussagen zu Namenskonventionen zu suchen).

  • Was ist der Scode von resultsMapper?
  • Ist requestBuildingein Parameter?
  • etc...

Hier ist mein einfacher Vorschlag, wie Variablen benannt werden sollten:

  • Statische Klassenattribute (dh Konstanten): ALL_CAPS_WITH_UNDERSCORES (zB HOST_NAME).
  • Klassenattribute (dh Klasseninstanzvariablen): camelCase (zB resultsMapper).
  • Verfahrensparameter: mit dem Präfix a(z aQuery, aClazz).
  • Lokale Variablen: mit dem Präfix my(zB myIndexName, myType).

Der obige Code wird:

public <T> Page<T> moreLikeThis(MoreLikeThisQuery aQuery, Class<T> aClazz) {
  int myStartRecord = 0;
  ElasticsearchPersistentEntity myPersistentEntity = getPersistentEntityFor(aClazz);
  String myIndexName = isNotBlank(aQuery.getIndexName()) ? aQuery.getIndexName() : myPersistentEntity.getIndexName();
  String myType = isNotBlank(aQuery.getType()) ? aQuery.getType() : myPersistentEntity.getIndexType();

  Assert.notNull(myIndexName, "No 'indexName' defined for MoreLikeThisQuery");
  Assert.notNull(myType, "No 'type' defined for MoreLikeThisQuery");
  Assert.notNull(aQuery.getId(), "No document id defined for MoreLikeThisQuery");

  MoreLikeThisRequestBuilder myRequestBuilder = client.prepareMoreLikeThis(myIndexName, myType, aQuery.getId());

  if (aQuery.getPageable() != null) {
     myStartRecord = aQuery.getPageable().getPageNumber() * aQuery.getPageable().getPageSize();
     myRequestBuilder.setSearchSize(aQuery.getPageable().getPageSize());
  }
  myRequestBuilder.setSearchFrom(myStartRecord);

  if (isNotEmpty(aQuery.getSearchIndices())) {
     myRequestBuilder.setSearchIndices(toArray(aQuery.getSearchIndices()));
  }
  if (isNotEmpty(aQuery.getSearchTypes())) {
     myRequestBuilder.setSearchTypes(toArray(aQuery.getSearchTypes()));
  }
  if (isNotEmpty(aQuery.getFields())) {
     myRequestBuilder.setField(toArray(aQuery.getFields()));
  }
  if (isNotBlank(aQuery.getRouting())) {
     myRequestBuilder.setRouting(aQuery.getRouting());
  }
  if (aQuery.getPercentTermsToMatch() != null) {
     myRequestBuilder.setPercentTermsToMatch(aQuery.getPercentTermsToMatch());
  }
  if (aQuery.getMinTermFreq() != null) {
     myRequestBuilder.setMinTermFreq(aQuery.getMinTermFreq());
  }
  if (aQuery.getMaxQueryTerms() != null) {
     myRequestBuilder.maxQueryTerms(aQuery.getMaxQueryTerms());
  }
  if (isNotEmpty(aQuery.getStopWords())) {
     myRequestBuilder.setStopWords(toArray(aQuery.getStopWords()));
  }
  if (aQuery.getMinDocFreq() != null) {
     myRequestBuilder.setMinDocFreq(aQuery.getMinDocFreq());
  }
  if (aQuery.getMaxDocFreq() != null) {
     myRequestBuilder.setMaxDocFreq(aQuery.getMaxDocFreq());
  }
  if (aQuery.getMinWordLen() != null) {
     myRequestBuilder.setMinWordLen(aQuery.getMinWordLen());
  }
  if (aQuery.getMaxWordLen() != null) {
     myRequestBuilder.setMaxWordLen(aQuery.getMaxWordLen());
  }
  if (aQuery.getBoostTerms() != null) {
     myRequestBuilder.setBoostTerms(aQuery.getBoostTerms());
  }

  SearchResponse myResponse = myRequestBuilder.execute().actionGet();
  return resultsMapper.mapResults(myResponse, aClazz, aQuery.getPageable());

}

Ist das perfekt Ich glaube nicht. Was die Variablen betrifft, ist das oben Gesagte jetzt einfacher zu lesen. Es gibt andere Dinge wie Ausrichtung und Abstand, auf die ich in dieser Antwort nicht eingehen werde, da es sich nicht um die Frage handelt, die auch das Lesen erleichtern würde.

Du magst Camel Case nicht? Gut, verwenden Sie Unterstriche usw., aber stellen Sie Ihren lokalen Variablen und Ihren Parametern ein Präfix voran, damit sie sich von den Klasseninstanzvariablen unterscheiden.

Sie mögen aund my- gut, bleiben Sie einfach in Ihrem Projekt konsistent und verwenden Sie etwas anderes ... aber verwenden Sie etwas.

Regel 1: Konsistenz innerhalb des Projekts.

Regel 2: Erleichtern Sie das Lesen und fordern Sie den Leser nicht auf, alles zu wissen, bevor er lernen kann.

ETL
quelle
3

Dies ist größtenteils eine Frage der Präferenz, und als solche gibt es keine "richtige" Antwort. Diese Frage könnte also tatsächlich geschlossen sein. Aber bevor es soweit ist, möchte ich Ihnen sagen, dass ich Ihnen vollkommen zustimme. Präfixe verringern für mich die Sichtbarkeit. Ganz zu schweigen von der Tatsache, dass Präfixe für nützlichere Zwecke verwendet werden sollten, wie sie ursprünglich in der ungarischen Notation vorgesehen waren Dinge , und nicht für Dinge, für die Ihre IDE sowieso Hervorhebungen bereitstellen kann.

Ich verwende zum Beispiel SatzFall-Daten (ob Variablen oder Konstanten) und Kleinbuchstaben für Parameter und lokale Variablen, da zwischen den beiden wirklich nur ein sehr geringer, wenn überhaupt, Unterschied besteht. Ich verwende niemals headlessCamelCase, weil es lahm ist : Ein Einzelkomponenten-Bezeichner sieht aus wie Kleinbuchstaben, selbst wenn es headlessCamelCase sein sollte.

Mike Nakis
quelle