Processingで学ぶ 実践的プログラミング専門課程

第3回ネーミングルールを持とう

導入

コーディングルール(またはコーディング規約とは、ソースコードを書く際の約束事です。

コーディングルールを決めて守ることで、統一感があり読みやすいコードになります。コードが読みやすいとメンテナンスがしやすくなります。メンテナンスがしやすければバグが入り込む可能性が小さくなります。複数人でコーディングするならば、コーディングルールを取り決めることが必要です。コーディングルールの違いで意思の疎通が滞るなど、この上なく無駄なことです。

唯一絶対のコーディングルールはありませんが、ある程度一般的に認知されている標準的なルールがあります。なるべく標準的なルールを元に決定すると便利です。全国から集まった人たちが話し合いをするときに、標準語を使用することが好ましいことに似ています。

今回はコーディングルールの一つ、ネーミングのルールを学習します。

展開

大前提:意味のある名前をつける

大前提でありながら、意外といい加減になっているのが意味のある名前をつけることです。とりあえず動くコードを書くために、つい適当な名前の変数やメソッドを作ってしまうことがあるものです。適当とまでは行かないまでも、思慮に欠ける名前をつけたことはないでしょうか。そしてそれを各所で使ううちに、適切な名前に直す手間がおっくうになって、そのまま放置してしまいます。数日後、その変数やメソッドを作ったのはなぜか、意味は何なのかが分からなくなっているのです。

例えば、次のコードChokeYourself.pdeを見てください。

ChokeYourself.pde
class House{
  House(){
    println("House object created.");
  }
  void open(int n){
    println("No. " + n + " Door opened!");
  }
} // end of class House

House h    = new House();
int   temp = 0; // 典型的な無意味名称。何に使ってるんだっけ?

void setup(){
  temp = 5; // あれ?tempって何の意味だっけ?
  h.open(temp); // open?何を?窓を?ドアをだっけ?
} // end of void setup

メソッドopenは窓を開けるのか、ドアを開けるのかコードだけでは判定できません。やがてopenDoorメソッドやopenWindowメソッドを作ることになるでしょう。あるいはopen(DOOR)open(WINDOW,3)などとしてもよいでしょう。単にopenだけでは何をどうしたかったのか、書いた本人も忘れてしまうことでしょう。

また、整数変数tempは何のための変数でしょうか。最後までコードを追って行き、Houseクラスの実装と照らし合わせると、開くドアの番号であろうと推測できました。それならばdoorNumberなどと目的をはっきり記述した名前にするべきです。open(doorNumber)とメソッドを呼べばコードの意図が明確になります。

変数やメソッド、クラスなど、名前をつけるのはなかなか頭を使う仕事です。ここで労力を割いていい名前をつけておくと、後々楽になります。書き捨てのスクリプトではなく、コードを書くならば、名前はしっかり考えてつけましょう。

[作業] 開いたドアや窓は閉めなければなりません。閉じるメソッドの名称や引数の取り方を検討してください。

[作業] ⁠開く」「閉じる」を家に属するメソッドと考えてきましたが、その他にも別のクラスのメソッドにすることが考えられます。どのような考え方ができるか検討してください。

英語を使おう

プログラミング言語の各命令は、英語を元に作られています。ですから変数名やクラス名は英語で記述するほうが読む際に自然です。

GoodCode.pde
String name = "Taro";
int    age  = 16;
float  height = 173.5;
print("Hello " + name + 
      ". You are " + age + " years old! "
       + height + " cm tall.");

String「コンピュータ用語として文字列」を表す英語ですし、print「表示」を表す英語です。

ところで、Java言語ではUnicodeの文字列ならば、日本語で変数名やクラス名、メソッド名を作成することができます。

Unicodeの変数名を持つコードを実行したところ
画像

しかし、この連載で学んでいる方は是非ともProcessingやJavaのコードを英語で書くようにしてください。一番の理由は英語やローマ字、その他の言語の単語がコードに並ぶと紛らわしいことです。

Bad.java
String shimei = "Taro";
int    toshi  = 16;
float   身長 = 173.5;
println("Hello " + shimei + ". You are " + toshi + " years old! " 
        + 身長 + " cm tall.");

変数名ならまだしも、メソッド名がローマ字だと混乱の極みです。この程度のJavaコードはProcessingでもほぼそのまま動くのですが、float型で宣言した変数「身長」はProcessingではエラーになります。

私たち日本人には、ローマ字や日本語で書かれた変数名やメソッド名は分かりやすいものです。個人だけで使用するコードやごく少人数のチームでコードを共有する場合などでは、日本語の変数名やメソッド名を絶対的には否定しません。実際、日本語変数や関数名、メソッド名を推奨するプログラミング言語がありますし、予約語が日本語という言語もあります。

しかし、Java言語やProcessingを使用している場合、すべての実行環境で日本語で書かれたコードが実行可能か保証がありません。実際、現在このテキストで利用しているバージョンのProcessingの開発環境(Ver.2.2.1)ではコンパイルを通してくれません。

ProcessingでUnicodeの変数名を利用したところ
画像

なるべくメンテナンス性の高いソースコードを書くためにも、得意不得意に関わらず適切な英語を使う努力をしましょう。より多くの人たちとコードを共有する希望を持っているなら、なおさらコードには英語を用いましょう。

ソフトウエアの世界では英語が必須です。

もし、使用した英語に不安があるならば、コメントにネーミングの意図を日本語で書き残しましょう。

[作業] 次のsketchに使われている変数を、適切な英単語を調べて書き換えてください。

変数名を省略する事で、比較的読みやすい場合
double taijyuu = 75.4; // [kg]
double shintyou = 174.3 * 0.01; // [m]
double bmi = taijyuu / (shintyou * shintyou);
println("あなたのBMIは" + bmi + "です。");

複数の単語から成る名前の組み立て方

複数の単語で成り立つ名前を使う場合、単語の間に空白をはさむことができません。空白をはさまずに、複数の単語からなる名称を記述する方法(綴り方)を3つ紹介します。これらはそれぞれ使う場合(ケース)を分けます。すると、名前をぱっと一目見ただけで、その名前がクラス名なのか、パッケージ名なのか、メソッド名なのか、……などが判別できるのです。

3つの綴り方

綴り方の名称は次のとおりです。

ローワーキャメルケース(Lower Camel Case) 先頭の単語以外の単語の頭文字が大文字
アッパーキャメルケース(Upper Camel Case) 単語の頭文字が大文字。別名Pascalケース
スネークケース(Snake Case) 単語の間の区切りがアンダーバー_

場合に応じた綴り分け

以下に、場合に応じた綴り分けのルールを示します。

分類 解説
変数名 hasGirlFriend ローワーキャメルケース(以後LCC)
定数変数 GIRL_FRIEND_NAME すべて大文字のスネークケース
クラス名 FileReader アッパーキャメルケース(以後UCC)
インタフェイス名 IFileReader I + UCC
インタフェイスを実装するクラス FileReaderImpl UCC + Impl
抽象クラス AbstractFileReader Abstract + UCC
テストクラス FileReaderTest UCC + Test
パッケージ名 programmingnextstep すべて小文字
メソッド createFileReader LCCで先頭の単語は動詞

[作業] 携帯電話の機種変更を検討するプログラムを作っているとします。検討に必要なデータを保持するクラスと、各種データを格納するフィールド、必要なメソッドを検討し、それぞれに適切な名前をつけてください。

大文字と小文字の違いで名前を区別しない

Java言語はC言語と同じく、同じ綴りでも大文字と小文字が違えば別の名前となります。このような名称の区別方法は、バグやミスの温床になりますので、Java言語では推奨しません。

例えば名前を扱うために、次のように変数を名付けてしまったとします。

  • 在校生名:name
  • 保護者:Name

すると、ソースコード中で混乱が発生するでしょう。そして先に紹介した変数名の綴り方ルールにも反します。

このような区別が必要な場合には、次のようにすれば間違いありません。

  • 在校生名:studentName
  • 保護者名:parentName

大文字と小文字で区別できて便利だとは考えない癖をつけてください。

省略しない

単語は極力省略せずに記述しましょう。⁠生徒名」Student's NameからSNと省略したとしましょう。仮にどこかにSNは生徒名の略」とコメントしておいたとしても、コメントからは離れた場所ではSNが生徒名であることを容易に想像できるとは限りません。

例外的に、1画面程度の範囲のスコープ(変数やオブジェクトの有効な範囲)でのみ有効なローカル変数は、省略形の名前の使用を許容してもいいでしょう。ごく短い関数の中だけで用いられる変数、例えば「彼女の名前」ならばgfn、つまりgirlFriendNameの頭文字を取ってもよいでしょう。省略形を用いることで式がシンプルになるかどうか、後々誤解の可能性があるかどうかが基準です。

例えば、円の直径寸法を代入する実数変数を用意するとします。この変数名はdiameterが良いでしょうか。dが良いでしょうか。この場合はどちらでも良いでしょう。省略形のdは直径寸法の変数として一般に認知されています。むしろdiameterと書かれていると、私などは「あれ?」っと考えてしまうほどです。円の面積を求める式を書く際にも、省略形を用いないとやや読みにくい式になります。しかし次の式ぐらいなら差が際立ちませんね。

double a = 0.0;
double d = 10.0;
a = PI * d * d;
println("直径" + d + "の円の面積は" + a);
変数名を省略しないため式がやや長くなった
double area = 0.0;
double diameter = 10.0;
area = PI * diameter * diameter;
println("直径" + diameter + "の円の面積は" + area);

for文等のループ構造のカウンタ変数名には、慣習的に外側のループからi, j, k,…とアルファベット1文字を使うことがあります。長過ぎず、簡潔にカウンタ変数に名称が与えられるなら、慣習にこだわらず目的に応じた名称を与えるべきでしょう。

以上のことから、基本的には名称は省略を用いないことにしてください。ただし、ごく狭い範囲で使う変数やオブジェクトの名称ならば、ある程度省略や短縮を行っても問題になりません。また、ある程度複雑な式の中で使用する変数は、なるべく短い方が式の見通しを良くします。

変数名をつける場合には、このあたりのさじ加減を意識するべきです。

演習

演習1(難易度:easy)

以下の変数・クラス・定数を、場合に応じた文字で書き分けましょう。

  1. 白い靴の数(number of white shoes⁠⁠:変数
  2. 下駄箱に入れられる靴の最大数(capacity of shoes closet⁠⁠:定数
  3. 下駄箱(shoes closet⁠⁠:クラス
  4. 収納(closet⁠⁠:インタフェイス
  5. 収納インタフェイスを実装した下駄箱クラス:クラス
  6. 収納:抽象クラス
  7. 下駄箱に靴をしまう(put shoes back⁠⁠:メソッド

演習2(難易度:middle)

以下のそれぞれの場合について、適切な名前をつけましょう。

  1. ランチメニュー注文の文字列を入れる変数名
  2. カツカレーセットの値段を持つ整数定数名
  3. 食券自動販売機の役割を担うクラス名
  4. 食堂で提供するメニュー品目のインタフェイス名
  5. 食堂で提供する親子丼の、食堂で提供するメニュー品目のインタフェイスを実装するクラス名
  6. 食堂で提供するメニュー品目の抽象クラス
  7. 食券自動販売機の役割を担うクラスのテストクラス
  8. 食堂システムのパッケージ名
  9. 食券自動販売機の発券メソッド名

演習3(難易度:middle)

台形の面積を求めるメソッドを作ってください。引数の変数名は意味の分かりやすい名前にしましょう。

void setup(){
  double a = 10.0; //上底の長さ
  double b = 20.0; //下底の長さ
  double c = 15.0; //高さ
  println("上底 = " + a);
  println("下底 = " + b);
  println("高さ = " + c);
  println("面積 = " + areaTrapezoid(a,b,c));
}

// ここからメソッドareaTrapezoidを書いてください

まとめ

  • Java言語/Processingの基本的なコーディングルールであるネーミングルールを学習しました。

学習の確認

それぞれの項目でAを選択できなければ、本文や演習にもう一度取り組みましょう。

  1. 変数名やクラス名などに英語を使用する目的が理解できましたか?
    1. 理解できて、有効性を認めた。
    2. 理解できたが、納得はしていない。
    3. 理解できないし、有効だとも思えない。
  2. 演習問題をスムーズに解くことができましたか?
    1. できた。
    2. テキストを見ながら何とかできた。
    3. できなかった。

参考文献

  • 『Javaルールブック ~読みやすく効率的なコードの原則』⁠大谷晋平、米林正明、片山暁雄、横田健彦 共著、電通国際情報サービス 監修、技術評論社
    • コンパクトな書籍で、効率良くJava言語の標準的なコーディングルールを学習できます。
  • 『プログラミング作法』⁠Brian W.Kernighan, Rob Pike 著、福崎俊博 訳、KADOKAWA
    • 第1章「スタイル」にコーディングルールとその重要性がコンパクトにまとめられています。

演習解答

演習1 書き分け

  1. numberOfWhiteShoes
  2. CAPACITY_OF_SHOES_CLOSET
  3. ShoesCloset
  4. ICloset
  5. ShoesClosetImpl
  6. AbstractCloset
  7. putShoesBack

演習2 名前付け

  1. orderdDish
  2. NUGGET_CURRY_PRICE
  3. VendingMachine
  4. ICafeteriaMenu
  5. OYAKO_DONCafeteriaMenuImpl
  6. AbstractCafeteriaMenu
  7. VendingMachineTest
  8. cafeteriasystem
  9. VendingMachine.issue

演習3 sketch作成

おすすめ記事

記事・ニュース一覧