Convenciones de nomenclatura, por ejemplo, variables locales y de parámetros [cerrado]

12

Estaba discutiendo con un desarrollador senior las convenciones de codificación para aplicar a nuestros proyectos (principalmente proyectos Java / JEE). No estoy de acuerdo con una convención que él propuso:

  

Los nombres de las variables de instancia deben comenzar con "_", las variables locales con   "loc" y los parámetros del método con "par", por lo que sería fácil de identificar   una variable de origen y alcance.

Si bien presentó argumentos para la memoria a corto plazo y la legibilidad, no estaba de acuerdo con el hecho de que disminuye la legibilidad, los IDE como las variables de formato Eclipse de manera diferente según su tipo, y este problema se evitaría con una buena clase y método. diseño.

¿Tiene alguna opinión, argumento o estudio que respalde mi punto (o se opone)?

    
pregunta H-H 02.01.2012 - 08:41

3 respuestas

15

Como dice Wikipedia sobre el tema - Reglas para nombrar java,

  

Las variables locales, las variables de instancia y las variables de clase también son   escrito en lowerCamelCase. Los nombres de variables no deben comenzar con   caracteres de subrayado (_) o signo de dólar ($), aunque ambos son   permitido. Ciertas convenciones de codificación establecen que los guiones bajos deben ser   usado para prefijar todas las variables de instancia, para mejorar la lectura y   Comprensión del programa.

De acuerdo con mi experiencia con los estándares de codificación, los nombres de variables de instancia que comienzan con "_" no son tan buenos como dicen los estándares de wikipedia.

las variables locales con "loc" y los parámetros del método con "par", como usted dijo, sería fácil identificar el origen y el alcance de una variable, pero debería ser para usted, no para los otros programadores que pueden revisar su código para mantenimiento algún día.

De acuerdo con la especificación Clean Code sobre los métodos que deben ser cortos, tanto como puedan hacer para facilitar la lectura. y los nombres de las variables no deben ser asignados mentalmente, deben ser relevantes para la operación que realiza su método.

Prefijos de miembros / alcance, Tampoco es necesario prefijar las variables miembro con m_ más. Tus clases y funciones. debe ser lo suficientemente pequeño como para que no los necesites. Y deberías estar usando una edición entorno que resalta o colorea a los miembros para que sean distintos.

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

Además, las personas aprenden rápidamente a ignorar el prefijo (o sufijo) para ver el significado parte del nombre. Cuanto más leemos el código, menos vemos los prefijos. Eventualmente el los prefijos se convierten en desorden oculto y en un marcador de código anterior.

    
respondido por el Niranjan Singh 02.01.2012 - 09:38
3

Esto es en gran medida una cuestión de preferencia, y como tal no hay una respuesta 'correcta'. Por lo tanto, esta pregunta podría estar cerrada. Pero antes de que lo haga, déjame decirte que estoy totalmente de acuerdo contigo. Los prefijos disminuyen la visibilidad en lo que a mí respecta. Sin mencionar el hecho de que si hay prefijos, se deben usar para cosas más útiles, como la intención original del Notación húngara , y no por las cosas que su IDE puede proporcionar resaltado de todos modos.

Utilizo SentenciaCase para datos de ejemplo (ya sean variables o constantes) y lower_case para parámetros y variables locales, ya que realmente hay muy poca diferencia, si es que hay alguna, entre los dos. Nunca, nunca uso headlessCamelCase porque es cojo : un identificador de un solo componente parece en minúsculas, incluso si estaba destinado a ser headlessCamelCase.

    
respondido por el Mike Nakis 02.01.2012 - 10:22
3

Esta es una pregunta antigua, pero voy a publicar aquí de todos modos. Tengo más de 20 años de programación y trato con el código de otras personas.

Creo que nombrar su variable con una breve indicación en cuanto a su alcance es realmente útil para la siguiente persona (o usted) que verá su código.

Uno no ve el código en un IDE con colores bonitos (y no puedo recordar lo que significan los colores y los diferentes IDE muestran diferentes colores, etc.).

Es cierto, los métodos deben ser lo suficientemente cortos para que no estén cargados con toneladas de variables y toneladas de código, sino incluso con uno breve: cuando se ve un código que no es del todo familiar, a veces es difícil saber si una variable es una clase Variable, variable local o parámetro del método.

Poder distinguir de un vistazo hace que sea muy fácil revisar el código con el que no está familiarizado.

Toma este ejemplo:

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

Ahora, tómate un tiempo y mira el código (extraído de ElasticsearchTemplate del proyecto spring-data-elasticsearch, el código que estaba revisando, lo que me impulsó a buscar en Google lo que dice la gente sobre las convenciones de nombres).

  • ¿Cuál es el scode de resultsMapper ?
  • ¿Es requestBuilding un parámetro?
  • etc ...

Aquí está mi simple sugerencia sobre cómo deben nombrarse las variables:

  • Atributos estáticos de clase (es decir, constantes): ALL_CAPS_WITH_UNDERSCORES (por ejemplo, HOST_NAME ).
  • Atributos de clase (es decir, variables de instancia de clase): camelCase (por ejemplo, resultsMapper ).
  • Parámetros del método: prefijados con a (por ejemplo, aQuery , aClazz ).
  • Variables locales: con el prefijo my (por ejemplo, myIndexName , myType ).

El código anterior se convierte en:

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

}

¿Eso es perfecto? No lo creo. Pero lo anterior, en lo que respecta a las variables, ahora es más fácil de leer. Hay otras cosas, como la alineación y el espaciado, en las que no entraré en esta respuesta, ya que no están relacionadas con la pregunta, lo que también facilitaría la lectura.

¿No te gusta Camel Case? Bien, use guiones bajos, etc., pero prefija sus variables locales y sus parámetros para que sean diferentes a las variables de instancia de clase.

No te gustan a y my - bien, solo mantente consistente en tu proyecto y usa otra cosa ... pero usa algo.

Regla # 1: coherencia dentro del proyecto.

Regla # 2: facilita la lectura y no requiere que el lector sepa todo antes de que pueda aprender.

    
respondido por el ETL 30.11.2014 - 02:27

Lea otras preguntas en las etiquetas