web-dev-qa-db-ja.com

オブジェクトのラッピングとフィールドのコピー

ほとんどすべてのソフトウェアには、外部に公開したくない内部データ構造がいくつかあります(たとえば、APIを介して)。

1:1データベーステーブルを表すクラスがいくつかあるとしましょう-UserUserGroupGroupPermissionなど。

次に、APIで公開される外部クラスExternalUserを作成し、ユーザーの詳細とユーザーグループの詳細を公開します。

ExternalUserのプロパティを指定するには2つのオプションがあります。

  1. プロパティのコピー --ExternalUserには、プロパティのサブセットまたはUserおよびUserGroupから派生したプロパティのコピーがあります

    1.1。 ExternalUserには、たとえば、usernamefullNameuserGroupsなどをプロパティとして含めることができます。

    1.2これらのプロパティはすべて、オブジェクトの作成時に入力され、内部UserおよびUserGroupsからコピーされます

  2. ラッピングオブジェクト-ExternalUserにはUserおよびUserGroupへの参照があります。

    2.1 ExternalUserには、内部モデルへの参照を保持するプライベートuseruserGroupがあります。

    2.2 getNameのようなメソッドは、内部のuser.getNameなどに委任します。

トランザクションを処理している場合、データのリーク、メモリの使用、およびセッション管理の両方の長所と短所を確認できます。

パターン/標準、または一方のオプションがもう一方のオプションよりもはるかに優れている理由はありますか?

2
SDekov

私があなたを正しく理解している場合、プロパティをコピーすることは、カプセル化を使用せずnot、単に個々のフィールドをExternalUserのインスタンスに設定することを意味します、私は正しいですか?

プロパティをコピーすることにより、基本的にプログラムをより堅牢にすることを試みます。内部にカプセル化された洗練されたタイプを持たないExternalUserなどのPOJOクラスは、プログラムの実際の実装を、それを使用するものと切り離す非常に良い方法です。 APIを呼び出すユーザーは、おそらくExternalUserのインスタンスを受け取り、いかなる種類の問題も発生しません。データは存在し、必要に応じて便利にシリアル化できます。

内部クラスのインスタンスをカプセル化することにより、ExternalUserクラスは実装にはるかに依存するようになります。これは必ずしも悪いことではありません。UserおよびUserGroupのメソッドを変更すると、このロジックがExternalUserまたは他の場所。ただし、この方法で行う場合は、すべての内部実装を非表示にするように注意する必要があります。 ExternalUserはこれ専用のクラスである必要があるため、すべてのパブリックメソッドと、はい、プライベートメソッドもUserまたはUserGroupインスタンスを返さないようにする必要があります。なぜプライベートメソッドも?リフレクションを介してプライベートメソッドにアクセスできるためです。

堅牢性を好むわけではありませんが、DRYの原則に従っています。これにより、プログラムがより柔軟になり、一般的に保守が容易になります。

私の個人的な好みは、インターフェースを単純で堅牢に保つことなので、ExternalUserにはPOJOクラスを使用します。 DRYの原則に可能な限り従う場合は、呼び出し元にデータを返すまで、ExternalUserの使用を避けてください。ExternalUserは、 strictlyこの時点での外部クラスですが、これは小さなプロジェクトでは少々やり過ぎかもしれませんので、最終的には個人の好みに依存します。

4
Neil

2つのケースがあります

1. REST APIおよびその他のIOチャネル

通常、追加のオブジェクトは必要ありません。どうして?出力をシリアル化する場合、通常は@Ignore@Exposeなどのアノテーションを使用して、データをJSON/XMLに選択的にシリアル化できるためです。

2.コードライブラリとしてパッケージ化

次に、プロパティをExternalUserなどにコピーする必要があります。どうして?個人会員の内容を振り返って調べることはおそらく可能だろうから。

0
dagnelies

APIの場合は、どちらも行う必要はありません。

Apiのクライアントライブラリで使用するには、ExternalUserオブジェクトが必要なので、そのうちの1つが必要です。

外部ユーザーのフィールドのデータのみを含む文字列を生成するためにAPIが必要です。ただし、これを実現するためにExternalUserオブジェクトをシリアル化する必要はありません。

Userオブジェクトから必要なプロパティのみを含めるようにシリアライザーを構成するだけで済みます。

0
Ewan