SlideShare una empresa de Scribd logo
1 de 71
Descargar para leer sin conexión
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
   インターフェイスはクラスを切り離すために非常に効果的なメ
    カニズムである。
     双方向の関係性を防ぐことができる
     別の実装に置き換えることが容易である
     本番環境以外で高価な外部サービスやリソースを一時的にス
     タブに置き換えることができる
     ユニットテストでダミー実装やフェイクオブジェクトに置き
     換えることができる
     特定のインターフェイスが要求されても、依存性注入フレー
     ムワークを使って、どのクラスを選択するかを集中管理でき
     る
派生クラスは、ベースクラスであるかのように処理を実行できなくてはな
               らない
                                              AV1011
   派生クラスを参照された場合でも、ベースクラスの参照と同じよう
    に使用できるようにするべきである
   Note このルールは、S.O.L.I.D. 原則のひとつであるリスコフの置換
    原則としても知られている
オブジェクトが依存するほかのオブジェクトを公開するのを避ける
                                        AV1014
   デメテルの法則に違反している可能性がある。
   オブジェクトは依存するほかのクラスを公開するべきではない。
     将来それを置き換える機会を制限してしまう。

   Note 流れるようなインターフェイスパターンはこのルールに違反し
    ているように見えるが、メソッドチェーンを可能にするために自分
    自身を返しているだけである。
   例外 制御の反転や依存性注入のためだけにプロパティを公開するの
    はOK
ステートフルなオブジェクトを静的メンバーとして公開してはいけない
                                           AV1125
   ステートフルなオブジェクトとは、多くのプロパティ多くの振る舞
    いが含まれているオブジェクト
   静的プロパティや静的メソッドを通じて、オブジェクトを他のオブ
    ジェクトに公開した場合、リファクタリングやユニットテストが難
    しく、ステートフルオブジェクトに依存したクラスになってしまう。
   HttpContext.Currentプロパティはこの例のひとつ
     ひどいコードとしてHttpContextのソースコードを参照して欲し
     い
コレクションクラスの代わりにIEnumerable<T>やICollection<T>を返す
                                                               AV1130
   呼び出し元で内部コレクションを変更できないようにしたいので、
    配列、リストなどのコレクションクラスを直接返してはいけない。
    代わりにIEnumerable<T>や、呼び出し元でカウントが必要なら
    ICollection<T>を返す。
   Note .NET 4.5を使っているのであれば、 IReadOnlyCollection<T>、
    IReadOnlyList<T>、IReadOnlyDictionary<TKey, TValue>も使用するこ
    とができる。
いくつかの種類のステータスで返すよりも例外をスローする
                                      AV1200
   成功か失敗かを報告する値を返すコードベースでは、ネストされた
    ifステートメントですべてのコードで振り分けする傾向にある。呼
    び出し元はよく戻り値のチェックを忘れる。
   構造化例外ハンドリングは、例外のスロー、高いレイヤでのキャッ
    チや例外の置き換えを許可している。ほとんどのシステムで、予期
    しない状況での例外のスローはとても一般的である。



             例外はコストが高いのでステータスを返したい。
             予期しない状況であれば、例外を返してもよい。
リッチで意味のある例外メッセージテキストを提供する
                                           AV1202
   メッセージは、例外が発生した理由を説明して、例外を避けるため
    にはどうする必要があるかを明確に説明する必要がある。




                開発者向けという意味なら問題ない。
        ユーザー向けというのであれば、リリースまでに修正するべきである。
非同期コード内の例外をきちんと処理する
                                             AV1215
   async/awaitやTaskのコードで例外をスローまたは処理するときは、
    以下の2つのルールを忘れてはいけない。
             ブロックとTaskのアクション で例外が発生したとき
     async/await
     は、awaitしているものに伝搬される
     非同期ブロックの前のコードで発生した例外は、呼び出し元に伝
     搬される
各イベントを発生させるためにprotected virtualメソッドを使用する
                                                   AV1225
   rotectedメソッドをオーバーライドすることで、派生クラスから
    ベースクラスのイベントを処理することができる。
   protected virtualメソッドの名前は、イベントと同じ名前にOnをつ
    けた名前にするべきである。
   たとえば、TimeChangedというイベントのprotected virtualメソッ
    ドはOnTimeChangedという名前にする。
   Note protected virtualメソッドをオーバーライドした派生クラス
    は、ベースクラスの実装を呼び出す必要はない。ベースクラスは、
    実装が呼び出されなかったとしても正しく動作できなくてはならな
    い。

           長いけど要は、OnXXXでイベント処理できるように作れってことね。
該当する場合は、ジェネリック制約を使用する
                                                                AV1240
   ジェネリック型かメソッドのobject型からキャストする代わりに
    where制約やas演算子をジェネリックパラメータの正確な特性を指
    定するために使用する。例えば:
