Convenzioni di denominazione, ad esempio variabili locali e dei parametri [chiuso]


13

Stavo discutendo con un anziano sviluppatore di convenzioni di codifica da applicare ai nostri progetti (principalmente progetti Java / JEE). Non sono d'accordo con una convenzione che ha proposto:

I nomi delle variabili di istanza dovrebbero iniziare con "_", variabili locali con "loc" e parametri del metodo con "par", quindi sarebbe facile identificare un'origine e un ambito delle variabili.

Mentre ha avanzato argomenti per memoria a breve termine e leggibilità, non sono d'accordo sul fatto che diminuisca piuttosto la leggibilità, IDE come le variabili di formato Eclipse differiscono in base al loro tipo e questo problema sarebbe evitato con una buona progettazione di classe e metodo.

Hai qualche opinione, argomento o studio a sostegno del mio punto (o si oppone)?


Dici di essere in disaccordo sul "fatto che diminuisca piuttosto la leggibilità". Non sto dicendo che ti sbagli, ma quali prove hai fornito a sostegno di tale affermazione? Non sono a conoscenza di alcuna ricerca che dice che ridurrà la leggibilità (ho studiato cognitiva alla psicologia della scuola di specializzazione prima di diventare uno sviluppatore, quindi questa è un'area di interesse per me.)
AdamJonR

Lo intendevo perché è ingombrante. Ma non ho prove diverse dalla mia opinione personale
HH

I prefissi duplicano le informazioni che sono già contenute nel codice e visualizzate in qualsiasi ambiente decente. E come tutti sappiamo, le informazioni duplicate possono diventare incoerenti. DRY dovrebbe indicarti di non utilizzare i prefissi.
Julia Hayward,

Risposte:


15

Come dice Wikipedia sull'argomento - Regole per la denominazione di Java,

Anche le variabili locali, le variabili di istanza e le variabili di classe sono scritte in lowerCamelCase. I nomi delle variabili non devono iniziare con caratteri di sottolineatura (_) o segni di dollaro ($), anche se entrambi sono consentiti. Alcune convenzioni di codifica affermano che i caratteri di sottolineatura dovrebbero essere usati per anteporre a tutte le variabili di istanza, per una migliore lettura e comprensione del programma.

Secondo la mia esperienza con gli standard di codifica, i nomi delle variabili di istanza che iniziano con "_" non sono molto buoni, come affermano gli standard di Wikipedia.

variabili locali con "loc" e parametri del metodo con "par", come hai detto, sarebbe facile identificare un'origine e un ambito delle variabili, ma dovrebbe essere per te, non per gli altri programmatori che un giorno potrebbero passare il codice per la manutenzione .

Secondo la specifica del codice pulito sui metodi, questi dovrebbero essere brevi quanto possono fare per la leggibilità e i nomi delle variabili non dovrebbero essere mappati a mente, dovrebbero essere rilevanti per l'operazione che il metodo esegue.

Prefissi membro / ambito, inoltre non è più necessario aggiungere un prefisso alle variabili membro con m_. Le tue classi e funzioni dovrebbero essere abbastanza piccole da non averne bisogno. E dovresti utilizzare un ambiente di modifica che evidenzi o colora i membri per renderli distinti.

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;
}
}

Inoltre, le persone imparano rapidamente a ignorare il prefisso (o suffisso) per vedere la parte significativa del nome. Più leggiamo il codice, meno vediamo i prefissi. Alla fine i prefissi diventano disordine invisibile e un marcatore di codice più vecchio.


4

Questa è una vecchia domanda, ma pubblicherò comunque qui. Ho circa 20 anni di programmazione e di gestione del codice di altre persone.

Penso che nominare la tua variabile con una breve indicazione del loro ambito sia davvero utile per la prossima persona (o te) che guarderà il tuo codice.

Uno non guarda già il codice in un IDE con bei colori (e non ricordo cosa significano i colori e diversi IDE mostrano colori diversi, ecc.).

È vero, i metodi dovrebbero essere abbastanza brevi, quindi non sono caricati con tonnellate di variabili e tonnellate di codice ma anche su uno corto - quando guardi un codice totalmente sconosciuto, a volte è difficile dire se una variabile è una variabile di classe, locale parametro variabile o metodo

Essere in grado di distinguere a colpo d'occhio rende molto facile rivedere il codice con cui non si ha familiarità.

Prendi questo esempio:

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());
}

Ora, prenditi un po 'di tempo e guarda il codice (estratto da ElasticsearchTemplate del progetto spring-data-elasticsearch - il codice che stavo rivedendo che mi ha spinto a cercare su Google ciò che la gente dice sulle convenzioni di denominazione).

  • Qual è la scode di resultsMapper?
  • È requestBuildingun parametro?
  • eccetera...

Ecco il mio semplice suggerimento su come le variabili dovrebbero essere nominate:

  • Attributi statici di classe (cioè costanti): ALL_CAPS_WITH_UNDERSCORES (ad es HOST_NAME.).
  • Attributi di classe (ovvero variabili di istanza di classe): camelCase (ad es resultsMapper.).
  • Parametri di metodo: prefisso a(ad esempio aQuery, aClazz).
  • Le variabili locali: con il prefisso my(ad esempio myIndexName, myType).

Il codice sopra diventa:

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());

}

È perfetto? Io non la penso così. Ma quanto sopra, per quanto riguarda le variabili, è ora più facile da leggere. Ci sono altre cose come l'allineamento e la spaziatura, che non affronterò in questa risposta in quanto non è correlata alla domanda, il che renderebbe anche più facile la lettura.

Non ti piace Camel Case? Bene, usa i trattini bassi, ecc., Ma aggiungi il prefisso alle tue variabili locali e ai tuoi parametri per renderle diverse dalle variabili di istanza di classe.

Non ti piace ae my- bene, rimani coerente nel tuo progetto e usa qualcos'altro ... ma usa qualcosa.

Regola n. 1: coerenza all'interno del progetto.

Regola n. 2: facilita la lettura e non richiede al lettore di sapere tutto prima di poter imparare.


3

Questa è in gran parte una questione di preferenza e come tale non esiste una risposta "corretta". Quindi, questa domanda potrebbe effettivamente essere chiusa. Ma prima che lo faccia, lascia che ti dica che sono totalmente d'accordo con te. I prefissi riducono la visibilità per quanto mi riguarda. Per non parlare del fatto che, se devono esserci dei prefissi, dovrebbero essere usati per cose più utili, come l'intenzione originale della Notazione ungherese , e non per cose che il tuo IDE può comunque mettere in evidenza.

Uso FraseCase per i dati di istanza (variabili o costanti) e lower_case per i parametri e le variabili locali, poiché tra i due c'è davvero poca differenza. Non uso mai headlessCamelCase perché è zoppo : un identificatore monocomponente sembra minuscolo, anche se doveva essere headlessCamelCase.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.