インスタンス、ローカル変数、パラメータ変数の命名規則[非公開]


13

私はプロジェクト(主にJava / JEEプロジェクト)に適用するために、シニア開発者のコ​​ーディング規約と話し合っていました。私は彼が提案した一つのコンベンションに反対しました:

インスタンス変数名は「_」で始まり、ローカル変数は「loc」で、メソッドパラメーターは「par」で始まる必要があるため、変数の起点とスコープを簡単に識別できます。

彼は短期記憶と読みやすさについて議論を進めましたが、読みやすさをむしろ低下させるという事実、EclipseのようなIDEは変数をその型によって異なるようにフォーマットするという事実に異議を唱え、この問題は適切なクラスとメソッドの設計で回避されるでしょう。

私の主張を支持する(または反対する)意見、議論、研究はありますか?


あなたは「読みやすさをむしろ低下させるという事実」に同意しないと言います。あなたが間違っていると言っているわけではありませんが、その主張を裏付けるためにどのような証拠を提供しましたか?(これは私のために関心領域があるので、私は開発者になる前に、大学院心理学で認知勉強しました。)私はそれが可読性が低下しますと言う任意の研究を認識していないよ
AdamJonR

散らかっているのでそれを意味しました。しかし、私は私の個人的な意見以外の証拠はありません
HH

プレフィックスは、すでにコードに含まれており、適切な環境で表示される情報を複製します。そして、ご存知のように、重複する情報は一貫性を欠く可能性があります。DRYは、プレフィックスを使用しないように指示する必要があります。
ジュリアヘイワード

回答:


15

ウィキペディアが被写体に言う-ジャワの命名規則、

ローカル変数、インスタンス変数、およびクラス変数もlowerCamelCaseで記述されています。変数名は、アンダースコア(_)またはドル記号($)で始まっていてはいけません。両方とも許可されています。特定のコーディング規約では、読みやすさとプログラムの理解を向上させるために、すべてのインスタンス変数の前にアンダースコアを使用する必要があると規定されています。

コーディング標準に関する私の経験によれば、ウィキペディアの標準が言うように、インスタンス変数名は「_」で始まります。

「loc」のローカル変数、および「par」のメソッドパラメータ。変数の起源とスコープを簡単に特定できると述べましたが、いつかはメンテナンスのためにコードを実行する他のプログラマではなく、あなたのためにすべきです。 。

メソッドに関するClean Code仕様に従って、これらは読みやすさのためにできる限り短くする必要があり、変数名はマインドマップされるべきではなく、メソッドが実行する操作に関連する必要があります。

メンバー/スコープの接頭辞、メンバー変数の前にm_を付ける必要もなくなりました。クラスと関数は、それらを必要としない程度に小さくする必要があります。また、メンバーを強調または色分けして、メンバーを明確にする編集環境を使用する必要があります。

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

その上、人々は名前の意味のある部分を見るために接頭辞(または接尾辞)を無視することをすぐに学びます。コードを読むほど、プレフィックスが少なくなります。最終的に、プレフィックスは目に見えない混乱と古いコードのマーカーになります。


4

これは古い質問ですが、とにかくここに投稿します。私は20年以上のプログラミングと他の人のコードの取り扱いを行っています。

変数のスコープを示す短い名前で変数に名前を付けると、コードを見る次の人(または自分)にとって本当に便利だと思います。

きれいな色のIDEのコードはまだ見ていません(色の意味や、異なるIDEが異なる色を表示するなど、私は思い出せません)。

確かに、メソッドは十分に短くなければならないので、大量の変数と大量のコードがロードされませんが、短いものでもロードされます-完全になじみのないコードを見ると、変数がクラス変数であるかどうか、ローカル変数またはメソッドのパラメーター。

一目で区別できると、慣れていないコードを簡単に確認できます。

次の例をご覧ください。

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

さて、時間をかけてコードを見てください(spring-data-elasticsearchプロジェクトのElasticsearchTemplateから抽出-命名規則について人々が言うことをGoogleで検索するように促したレビュー中のコード)。

  • のコードはresultsMapper何ですか?
  • あるrequestBuildingパラメータには?
  • 等...

変数の命名方法に関する私の簡単な提案を次に示します。

  • クラスの静的属性(つまり定数):ALL_CAPS_WITH_UNDERSCORES(例HOST_NAME)。
  • クラス属性(クラスインスタンス変数):camelCase(eg resultsMapper)。
  • メソッドのパラメータ:接頭辞a(例えばaQueryaClazz)。
  • ローカル変数:接頭辞my(例えばmyIndexNamemyType)。

上記のコードは次のようになります。

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

}

完璧ですか?そうは思いません。しかし、変数に関する限り、上記は読みやすくなりました。配置や間隔など、質問に関連していないため、この回答では説明しません。読みやすくすることもできます。

キャメルケースが嫌いですか?罰金、アンダースコアなどを使用しますが、ローカル変数とパラメータにプレフィックスを付けて、クラスインスタンス変数とは異なるようにします。

あなたは好きではaありませんmy-結構です、プロジェクト内で一貫性を保ち、他の何かを使用します...しかし、何かを使用します。

ルール#1:プロジェクト内の一貫性。

ルール#2:読みやすくし、読者が学習する前にすべてを知る必要がないようにします。


3

これは主に好みの問題であり、「正しい」答えはありません。したがって、この質問は実際には閉じられている可能性があります。しかし、それが起こる前に、私はあなたに完全に同意することを伝えさせてください。プレフィックスは、私に関する限り、可視性を低下させます。接頭辞がある場合、ハンガリー記法の本来の意図のように IDEが強調表示を提供できるものではなく、より有用なものに使用する必要があるという事実は言うまでもありません。

インスタンスデータ(変数または定数)にSentenceCaseを使用し、パラメーターとローカル変数にlower_caseを使用します。これは、両者の違いがあったとしてもごくわずかだからです。headlessCamelCase はラメからです。単一コンポーネントの識別子は、headlessCamelCaseを意図していたとしても、小文字のように見えます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.