class SomeClass
{}

// Don't
class MyClass<T>
{
    void SomeMethod(T t)
    {
         object temp = t;
         SomeClass obj = (SomeClass) temp;
    }
}

// Do
class MyClass<T> where T : SomeClass
{
    void SomeMethod(T t)
    {

    }
        SomeClass obj = t;
                                             要はwhereを使えってことね。
}
二重否定の条件を避ける
                                               AV1502
   customer.HasNoOrdersのようなプロパティは間違っていないが、以
    下のように否定条件で使用するのは避ける :
   bool hasOrders = !customer.HasNoOrders;
   二重否定は単純な表現よりも理解が難しく、人々は二重否定を簡単
    に読むことができない。



          二重否定だけじゃなくて、HasNo~というプロパティ名はどうだろう?
             ! がNotというのは視認性が低い。(言語レベルの問題)
変数の宣言と初期化は可能な限り遅らせる
                                             AV1521
   CとVisual Basicのようにすべての変数をブロックの最初に宣言する
    スタイルは避け、各変数が必要になった時点で定義して初期化する。




            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>();
countries.Add(“Netherlands”);
countries.Add(“United States”);

    コレクションやディクショナリ初期化子を使用する。
var countries = new List<string> { “Netherlands”, “United States” };


                                      Immutableにするためにコンストラクタで渡すことも多い
ループ変数をforやforeachループの中で変更しない
                                                         AV1530
   ループ変数を一か所だけでなく、ループ処理の中で変更すると通常
    は混乱をきたすことになる。このルールはforeachループにも適用さ
    れるが、通常は列挙子がコレクションの変更を検出する。
for (int index = 0; index < 10; ++index)
{
   if (some condition)
   {
       index = 11; // 誤り! 代わりに‘break’ か‘continue’を使用する
   }
}




                          3つずつ進めるために内部でインクリメントすることがある
                         +3するよりもインクリメントのほうがクロック数を節約できる
ループのネストを避ける
                                        AV1532
   ネストされたループを持つメソッドは単一のループのものより理解
    しづらい。実際のところ、ネストされたループを持つほとんどの
    ケースは、データを結合するためにfrom キーワードを2回以上使用
    してLINQクエリに置き換えることで大幅にシンプルにできる。




                 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 ステートメントを控える
                                           AV1540
   ひとつの入り口、ひとつの出口は可読性の高いフロー制御を維持す
    る原則である。ただし、メソッドが非常に小さく、ガイドライン
    AV1500に準拠している場合、複数のreturnステートメントは、何カ
    所かで更新されるbooleanフラグを管理するよりも可読性を向上させ
    る。




            コードが長いときには途中でreturnしてもよいのでは?
             無駄にひとつのメソッドにとどまる必要はない。
単純な(条件付きの)割り当ての代わりにif-else ステートメントを
             使用しない
     直接の意図を表現する。例えば、以下よりも                 AV1545
     bool pos;
     if (val > 0)
     {
         pos = true;
     }
     else
     {
         pos = false;
     }
     以下のように書く。
     bool pos = (val > 0);   // 初期化

     または、以下の代わりに
     string result;
     if (someString != null)
     {
         result = someString;
     }
     else
     {
         result = “Unavailable”;
     }
     return result;

     以下のように書く
     return someString ?? “Unavailable”;
他のオーバーロードからもっともパラメータの多いメソッドを呼
             び出す
                                                                                  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つ以上のメソッドにリファクタリングする必要がある。代替のソ
    リューションとしてはフラグを列挙に置き換えることである。
略称を使用しない
                                                 AV1706
   例えば、OnBtnClickではなくOnButtonClickを使用する。一文字の変
    数名を避け、iやqではなく、indexやqueryを使用する。
   例外 あなたの領域(ドメイン)で広く受け入れられて、よく知られ
    ている略称。例えば、UserInterfaceではなくUIなど。
メンバー、パラメータ、変数には、型ではなく意味に応じた名前
            をつける
                                             AV1707
   機能名を使用する。例えば、GetIntではなくGetLengthを使用する。
   名前にEnum、Class 、Struct のような用語を使用しない。
   コレクション型の識別子には、複数形の名前をつける。
型名には、名詞、名詞句、形容詞句を使用する
                                              AV1708
   悪い例としてSearchExamination(検査するため検索ページ)、
    Common (名詞で終わらない、目的を説明していない) 、
    SiteSecurity (名前は技術的にはOKだが、目的についてなにも説明
    していない)があげられる。よい例としては、BusinessBinder、
    SmartTextBox、EditableSingleCustomerがある。
   クラスにUtilityやHelperなどの用語は使用しない。このようなクラ
    スは通常、静的クラスであり、オブジェクト指向の原則(AV1008も参
    照)を考慮していない。
