抽象DAL-内部クラスでインターフェイスを使用しますか?


8

データアクセスレイヤー(DAL)と緊密に結合されたビジネスロジックレイヤー(BLL)があります。次のように呼び出します。

using (FooData data = new FooData())
{
  data.DoSomething();
}

internalBLLだけがDALにアクセスできるように、すべてのデータクラスはであり、それらはロジッククラスと同じアセンブリにあることに注意することが重要です。

(ユニットテストを容易にするために)これらを分離するための1つのアイデアは、IFooDataのようなIDataClassインターフェイスを作成することです。インターフェイスを実装するためにデータクラスをパブリックにする必要があるため、最初は問題だと思いました。ただし、メソッドをパブリックにする必要がある場合でも、データクラスを内部に保持できるはずです。

public interface IFooData
{
  void DoSomething();
}

internal class FooData : IFooData  // Notice the class is internal
{
  public void DoSomething();  // Method is public, but that's ok because class is internal
}

したがって、メソッドがパブリックであっても、クラス自体は内部であるため、BLLアクセスのみを許可する必要があります。

このアプローチには本質的に問題がありますか?DALを公開して世界に公開することなく、ユニットテストのためにDALを抽象化するより良い方法はありますか?


1
このようにDALをロックしておくことで何を達成しようとしていますか?なぜそれを秘密にしておくのですか?たくさんのメソッドを公開しているため、だれがそれらを呼び出しているかを正確に気にする必要はありません。間違った場所から呼び出されて問題がある場合は、コードレビューの問題があります。
2012

メソッドを内部にすることで、BLLのみがアクセスできるようになり、すべての開発者がBLLを通過する必要があります。大規模な開発チームがある場合、ミスを最小限に抑えるためにできることは何でも良いことです。
ボブ・ホーン

あなたはコードを使用する開発者をある程度把握しようとしていると思いますが、そうすることで別の問題が発生しました。これが私がコメントした理由です-メソッドをパブリックにすることは何の問題もありません(これは通常の慣行です)人々が間違った方法でそれらを使用している場合は、コードレビューの問題があります。
slugster

同意しません。なぜ内部修飾子とプライベート修飾子があるのですか?なぜすべてを公開しないのですか?
ボブ・ホーン

あなたがポイントを完全に逃したボブ。DALは、インターフェイスであるCONTRACTを介して公開データを公開します。標準のOOの実践は、誰がそれを呼び出しているかを知らないことを意味しています。さんはそれをもう一回言ってみましょう:あなたができるクラスは内部作るが、あなたはしないでください必要に。世界の残りの部分はこのアプローチでなんとか乗り越えています、なぜあなたはどうですか?また、同じDALを呼び出す必要のある別のBLまたはサービスがある瞬間に、自分の足を撃ちました。フレンドアセンブリを追加し続けますか?
スラッグスター

回答:


13

インターフェイスを抽出し、BLLがインターフェイスタイプのみを使用していることを確認することは、データベースなしでBLLをテスト可能にするための良い方法です。

あなたがやっていることは絶対に大丈夫です。


3
あなたがやっていることはうまくいくと付け加えますが、それは最初のステップにすぎません。もしあなたが今やっていることがusing (IFooData data = new FooData())あなたのBLLにあるなら、あなたはインターフェースを導入することを除いて実際には何も変更していません。ここで、IFooData外部でインスタンス化する方法を見つける必要があります。そうしないと、BLLテストは引き続きDALに結合されます。
Avner Shahar-Kashtan 2012

同意した。私は実際に次のようなことをしています:DataAccessFactory.GetDataInterface<IFooData>().DoSomething();
ボブ・ホーン

1

を使用してInternalsVisibleToAttribute、DALをビジネスレイヤーから切り離すことができますが、DALメソッドは内部的に保持されます。DALをフレンドアセンブリとして作成することになります。

Assembly.csDALにアクセスできるアセンブリをDALのファイルで指定する必要があるため、これは優れたアプローチではない場合があります。したがって、まだいくつかのカップリングが関係しています(DALはBLLについて知っています)。

だから、あなたの質問に答えるために、あなたのアプローチに何も問題はありません。しかし、フレンドアセンブリを利用すると、より抽象化され、おそらくコードをよりテストしやすくするのに役立ちます。

これがお役に立てば幸いです。


BLLからDALを削除する必要はありません。インターフェイスを実装するだけです。
ボブ・ホーン

ちなみに、ありがとう。私はに精通しておりInternalsVisibleTo、DALを別のアセンブリに移動する必要がある場合、それは確かに役立ちます。
ボブ・ホーン

@BobHorn、だから私はそれを取得しません。dalクラスを内部クラスにするための問題は何ですか?DALインターフェイスを内部として作成することもできます。ここには問題はありません。
Marcelo De Zen

