バックアップです。
うっかりコーディング規約のページを削除してしまいそうになったので、バックアップページを作りました。
コーディング規約
ファイル構成
1.ファイル名
publicクラスはそのクラスの1ファイルにする。
例:public class Customer は Customer.cs に入れる。
publicクラスはそのクラスの1ファイルにする。
例:public class Customer は Customer.cs に入れる。
非パブリッククラスはそのクラスが主に使われるパブリッククラスのファイルに含めてよい。
例外クラスは、1ファイルに複数クラスをまとめてもよい。
例外クラスは、1ファイルに複数クラスをまとめてもよい。
2.ファイルの位置
プロジェクトのルートディレクトリを決め、名前空間の “.” をディレクトリ階層に置き換えた位置に入れる。但し、ソリューション / プロジェクトに対応している名前空間の階層は、ソリューション名 / プロジェクト名をディレクトリ名に使用する。
プロジェクトのルートディレクトリを決め、名前空間の “.” をディレクトリ階層に置き換えた位置に入れる。但し、ソリューション / プロジェクトに対応している名前空間の階層は、ソリューション名 / プロジェクト名をディレクトリ名に使用する。
命名規約
1.英語と日本語
全ての識別子の名前は英語を用いること。
全ての識別子の名前は英語を用いること。
2.名前空間
企業略式名.組織略式名.テクノロジー名.機能名を使用する。また、テクノロジー名にはソリューションが、機能名にはプロジェクトが対応していること。
using Project5j.Bomberman...
企業略式名.組織略式名.テクノロジー名.機能名を使用する。また、テクノロジー名にはソリューションが、機能名にはプロジェクトが対応していること。
using Project5j.Bomberman...
3.クラス名
単語ごとに先頭大文字。
例:class PascalCasing
単語ごとに先頭大文字。
例:class PascalCasing
4.例外クラス名
最後をExceptionとしたクラス名。
例:class ClassNameEndsWithException
最後をExceptionとしたクラス名。
例:class ClassNameEndsWithException
5.インターフェイス名
クラス名に同じ。また常に最初にIを付ける。
例:interface INameOfInterface
また、クラスにある能力を加える様な利用の場合、その能力を示す形容詞とし、-ableを接尾にする。
例: IEnumerable, ICloneable, IXmlSerializable, …
クラス名に同じ。また常に最初にIを付ける。
例:interface INameOfInterface
また、クラスにある能力を加える様な利用の場合、その能力を示す形容詞とし、-ableを接尾にする。
例: IEnumerable, ICloneable, IXmlSerializable, …
6.抽象クラス名
抽象クラス名に適当な名前が無いとき、 Abstract から始まりサブクラス名を連想させる名前を付ける。
例:abstract class AbstractBeforeSubClassName
抽象クラス名に適当な名前が無いとき、 Abstract から始まりサブクラス名を連想させる名前を付ける。
例:abstract class AbstractBeforeSubClassName
7.非パブリックメンバ
先頭に"_"を付加する。
単語の先頭は小文字。それ以降、単語ごとに先頭大文字
例:private object _objectName;
先頭に"_"を付加する。
単語の先頭は小文字。それ以降、単語ごとに先頭大文字
例:private object _objectName;
8.パブリックメンバ
単語ごとに先頭大文字。
例:public object ObjectName;
単語ごとに先頭大文字。
例:public object ObjectName;
9.定数(const)
大文字もしくは大文字を"_"でつないだもの。
例:const int UPPERCASE = 0;
const int UPPERCASE_WITH_UNDERSCORES = 0;
大文字もしくは大文字を"_"でつないだもの。
例:const int UPPERCASE = 0;
const int UPPERCASE_WITH_UNDERSCORES = 0;
10.列挙型(enum)
単語ごとに先頭大文字。
例:enum PascalCasing
単語ごとに先頭大文字。
例:enum PascalCasing
11.列挙値
単語ごとに先頭大文字。
例:PascalCasing
単語ごとに先頭大文字。
例:PascalCasing
12.イベント名
単語ごとに先頭大文字。
例:event PascalCasingEvent()
単語ごとに先頭大文字。
例:event PascalCasingEvent()
13.デリゲート名
単語ごとに先頭大文字。変数名の末尾にHandlerを付加する。
どのような場合に呼び出されるか変数名を見てわかる名前をつけること。
悪い例:public delegate void StateHandler();
public delegate void TimeOutHandler();
単語ごとに先頭大文字。変数名の末尾にHandlerを付加する。
どのような場合に呼び出されるか変数名を見てわかる名前をつけること。
悪い例:public delegate void StateHandler();
public delegate void TimeOutHandler();
良い例:public delegate void StateChangedHandler();
public delegate void ThreadTimeOutHandler();
public delegate void ThreadTimeOutHandler();
14.メソッド名
先頭小文字。あとは単語ごとに大文字。
例:void pascalCasing();
object pascalCasing();
先頭小文字。あとは単語ごとに大文字。
例:void pascalCasing();
object pascalCasing();
15.ファクトリメソッド(オブジェクトをnewするもの)
createの後に先頭が小文字で始まるオブジェクト名を付加する。
例:ObjectName createObjectName();
createの後に先頭が小文字で始まるオブジェクト名を付加する。
例:ObjectName createObjectName();
16.コンバータメソッド(オブジェクトを別のオブジェクトに変換するもの)
to, fromの後に先頭が小文字で始まるオブジェクト名を付加する。
例:void toObjectName();
ObjectName fromObjectName(object obj1);
to, fromの後に先頭が小文字で始まるオブジェクト名を付加する。
例:void toObjectName();
ObjectName fromObjectName(object obj1);
17.プロパティ名
単語ごとに先頭大文字。
例:object PascalCasing {
}
単語ごとに先頭大文字。
例:object PascalCasing {
}
18.Boolean変数を返すメソッド
Is + 形容詞、Can + 動詞、Has + 過去分詞、三単元動詞、三単元動詞 + 名詞。
良い例:bool IsEmpty()
bool CanGet()
bool HasChanged()
bool Contains(object x)
bool ContainsKey(string key)
Is + 形容詞、Can + 動詞、Has + 過去分詞、三単元動詞、三単元動詞 + 名詞。
良い例:bool IsEmpty()
bool CanGet()
bool HasChanged()
bool Contains(object x)
bool ContainsKey(string key)
悪い例:bool Empty() //「空にする」という動詞的な意味に取れる。
bool CheckXXX() // trueがどちらの意味か分かりづらい。
理由 :if, while文等の条件が読みやすくなる。
またtrueがどちらの意味か分かりやすい。
bool CheckXXX() // trueがどちらの意味か分かりづらい。
理由 :if, while文等の条件が読みやすくなる。
またtrueがどちらの意味か分かりやすい。
19.bool変数
形容詞、is + 形容詞、can + 動詞、has + 過去分詞、三単元動詞、三単元動詞 + 名詞。
例:bool _isEmpty;
bool _dirty;
bool _containsMoreElements;
形容詞、is + 形容詞、can + 動詞、has + 過去分詞、三単元動詞、三単元動詞 + 名詞。
例:bool _isEmpty;
bool _dirty;
bool _containsMoreElements;
20.名前の対称性
クラス名、メソッド名を付ける際は、以下の英語の対称性に気を付ける。
Add / Remove
Insert / Delete
Get / Set
Start / Stop
Begin / End
Send / Receive
First / Last
Push / Pop
Up / Down
Upper / Bottom
Show / Hide
Source / Target
Open / Close
Source / Destination
Increment / Decrement
Lock / Unlock
Old / New
Next / Previous
クラス名、メソッド名を付ける際は、以下の英語の対称性に気を付ける。
Add / Remove
Insert / Delete
Get / Set
Start / Stop
Begin / End
Send / Receive
First / Last
Push / Pop
Up / Down
Upper / Bottom
Show / Hide
Source / Target
Open / Close
Source / Destination
Increment / Decrement
Lock / Unlock
Old / New
Next / Previous
21.ループカウンタ
スコープ(通用範囲)が狭いループカウンタには i, j, k という名前をこの順に使う。
スコープ(通用範囲)が狭いループカウンタには i, j, k という名前をこの順に使う。
22.スコープが狭い名前
スコープが狭い変数名は,型名を略したものを使って良い。
例: DataSet ds = new DataSet();
スコープが狭い変数名は,型名を略したものを使って良い。
例: DataSet ds = new DataSet();
23.意味がとれる名前
変数名から役割が読み取れる名前をできる限り指定すること。
悪い例:Copy(string s1, string s2)
変数名から役割が読み取れる名前をできる限り指定すること。
悪い例:Copy(string s1, string s2)
良い例:Copy(string source, string destination)
ガイドライン
1.public Variable
インスタンス変数は、極力publicにせず、妥当なプロパティを設ける。
理由:オブジェクト指向の標準。クラスの内部状態に勝手にアクセスさせるのはよくない。ただし、以下の条件をすべて満たす場合、インスタンス変数をpublicにし、直接アクセスさせてもよい。
●そのインスタンス変数が他のインスタンス変数と独立であり、単独で変更されても内部の整合性をくずさない。
●どちらにしても,get / setアクセサを書く。
●インスタンス変数の実装が将来に渡って変更されないことが確定している。
インスタンス変数は、極力publicにせず、妥当なプロパティを設ける。
理由:オブジェクト指向の標準。クラスの内部状態に勝手にアクセスさせるのはよくない。ただし、以下の条件をすべて満たす場合、インスタンス変数をpublicにし、直接アクセスさせてもよい。
●そのインスタンス変数が他のインスタンス変数と独立であり、単独で変更されても内部の整合性をくずさない。
●どちらにしても,get / setアクセサを書く。
●インスタンス変数の実装が将来に渡って変更されないことが確定している。
2.状態取得と状態変更の分離
メソッドは,「1つの事」を行うように設計せよ。特に、状態変更と状態取得の2つのサービスを1つのメソッドで行わない。状態を変更するメソッドの return 値はvoidにせよ。
理由1:1つの事を行うメソッドの方が分かりやすい。
理由2:並行性の制御、例外の安全保証がしやすい。
理由3:サブクラス化による拡張がしやすい。
メソッドは,「1つの事」を行うように設計せよ。特に、状態変更と状態取得の2つのサービスを1つのメソッドで行わない。状態を変更するメソッドの return 値はvoidにせよ。
理由1:1つの事を行うメソッドの方が分かりやすい。
理由2:並行性の制御、例外の安全保証がしやすい。
理由3:サブクラス化による拡張がしやすい。
3.オブジェクトの同値比較
オブジェクトの比較では Equals() メソッドを使い、== , != を使うな。特に、Stringの比較では == , != を使用してはならない。
理由:もし実装者がEquals()を用意しているなら、それを使ってほしくて実装したはず。また、Stringの比較では設定により大文字/小文字が区別されない場合があるため。
オブジェクトの比較では Equals() メソッドを使い、== , != を使うな。特に、Stringの比較では == , != を使用してはならない。
理由:もし実装者がEquals()を用意しているなら、それを使ってほしくて実装したはず。また、Stringの比較では設定により大文字/小文字が区別されない場合があるため。
4.宣言と初期化
ローカル変数は、初期値と共に宣言すること。
ローカル変数は、初期値と共に宣言すること。
5.大小比較演算子
大小の方向を統一することを目的として、
“<”、 “<=” を使い、”>”、 “>=” はなるべく避けること。
大小の方向を統一することを目的として、
“<”、 “<=” を使い、”>”、 “>=” はなるべく避けること。
6.メソッド引数の変更は悪
原則としてメソッドの引数は入力であり、出力としては使わないこと。すなわちメソッド内部で引数の状態を変更するメソッドを呼ばないこと。出力引数に新たなオブジェクトを代入しないこと。
悪い例:
void MoveX(Point p, int dx) {
p.X = p.X() + dx; // 引数を変更している(なるべく避ける)
}
void MoveX(Point p, int dx) {
Point p = New Point(p.X + dx, p.Y);
// これは呼び出し側に伝わらない
}
例外:パフォーマンスを気にする場合。
原則としてメソッドの引数は入力であり、出力としては使わないこと。すなわちメソッド内部で引数の状態を変更するメソッドを呼ばないこと。出力引数に新たなオブジェクトを代入しないこと。
悪い例:
void MoveX(Point p, int dx) {
p.X = p.X() + dx; // 引数を変更している(なるべく避ける)
}
void MoveX(Point p, int dx) {
Point p = New Point(p.X + dx, p.Y);
// これは呼び出し側に伝わらない
}
例外:パフォーマンスを気にする場合。
7.パフォーマンス調整は二の次
複雑な処理の場合、最初からパフォーマンスを気にしたコーディングをするべきではない。先に可読性、保守性を優先する。
複雑な処理の場合、最初からパフォーマンスを気にしたコーディングをするべきではない。先に可読性、保守性を優先する。
コメント
1.クラス
<summary>から始まり</summary>で終わるNDoc(*)形式を採用する。
クラスやインターフェイスなどを継承している場合は<remarks>から始まり</remarks>で終わるNDoc形式を採用する。
例:///<summary>
///概要
///</summary>
///<remarks>
///このクラスはProject5j.Bomberman.Class1を継承している。
///</remarks>
public class Class2 : Project5j.Bomberman.Class1 {
}
<summary>から始まり</summary>で終わるNDoc(*)形式を採用する。
クラスやインターフェイスなどを継承している場合は<remarks>から始まり</remarks>で終わるNDoc形式を採用する。
例:///<summary>
///概要
///</summary>
///<remarks>
///このクラスはProject5j.Bomberman.Class1を継承している。
///</remarks>
public class Class2 : Project5j.Bomberman.Class1 {
}
2.メンバ
<summary>から始まり</summary>で終わるNDoc形式を採用する。
例:///<summary>
///概要
///</summary>
object _objectName;
<summary>から始まり</summary>で終わるNDoc形式を採用する。
例:///<summary>
///概要
///</summary>
object _objectName;
3.プロパティ・インデックス
<value>から始まり</value>で終わるNDoc形式を採用する。
getアクセサを実装している場合は「取得する」と記述して、setアクセサを実装している場合は「設定する」と記述する。
例:///<value>
///値を取得する。
///</value>
object ObjectName {
get {
return _object;
}
}
<value>から始まり</value>で終わるNDoc形式を採用する。
getアクセサを実装している場合は「取得する」と記述して、setアクセサを実装している場合は「設定する」と記述する。
例:///<value>
///値を取得する。
///</value>
object ObjectName {
get {
return _object;
}
}
///<value>
///値を取得・設定する。
///</value>
object ObjectName {
get {
return _object;
}
set {
_object = value;
}
}
///値を取得・設定する。
///</value>
object ObjectName {
get {
return _object;
}
set {
_object = value;
}
}
4.メソッド
<summary>から始まり</summary>で終わるNDoc形式を採用する。
例:///<summary>
///概要
///</summary>
///<param name="obj1">オブジェクト1</param>
///<return>戻り値の説明</return>
public object methodName(object obj1) {
}
<summary>から始まり</summary>で終わるNDoc形式を採用する。
例:///<summary>
///概要
///</summary>
///<param name="obj1">オブジェクト1</param>
///<return>戻り値の説明</return>
public object methodName(object obj1) {
}
5.メソッド内部
いかなる場合でも、半角スペースを前後に使用した/* ... */を採用する。
例:/* 処理1 */
・・・
/*
* 処理1
* ここんところをこう、こう、こう。
*/
いかなる場合でも、半角スペースを前後に使用した/* ... */を採用する。
例:/* 処理1 */
・・・
/*
* 処理1
* ここんところをこう、こう、こう。
*/
(*)NDoc:ソースコードのコメントをXML, HTML形式でのドキュメントに変換するツール。
初版 2006.09.17 Y.Kawauchi