ジェネリック型パラメータには説明的な名前を使用する
                                             AV1709
   常にパラメータ名のプレフィックスにTを使用する
   一文字の名前が完全にそれを説明しない限り常に説明的な名前を使
    用し、長い名前に価値がない場合は、ひともじTを型パラメータとし
    て使用する。
   型パラメータの名前には、設定された制約を示す名前を検討する。
    例えば、ISessionの制約があるパラメータはTSessionと呼ばれる。
プロパティ名を適切につける
                                                     AV1715
   プロパティ名には、名詞、名詞句、ときどき形容詞句を使用する
   Booleanプロパティには肯定的なフレーズを使用する。例えば
    CantSeekではなくCanSeek
   Booeanプロパティには、Is、 Has、 Can、 Allows、Supportsなどの
    プレフィックスを検討する
   型と同じ名前のプロパティを検討する。列挙型に強い型付けされて
    いるプロパティは、列挙型と同じ名前を使用することができる。例
    えば、CacheLevelという名前の列挙型がある場合、その中のひとつ
    の値を返すプロパティ名もCacheLevelにすることができる


                 Cantは、英語の言語的な問題。Tの発音は微妙
動詞と目的語をペアにしたメソッド名を使用する
                                                      AV1720
   ShowDialogのように動詞-目的語をペアにしたメソッド名を使用する。
    よい名前は、メンバーを「どうする(What)」かのヒントを与えるべ
    きであり、可能であれば、「なぜ(Why)」も含める。また、メソッド
    名にはAndを含めてはいけない。これは、メソッドがひとつ以上の
    ことをしていることを暗示しており、AV1115で説明されている単一
    責任の原則に違反している。




            Andはだめだけど、Orはいいの?String.IsNullOrEmpty()
イベント名には、動詞か動詞句を使用する
                                                           AV1735
   イベント名には、動詞か動詞句を使用する。例えば: Click、
    Deleted、 Closing、 Minimizing、Arriving。例えば、Searchイベント
    は以下のように宣言される:
   public event EventHandler<SearchArgs> Search;




                     意外とing→edという順番を知らない人もいる。
                        英語は不規則変化するのがちょっと
非同期メソッドの接尾辞にはTaskAsyncまたはAsyncを使用する
                                              AV1755
   一般的な規約では、TaskやTask<TResult>を返すメソッドは、接尾辞
    にAsyncを使用するが、そのようなメソッドがすでに存在している場
    合、代わりにTaskAsync を使用する。
匿名メソッドではなくラムダ式を使用する
                                                                              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タイプとメンバーにドキュ
                メントを記述する
                                             AV2305
    どこかであなたのクラスが使われたときにVisual Studioでドキュメ
     ントがポップアップされるようにドキュメントを記述する。あなた
     のクラスを正しくドキュメント化することによって、ツールはクラ
     スのドキュメントを生成することができる。




                コメントをローカライズできないのが問題
                  国際化対応できるようにして欲しい
他の開発者を念頭に置いてXMLドキュメントを記述する
                                     AV2306
   他の開発者を念頭に置いて、型のドキュメントを記述する。
   彼または彼女がソースコードにアクセスできないことを想定して、
    その型の機能を最大限に活用できる方法を説明するようにする。




                  多言語対応が難しい。
              ローカライズできるようにして欲しい。
インラインコメントを避ける
                                      AV2310
   コメントを使ってコードのブロックを説明する必要性を感じた場合、
    明確な名前を持つブロックに置き換えることを検討する。




           日本人がソースコードを文章として読めるかどうか。
使えるオブジェクトを返すコンストラクターだけを作成する
                                          AV1001
   オブジェクトが使用可能になるまでに追加でプロパティに値をセッ
    トする必要がないように設計する。
   ただし、コンストラクターに3つより多いパラメータが必要 (AV1561
    に違反している) な場合、そのクラスは責務を持ちすぎている
    (AV1000に違反) 可能性がある。
複数の実装をサポートするためにベースクラスではなくインター
          フェイスを使用する
                                           AV1004
   クラスに拡張ポイントを公開したい場合、ベースクラスではなくイ
    ンターフェイスを公開した方がよい
   拡張ポイントのユーザーが望まない動作をするベースクラスの実装
    を強要したくないはず
   ただし、開始点としてデフォルト実装(abstract)を提供することで便
    利になるかもしれない
静的クラスを避ける
                                           AV1008
   拡張メソッドコンテナをのぞいて静的なクラスは粗悪な設計のコー
    ドに繋がることが多い。
   またすごいハックツールを使いたい場合を除いて、テストの分離が
    難しくなる。
   Note 静的クラスがどうしても必要な場合、Staticとしてマークして
    コンパイラがインスタンスメンバーとクラスをインスタンス化する
    ことを防ぐようにする。これで明示的なprivateコンストラクターを
    作成する必要がなくなる。
