コーディング規約は非常に色々なものが提案されているが、その色々なものを見て来た中で、かなり自分勝手な方向でまとめてみる。
はじめに
コーディング規約というのは、さまざまな団体で独自に定められており、時にはそれが競合することもあろうかと思う。特にC++のプレフィックス関連が顕著だと思う。それに比べて、C#は割りと落ち着いたコーディング規約が根付いているのか、私の短いプログラミング人生の中で、そこまで読みにくいと思ったコードを見たことがない。これは、C#の言語構造やVisualStudioの自動整形も関係しているのかもしれないが。
というわけで、厳格なコーディング規約を設けずとも、それなりに読めてしまうC#でも、やはり規約を定めて、より読みやすく、統一性を持たせたコードを生産することは、非常に有意義なことだと考える。
代表的な記法
C#の命名規約についてを参考にしてほしい。一部を抜粋しておく。
Camel方式
private int sampleCount; private void sampleMethod(); int sampleMember; // 公開範囲を指定しない場合、privateになる
先頭の単語が小文字で、後に続く単語は、頭を大文字にして連結する。
- アンダースコア(_)は使用しない
- 先頭を大文字にしない
- 先頭以外の単語は頭を大文字にする
- privateなフィールドやメソッドは基本、これに従う
Pascal方式
public static string SampleFilename = "sample.txt"; public void SampleMethod();
すべての単語は頭を大文字にし、それぞれ連結する。
- アンダースコア(_)は使用しない
- すべての単語の頭は大文字
- publicなフィールド(静的なもの)やメソッドは基本、これに従う
- publicなプロパティもこれに従う
主な禁止事項
大文字をアンダーバーで区切る定数表現は使わない
public static int SAMPLE_CONST_VALUE = 10; public const string SAMPLE_FILENAME = "sample.txt";
C#においてこの表現は、どのような場面でも使用されない。C/C++における定数やプリプロセッサマクロ、Javaにおける定数などでこの表現が見られるが、C#では廃止されるべきだという考えが多数を占めている。
C#における定数表現は、Pascalを使用する。これは、既存のColor構造体の色を表す定数フィールドなどからも見て取れる(Color.Redなどとなっている)
プレフィックスを使用しない(主にハンガリアン記法)
string m_strSampleName; // フィールド(メンバ)変数の文字列name unsigned long g_ulSampleNum; // グローバルな符号なしlong整数
変数名の前に、その変数がどんな型であるかを明記する記法がある。これは、一般的にハンガリアン記法などと呼ばれている。
以前これに似た記法を積極的に使用していたMicrosoftも、.NET Frameworkでは非推奨どころか、使用しないこととしている。反対意見は調べれば色々と出てくるため割愛するとして、以下に有用性を主張する意見の解説を書く。
VSUG「ローカルxxxの命名について 」の議論にもあるように、フィールド変数などはアンダースコアを付けるという意見も、かなり見られる。これ派は、主に以下の点を主張している。
- フィールド変数名などを度忘れした時、アンダースコアを入力すると候補が表示されるため便利
- 公開範囲を限定された変数だとひとめでわかり便利
これについて、私は思うのだ。結局、ハンガリアン記法時代の[m_]と同じ。上記の利便性は、十分[this.]で達成されると、私は考える。この、「公開範囲をプレフィックスで明記する」という問題は、ある意味、宗教戦争といっても良いだろう。アンダーバー派の言い分も十分理解できるが、私にはどうしてもアンダーバーから始まる変数を定義する気が沸かない。
コーディング規約が定められた環境でプレフィックスを書けと言われたら従う他ないが、一応ここでの結論は「プレフィックスは公開範囲を表すものであっても、意味を表すもの(アプリケーションハンガリアンとも呼ばれる)であっても、付けるべきではない」としておく。
大原則
大原則として提案したいことがある。
- privateなものはCamel
- publicなものはPascal
- 静的な定数はPascal
- インターフェイスのプレフィックスとして[I(大文字のアイ)]を付ける
……早速、色々と議論を呼びそうなものを提案してしまった予感がする。
特に、私のような頭の回転の遅いものが、舌先三寸で丸め込まれそうな「インターフェイスのプレフィックスはI」というものである。これは、.NET Frameworkの仕様上そうなっているから、としか言えない。とりあえず、よく使うものは、以上のようなものだろうか。例外には後ろにExceptionを付ける等もあるが、日常的に使用しなさそうなので、わざわざの明記は避ける。
private method
前の記事でも話題にしたが、private methodの扱いに迷う。この記事での結論は、Camelで書くということにしておく。
このことを推論する理由は、以下のような操作を行った時に起きる不都合からである。ちなみに、本家ではメソッドはPascalに従うと書いてある。これをどう取るか、でもあるが。
- privateフィールド変数はCamel方式に従うため、VisualStudioでGUIを作る時のボタン名はsampleButtonとした
- sampleButtonのClickイベントを追加すると、自動で「private void sampleButton_Click(object sender, EventArgs e)」という空のメソッドが生成される
- メソッドはPascal方式に従うという原則に反する
このことから、本家の表記は、外部に提供する場合(public)に限っているのではないかと思われる。このことは、プロパティの項目からも、何かを匂わせる。プロパティもPascal指定があるが、サンプルコードがpublicなものだけな点は、考えすぎだろうか。
そもそもの前提にしている、privateなフィールドはCamelであるという規約も、実は怪しい感じではあるが。
結論?総論?
とりあえず気になった点だけをまとめてみたが、雑多であまり意義のないものになってしまったかもしれない。こういう問題を考える時に忘れがちなのが、読みやすいコードを書くために統一するという大前提であって、そのことを忘れて、ただ気持ち悪いからという理由を挙げるのはいかがなものかと、反省している。
混ぜ返すようだが、そのコミュニティでプレフィックスでわかりやすいという共通の認識があれば、別に使っても良いのかなー?
private methodについてですが、イベントメソッドの名前がPascalに反するというなら、Camelにも反していますよ。
Camelは(もちろんPascalも)アンダーバー“_”を使えませんから。
イベントは命名規則が特殊なものと考えたほうが良いかもしれません。
MSの本家とおっしゃられてる部分は「クラスライブラリ開発者向けの」ガイドラインなので、ソースを公開することは対象としていないはずです。
あれはコーディング規約というより、他の人が使うときにバラバラの命名規則で混乱しないようにとの意味だと思います。
ですので外から見えない部分については何も記載されていません。
privateフィールド変数はCamel形式に従う、とも書いてないですよ。
ですのでprivateは基本的に自由なはずですが、慣例的にprotectedやpublicと同じ規則を使うことが多いようです。
場合によっては先頭にアンダーバー“_”をつけたりする人もいますね。
前記事の参考ページでもそのような結論になっていたと思いますが…。
コメントありがとうございます。
ご指摘の件(イベントのアンダーバー)ですが、確かにその通りです。特殊な上で、アンダーバー以外でprivate methodと同義だと考えると、private methodの場合のみについて考えれば良いことになりますので、アンダーバーの箇所だけは無視して考えています。その部分にはあえて追求しません。
クラスライブラリ開発者向けのガイドラインということですが、確かにそう書いてありますね。基本的に、外部に提供する機能(public method, public propertyなど)についての統一の指標となるものであって、外部から見ることの出来ないprivateなものについては規定がありません。
private fieldについては仰るとおり規定がないわけです。
この場合の私の主張としましては、プレフィックスは基本使わないと言っているなら、アンダーバーという”プレフィックス”の付いたprivate fieldも、なんとなく気持ち悪いというわけです。ただ、MSの開発者たちは、アンダーバーやm_を使っている場合もあるとどっかで見た気がします。< m_などは、意味を表すプレフィックスになりますので、正直微妙なところだと思います。strやiなどといった型を表すプレフィックスはやるべきでないと考える人が多いようですね。しかし、GUIなどで用いるformやbuttonなどには、fやbといったプレフィックス、もしくは、FormやButtonといったサフィックスをつけたりする人も多いようですし、私も後者はやってしまいます。 そういうわけで長々と書きましたが、結局、自分もしくはグループ内でやりやすいように書くとしか良いようがないと思うんですよね、結局。 ほとんどのコーダーの間で共通した認識としては、引数などの局所変数はCamelと言ったことが挙げられると私は思ってますが、私としてはそういうものにprivateという共通項を見つけ出してprivate methodはCamelかなと考えた次第です。 この場合、「C#コーディング規約の個人的なまとめ」というよりは、「C#コーディング規約の個人的な提案」にしたほうが自然だったかもしれないです。
「大文字をアンダーバーで区切る定数表現」これって、そもそも定数を区別するためじゃなく、プリプロセッサーと
言語の識別子の衝突を避けるためなんですよね。C#はプリプロセッサ—が存在するので、定数に大文字だけの名前を
使っちゃいけないのは当然として、プリプロセッサー自体に対しては、大文字だけで書く規則を適用しないと
危険なんですよね。
浅学ながら失礼します
CamelとPascal逆なのではないでしょうか
こちらの間違いだったらすみません
msdnライブラリには以下の記述がありました。間違っていないとは思います……
http://msdn.microsoft.com/ja-jp/library/ms229043(v=vs.80).aspx
VisualStudioには「インテリセンス」なる便利な機能がある。
コーディング力がだんだん落ちてきている老兵には必須機能である…しかし、その機能を無視して命名するのはどうかと思う。
ので、我輩は
・メソッドのArgumentsなどはアンダーバー(_)+Pascal形式
・Privateはアンダーバー(_)+アンダーバー(_)+camel形式
・PublicなものはPascal形式
を採用している。
型を示すプレフィックスはうっとおしいしつけないのはまあわかるけど
今までの経験上メンバ変数に this. Me. を つけてるやつはあまりいない。
メンバ変数に m_ がついてるだけでかなり見やすくなるのは事実。
private void Form1_Load
ピンバック: ファイル自動バックアップバッチプログラムの作成 – 仕様編 – | Web屋のへっぽこ開発備忘録
プリプロセッサー意外の識別子を全部大文字にする件ですが実はCやC++でも禁止です。MSが勝手に大文字を乱用したために大文字の風習が広まっているようですが、全部大文字にするのは、プリプロセッサーで定義した識別子とその他の識別子が衝突して上書きされるのを防ぐため。ですので、特にCやC++でプリプロセッサー以外の識別子を全部大文字にしてはいけません。