1

私は最近、初めてSQL ServerデータベースにCRUDアプリケーションを構築するためにMVCを初めて使用しました。 Entity Frameworkと提供された足場ユーティリティはこれを非常に簡単にしました。私は、モデルのデータアノテーションを使ってデータフィールドのラベル名や検証などを集中させる方法が特に好きです。私は直感的で整理されたMVCを見つけました。エンジニアリングフレームワークを使用した変更トラッキングのようなカスタム機能を、余分なコードや欲求不満なく追加することができました。ユニットテスト、依存性注入、AutoMapperアノテーション

次に、私はそれを次のレベルに持ち込み、単体テストを組み込むことに決めました。物事はすぐにはるかに複雑になりました。

私は、実際のデータベースを使った単体テストは問題があり、遅く、一般的には推奨されないことを読んでいます。モックデータベースの呼び出しをスワップするか、メモリ内のデータベースの代用を使用することをお勧めします。意味をなさないだから、私がやった最初のことは、データベースコールを分離するための別個のリポジトリレイヤーをコード化することでした。私はすぐにこれだけでは不十分であることを発見しました。テスト時にコードを書き直すことなく、あるリポジトリを別のリポジトリに簡単にスワップするには、依存性注入を伴う制御パターンの逆変換を使用して、コンポーザを介してコントローラに正しいリポジトリ実装を注入する必要があります。依存関係注入はインターフェースに依存するので、すべてのリポジトリクラスのインターフェース定義を追加し、注入を管理し、正しいインターフェース実装を注入するためにNinjectをインストールする必要がありました。また、複数のリポジトリを更新し、すべての変更を一度コミットするプロセスをカプセル化するために、Unit of Workインタフェースを実装しました。

私は、CRUDアプリケーションの既存のレコードを編集するときに、組み込みフィールドマッパーが、依存関係注入で構築された編集済みオブジェクトをポストバックできないことを発見しました。これにより、ビューに必要な正確なフィールド情報を定義するだけで、AutoMapperを使用してデータモデルを各ビューモデルにマッピングし、ポスト後に再び戻す、ビューごとに別々の単純化されたビューモデルの哲学に導かれました。だから、より多くの学習、インストールと配線の後、私はこれを働かせました。残念ながら、AutoMapperは項目間のフィールド値をマップしますが、データ注釈はマップしません。これは、データ・モデルと4,5ビュー・モデルの間のすべてのデータ注釈を、ラベル付け、フィールド検証などのために各クラスごとに複製する必要があることを意味します。私はSOにこれを対処するためのいくつかの提案を見つけましたが、彼らは単純か堅牢に見えませんでした。これはショーストッパーではないはずですが、それは私が遭遇した最初の重大な障害であり、私は合理的な解決策を見つけることができず、それは私を悩ませています。

私の質問:

  1. 誰もがAutoMapperは、データ注釈をマッピングするために取得するための実証済みの方法を持っていますか?同じように動作するが、この問題を解決する別のマッパーはありますか?

  2. 上記の作業はすべて、代用データベースを使用して単体テストを行うことを希望していました。私のプロジェクトのコードサイズと複雑さは、オリジナルのMVCプロジェクトから大幅に増加し、スカフォールディングを使用して自動的に作成されたクラスが作成されました。私はコンセンサスが、これがテストと将来の開発とリファクタリングのためにプロジェクトを編成する「正しい」方法だが、それは本当に価値があるのだろうということですね。私のテストで実際のデータベースのコピーを使っただけであれば、はるかに単純なプロジェクトができました。私は他の人の経験や見解を聞きたいです。

+0

メンテナンス可能なテスト可能なプロジェクトを作成するには正しい方法です(DbContextを単純に嘲笑するだけでいくつかのステップをスキップすることができました)が、本当に不明な点は「データアノテーションをマッピングする」ことです。 – CodeCaster

+0

フィールドのラベルとして特定の文字列を表示するためにデータモデル内の電子メールフィールドに[Display]データアノテーションを、クリック可能な電子メールリンクとしてフィールド値を表示する[DataType]アノテーションを使用する場合、これらのアノテーションをビューモデルにそのフィールドをマップすると、ビューモデルに適用されます。私は、ビューモデル内のマップされたフィールドに注釈を再定義する必要はありません。 –

+0

正確に物事を詳述してくれる素敵な言葉遣いの質問! – Irfan

答えて

1

私の知る限り、あなたは(例えば[Display]など)を参照するデータの注釈はプレゼンテーション層のためのものです。それらをデータベースモデルに入れるのは意味がありません。適切なレイヤーに配置する場合は、複製する必要はありません。

プレゼンテーションレイヤーに属していないデータレイヤー(フィールド長やテーブル結合など)専用の属性があります。基本的には、機能ごとに分けておく必要があります。

+0

私はこれらがプレゼンテーションアイテムであることに同意します。したがって、ビューモデルにもっと適切に関連付けられています。しかし、特定のクラスのフィールドが重複する複数のビューモデルがある場合、どのようにして同じアノテーションを複数回再定義することを避けることができますか?完璧な世界では、データモデル上のすべての注釈属性を定義し、ビューモデル内の明示的な注釈でそれらをオーバーライドしない限り、これらをマッパーが使用するようにしたいと考えています。 –

+0

簡単な答えは、ある種の機能を持っているビューモデルを書くことです。いくつかの異なる機能を持つ同様のビューを持っているなら、継承を使うことができますが、たいていの場合、複雑になってしまいます。新しいVM型を作成し、注釈を再実装します。ほとんどの場合、ピースの量を増やすとプロジェクトはより複雑に見えますが、実際にはもっとメンテナンス可能で構造化されています。 – Charleh

0

実際にDBコールをコントローラから分離するためのリポジトリの実装のみになりました。これにより、リポジトリの機能を個別にテストし、期待どおりのデータを取得していることを確認できます。

私は、依存関係注入、フィールドマッピング、およびフィールドアノテーションの重複のすべての余分な複雑さとオーバーヘッドが、この場合のテストの利点を上回ると判断しました。特にCRUDアプリケーションの場合、機能の98%がデータベースアクセスまたはデータ表示のいずれかです。テストするビジネスロジックはありません。