c#coding guideline その2_20130325
TRANSCRIPT
Coding Guidelines for C# 3.0, 4.0 and 5.0 のご紹介 2回目
尾崎 義尚 @yoshioms
2013.3.25
C# コーディング ガイドライン日本語版
aviva SolutionsのDennis Doomenさんが公開しているコーディングガイドライン
aviva Solutions
オランダにあるコンサルティング会社
ソフトウェア開発のコンサルティングもやってるらしい
http://csharpguidelines.codeplex.com/releases/view/98254
C# コーディングガイドラインの一例 1/2
もう10年以上前のもので内容が古くなっている
欲しい情報が不足している
不要な情報が含まれている
C# コーディングガイドラインの一例 2/2
そもそも情報が少なすぎる
4ページしかない
っていうか、命名規約しかない。
https://docs.google.com/presentation/d/1ajbucKh09cSD_N3m5iUV9jBi7Ji34QczxD6xnjwfcIo/edit
時代に合わせた
コーディング標準が
必要!
さまざまな反響
Kokudoriさんの読評がすごい!
http://d.hatena.ne.jp/Kokudori/20130214/1360868503
文書の基本構造
重要度に応じて必要な規約を選択する
❶ 絶対に守るべきガイドライン
❷ 強くお薦めするガイドライン
❸ 状況に応じては推奨するガイドライン
全部を採用する必要はありません。
プロジェクトにあった選択を。
インターフェイスは小さく、集中的であるべきである
目的と役割を明確に説明できる名前を持つべきである
関連性の薄いメンバーを組み合わせてはならない
メンバーの責務を元にメンバーを分離して、呼び出し元は特定のタスクに関連するインターフェイスを呼び出すか実装する
インターフェイス分離原則として一般的に知られている
AV1003
クラスを分離するためにインターフェイスを使用する
インターフェイスはクラスを切り離すために非常に効果的なメカニズムである。
双方向の関係性を防ぐことができる
別の実装に置き換えることが容易である
本番環境以外で高価な外部サービスやリソースを一時的にスタブに置き換えることができる
ユニットテストでダミー実装やフェイクオブジェクトに置き換えることができる
特定のインターフェイスが要求されても、依存性注入フレームワークを使って、どのクラスを選択するかを集中管理できる
AV1005
派生クラスは、ベースクラスであるかのように処理を実行できなくてはならない
派生クラスを参照された場合でも、ベースクラスの参照と同じように使用できるようにするべきである
Note このルールは、S.O.L.I.D. 原則のひとつであるリスコフの置換原則としても知られている
AV1011
オブジェクトが依存するほかのオブジェクトを公開するのを避ける
デメテルの法則に違反している可能性がある。
オブジェクトは依存するほかのクラスを公開するべきではない。
将来それを置き換える機会を制限してしまう。
Note 流れるようなインターフェイスパターンはこのルールに違反しているように見えるが、メソッドチェーンを可能にするために自分自身を返しているだけである。
例外制御の反転や依存性注入のためだけにプロパティを公開するのはOK
AV1014
ステートフルなオブジェクトを静的メンバーとして公開してはいけない
ステートフルなオブジェクトとは、多くのプロパティ多くの振る舞いが含まれているオブジェクト
静的プロパティや静的メソッドを通じて、オブジェクトを他のオブジェクトに公開した場合、リファクタリングやユニットテストが難しく、ステートフルオブジェクトに依存したクラスになってしまう。
HttpContext.Currentプロパティはこの例のひとつ
ひどいコードとしてHttpContextのソースコードを参照して欲しい
AV1125
コレクションクラスの代わりにIEnumerable<T>やICollection<T>を返す
呼び出し元で内部コレクションを変更できないようにしたいので、配列、リストなどのコレクションクラスを直接返してはいけない。代わりにIEnumerable<T>や、呼び出し元でカウントが必要ならICollection<T>を返す。
Note .NET 4.5を使っているのであれば、 IReadOnlyCollection<T>、IReadOnlyList<T>、IReadOnlyDictionary<TKey, TValue>も使用することができる。
AV1130
いくつかの種類のステータスで返すよりも例外をスローする
成功か失敗かを報告する値を返すコードベースでは、ネストされたifステートメントですべてのコードで振り分けする傾向にある。呼び出し元はよく戻り値のチェックを忘れる。
構造化例外ハンドリングは、例外のスロー、高いレイヤでのキャッチや例外の置き換えを許可している。ほとんどのシステムで、予期しない状況での例外のスローはとても一般的である。
AV1200
例外はコストが高いのでステータスを返したい。予期しない状況であれば、例外を返してもよい。
リッチで意味のある例外メッセージテキストを提供する
メッセージは、例外が発生した理由を説明して、例外を避けるためにはどうする必要があるかを明確に説明する必要がある。
AV1202
開発者向けという意味なら問題ない。ユーザー向けというのであれば、リリースまでに修正するべきである。
非同期コード内の例外をきちんと処理する
async/awaitやTaskのコードで例外をスローまたは処理するときは、以下の2つのルールを忘れてはいけない。
async/await ブロックとTaskのアクション で例外が発生したときは、awaitしているものに伝搬される
非同期ブロックの前のコードで発生した例外は、呼び出し元に伝搬される
AV1215
各イベントを発生させるためにprotected virtualメソッドを使用する
rotectedメソッドをオーバーライドすることで、派生クラスからベースクラスのイベントを処理することができる。
protected virtualメソッドの名前は、イベントと同じ名前にOnをつけた名前にするべきである。
たとえば、TimeChangedというイベントのprotected virtualメソッドはOnTimeChangedという名前にする。
Note protected virtualメソッドをオーバーライドした派生クラスは、ベースクラスの実装を呼び出す必要はない。ベースクラスは、実装が呼び出されなかったとしても正しく動作できなくてはならない。
AV1225
長いけど要は、OnXXXでイベント処理できるように作れってことね。
該当する場合は、ジェネリック制約を使用する
ジェネリック型かメソッドのobject型からキャストする代わりにwhere制約やas演算子をジェネリックパラメータの正確な特性を指定するために使用する。例えば:
AV1240
class SomeClass{}
// Don'tclass MyClass<T>{
void SomeMethod(T t){
object temp = t;SomeClass obj = (SomeClass) temp;
}}
// Doclass MyClass<T> where T : SomeClass{
void SomeMethod(T t){
SomeClass obj = t;}
}
要はwhereを使えってことね。
二重否定の条件を避ける
customer.HasNoOrdersのようなプロパティは間違っていないが、以下のように否定条件で使用するのは避ける :
bool hasOrders = !customer.HasNoOrders;
二重否定は単純な表現よりも理解が難しく、人々は二重否定を簡単に読むことができない。
AV1502
二重否定だけじゃなくて、HasNo~というプロパティ名はどうだろう?! がNotというのは視認性が低い。(言語レベルの問題)
変数の宣言と初期化は可能な限り遅らせる
CとVisual Basicのようにすべての変数をブロックの最初に宣言するスタイルは避け、各変数が必要になった時点で定義して初期化する。
AV1521
C(99)やVBでも最初に宣言しなくても大丈夫になってるよ。
ステートメントをわけるよりもオブジェクトやコレクションの初期化子を使用する
以下のようにする代わりにAV1523
var startInfo = new ProcessStartInfo(“myapp.exe”);
startInfo.StandardOutput = Console.Output;
startInfo.UseShellExecute = true;
オブジェクト初期化子を使用する。var startInfo = new ProcessStartInfo(“myapp.exe”)
{
StandardOutput = Console.Output,
UseShellExecute = true
};
同様に、以下の代わりに
var countries = new List<string> { “Netherlands”, “United States” };
var countries = new List<string>();
countries.Add(“Netherlands”);
countries.Add(“United States”);
コレクションやディクショナリ初期化子を使用する。
Immutableにするためにコンストラクタで渡すことも多い
ループ変数をforやforeachループの中で変更しない
ループ変数を一か所だけでなく、ループ処理の中で変更すると通常は混乱をきたすことになる。このルールはforeachループにも適用されるが、通常は列挙子がコレクションの変更を検出する。
AV1530
for (int index = 0; index < 10; ++index)
{
if (some condition)
{index = 11; // 誤り! 代わりに‘break’ か‘continue’を使用する
}
}
3つずつ進めるために内部でインクリメントすることがある+3するよりもインクリメントのほうがクロック数を節約できる
ループのネストを避ける
ネストされたループを持つメソッドは単一のループのものより理解しづらい。実際のところ、ネストされたループを持つほとんどのケースは、データを結合するためにfrom キーワードを2回以上使用してLINQクエリに置き換えることで大幅にシンプルにできる。
AV1532
fromというよりもjoin
if、else、while、for、foreach、case などのキーワードの後に常にブロックを追加する
これはフォーム内のステートメントの混乱も防ぐこともできる:AV1535
if (b1) if (b2) Foo(); else Bar(); // どちらの ‘if’ が ‘else’に進むのか
// 正しくは:
if (b1)
{
if (b2)
{
Foo();
}
else
{
Bar();
}
}
上のコードには悪意がある。面倒なので書かないことも多い。(書かないことがある人が多かった)
すべてのif-else-ifステートメントはelseで終わる
例えば、AV1537
void Foo(string answer)
{
if (answer == "no")
{
Console.WriteLine("You answered with No");
}
else if (answer == "yes")
{
Console.WriteLine("You answered with Yes");
}
else
{// ここに到達したときになにが起こるのか 無視 そうじゃない場合は、
// throw an InvalidOperationException.
}
}
カバレッジを下げてしまうのでちょっと。。。
複数のreturn ステートメントを控える
ひとつの入り口、ひとつの出口は可読性の高いフロー制御を維持する原則である。ただし、メソッドが非常に小さく、ガイドラインAV1500に準拠している場合、複数のreturnステートメントは、何カ所かで更新されるbooleanフラグを管理するよりも可読性を向上させる。
AV1540
コードが長いときには途中でreturnしてもよいのでは?無駄にひとつのメソッドにとどまる必要はない。
単純な(条件付きの)割り当ての代わりにif-else ステートメントを使用しない
直接の意図を表現する。例えば、以下よりも AV1545
bool pos;
if (val > 0)
{
pos = true;
}
else
{
pos = false;
}
bool pos = (val > 0); // 初期化
以下のように書く。
return someString ?? “Unavailable”;
または、以下の代わりに
以下のように書く
string result;
if (someString != null)
{
result = someString;
}
else
{
result = “Unavailable”;
}
return result;
他のオーバーロードからもっともパラメータの多いメソッドを呼び出す
このガイドラインは、オプショナル引数を持つオーバーロードにのみ適用される。例えばAV1551
public class MyString
{
private string someText;
public MyString(string text)
{
this.someText = text;
}
public int IndexOf(string phrase)
{
return IndexOf(phrase, 0, someText.Length);
}
public int IndexOf(string phrase, int startIndex)
{
return IndexOf(phrase, startIndex, someText.Length - startIndex );
}
public virtual int IndexOf(string phrase, int startIndex, int count)
{
return someText.IndexOf(phrase, startIndex, count);
}
}
MyStringクラスはIndexOf の3つのオーバーロードを提供するが、そのうち2つはもっともパラメータの多いものを呼び出す。同じルールがクラスのコンストラクターに適用される; もっとも完全なオーバーロードを実装して、他のオーバーロードからthis()初期化子を使って呼び出す。また、同じ名前のパラメータは同じすべてのオーバーロードで同じ位置に現れるようにするべきである。
重要 派生クラスでこれらのメソッドのオーバーロードを可能にしたい場合、もっとも完全なオーバーロードをprotected virtualにして、すべてのオーバーロードから呼ばれるようにする。
bool フラグを受け取るメソッドを避ける
以下のようなシグニチャのメソッドについて考えてみよう:AV1564
public Customer CreateCustomer(bool platinumLevel) {}
Customer customer = CreateCustomer(true);
フラグを受け取るメソッドは2つ以上のことをやっていることが多く、2つ以上のメソッドにリファクタリングする必要がある。代替のソリューションとしてはフラグを列挙に置き換えることである。
一見するとこのシグニチャは問題ないように見えるが、このメソッドを呼び出すと、完全に目的を見失うことになる:
略称を使用しない
例えば、OnBtnClickではなくOnButtonClickを使用する。一文字の変数名を避け、iやqではなく、indexやqueryを使用する。
例外あなたの領域(ドメイン)で広く受け入れられて、よく知られている略称。例えば、UserInterfaceではなくUIなど。
AV1706
メンバー、パラメータ、変数には、型ではなく意味に応じた名前をつける
機能名を使用する。例えば、GetIntではなくGetLengthを使用する。
名前にEnum、Class 、Struct のような用語を使用しない。
コレクション型の識別子には、複数形の名前をつける。
AV1707
型名には、名詞、名詞句、形容詞句を使用する
悪い例としてSearchExamination(検査するため検索ページ)、Common (名詞で終わらない、目的を説明していない) 、SiteSecurity (名前は技術的にはOKだが、目的についてなにも説明していない)があげられる。よい例としては、BusinessBinder、SmartTextBox、EditableSingleCustomerがある。
クラスにUtilityやHelperなどの用語は使用しない。このようなクラスは通常、静的クラスであり、オブジェクト指向の原則(AV1008も参照)を考慮していない。
AV1708
ジェネリック型パラメータには説明的な名前を使用する
常にパラメータ名のプレフィックスにTを使用する
一文字の名前が完全にそれを説明しない限り常に説明的な名前を使用し、長い名前に価値がない場合は、ひともじTを型パラメータとして使用する。
型パラメータの名前には、設定された制約を示す名前を検討する。例えば、ISessionの制約があるパラメータはTSessionと呼ばれる。
AV1709
プロパティ名を適切につける
プロパティ名には、名詞、名詞句、ときどき形容詞句を使用する
Booleanプロパティには肯定的なフレーズを使用する。例えばCantSeekではなくCanSeek
Booeanプロパティには、Is、 Has、 Can、 Allows、Supportsなどのプレフィックスを検討する
型と同じ名前のプロパティを検討する。列挙型に強い型付けされているプロパティは、列挙型と同じ名前を使用することができる。例えば、CacheLevelという名前の列挙型がある場合、その中のひとつの値を返すプロパティ名もCacheLevelにすることができる
AV1715
Cantは、英語の言語的な問題。Tの発音は微妙
動詞と目的語をペアにしたメソッド名を使用する
ShowDialogのように動詞-目的語をペアにしたメソッド名を使用する。よい名前は、メンバーを「どうする(What)」かのヒントを与えるべきであり、可能であれば、「なぜ(Why)」も含める。また、メソッド名にはAndを含めてはいけない。これは、メソッドがひとつ以上のことをしていることを暗示しており、AV1115で説明されている単一責任の原則に違反している。
AV1720
Andはだめだけど、Orはいいの?String.IsNullOrEmpty()
イベント名には、動詞か動詞句を使用する
イベント名には、動詞か動詞句を使用する。例えば: Click、Deleted、 Closing、 Minimizing、Arriving。例えば、Searchイベントは以下のように宣言される:
public event EventHandler<SearchArgs> Search;
AV1735
意外とing→edという順番を知らない人もいる。英語は不規則変化するのがちょっと
非同期メソッドの接尾辞にはTaskAsyncまたはAsyncを使用する
一般的な規約では、TaskやTask<TResult>を返すメソッドは、接尾辞にAsyncを使用するが、そのようなメソッドがすでに存在している場合、代わりにTaskAsync を使用する。
AV1755
匿名メソッドではなくラムダ式を使用する
ラムダ式は、匿名メソッドよりもはるかにエレガントである。なので、以下の代わりに
AV2221
Customer c = Array.Find(customers, delegate(Customer c)
{
return c.Name == “Tom”;
});
ラムダ式を使用する。
Customer c = Array.Find(customers, c => c.Name == “Tom”);
また、以下の方がさらによい。
var customer = customers.Where(c => c.Name == “Tom”);
delegateは負の遺産
すべてのpublic、protected、internalタイプとメンバーにドキュメントを記述する
どこかであなたのクラスが使われたときにVisual Studioでドキュメントがポップアップされるようにドキュメントを記述する。あなたのクラスを正しくドキュメント化することによって、ツールはクラスのドキュメントを生成することができる。
AV2305
コメントをローカライズできないのが問題国際化対応できるようにして欲しい
他の開発者を念頭に置いてXMLドキュメントを記述する
他の開発者を念頭に置いて、型のドキュメントを記述する。
彼または彼女がソースコードにアクセスできないことを想定して、その型の機能を最大限に活用できる方法を説明するようにする。
AV2306
多言語対応が難しい。ローカライズできるようにして欲しい。
インラインコメントを避ける
コメントを使ってコードのブロックを説明する必要性を感じた場合、明確な名前を持つブロックに置き換えることを検討する。
AV2310
日本人がソースコードを文章として読めるかどうか。
使えるオブジェクトを返すコンストラクターだけを作成する
オブジェクトが使用可能になるまでに追加でプロパティに値をセットする必要がないように設計する。
ただし、コンストラクターに3つより多いパラメータが必要 (AV1561
に違反している) な場合、そのクラスは責務を持ちすぎている(AV1000に違反) 可能性がある。
AV1001
複数の実装をサポートするためにベースクラスではなくインターフェイスを使用する
クラスに拡張ポイントを公開したい場合、ベースクラスではなくインターフェイスを公開した方がよい
拡張ポイントのユーザーが望まない動作をするベースクラスの実装を強要したくないはず
ただし、開始点としてデフォルト実装(abstract)を提供することで便利になるかもしれない
AV1004
静的クラスを避ける
拡張メソッドコンテナをのぞいて静的なクラスは粗悪な設計のコードに繋がることが多い。
またすごいハックツールを使いたい場合を除いて、テストの分離が難しくなる。
Note 静的クラスがどうしても必要な場合、Staticとしてマークしてコンパイラがインスタンスメンバーとクラスをインスタンス化することを防ぐようにする。これで明示的なprivateコンストラクターを作成する必要がなくなる。
AV1008
プロパティの代わりにメソッドを使用する
フィールドの値をセットするよりも負荷が大きいもの
Object.ToString メソッドのように変換を意味するもの
引数が同じでも、呼び出されるたびに異なる結果を返す場合。例えば、NewGuidメソッドは、呼び出されるたびに違う値を返すもの
直接関係ないプロパティの内部状態によって異なる(コマンドとクエリ分離に違反)など、操作の副作用が発生するもの
例外内部キャッシュへの投入や遅延読み込みはよい例である。
AV1105
プロパティとメソッドの使い分け基準
プリミティブよりもドメイン固有の値型を検討する
string, int, decimalなどを使うのではなく、ISBN番号、Eメールアドレスや金額などドメイン固有の型など、データとそれに適用されるバリデーションルールの両方をラップした専用の値オブジェクトの作成を検討する。
これを行うことにより、同じビジネスルールが複数存在することがなくなり、保守性とバグの防止の両方が改善される。
AV1140
わかるけど面倒なことも多い。簡単にできる言語もある。
もっとも適した例外をスローする
例えば、メソッドが引数にnullを受け取った場合、基本型のArgumentExceptionではなく、ArgumentNullExceptionをスローするべきである。
AV1205
プロパティ変更イベントの提供を検討する
プロパティが変更された時に発生するイベントの提供を検討する。PropertyChangedという名前のイベントを付けるべきで、Propertyはこのイベントに関連づけられたプロパティの名前に置き換えられるべきである。
Note クラスが、対応するイベントが必要な多くのプロパティを持っている場合、INotifyPropertyChangedインターフェイスの実装を検討する。これはプレゼンテーションモデルとModel-View-ViewModelパターンでよく使用されている。
AV1230
アセンブリ名にはそれに含まれる名前空間を使用する
すべてのDLLは<Company>.<Component>.dll のパターンで、<Company>は、企業名で、<Component>はひとつ以上のドットで区切られた節を含んでいる名前を使用するべきである。例えば、
AvivaSolutions.Web.Controls.dll.
例として、アセンブリで公開しているAvivaSolutions.Web.Binding名前空間の下のグループを検討してみよう。ガイドラインによるとアセンブリは次のように呼ばれるべきである。
AvivaSolutions.Web.Binding.dll.
例外無関係な複数の名前空間からクラスを集めてひとつのアセンブリに結合する場合、アセンブリの最後にCoreをつけることを検討する。ただし、名前空間にはつけない。例えば、
AvivaSolutions.Consulting.Core.dll.
AV1505
ソースファイル名にはそれに含まれる型を使用する
ファイルの名前にはPascal Caseを使用して、アンダースコアを使用しない。
AV1506
ソースコードファイルに含めるのはひとつの型に制限する
例外ネストされた型は明らかに同じファイルの一部である必要がある。
AV1507
ソースファイル名には、partialタイプの論理機能をつける
Partialタイプを使用して、ファイルごとに一部を割り当てている場合、それぞれのファイル名は論理パートの後にパートが果たしていることをつける。例えば、
// In MyClass.cs
public partial class MyClass
{...}
// In MyClass.Designer.cs
public partial class MyClass
{...}
AV1508
完全な型名の代わりにusing ディレクティブを使用する
名前の衝突を防ぐために完全な名前を制限する。例えば、以下のように使用しない。
var list = new System.Collections.Generic.List<string>();
代わりに以下のようにする。
using System.Collections.Generic;
var list = new List<string>();
名前の衝突を防ぐ必要がある場合、usingディレクティブを使って別名を割り当てる:
using Label = System.Web.UI.WebControls.Label;
上記3つの例では、期待している型が明確である。より詳細な varによるメリット・デメリットは、Eric Lippert氏の型推論を使うかどうかを参照して欲しい。
AV1510
まじで?あんまりみたことがない。
パラメータを一時変数として使用しない
一時的な状態を保持する便利な変数としてパラメータを使用してはならない。一時的な変数と型が同じであったとしても、一時変数としての目的を反映していない。
AV1568
使っちゃうこともある。きちんとした変数がついていれば使われないかも
変数、パラメータ、型メンバーに数字を含めない
ほとんどのケースで明確に意図を示さない名前をつけているのは怠けているだけである。
AV1704
COMを否定したいんだよね?
メンバー名は、関連する.NET Frameworkクラスのメンバーと同様にする
.NET開発者はすでにフレームワークユーザーのパターンになれているため、同じパターンのものはあなたのクラスの助けになる
例えば、コレクションのように振る舞うクラスを定義した場合、AddItem、Delete、NumberOfItemsではなく、Add、Remove 、Countのようなメンバーを提供する。
AV1711
ドメインの言葉があれば、それを使った方がいいかも。DeleteとRemoveは混乱しているかも。
名前空間名には、名前、レイヤ、動詞、機能を使用する
例えば、以下の名前空間はこのガイドラインのよい例である。
AvivaSolutions.Commerce.Web
NHibernate.Extensibility
Microsoft.ServiceModel.WebApi
Microsoft.VisualStudio.Debugging
FluentAssertion.Primitives
CaliburnMicro.Extensions
Note 名前空間には型の名前を含めてはいけないが、複数形の名詞、例えば Collectionsは通常OKである。
AV1725
事前イベントと事後イベントには、-ing と -ed を使用する
例えば、ウィンドウが閉じる前に発生するcloseイベントはClosing
ウィンドウが閉じた後で発生するイベントはClosed
事前、または事後イベントを示すためにBeforeやAfterプレフィックスやサフィックスを使用してはいけない。
DeletingとDeletedイベントをBeginDeleteとEndDeleteとしてイベントを定義するのは避ける。
Deleting: オブジェクトが削除される前に発生する
Delete:オブジェクトがイベントハンドラで削除される必要がある時に発生する
Deleted: オブジェクトがすでに削除されたときに発生する
AV1737
イベントハンドラのプレフィックスとしてOnを使用する
イベントを処理するメソッドにはOnをプレフィックスにするとよい。例えば、Closingイベントを処理するメソッド名はOnClosingにする。
AV1738
重要でないラムダパラメータにはアンダースコアを使用する
例えば、イベントをサブスクライブするのにラムダステートメントを使用する場合、イベントの実際のパラメータは重要でないことをより明確にするため、以下の規則を使用する。
button.Click += (_, __) => HandleClick();
AV1739
クラス内の拡張メソッドのグループは、Extensionsサフィックスを使用する
拡張メソッドの名前が、他のメンバーや拡張メソッドと競合する場合、クラス名にプレフィックスを付ける必要がある。Extensionsサフィックスを持つクラスは可読性を向上させる。
AV1745
IEnumerable<T>が空かどうかを確認するためにAny()の使用を検討する
メソッドや他のメンバーがCountプロパティを公開しないIEnumerable<T>や他のコレクションクラスを返す場合、コレクションにアイテムが含まれているかどうかを判定するためにCount()ではなくAny()拡張メソッドを使用する。
Count()を使用する場合、コレクション全体を反復する重大なインパクト(それが実際に永続ストアへのIQueryable<T>など)を与えるリスクがある。
Note IEnumerable<T>を返す場合、AV1130 で説明されているようにオーナーが外部からの編集を防ぎ、.NET 4.5以上で開発している場合は、新しい読み取り専用クラスを検討する。
AV1800
ローカライズされたリソースを参照するプロパティ、変数、フィールドに適切な名前をつける
このトピックのガイドラインは、エラーメッセージやメニューテキストのようにローカライズされたリソースに適用される。
リソースキーにPascal caseを使用する
短い識別子よりも説明的なものを提供する。可能であれば簡潔にするが、読みやすさを重視する。
リソースの名前には、英数字のみを使用する。
AV2205
デプロイメントで変更される文字列をハードコードしない
例えば、接続文字列やサーバーアドレスなど。
ConfigurationManagerクラスのConnectionStringsプロパティやVisual
Studioによって生成されたSettingsクラスなどのResourcesを使用する。
実際の値は、app.configやweb.config(と間違えなくカスタム構成ストア)で維持する。
AV2207
AssemblyInfo.csファイルの属性を正しく埋める
会社名、説明、著作権、バージョンなどの属性が埋められていることを確認する。すべてのアセンブリで、バージョンなどのフィールドに同じ値がきちんと埋められていることを確認するひとつの方法は、AssemblyInfo.csの対応する属性をソリューション内のプロジェクトで共有されるSolutionInfo.csに移動することである。
AV2215
そうだよねー。でも面倒
シンプルな表現へのLINQ(クエリ式)は避ける
以下の記述よりも
var query = from item in items where item.Length > 0;
System.Linq名前空間の拡張メソッドを使用する。
var query = items.Where(i => i.Length > 0);
LINQクエリは可読性のために複数行で書くべきなので、2番目の例の方がもう少し可読性が高い。
AV2220
クエリ式自体それほど使っていない。拡張メソッドがほとんど。
MSDNスタイルのドキュメントを記述する
開発者がドキュメントをより簡単に見つけられるように以下のMSDN
オンラインヘルプのスタイルと単語を選択する。
Tip GhostDocは、ショートカットキーを使用してコードをドキュメント化する起点を生成することができる。
AV2307
後で作業を追跡できるようにするためにコメントを使用しない
TODOなどのコメントを使って、コードのブロックややるべき作業を記述することは、やるべき作業を追跡する合理的な方法に見えるかもしれない。
しかし実際には、誰もそのようなコメントを探すことはない。残作業を追跡するためにTeam Foundation Serverなどの作業アイテムトラッキングシステムを使用する。
AV2318
VSでもTODOリストが出てくる。
企業ごとの名前空間の並び順とグループ
AV2402
そうなんだ?コーディングガイドラインと一緒に公開されているReSharperルールセットを入れると自動的にやってく
れる。
// Microsoft 名前空間を最初にする
using System;
using System.Collections;
using System.XML;
// その後、他の名前空間をアルファベット順に
using AvivaSolutions.Business;
using AvivaSolutions.Standard;
using Telerik.WebControls;
using Telerik.Ajax;
全部を採用する必要はありません。
プロジェクトにあった選択を。