1

まず、私の英語が下手でごめんなさい:D 最近、ソフトウェア工学の試験のためにデザインパターンをより深く勉強していて、この試験のプロジェクトとしてソフトウェアシステムを設計しなければなりません。

私が処理できない問題があります: エンティティ クラス (アプリケーション ドメインのデータを表す) を他のすべてから切り離す方法です!

つまり、より具体的に言えば、Patient クラス (独自のプライベート属性と public getter および setter メソッドを持つ) がある場合、これはエンティティ クラスであり、これまでのところ正しく理解できたと思います:D

では、MVC パターン アーキテクチャを使用してプログラムを設計することを選択したとしましょう。Patient クラスはモデルに含まれますが、それは正しいですか?

さて、そのクラスを扱うすべてのビューは、それへの参照を持ちます: 3 つのビューがあるとしましょう: すべての患者を表示する最初のビュー、患者を変更する別のビュー、新しい患者を登録する最後のビュー (実際にはレポートを提出するクラスは他にもありますが、今は関係ないと思います)。

これらのクラスのそれぞれは、そのデータを表示するために患者の構造を認識します。たとえば、ゲッター メソッドを呼び出して何らかの方法でデータを表示します。

ビューは意味的にデータ (=モデル) に関連付けられているため、これを回避する方法はないと思います。つまり、データが文字列、日付、または整数であるかどうかを認識しなければならないということです。そのセマンティクス (現実の世界で何を表しているか) も知っている必要があります。そのため、Patient クラスへの参照を削除するだけではあまり意味がないと思います。

ここで問題の核心は次のとおりです: クラス Patient の変更が、それを使用するすべてのクラス (ビューだけでなく) に伝播するのを防ぐにはどうすればよいでしょうか?

つまり、要件の変更により、属性 String Cellular が String[] Cellular で変更されたとしましょう。変更する必要があります: 1) DB / DB インターフェイス 2) 患者クラス 3) (最悪) 患者を使用するすべてのクラス!!

これを回避する方法は?良いプロジェクトでは、単一のクラスの変更が、そのクラスを使用するすべてのモジュールへの一連の変更に反映されるべきではないと思いますが、私は初心者であり、これを防ぐ方法が思いつきません。

要件の変更はインターフェースの変更に反映されるため、エンティティークラスに安定したインターフェースを使用する良い方法を考えることさえできません (インターフェースが変更されることを意図しているとは思いません!)。

助けてください!!

4

4 に答える 4

1

頭に浮かぶ最初のコメントは、Cellular 属性を使用する一連のクラスを悪いことのように変更する必要があるということです。

これは、厳密に型指定された言語の特徴の 1 つです。これにより、その属性が使用されるシステム全体で型の一貫性が保たれます。

たとえば、Cellular フィールドが String から String[] に変更された場合、もちろん DB モデルも調整して、1 対 1 の関係から 1 対多の関係への変更を反映する必要があるため、データ アクセス オブジェクト (または ORM)レイヤー構成) を調整して、変更を反映する必要があります。コンパイラがそれを手放さないのは良いことです。

もう 1 つのコメントは、Cellular フィールドを使用するクラスのみを調整する必要があるということです。しかし、ここでも、それは良いことです。したがって、患者の携帯電話番号を収集するユーザー インターフェイスがある場合、コンパイラは、ユーザーが複数の番号を収集できるようにする必要があることを通知します。

ソフトウェアを設計するときは、モデルをできるだけ正しくするために多くの時間を費やすことが非常に重要です。また、要件がある程度変更されることを知っているので、リファクタリングを恐れないことも非常に重要です。Eclipse、NetBeans、IntelliJ などの最新の IDE は、忙しいリファクタリング作業のほとんどを支援し、代わりに行うことができます。

于 2012-07-31T18:30:15.273 に答える
0

すべての変更をモデル、ビュー、または永続化レイヤーに分離できるわけではありません。しかし、あなたの場合、患者モデルに一般的な連絡先フィールドのリストを持たせることができます。ビューはそれらのリストを取得し、ユーザー向けに編集可能なテキスト ボックスを作成します。DatabaseMapper は、これらのフィールドも一般的に保持します。

そのため、Cellular の追加は、GUI を大幅に変更する必要がない限り、純粋にモデル内で行うことができます。必要があることがわかっていない限り、一般的に構築を開始することはありませんが、リファクタリングすることはできます。

于 2012-07-31T18:38:40.487 に答える
0

エンティティ クラスについては、すべてのビジネス エンティティを定義し、それらの間で共通の動作パターンを推測できるようになった後、インターフェイスの抽象化を最後まで残す必要があると思います。そうして初めて、それらの間で共通のインターフェースを推測できます。しかし、エンティティ クラスは最終的に具体的です。それらをさらに抽象化しようとしても意味がありません。

最終的に、これらの具象クラスを変更するには、それらと対話するコントローラー/ビューも変更する必要があります。これについて心配しないでください。各エンティティのすべてのビューを定義したら、抽象化がある場合は、抽象化の作業を開始できます。

具象エンティティをすでに定義している場合は、ビューの抽象化を開始できます。金融の例として、Trade クラスがあるとします。明らかに、BondTrade、EquityTrade などの特定の種類の取引を行うことができます。つまり、BondTradeView、EquityTradeView などの具体的なビューを持つことができる TradeView も使用できます。より高いレベルの抽象化を行うことができますが、最終的には、特定のビューを定義する具象クラスが必要になります。

例として Facade Design パターンを見てください。ファサードを使用して、具体的な実装に基づいてビューを作成できます。これは、すべての具体的なエンティティを統合する方法です。エンティティに基づいて、どのビューをどのように作成するかを知るためのロジックが含まれます。これは、エンティティに対して行われた伝播された変更を簡素化する方法です。

于 2012-07-31T18:40:27.703 に答える
0

わかりましたので、次のステートメント:

これらのクラスのそれぞれは、そのデータを表示するために患者の構造を認識します。たとえば、ゲッター メソッドを呼び出して何らかの方法でデータを表示します。

半分だけの真実です。あなたのビューは、 a が何であるかを知っているべきではありませんPatient。おそらくPatientView、それが動作するモデルと呼ばれるものがあります。したがって、モデルとビューの間にあるピースは、突然変異を実行する必要があります。基本的には次のようになります。

public PatientView convertPatient(Patient patient)  
{  
    return new PatientView(patient.foo(),patient.bar(),etc);  
} 

関数のコントラクトは、PatientViewオブジェクトが呼び出し元に返されることを保証します。その後、このクラスは、それをカプセル化するクラスによって定義されるインターフェイスの一部になります。これには、ビューが a が何であるかを知らないという利点もありますPatient

基礎となるモデル、つまりアプリケーション全体を駆動するものに何らかの変更が加えられると、もちろん何らかの波及効果が生じます。コンバーターを使用すると、アプリケーションのどの部分も aPatientが何であるかを実際に認識してはならず、患者をその部分に期待されるものに変換するビュー、コントローラーなどの各領域間にコネクターが存在する必要があるため、タッチポイントを最小限に抑えるのに役立ちます。アプリケーション。

于 2012-07-31T18:40:57.130 に答える