Kokudoriingスマートフォン用の表示で見るKokudoriing技術系与太話ブログこの広告は、90日以上更新していないブログに表示しています。5.0」というC#のコーディングガイドラインがあるんですが、それが日本語翻訳されたらしいとのこと。5.0早速読んでみたのでその感想を。当たり前ですが万人受けするガイドラインなんてあるはず無いのでいくつかは僕には合いませんでした。間違ってたらこっそりゆっくりまったり優しくご指摘いただければ幸いです。間違った方向に入るものを含むべきではないことを意味する。重箱の隅つつきですが、驚き最小の法則は「利用者の期待に合わせるべきだ」という趣旨であって理解はともかく間違ってるかどうかは問いません。(少なくとも人間工学の文脈の中では)よくあることですが、正しい方法のほうが何かと理解されません。これは技術的負債とのトレードオフです。インテリジェントなコード検証エンジンであり、いくつかの構成を行うことでコーディングガイドラインの多くの側面をすでにサポートしている。ReSharperに言及してるコーディングガイドラインってだけで素敵ですね。Studioに依存しちゃってる(つまりWindowsに依存しちゃってる)訳ですが・・。すべての状況で適用する必要はないが、推奨するガイドライン壱があるのは言語設計上のバグとしか言い様がない(もちろん設計上の原則なら仕方ないですけども)。バーランドメイヤー先生がOOSC本でも仰ってましたが、絶対にすべきでないのなら言語がそれを許すべきじゃないです。C#で壱はいくつか思い当たるわけですが・・。参)オブジェクトが使用可能になるまでに追加でプロパティに値をセットする必要がないように設計する。OOSC本ではコンストラクタはオブジェクトのクラス不変条件を成立されるための機構だと説明されてましたし僕も同意します。オプショナルな値セットなら良いんですが、コンストラクタを通したのにそのオブジェクトが使用不可状態(InvalidOperationExceptionをスロー)というのは罠過ぎますし誰も得しないです。コンストラクタのパラメータの数が増えるのを懸念してるっぽいですが、パラメータを別オブジェクトにまとめるなりファクトリにするなりあるんじゃないですかね。個人的にこれは壱、最低でも弐かなあと。「すべての状況で適用する必要はない」のであれば「どのような状況であれば適用にしなくても良い」のかの理由がほしいなあ。壱)文字列やコレクションのプロパティ、メソッド、引数はnullであってはならない。うーん、.NETにnull非許容参照型が無いのが大変悔やまれる。これは大賛成なんだけども、じゃあ現実問題どうしよう。null入れんなってルールでnullチェックは一切しない?簡単な線引ならpublic/protectedメソッドはnullチェックしてNullArgumentException、privateメソッドはノーチェックあるいはnullチェックアサーションあたりが無難?あとプロパティでNullArgumentExceptionって出して良いもんなんですかね?というかプロパティで例外全般を出して良いのかしら。なんとなくプロパティは軽量アクセサに留めて例外投げない(NullArgumentExceptionも)方が自然な気もするが果たして。ちなみにnullチェック以外には防御的プログラミングという、nullが来たらデフォ値に変換したりなんやかんやして出来るだけ処理できるように頑張るという方法もある。参)プリミティブよりもドメイン固有の値型を検討する。マーティン・ファクラーさんのPoEAAで言う所のバリューオブジェクトですね。これには賛成なんですが、C#(というか.NET)は結構サポートひどいですね。バリューオブジェクトは原則イミュータブルであるべきです。(String型のように破壊的メソッドを定義しない)次に、値等価性をサポートすべきです。Equalメソッドをオーバーライドします。次に==演算子もオーバーライドするでしょう。==演算子が等しいオブジェクト同士はGetHashCodeメソッドの戻り値も等しくなければならないというルールがあります。==演算子をオーバーライドしたのならば、GetHashCodeメソッドもオーバーライドしなければなりません。GetHashCodeはインスタンス毎に固有の異なるハッシュ値を返さなければなりません。ハッシュ関数なわけですからランダム分布するように工夫する必要もあります。うーん、コスト高いなあ・・。因みにPoEAAで「.NETはバリューオブジェクト用に構造体って機構があるから便利だね」的なことが書かれてますが、.NETの構造体は意味的でなくメモリ配置的な分け方であり、構造体の積極的な使用は推奨されてません。クラスだろうとイミュータブルなら振る舞いは同じです。第3版によると、構造体はおよそ16バイト以下のデータを格納する際に考慮すべきだそうです。例外メッセージはエンドユーザーに見せない事を前提とし、技術者向けの内容にすべきだそうです。)コレクションクラスの代わりにIEnumerableやICollectionを返す。)LINQ式を戻り値として返す前に評価する。んー、これはどうなのか。値を返すのにIEnumerableを返すのはめちゃくちゃややこしいので是非ともやめて頂きたい。いうか後者が壱なのは何なのか。Object全否定というか・・。)メソッドは7ステートメントを超えるべきではない。複雑性を数値化する動きは総じて嫌い。)デフォルトでは、すべてのメンバーをprivateに、型をinternalにする。C#ではメンバの可視性のデフォルトはprivate、型はinternalです。デフォのままで行けと。ここまで書くのなら「デフォルトの修飾子と同じ時は修飾子を省略すべきかどうか?」にまで踏み込んでいただきたかった。因みに自分は省略する派です。アンダース・ヘルスバーグさんがアクセス修飾子のデフォルトを決めた気持ちを汲み取りたい的な意味で。)二重否定の条件を避ける。customer.HasNoOrdersのようなプロパティは間違っていないが、以下のように否定条件で使用するのは避ける。!customer.HasNoOrders;これはHasNoXxx的な否定的プロパティ/メソッドを定義すること自体は容認していると言う事?ただただ罠っぽいからHasXxx系に統一したいんだけどもなあ・・。ナンバーを使ってはいけないまあ王道ですね。ガイドライン上ではサンプルコードとしてconstが使用されてます。原則としてconstの使用は控えましょう。代わりにreadonlyをどうぞ。constは完全なマクロです。コンパイル時にコードレベルで値を展開します。別アセンブリにまたがるconst値がある場合、const値が何らかの理由で変更しなければならない場合、最悪再コンパイルが必要です。readonlyはイミュータブル(最大入不可)が保証されるだけのただの変数なのでそのような問題は発生しません。constで得られるメリットよりもconstで被るデメリットの方が多いケースが殆んどです。constを使用するならば、値は絶対に変更しないことを保証しなければなりません。)型が確実に明確なときにだけvarを使用する。皆さんそんなに型推論を怖がるのです?しかも壱・・。なると生産性が落ちるのです?また、ガイドラインに以下のようなサンプルコードが。なにを期待しているのかが明確じゃない。戻り値の型を知らなければならないのでしょう?そもそもオブジェクト指向というものを考えた時、オブジェクトとは対象の振る舞いによって定義されます。グワグワと鳴いてほしい。あるならばガチョウだ。ガチョウだから歩いてほしい訳ではありません。オブジェクト指向とはドメインのモデル化であって現実のモデル化ではありません。必要のない振る舞いなど、いくら正しかろうが必要ありません。我々が欲しいのはその型が何であるかではなく、それが何を出来るか、です。そんなものはIntelliSenseが教えてくれます。人間様がわざわざ型なんてものを意識しなければならないだなんて息苦しいだけです。期待が明白な名前であれば戻り値の型などわざわざ明記する理由はありません。float等の基本型に関してはリテラル表記によって型が変わりますが、これもリテラル表記の表現力が増えただけであり特に問題はないように思えます。自分ならリテラル表記を勉強するように言います。ようなtrueとの比較は全く意味が無い。C#はifやらwhileやらの条件式はbool値しか書けないので紛らわしさも発生しない。場合は少し複雑になる。