私はRCPアプリケーションに取り組んでいます。このアプリケーションは初めてです。
Spring Beanは、エンティティを保存/フェッチするビジネスロジックを記述するために使用されます。
ただし、エンティティをクライアントに直接送信するのではなくDTOに変換していますでクライアントにデータを入力します。保存中に、DTOをエンティティに変換して保存しています。
これらの変換の利点は何ですか?誰かが説明できますか?
開発者が「これを行う意味は何ですか?」そのために、いくつかの例を示します。
すべての例は、この単純なデータモデルに基づいています。
Person
エンティティには5つのプロパティがあります:Id, FirstName, LastName, Age, CityId
また、アプリケーションがこのデータをさまざまな方法(レポート、フォーム、ポップアップなど)で使用すると想定できます。
アプリケーション全体がすでに存在しています。私が言及するすべては、既存のコードベースへの変更です。これは覚えておくことが重要です。
例1-基になるデータ構造の変更-DTOなし
要件が変更されました。人の年齢は政府のデータベースから動的に取得する必要があります(姓名に基づいて仮定しましょう)。
Age
値をローカルに保存する必要がないため、Person
エンティティから削除する必要があります。ここでは、エンティティがデータベースデータを表していることを理解することが重要です。データベースにない場合、エンティティにはありません。
政府のWebサービスから年齢を取得すると、別のオブジェクト(またはint)に保存されます。
しかし、フロントエンドにはまだ年齢が表示されています。すべてのビューはPerson.Age
プロパティを使用するように設定されましたが、現在は存在しません。問題が発生します:人物のAge
を参照するすべてのビューを修正する必要があります。
例2-基になるデータ構造の変更-DTOを使用
古いシステムには、同じ5つのプロパティId, FirstName, LastName, Age, CityId
を持つPersonDTO
エンティティもあります。 Person
を取得した後、サービスレイヤーはそれをPersonDTO
に変換して返します。
しかし今、要件は変更されました。人の年齢は政府のデータベースから動的に取得する必要があります(姓名に基づいて仮定しましょう)。
Age
値をローカルに保存する必要がないため、Person
エンティティから削除する必要があります。ここでは、エンティティがデータベースデータを表していることを理解することが重要です。データベースにない場合、エンティティにはありません。
ただし、中間にPersonDTO
があるため、このクラスがkeepAge
プロパティを使用できることを確認することが重要です。サービスレイヤーはPerson
をフェッチし、PersonDTO
に変換します。次に、政府のWebサービスから個人の年齢もフェッチし、その値をPersonDTO.Age
に格納します。そのオブジェクトを渡します。
ここで重要なのはサービスレイヤーを使用するユーザーには、古いシステムと新しいシステムの違いは見られないです。これにはフロントエンドが含まれます。古いシステムでは、完全なPersonDTO
オブジェクトを受け取りました。また、新しいシステムでは、完全なPersonDTO
オブジェクトを引き続き受け取ります。 ビューを更新する必要はありません。
関心の分離というフレーズを使用する場合、これが意味します。2つの異なる関心(データベースへのデータの保存、フロントエンドへのデータの提示)があり、それぞれ異なるデータタイプが必要です。これら2つのデータ型に現在同じデータが含まれている場合でも、将来的には変更される可能性があります。
上記の例では、Age
は2つのデータ型の違いです。Person
(データベースエンティティ)はAge
を必要としませんが、PersonDTO
(フロントエンドのデータ型)では必要です。
懸念事項を最初から分離する(=個別のデータ型を作成する)ことで、コードベースはデータモデルに加えられた変更に対してはるかに回復力があります。
DTOオブジェクトがあると、新しい列がデータベースに追加されたときに、エンティティとDTOの両方にプロパティを追加するという二重の作業が必要になると主張するかもしれません。それは技術的に正しいです。 1つのクラスではなく2つのクラスを維持するには、少し余分な労力が必要です。
ただし、必要な労力を比較する必要があります。 1つ以上の新しい列が追加されると、いくつかのプロパティのコピー/貼り付けにそれほど時間がかかりません。データモデルが構造的に変更されると、おそらくコンパイル時にではなく実行時にのみバグを引き起こすような方法でフロントエンドを変更する必要があり、かなり多くの労力を要し、開発者はバグを探す必要があります。
もっと例を挙げましょうが、原則は常に同じです。
要約するには
Person
)Name
を持っています。ただし、すべてにName
プロパティがあるからといって、共有のEntityWithName
基本クラスから継承する必要があるわけではありません。異なるName
プロパティには意味のある関係はありません。Name
がTitle
に名前が変更されるか、人がFirstName
とLastName
を取得する)、それらはあなたです。そもそも不要だった継承を元に戻すために、より多くの労力を費やす必要があります。懸念事項を分離することを検討する経験則として、次のように考えてください。
すべての懸念事項(UI、データベース、ロジック)が別の場所にいる別の人によって処理されると仮定します。メールでのみ通信できます。
十分に分離されたコードベースでは、特定の懸念事項への変更は1人の担当者のみが処理する必要があります。
これらすべての開発者が同じPerson
エンティティを使用していて、エンティティに小さな変更が加えられた場合、プロセスにeveryoneが関与する必要があります。
しかし、レイヤーごとに個別のデータクラスを使用することにより、その問題はそれほど一般的ではありません。
PersonDTO
オブジェクトを返すことができる限り、ビジネス開発者とUI開発者は、データの格納/取得方法の変更を気にしません。ここでのキーフレーズはそれらには影響しないためです。懸念事項を適切に分離することは、他の当事者への影響を最小限に抑えることを目的としています(したがって、関与する必要があります)。
もちろん、いくつかの大きな変更は、複数の人を含めることを避けることができません。まったく新しいエンティティがデータベースに追加されたとき。ただし、アプリケーションの有効期間中に行う必要がある小さな変更の量を過小評価しないでください。大きな変更は少数の少数です。