web-dev-qa-db-ja.com

ネストされたPOJO、コレクションの公開、変更の検出

ファイルから読み取ったデータを表すプレーンオブジェクトクラスがいくつかあります。彼らはこのように見えます:

public class Command {
    private String name;
    private List<Message> messages;
}
public class Message {
    private Type type;
    private Map<String, Object> params;
}

変数のゲッターとセッター。ただし、messagesリストまたはparamsマップを公開する方法がわかりませんでした。最初は、リストまたはマップごとに一連のadd/remove/iterateメソッドを記述しなくても済むように、リストまたはマップを返すだけのgetterが必要でした。コレクションオブジェクトにはこれらのメソッドなどが含まれているので、これらのオブジェクトを返すだけが最も便利に思えました。ただし、データがいつ変更されたかを知るためのオブジェクトもあるので、それに応じてビューを更新したり、特定のファイルが変更されて保存する必要があるかどうかを追跡したりできます。これは、これらのフィールドにadd/remove/iterate/keyset/entrySet/etcのデリゲートを実装する必要があることを意味しますが、多くの追加メソッドを追加し、コードの利便性を大幅に低下させます。リスト、マップ、セットなどを含むことができるプレーンオブジェクトを処理し、データがいつ変更されたかを知ることができる場合、ここでのベストプラクティスは何ですか?

また、子オブジェクトがそれを作成したオブジェクトへの参照を持つ必要があるかどうかについても関連する質問がありました。 Messageオブジェクトが変更された場合、その親Commandオブジェクトはその変更についてどのように知るのですか? MessageクラスにCommandがリスナーでサブスクライブするイベントがある場合、またはMessageオブジェクトが含まれているCommandオブジェクトへの参照を持っている場合、データが変更されたときにメソッドを呼び出す/そのCommandオブジェクトにフィールドを設定しますか?ここでのベストプラクティスは何ですか、またはファイルデータのオブジェクトとしての格納方法を完全に変更する必要がありますか?

4
AniDev

含まれているコレクションをクライアントに直接公開しないことをお勧めします。関係を管理する(すべて取得、追加、削除など)ために包含クラスで通常提供する「標準」メソッドのリストがあります。

理論的には、実際のコレクションはクライアントに返さず、同じオブジェクトを含む不変のコピーをクライアントに返すことはお勧めしません。この方法では、クライアントはコレクションを直接変更できませんが、デリゲートメソッドを経由する必要があります。

双方向の関係は問題ではありませんが、少しトリッキーです。必要に応じてそれらを使用しますが、使用しない場合は追加の複雑さを避けてください。双方向性がモデルで正しく維持されていることを確認する必要があり、クライアントコードに依存しないでください。複雑さは、構築後にどの変異が可能かによって異なりますが、一般的には次のとおりです。

  • コマンドにメッセージを追加する場合、そのコマンドは常にメッセージに設定されている必要があります(逆も同様)
  • コマンドからメッセージを削除する場合、メッセージのコマンドリファレンスをnullに設定する必要があります(逆も同様)
2
Cornel Masson

シナリオに応じて、コレクションをReadOnlyCollection(プログラミング言語に応じて同様)として公開するか、ObservableCollection(追加、削除のイベントがある)を使用します。 、など)、変更に対応できるようにします。後者が本当に必要かどうかを検討してください。ほとんどのシナリオでは、最初のルートに進みます。ダウンストリームの開発者が管理するコレクションの変更を許可されている場合は、これを明示的なAPIにします。

0
herzmeister

私はリスクを取って、データをできるだけソースに近いところにモデル化したと想定します。

この場合:

Listメッセージは単なる構造であり、はい、使用できる多くのメソッドがありますが、このメソッドは技術的なメソッドであり、Listクラスに対する通常の操作です。

明確な名前を使用して、より人間が読みやすいCommandクラスのメソッドを作成したい場合は、このアプローチからいくつかの興味深いことがわかります。たとえばF:

//pseudo-code here
public void AddMessage(Message message) 
{
  ValidateMessageSefty(); // returns an exception if is not
  List.Add(message);
}

私のブログには、同様のトピックに関する読みやすい記事がいくつかあります: CodeJoy.blogspot.com 、特に Good Codeとは

0
Pablo Granados