プロパティの代わりにメソッドを使用する
                                        AV1105
   フィールドの値をセットするよりも負荷が大きいもの
   Object.ToString メソッドのように変換を意味するもの
   引数が同じでも、呼び出されるたびに異なる結果を返す場合。例え
    ば、NewGuidメソッドは、呼び出されるたびに違う値を返すもの
   直接関係ないプロパティの内部状態によって異なる(コマンドとクエ
    リ分離に違反)など、操作の副作用が発生するもの
   例外 内部キャッシュへの投入や遅延読み込みはよい例である。




                  プロパティとメソッドの使い分け基準
プリミティブよりもドメイン固有の値型を検討する
                                                   AV1140
   string, int, decimalなどを使うのではなく、ISBN番号、Eメールアド
    レスや金額などドメイン固有の型など、データとそれに適用される
    バリデーションルールの両方をラップした専用の値オブジェクトの
    作成を検討する。
   これを行うことにより、同じビジネスルールが複数存在することが
    なくなり、保守性とバグの防止の両方が改善される。




                     わかるけど面倒なことも多い。
                      簡単にできる言語もある。
もっとも適した例外をスローする
                                                        AV1205
   例えば、メソッドが引数にnullを受け取った場合、基本型の
    ArgumentExceptionではなく、ArgumentNullExceptionをスローする
    べきである。
プロパティ変更イベントの提供を検討する
                                                 AV1230
   プロパティが変更された時に発生するイベントの提供を検討する。
    PropertyChangedという名前のイベントを付けるべきで、Propertyは
    このイベントに関連づけられたプロパティの名前に置き換えられる
    べきである。
   Note クラスが、対応するイベントが必要な多くのプロパティを持っ
    ている場合、INotifyPropertyChangedインターフェイスの実装を検討
    する。これはプレゼンテーションモデル とModel-View-ViewModelパ
    ターンでよく使用されている。
アセンブリ名にはそれに含まれる名前空間を使用する
                                                   AV1505
   すべてのDLLは<Company>.<Component>.dll のパターンで、
    <Company>は、企業名で、<Component>はひとつ以上のドットで区
    切られた節を含んでいる名前を使用するべきである。例えば、
   AvivaSolutions.Web.Controls.dll.
   例として、アセンブリで公開しているAvivaSolutions.Web.Binding名
    前空間の下のグループを検討してみよう。ガイドラインによるとア
    センブリは次のように呼ばれるべきである。
   AvivaSolutions.Web.Binding.dll.
   例外 無関係な複数の名前空間からクラスを集めてひとつのアセンブ
    リに結合する場合、アセンブリの最後にCoreをつけることを検討す
    る。ただし、名前空間にはつけない。例えば、
   AvivaSolutions.Consulting.Core.dll.
ソースファイル名にはそれに含まれる型を使用する
                                           AV1506
   ファイルの名前にはPascal Caseを使用して、アンダースコアを使用
    しない。
ソースコードファイルに含めるのはひとつの型に制限する
                                      AV1507
   例外 ネストされた型は明らかに同じファイルの一部である必要があ
    る。
ソースファイル名には、partialタイプの論理機能をつける
                                          AV1508
    Partialタイプを使用して、ファイルごとに一部を割り当てている場
     合、それぞれのファイル名は論理パートの後にパートが果たしてい
     ることをつける。例えば、
    // In MyClass.cs
    public partial class MyClass
    {...}
 

    // In MyClass.Designer.cs
    public partial class MyClass
    {...}
完全な型名の代わりにusing ディレクティブを使用する
                                                                AV1510
   名前の衝突を防ぐために完全な名前を制限する。例えば、以下のように使用しな
    い。
   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氏の 型推論を使うかどうかを参照して欲しい。

                                         まじで?
                                     あんまりみたことがない。
パラメータを一時変数として使用しない
                                     AV1568
   一時的な状態を保持する便利な変数としてパラメータを使用しては
    ならない。一時的な変数と型が同じであったとしても、一時変数と
    しての目的を反映していない。




                  使っちゃうこともある。
            きちんとした変数がついていれば使われないかも
変数、パラメータ、型メンバーに数字を含めない
                                     AV1704
   ほとんどのケースで明確に意図を示さない名前をつけているのは怠
    けているだけである。




                COMを否定したいんだよね?
メンバー名は、関連する.NET Frameworkクラスのメンバーと同
              様にする
                                                    AV1711
   .NET開発者はすでにフレームワークユーザーのパターンになれてい
    るため、同じパターンのものはあなたのクラスの助けになる
   例えば、コレクションのように振る舞うクラスを定義した場合、
    AddItem、Delete、NumberOfItemsではなく、Add、Remove 、
    Countのようなメンバーを提供する。




               ドメインの言葉があれば、それを使った方がいいかも。
                   DeleteとRemoveは混乱しているかも。
