6

ここでポインタと情報を探しています。正しい答えが 1 つもないと思われるので、この CW を作成します。これは C# 用であるため、以下で Linq を参照します。また、長文失礼いたしました。ここで質問を要約させてください。その後、完全な質問が続きます。

概要: UI/BLL/DAL/DB の 4 層アプリケーションで、ユーザー インターフェイスを変更して、より多くの列 (グリッドなど) を表示し、ビジネス ロジック層からデータ アクセス層へのリークを回避するにはどうすればよいでしょうか。表示するデータを取得します (既にデータベースにあると仮定します)。


3(4) 層の階層化されたアプリケーションを想定してみましょう。

  • ユーザー インターフェイス (UI)
  • ビジネス ロジック層 (BLL)
  • データ アクセス層 (DAL)
  • データベース(DB;第4層)

この場合、DAL は SQL ステートメントを作成し、データベースに対して実行してデータを返します。

そのようなレイヤーを「正しく」構築して常に「select *」を実行する唯一の方法はありますか? 私にはそれは大したことではありませんが、なぜ私が疑問に思っているのかを説明させてください.

UI に、有効な雇用記録を持つすべての従業員を表示したいとしましょう。「アクティブ」とは、雇用記録の from-to の日付に今日が含まれていることを意味します (または、ユーザー インターフェイスで設定できる日付も含まれている可能性があります)。

この場合、これらすべての人に電子メールを送信したいとします。そのため、BLL には、同じ人にまだ電子メールを送信していないことを確認するコードがあります。

BLL の場合、最小限のデータが必要です。おそらく、データ アクセス層を呼び出してアクティブな従業員のリストを取得し、次に、送信した電子メールのリストを取得する呼び出しを呼び出します。次に、それらを結合して新しいリストを作成します。おそらく、これはデータ アクセス層の助けを借りて行うことができますが、これは重要ではありません。

重要なことは、ビジネス層にとって必要なデータはそれほど多くないということです。おそらく、両方のリストの各従業員の一意の識別子が必要であり、一致してから、「これらはアクティブで、まだメールを送信していない従業員の一意の識別子です」と言うだけです。次に、ビジネス層が必要とするものだけを取得する SQL ステートメントを構築する DAL コードを構築しますか? すなわち。「SELECT id FROM employees WHERE ...」だけですか?

では、ユーザー インターフェイスはどうすればよいでしょうか。ユーザーにとっては、メールを送信する理由に応じて、より多くの情報を含めることがおそらく最善でしょう。たとえば、基本的な連絡先情報、勤務先の部署、マネージャーの名前などを含めたいと思うかもしれませんが、少なくとも名前と電子メール アドレスの情報を表示することは言うまでもありません。

UI はそのデータをどのように取得しますか? UI に十分なデータを返すように DAL を変更する必要がありますか? BLL を変更して、UI に十分なデータが返されるようにする必要がありますか? DAL から BLL に返されたオブジェクトまたはデータ構造を UI にも送信できる場合、おそらく BLL はあまり変更する必要はありませんが、UI の要件は、通信する必要があるレイヤーを超えてレイヤーに影響を与えます。 . また、2 つの世界が異なるデータ構造で動作する場合は、おそらく両方に変更を加える必要があります。

そして、UI が変更された場合、さらに列を追加してユーザーをさらに支援するには、UI を変更するためにどのくらい深くする必要がありますか? (データがデータベースに既に存在すると仮定しているため、そこで変更する必要はありません。)

出てきた 1 つの提案は、Linq-To-SQL と IQueryable を使用することです。これにより、何 (データの種類など) と理由 (WHERE 句など) を処理する DAL が IQueryable を返した場合、BLL はUI にそれらを返す可能性があり、必要なデータを取得する Linq クエリを作成できます。ユーザー インターフェイス コードは、必要な列を取得できます。IQuerables を使用すると、UI が実際にクエリを実行し、「select new { X, Y, Z }」を使用して必要なものを指定し、必要に応じて他のテーブルに結合できるため、これは機能します。