DALクラスを内部にすることは、私たちが現在持っていることであり、私たちが今後持ちたいものです。BLLがファクトリに具体的な実装を要求できるように、インターフェイスはパブリックである必要があり、実際のDALであるかモックであるかは気にしません。私の質問全体は本当に正気チェックだと思います。これを行うより良い方法がありませんか?
ボブ・ホーン

1

あなたはあなたの質問で説明したあなたの考えに動かないようですが、とにかく私は答えを提出します-誰かが将来いつかそれが役に立つと思うかもしれません。

DALを内部に維持することを主張しているが、それでもいくつかの単体テストを実行して、Microsoft単体テストツールを使用することを気にしない場合は、PrivateObjectアプローチを試してください。これはリフレクションのラッパーであり、常に自分でコーディングできますが、数行のタイピングを節約できます。

InternalsVisibleToを使用すること実行可能なアプローチですが、それは扱いにくいことに注意してください。使用している場合は、すでに高速の下り坂にいる可能性があります。internal何かがそのアセンブリの境界内でのみ公開されていることを意味します。その修飾子は通常、外部から使用できるものを望まないために使用されますそのアセンブリの場合は、すぐに向きを変え、InternalsVisibleToを宣言することでその概念に違反します。これは、リファクタリングのために叫んでいる大きな汚れた赤い旗です。デカップリングは、一方のアセンブリだけがもう一方のアセンブリを呼び出している場合の時間の無駄です。それらを一緒に接着することもできます。デカップリングは、複数のアセンブリがターゲットを呼び出していると推測します(ユニットテストの導入は、すでに述べたようにターゲットアセンブリに到達する方法があるため、「複数」にはカウントされません)。


なぜ私は自分のアイデアに動かないように見えるのですか?私はあなたに同意するつもりです。最初に私を説得するための話し合いが必要です。また、を使用してこの概念に違反していると言わないでくださいInternalsVisibleTo。使っていません。何らかの理由で、私がそれを使用していると想定しています。理由はわかりません。
ボブ・ホーン

ちなみに、私の考えを改めて考えさせて頂いております。ただし、私の意見も認められています。私はすぐに同意しませんので、むちゃくちゃにする必要はありません。
ボブ・ホーン

@ボブ、その特定の角度に夢中になって申し訳ありません。コメントから、「DALを別のアセンブリに移動する必要がある場合」は、DALがおそらく内部アイテム用であるべきだと示唆していたところが正しいと思います。ここにそれを書くことを確認するために何をすべきかを決定したら(答えが当てはまらない場合)、最終的に何が思いつくかを見るのは興味深いでしょう。
slugster 2012

1

技術的には、デザインに問題はありません。

ただし、別のアプローチを検討します。BLLをDALから分離する代わりに、DALをデータベースからより適切に分離します。メモリ内でのDALオブジェクトの作成を許可します。BLLがどこかからDALオブジェクトをロードする必要がある場合は、リポジトリパターン(ここを参照)を使用して、BLLがデータベースに直接接続しないようにします。そうすれば、

  • データベースを必要とせずに、DALオブジェクトの単体テストを簡単に作成する
  • テストデータとしてモックリポジトリを通じて、メモリ内に作成さDALのオブジェクトを提供することにより、あなたのBLLのためのユニットテストを作成します(これらのテストは実際に呼び出される必要がある場合は[OK]を、あなたは今主張できるユニット -testsを)

実際、緩んでいるのは、DALモックでBLLをテストする機能です。しかし実際には、これらのDALモックオブジェクトは通常、実際のDALオブジェクトによく似ており、BLLの有用なテストのベースを提供します。私見では、BLLの自動テストのために実際のDALオブジェクトを再利用するときに、コードの重複と不必要な労力を回避します。


0

インターフェイスアプローチは、BLLなどのコンシューマーのテスト中にDALをモックアウトするための優れた/主流のアプローチです。

ただし、DAL具象クラスを内部にすると、具象DALを直接テストすることが難しくなる可能性があることに注意してください。これは、バックドアを使用する必要なく、DALユニットテストもこのアセンブリに含める必要があることを意味します。反射のように。

また、将来のある時点で、IoCコンテナーを使用してインターフェースの背後に実装を構築することを検討する可能性があり、これも内部で作動する可能性があります。

BLL /他のレイヤーが具体的な実装ではなくインターフェイスを介してDALに結合する必要がある規則/ LINTルールを追加することで、「内部のみ」で達成しようとしているカプセル化を模倣できます。


ありがとうございます。ただし、Visual Studioの単体テストでは、他のアセンブリの内部メソッドとプライベートメソッドを実際にテストできます。
Bob Horn
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.