名前空間名には、名前、レイヤ、動詞、機能を使用する
                                        AV1725
   例えば、以下の名前空間はこのガイドラインのよい例である。
   AvivaSolutions.Commerce.Web
   NHibernate.Extensibility
   Microsoft.ServiceModel.WebApi
   Microsoft.VisualStudio.Debugging
   FluentAssertion.Primitives
   CaliburnMicro.Extensions
   Note 名前空間には型の名前を含めてはいけないが、複数形の名詞、
    例えば Collectionsは通常OKである。
事前イベントと事後イベントには、-ing と -ed を使用する
                                                        AV1737
    例えば、ウィンドウが閉じる前に発生するcloseイベントはClosing
    ウィンドウが閉じた後で発生するイベントはClosed
    事前、または事後イベントを示すためにBeforeやAfterプレフィック
     スやサフィックスを使用してはいけない。
    DeletingとDeletedイベントをBeginDeleteとEndDeleteとしてイベン
     トを定義するのは避ける。
    Deleting: オブジェクトが削除される前に発生する
    Delete:オブジェクトがイベントハンドラで削除される必要がある時
     に発生する
    Deleted: オブジェクトがすでに削除されたときに発生する
イベントハンドラのプレフィックスとしてOnを使用する
                                              AV1738
   イベントを処理するメソッドにはOnをプレフィックスにするとよい。
    例えば、Closingイベントを処理するメソッド名はOnClosingにする。
重要でないラムダパラメータにはアンダースコアを使用する
                                                AV1739
   例えば、イベントをサブスクライブするのにラムダステートメント
    を使用する場合、イベントの実際のパラメータは重要でないことを
    より明確にするため、以下の規則を使用する。
   button.Click += (_, __) => HandleClick();
クラス内の拡張メソッドのグループは、Extensionsサフィックス
            を使用する
                                           AV1745
    拡張メソッドの名前が、他のメンバーや拡張メソッドと競合する場
     合、クラス名にプレフィックスを付ける必要がある。Extensionsサ
     フィックスを持つクラスは可読性を向上させる。
IEnumerable<T>が空かどうかを確認するためにAny()の使用を検
                   討する
                                                   AV1800
    メソッドや他のメンバーがCountプロパティを公開しない
     IEnumerable<T>や他のコレクションクラスを返す場合、コレクショ
     ンにアイテムが含まれているかどうかを判定するためにCount()では
     なくAny()拡張メソッドを使用する。
    Count()を使用する場合、コレクション全体を反復する重大なインパ
     クト(それが実際に永続ストアへのIQueryable<T>など)を与えるリ
     スクがある。
    Note IEnumerable<T>を返す場合、AV1130 で説明されているように
     オーナーが外部からの編集を防ぎ、.NET 4.5以上で開発している場
     合は、新しい読み取り専用クラスを検討する。
ローカライズされたリソースを参照するプロパティ、変数、
      フィールドに適切な名前をつける
                                     AV2205
   このトピックのガイドラインは、エラーメッセージやメニューテキ
    ストのようにローカライズされたリソースに適用される。
   リソースキーにPascal caseを使用する
   短い識別子よりも説明的なものを提供する。可能であれば簡潔にす
    るが、読みやすさを重視する。
   リソースの名前には、英数字のみを使用する。
デプロイメントで変更される文字列をハードコードしない
                                                            AV2207
   例えば、接続文字列やサーバーアドレスなど。
   ConfigurationManagerクラスのConnectionStringsプロパティやVisual
    Studioによって生成されたSettingsクラスなどのResourcesを使用す
    る。
   実際の値は、app.configやweb.config(と間違えなくカスタム構成
    ストア)で維持する。
AssemblyInfo.csファイルの属性を正しく埋める
                                             AV2215
   会社名、説明、著作権、バージョンなどの属性が埋められているこ
    とを確認する。すべてのアセンブリで、バージョンなどのフィール
    ドに同じ値がきちんと埋められていることを確認するひとつの方法
    は、AssemblyInfo.csの対応する属性をソリューション内のプロジェ
    クトで共有されるSolutionInfo.csに移動することである。




                   そうだよねー。でも面倒
シンプルな表現へのLINQ(クエリ式)は避ける
                                                            AV2220
   以下の記述よりも
   var query = from item in items where item.Length > 0;
   System.Linq名前空間の拡張メソッドを使用する。
   var query = items.Where(i => i.Length > 0);
   LINQクエリは可読性のために複数行で書くべきなので、2番目の例の
    方がもう少し可読性が高い。




                クエリ式自体それほど使っていない。拡張メソッドがほとんど。