これは私には面倒に見えます。Linq フロントエンドの背後に隠されている場合でも、UI が SQL コード自体を実行すること。

ただし、これを行うには、BLL または DAL がデータベース接続を閉じることを許可しないようにする必要があります。また、IoC タイプの世界では、DAL サービスは UI コードが望むよりも少し早く破棄される可能性があります。 Linq クエリは、「破棄されたオブジェクトにアクセスできません」という例外で終了する場合があります。

だから私はポインタを探しています。私たちはどれくらい離れていますか?これにどう対処していますか?UI の変更が BLL を介して DAL に漏れるという事実は、非常に悪い解決策だと思いますが、今のところ、改善できるようには見えません。

私たちがどれほど愚かであるか教えてください。私が間違っていることを証明してください。

また、これはレガシー システムであることに注意してください。データベース スキーマの変更はまだ何年も前から行われていないため、「select *」と本質的に同等の処理を行う ORM オブジェクトを使用するソリューションは、実際にはオプションではありません。レイヤーのリスト全体をプルアップしたくない大きなテーブルがいくつかあります。

4

2 に答える 2

3

これは決して簡単に解決できる問題ではありません。私は多くの試み(あなたが説明した IQueryable アプローチを含む)を見てきましたが、完璧なものはありません。残念ながら、私たちはまだ完璧な解決策を待っています. それまでは不完全さを何とかしなければなりません。

私は、DAL の問題が上位層に漏れることを許してはならないことに完全に同意します。そのため、絶縁 BLL が必要です。

現在のプロジェクトでデータ アクセス テクノロジを再定義する余裕がない場合でも、ドメイン モデルを持続性無視の観点から考えると役立ちます。Persistence Ignorance の当然の帰結は、各ドメイン オブジェクトが、データベース列のようなものの概念を持たない自己完結型のユニットであることです。このようなオブジェクトでは不変条件としてデータの整合性を確保するのが最善ですが、これは、インスタンス化されたドメイン オブジェクトにすべての構成データが読み込まれることも意味します。これはどちらか一方の命題なので、各ドメイン オブジェクトが「適切な」量のデータを保持する (そしてロードする必要がある) ことを保証する適切なドメイン モデルを見つけることが重要になります。

オブジェクトが細かすぎると、DAL インターフェースがおしゃべりになる可能性がありますが、オブジェクトが粗すぎると、無関係なデータが読み込まれすぎる可能性があります。

非常に重要な作業は、ドメイン モデルの集計を分析して正しくモデル化し、適切なバランスを取ることです。Domain-Driven Designという本には、集合体のモデリングに関する非常にわかりやすい分析が含まれています。

この点で役立つもう 1 つの戦略は、ハリウッドの原則を可能な限り適用することです。あなたが説明する主な問題はクエリに関するものですが、よりコマンド指向に焦点を移すことができれば、常に大量のデータをロードする必要のない、より粗いインターフェースを定義できるかもしれません。

この課題に対する簡単な解決策を私は知りません。いくつかの問題に対処するのに役立つ、上で説明したようなテクニックがありますが、最終的には、経験、スキル、規律が必要な芸術です。

于 2009-10-06T10:52:23.333 に答える
1

UI 消費ケースであるビュー モデル (またはデータ転送オブジェクト) の概念を使用します。これらのオブジェクトを取得し、データが不完全な場合は、追加のデータを要求するのは BLL の仕事です (これをモデルと呼びます)。次に、BLL は、返すビュー モデルについて正しい決定を下すことができます。モデル (データ) の詳細が UI に浸透しないようにします。

UI <-- (viewmodel) ---> BLL <-- (model) --> Peristence/Data layers

この分離により、アプリケーションをより適切にスケーリングできます。ビュー モデルの構築と仕様は、linq2ql または別の orm テクノロジを使用して BLL で柔軟に実行できるため、永続化の独立性はこのアプローチから自然に外れると思います。

于 2009-10-06T08:53:06.447 に答える