Effective C# 3rd 読書メモ 16 コンストラクタ内で仮想関数を呼び出してはいけない

仮想関数は、コンストラクタの中で(C++プログラマーにとっては)奇妙な振る舞いをする。
たとえば、以下のコードを実行すると、出力されるのは「Set by initializer」である。

一般に、コンストラクタで仮想関数を実行すると、コードがひどく壊れやすくなる。
派生クラスが何をするか完全にコントロールすることはできないからだ。
コンストラクタ内での仮想関数の実行は禁止すべき(Never call)である。

『プログラミングASP.NET MVC 第3版』を読んだ

プログラミングMicrosoft ASP.NET MVC 第3版ASP.NET MVC 5 対応版 (マイクロソフト公式解説書)

ASP MVC 5の解説書。初歩的な解説も載っていますが、それ以上に「ASP MVCを使って良いアプリケーションを作るにはどうすればよいか」ということを詳しく書いてあります。

以下、目次

■第1部 ASP.NET MVCの基礎
第1章 ASP.NET MVCのコントローラー
第2章 ASP.NET MVCのビュー
第3章 モデルバインディングアーキテクチャ
第4章 入力フォーム
■第2部 ASP.MVCのソフトウェアデザイン
第5章 ASP.NET MVCアプリケーションの機能
第6章 アプリケーションのセキュリティ
第7章 ASP.NET MVCコントローラーの設計上の注意点
第8章 ASP.NET MVCのコントローラーのカスタマイズ
第9章 ASP.NET MVCでのテストとテスタビリティ
第10章 ASP.NET Web APIエグゼクティブガイド
■第3部 モバイルクライアント
第11章 効果的なJavaScript
第12章 モバイル対応のWebサイトの作成
第13章 マルチデバイスサイトの構築

500ページ長と大きめの本ですが、本書の中でも力を入れて読むべきなのは、第2部「ASP.MVCのソフトウェアデザイン」です。
特に、第7章「ASP.NET MVCコントローラーの設計上の注意点」には、さまざまな設計上のヒントが散りばめられています。

たとえば、MVCのControllerは、その名の通りの「Controller(さまざまなオブジェクトを統合して管理する責務)」ではなく、「Coordinator(さまざまなワーカーサービスの調整を行う責務)」として実装したほうが、シンプルに実装できる、といった指摘です。

もう1つ、個人的に気になったテクニックが、ビューモデルです。ビューモデルの概念は、WPFなどでは当たり前に用いられているようですが、WebのMVCの世界ではそれほど一般的ではありません。しかし、ビューモデルを使うことで、DBを操作するためのモデルクラスと、ビューに表示するデータを保持するだけのビューモデルクラスを分離することができます。このような分離は、単純なアプリケーションでは手間がかかるだけでメリットは薄いでしょうが、データベースのデータを画面上に表示するための整形処理等が必要な場合には、ビューモデルを活用することで、個々のクラスの実装を簡潔に保つことができます。

ASP MVCの入門者が最初に読む本としては適していませんが、2冊めに読む本としては良いと思います。

この本の著者(Dino Esposito氏)の本は良さそうだなと思ったので、以下の書籍も購入しました(ちょうど、Kidleで50%ポイント還元やってたので)。

.NETのエンタープライズアプリケーションアーキテクチャ第2版 .NETを例にしたアプリケーション設計原則

Effective C# 3rd 読書メモ 15 不要なオブジェクトの生成を避ける

GCは効率的に動作するが、それでも無駄なオブジェクトを作りすぎるとパフォーマンス上の悪影響が発生する。
全ての参照型は、ローカル変数であってもメモリ割り当てが行われる。
たとえば、以下のOnPaintメソッドは、PaintイベントのたびにFontのオブジェクトが生成されるため、効率が悪い。

以下のように、インスタンス変数にFontオブジェクトを保持すべきである。

一般に、参照型で、頻繁に生成されるローカル変数は、メンバー変数に格上げすべきである。

同様に、頻繁に使用されるインスタンスは、静的プロパティ等の形で取得できるようにすべきである。ここでは、以下のような遅延初期化のテクニックも利用できる。

最後にもう1つ、イミュータブルな型の変更は避けるべきである。たとえば、C#の文字列はイミュータブルである。文字列に変更を加えると、内部ではSystem.Stringの新しいインスタンスが生成されている。
文字列の組み立てには、補間文字列か、StringBuilderを使用すべきである。

補間文字列は、文字列が短い場合や、組み立てに際してロジックがほとんど必要ない場合に適している。
StringBuilderは、文字列が長い場合や、組み立てに際してロジックが必要な場合に適している。

Effective C# 3rd 読書メモ 14 初期化ロジックの重複を最小限にする

コンストラクタ初期化子を使うと、あるコンストラクタから別のコンストラクタを呼ぶことができる。
なお、以下では、C# 4.0で導入されたデフォルトパラメータを使用して、コンストラクタの数を減らしている。

なお、パラメータを必要としないコンストラクタと、全てのパラメータにデフォルト値が設定されたコンストラクタは異なる、という点に注意が必要である。
ジェネリクスで使う場合など、パラメータを必要としないコンストラクタが要求される場面があるため、全てのパラメータにデフォルト値を設定する場合、パラメータなしのコンストラクタも作成したほうがよい。

Effective C# 3rd 読書メモ 13 静的メンバーは適切な初期化を行う

静的クラスのメンバーの初期化には、初期化子または静的コンストラクタを使用すべきである。
インスタンスのコンストラクタや、何らかのprivateメソッド、その他の方法は使用すべきではない。
初期化に複雑な処理が必要なら、Lazy<T>クラスによる遅延初期化を考慮すべきだ。

以下は、初期化子を使用したSingletonパターンの実装例である。

静的コンストラクタは、初めてクラスにアクセスされた際に自動的に実行される。
静的コンストラクタは1つだけ定義可能で、引数をとることはできない。
静的コンストラクタを使用する理由として、最も一般的なのは初期化時の例外処理である。

参考: Lazy クラス