MSDNスタイルのドキュメントを記述する
                                           AV2307
   開発者がドキュメントをより簡単に見つけられるように以下のMSDN
    オンラインヘルプのスタイルと単語を選択する。
   Tip GhostDocは、ショートカットキーを使用してコードをドキュメ
    ント化する起点を生成することができる。
後で作業を追跡できるようにするためにコメントを使用しない
                                                AV2318
   TODOなどのコメントを使って、コードのブロックややるべき作業を
    記述することは、やるべき作業を追跡する合理的な方法に見えるか
    もしれない。
   しかし実際には、誰もそのようなコメントを探すことはない。残作
    業を追跡するためにTeam Foundation Serverなどの作業アイテムト
    ラッキングシステムを使用する。




                  VSでもTODOリストが出てくる。
企業ごとの名前空間の並び順とグループ
                                                 AV2402
 // Microsoft 名前空間を最初にする
 using System;
 using System.Collections;
 using System.XML;

 // その後、他の名前空間をアルファベット順に
 using AvivaSolutions.Business;
 using AvivaSolutions.Standard;

 using Telerik.WebControls;
 using Telerik.Ajax;




                    そうなんだ?
コーディングガイドラインと一緒に公開されているReSharperルールセットを入れると自動的にやってく
                      れる。
全部を採用する必要は
ありません。
プロジェクトにあった
選択を。

Más contenido relacionado

La actualidad más candente

Constexpr 中3女子テクニック
Constexpr 中3女子テクニックConstexpr 中3女子テクニック
Constexpr 中3女子テクニック
Genya Murakami
 
闇魔術を触ってみた
闇魔術を触ってみた闇魔術を触ってみた
闇魔術を触ってみた
Satoshi Sato
 
Haskell Day2012 - 参照透過性とは何だったのか
Haskell Day2012 - 参照透過性とは何だったのかHaskell Day2012 - 参照透過性とは何だったのか
Haskell Day2012 - 参照透過性とは何だったのか
Kousuke Ruichi
 
20分くらいでわかった気分になれるC++20コルーチン
20分くらいでわかった気分になれるC++20コルーチン20分くらいでわかった気分になれるC++20コルーチン
20分くらいでわかった気分になれるC++20コルーチン
yohhoy
 

La actualidad más candente (20)

ドライブレコーダ映像からの3次元空間認識 [MOBILITY:dev]
ドライブレコーダ映像からの3次元空間認識 [MOBILITY:dev]ドライブレコーダ映像からの3次元空間認識 [MOBILITY:dev]
ドライブレコーダ映像からの3次元空間認識 [MOBILITY:dev]
 
非同期処理の基礎
非同期処理の基礎非同期処理の基礎
非同期処理の基礎
 
中3女子でもわかる constexpr
中3女子でもわかる constexpr中3女子でもわかる constexpr
中3女子でもわかる constexpr
 
Constexpr 中3女子テクニック
Constexpr 中3女子テクニックConstexpr 中3女子テクニック
Constexpr 中3女子テクニック
 
C++20 モジュールの概要 / Introduction to C++ modules (part 1)
C++20 モジュールの概要 / Introduction to C++ modules (part 1)C++20 モジュールの概要 / Introduction to C++ modules (part 1)
C++20 モジュールの概要 / Introduction to C++ modules (part 1)
 
async/await のしくみ
async/await のしくみasync/await のしくみ
async/await のしくみ
 
(Unityよくわかってない人のための)なんとなくわかるかもしれないAssetBundle
(Unityよくわかってない人のための)なんとなくわかるかもしれないAssetBundle(Unityよくわかってない人のための)なんとなくわかるかもしれないAssetBundle
(Unityよくわかってない人のための)なんとなくわかるかもしれないAssetBundle
 
Marp Tutorial
Marp TutorialMarp Tutorial
Marp Tutorial
 
UniRxことはじめ
UniRxことはじめUniRxことはじめ
UniRxことはじめ
 
ROSでつながるVRChat
ROSでつながるVRChatROSでつながるVRChat
ROSでつながるVRChat
 
闇魔術を触ってみた
闇魔術を触ってみた闇魔術を触ってみた
闇魔術を触ってみた
 
Haskell Day2012 - 参照透過性とは何だったのか
Haskell Day2012 - 参照透過性とは何だったのかHaskell Day2012 - 参照透過性とは何だったのか
Haskell Day2012 - 参照透過性とは何だったのか
 
関数型プログラミングのデザインパターンひとめぐり
関数型プログラミングのデザインパターンひとめぐり関数型プログラミングのデザインパターンひとめぐり
関数型プログラミングのデザインパターンひとめぐり
 
