Je discutais avec un développeur senior des conventions de codage à appliquer à nos projets (principalement les projets Java/JEE). Je suis en désaccord avec une convention qu'il propose:
Les noms de variables d'instance doivent commencer par "_", les variables locales par "loc" et les paramètres de méthode par "par", il serait donc facile d'identifier une origine et une étendue de variable.
Bien qu'il ait avancé des arguments pour la mémoire à court terme et la lisibilité, je ne suis pas d'accord sur le fait que cela diminue plutôt la lisibilité, les IDE comme les variables de format Eclipse différemment selon leur type, et ce problème serait évité avec une bonne conception de classe et de méthode.
Avez-vous une opinion, des arguments ou des études qui soutiennent mon point (ou s'y opposent)?
Comme Wikipedia dit sur le sujet - Règles pour nommer Java,
Les variables locales, les variables d'instance et les variables de classe sont également écrites dans lowerCamelCase. Les noms de variable ne doivent pas commencer par des caractères de soulignement (_) ou de signe dollar ($), même si les deux sont autorisés. Certaines conventions de codage stipulent que les traits de soulignement doivent être utilisés pour préfixer toutes les variables d'instance, pour une meilleure lecture et une meilleure compréhension du programme.
D'après mon expérience avec les normes de codage, les noms de variables d'instance commençant par "_" ne sont pas très bons comme le disent les normes wikipedia.
les variables locales avec "loc", et les paramètres de méthode avec "par", comme vous l'avez dit, il serait facile d'identifier une origine et une portée de variable, mais cela devrait être pour vous, pas pour les autres programmeurs qui pourraient passer un jour votre code pour la maintenance .
Selon la spécification Clean Code sur les méthodes, celles-ci doivent être aussi courtes que possible pour la lisibilité et les noms de variables ne doivent pas être mappés, ils doivent être pertinents pour votre opération que votre méthode effectue.
Préfixes de membre/portée, vous n'avez plus besoin de préfixer les variables de membre avec m_. Vos classes et fonctions doivent être suffisamment petites pour que vous n'en ayez pas besoin. Et vous devez utiliser un environnement d'édition qui met en évidence ou colorise les membres pour les distinguer.
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;
}
}
De plus, les gens apprennent rapidement à ignorer le préfixe (ou suffixe) pour voir la partie significative du nom. Plus nous lisons le code, moins nous voyons les préfixes. Finalement, les préfixes deviennent un encombrement invisible et un marqueur de code plus ancien.
C'est une vieille question, mais je vais quand même poster ici. J'ai plus de 20 ans de programmation et de gestion du code d'autres personnes.
Je pense que nommer votre variable avec une brève indication quant à leur portée est vraiment très utile pour la prochaine personne (ou vous-même) qui examinera votre code.
On ne regarde pas déjà le code dans un IDE avec de jolies couleurs (et je ne me souviens pas ce que les couleurs signifient et différentes IDE montrent différentes couleurs, etc.) ).
Certes, les méthodes doivent être suffisamment courtes pour ne pas être chargées de tonnes de variables et de tonnes de code, mais même sur une version courte - lorsque vous regardez du code qui ne vous est pas familier, il est parfois difficile de dire si une variable est une variable de classe, locale variable ou paramètre de méthode.
Pour pouvoir distinguer en un coup d'œil, il est très facile de revoir le code que vous ne connaissez pas.
Prenez cet exemple:
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());
}
Maintenant, chronométrez-vous et regardez le code (extrait de ElasticsearchTemplate du projet spring-data-elasticsearch - le code que je révisais qui m'a incité à rechercher sur Google ce que les gens disent à propos des conventions de dénomination).
resultsMapper
?requestBuilding
est-il un paramètre?Voici ma simple suggestion sur la façon de nommer les variables:
Host_NAME
).resultsMapper
).a
(par exemple aQuery
, aClazz
).my
(par exemple myIndexName
, myType
).Le code ci-dessus devient:
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());
}
C'est parfait? Je ne pense pas. Mais ce qui précède, en ce qui concerne les variables, est maintenant plus facile à lire. Il y a d'autres choses telles que l'alignement et l'espacement, que je n'entrerai pas dans cette réponse car elles ne sont pas liées à la question, ce qui faciliterait également la lecture.
Vous n'aimez pas Camel Case? Bien, utilisez des traits de soulignement, etc., mais préfixez vos variables locales et vos paramètres pour les rendre différents des variables d'instance de classe.
Vous n'aimez pas a
et my
- très bien, restez juste cohérent dans votre projet et utilisez autre chose ... mais utilisez quelque chose.
Règle n ° 1: cohérence au sein du projet.
Règle n ° 2: facilite la lecture et n'exige pas que le lecteur sache tout avant de pouvoir apprendre.
C'est en grande partie une question de préférence, et en tant que telle, il n'y a pas de réponse "correcte". Donc, cette question pourrait être fermée. Mais avant cela, permettez-moi de vous dire que je suis totalement d'accord avec vous. Les préfixes diminuent la visibilité en ce qui me concerne. Sans parler du fait que s'il doit y avoir des préfixes, ils devraient être utilisés pour des choses plus utiles, comme l'intention originale de la notation hongroise , et non pour des choses que votre IDE peut de toute façon mettre en évidence.
J'utilise PhraseCase pour les données d'instance (variables ou constantes) et lower_case pour les paramètres et les variables locales, car il y a vraiment très peu, voire aucune, différence entre les deux. Je n'utilise jamais, headlessCamelCase parce que c'est boiteux : un identifiant à un seul composant ressemble à des minuscules, même s'il était destiné à être headlessCamelCase.