SQL上級者こそ知って欲しい、なぜO/Rマッパーが重要か?
SQL上級者こそ知って欲しい、なぜO/Rマッパーが重要か?SQL上級者こそ知って欲しい、なぜO/Rマッパーが重要か?
SQL上級者こそ知って欲しい、なぜO/Rマッパーが重要か?
 
React vac pattern
React vac patternReact vac pattern
React vac pattern
 
SQLアンチパターン - ジェイウォーク
SQLアンチパターン - ジェイウォークSQLアンチパターン - ジェイウォーク
SQLアンチパターン - ジェイウォーク
 
Web開発者が始める .NET MAUI Blazor App
Web開発者が始める .NET MAUI Blazor AppWeb開発者が始める .NET MAUI Blazor App
Web開発者が始める .NET MAUI Blazor App
 
20分くらいでわかった気分になれるC++20コルーチン
20分くらいでわかった気分になれるC++20コルーチン20分くらいでわかった気分になれるC++20コルーチン
20分くらいでわかった気分になれるC++20コルーチン
 
コルーチンの使い方
コルーチンの使い方コルーチンの使い方
コルーチンの使い方
 
Dockerからcontainerdへの移行
Dockerからcontainerdへの移行Dockerからcontainerdへの移行
Dockerからcontainerdへの移行
 

Similar a C#coding guideline その2_20130325

Let s database_testing
Let s database_testingLet s database_testing
Let s database_testing
Yuji Shimada
 
20120422i phonedeveloperworkshoppublished
20120422i phonedeveloperworkshoppublished20120422i phonedeveloperworkshoppublished
20120422i phonedeveloperworkshoppublished
Yoichiro Sakurai
 
Effective Modern C++ 勉強会 Item26
Effective Modern C++ 勉強会 Item26Effective Modern C++ 勉強会 Item26
Effective Modern C++ 勉強会 Item26
Akihiro Nishimura
 
20110820 metaprogramming
20110820 metaprogramming20110820 metaprogramming
20110820 metaprogramming
Masanori Kado
 

Similar a C#coding guideline その2_20130325 (20)

今日からできる!簡単 .NET 高速化 Tips
今日からできる!簡単 .NET 高速化 Tips今日からできる!簡単 .NET 高速化 Tips
今日からできる!簡単 .NET 高速化 Tips
 
Flutterを体験してみませんか
Flutterを体験してみませんかFlutterを体験してみませんか
Flutterを体験してみませんか
 
Apexコアデベロッパーセミナー(Apexコード)071010
Apexコアデベロッパーセミナー(Apexコード)071010Apexコアデベロッパーセミナー(Apexコード)071010
Apexコアデベロッパーセミナー(Apexコード)071010
 
規格書で読むC++11のスレッド
規格書で読むC++11のスレッド規格書で読むC++11のスレッド
規格書で読むC++11のスレッド
 
Javaチョットデキルへの道〜JavaコアSDKに見る真似したいコード10選〜
Javaチョットデキルへの道〜JavaコアSDKに見る真似したいコード10選〜Javaチョットデキルへの道〜JavaコアSDKに見る真似したいコード10選〜
Javaチョットデキルへの道〜JavaコアSDKに見る真似したいコード10選〜
 
Spock's world
Spock's worldSpock's world
Spock's world
 
Pfi Seminar 2010 1 7
Pfi Seminar 2010 1 7Pfi Seminar 2010 1 7
Pfi Seminar 2010 1 7
 
基礎からのCode Contracts
基礎からのCode Contracts基礎からのCode Contracts
基礎からのCode Contracts
 
PHP 2大 web フレームワークの徹底比較!
PHP 2大 web フレームワークの徹底比較!PHP 2大 web フレームワークの徹底比較!
PHP 2大 web フレームワークの徹底比較!
 
Let s database_testing
Let s database_testingLet s database_testing
Let s database_testing
 
安全なプログラムの作り方
安全なプログラムの作り方安全なプログラムの作り方
安全なプログラムの作り方
 
20120422i phonedeveloperworkshoppublished
20120422i phonedeveloperworkshoppublished20120422i phonedeveloperworkshoppublished
20120422i phonedeveloperworkshoppublished
 
Effective Modern C++ 勉強会 Item26
Effective Modern C++ 勉強会 Item26Effective Modern C++ 勉強会 Item26
Effective Modern C++ 勉強会 Item26
 
app-c.odp
app-c.odpapp-c.odp
app-c.odp
 
APASEC 2013 - ROP/JIT を使わずに DEP/ASLR を回避する手法を見てみた。
APASEC 2013 - ROP/JIT を使わずに DEP/ASLR を回避する手法を見てみた。APASEC 2013 - ROP/JIT を使わずに DEP/ASLR を回避する手法を見てみた。
APASEC 2013 - ROP/JIT を使わずに DEP/ASLR を回避する手法を見てみた。
 
Swift 2.0 で変わったところ「後編」 #cswift
Swift 2.0 で変わったところ「後編」 #cswiftSwift 2.0 で変わったところ「後編」 #cswift
Swift 2.0 で変わったところ「後編」 #cswift
 
Visual C++で使えるC++11
Visual C++で使えるC++11Visual C++で使えるC++11
Visual C++で使えるC++11
 
20110820 metaprogramming
20110820 metaprogramming20110820 metaprogramming
20110820 metaprogramming
 
Java class design
Java class designJava class design
Java class design
 
ソフトウェア設計原則【SOLID】を学ぶ #3 依存性逆転の原則.pdf
ソフトウェア設計原則【SOLID】を学ぶ #3 依存性逆転の原則.pdfソフトウェア設計原則【SOLID】を学ぶ #3 依存性逆転の原則.pdf
ソフトウェア設計原則【SOLID】を学ぶ #3 依存性逆転の原則.pdf
 

Más de Yoshihisa Ozaki

Windows 8.1 Update 1で更新されたInternet Explorer 11のF12開発者ツールアップデート
Windows 8.1 Update 1で更新されたInternet Explorer 11のF12開発者ツールアップデートWindows 8.1 Update 1で更新されたInternet Explorer 11のF12開発者ツールアップデート
Windows 8.1 Update 1で更新されたInternet Explorer 11のF12開発者ツールアップデート
Yoshihisa Ozaki
 
Internet Explorer 11 概要
Internet Explorer 11 概要Internet Explorer 11 概要
Internet Explorer 11 概要
Yoshihisa Ozaki
 
CLRの基礎 - プログラミング .NET Framework 第3版 読書会
CLRの基礎 - プログラミング .NET Framework 第3版 読書会CLRの基礎 - プログラミング .NET Framework 第3版 読書会
CLRの基礎 - プログラミング .NET Framework 第3版 読書会
Yoshihisa Ozaki
 
Ie10正式リリース版のhtml5 css3
Ie10正式リリース版のhtml5 css3Ie10正式リリース版のhtml5 css3
Ie10正式リリース版のhtml5 css3
Yoshihisa Ozaki
 

Más de Yoshihisa Ozaki (12)

Microsoft edge insider channelsがリリースされました
Microsoft edge insider channelsがリリースされましたMicrosoft edge insider channelsがリリースされました
Microsoft edge insider channelsがリリースされました
 
Microsoft によるオープンなweb デバッグ環境 comm tech festival-
Microsoft によるオープンなweb デバッグ環境 comm tech festival-Microsoft によるオープンなweb デバッグ環境 comm tech festival-
Microsoft によるオープンなweb デバッグ環境 comm tech festival-
 
Microsoft Edge F12 開発者ツール
Microsoft Edge F12 開発者ツールMicrosoft Edge F12 開発者ツール
Microsoft Edge F12 開発者ツール
 
Microsoft新しいブラウザーのウワサ
Microsoft新しいブラウザーのウワサMicrosoft新しいブラウザーのウワサ
Microsoft新しいブラウザーのウワサ
 
Internet Explorer 11 August Updateの F12 開発者ツール
Internet Explorer 11 August UpdateのF12 開発者ツールInternet Explorer 11 August UpdateのF12 開発者ツール
Internet Explorer 11 August Updateの F12 開発者ツール
 
Visual studio 14 CTP2 概要
Visual studio 14 CTP2 概要Visual studio 14 CTP2 概要
Visual studio 14 CTP2 概要
 
Windows 8.1 Update 1で更新されたInternet Explorer 11のF12開発者ツールアップデート
Windows 8.1 Update 1で更新されたInternet Explorer 11のF12開発者ツールアップデートWindows 8.1 Update 1で更新されたInternet Explorer 11のF12開発者ツールアップデート
Windows 8.1 Update 1で更新されたInternet Explorer 11のF12開発者ツールアップデート
 
Internet Explorer 11 の F12 開発者ツール
Internet Explorer 11 の F12 開発者ツールInternet Explorer 11 の F12 開発者ツール
Internet Explorer 11 の F12 開発者ツール
 
Internet Explorer 11 概要
Internet Explorer 11 概要Internet Explorer 11 概要
Internet Explorer 11 概要
 
CLRの基礎 - プログラミング .NET Framework 第3版 読書会
CLRの基礎 - プログラミング .NET Framework 第3版 読書会CLRの基礎 - プログラミング .NET Framework 第3版 読書会
CLRの基礎 - プログラミング .NET Framework 第3版 読書会
 
Ie10正式リリース版のhtml5 css3
Ie10正式リリース版のhtml5 css3Ie10正式リリース版のhtml5 css3
Ie10正式リリース版のhtml5 css3
 
Code Pack の話
Code Pack の話Code Pack の話
Code Pack の話
 

C#coding guideline その2_20130325

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