4

I have a couple plain object classes to represent data read from a file. They look something like this:

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

with getters and setters for the variables. However, I wasn't sure how to expose the messages list or the params map. At first I wanted to have a getter that just returns the list or map, to avoid having to write a bunch of add/remove/iterate methods for each list or map. The collection objects have these methods and many more, so it seemed most convenient to just return those objects. However, I also the objects to know when data is changed, so that a view can be updated accordingly, or to keep track of if a particular file has been modified and needs to be saved. This means I would have to implement delegates for add/remove/iterate/keyset/entrySet/etc for those fields, but would add a lot of extra methods and make the code much less convenient. What is the best practice here, when dealing with plain objects that can have lists, maps, sets, etc in them, while also being able to know when data is changed?

I also had a related question regarding whether a child object should have a reference to the object that created it. I was thinking about this because in the event that a Message object is modified, how does its parent Command object know about that change? Should the Message class have events that Command subscribes to with listeners, or should the Message object have a reference to the Command object it is contained in, and call a method/set a field in that Command object when data is modified? What is the best practice here, or should I completely change how file data is being stored as objects?

2
  • I think you should give more information about the data you're modelling. Now it's hard to see why the Command is modelled like a container for Messages for instance. If some objects only "represent data read from a file", then there's no need to modify them, is there?
    – COME FROM
    Jun 24, 2015 at 7:02
  • Well the idea is that these objects represent information that is presented to the user, who can modify the data in the objects and save them back to disk. Command is a container for messages because a Command consists of a name and a sequence of Messages to send. I'm not sure how else to model that relationship.
    – AniDev
    Jun 30, 2015 at 14:01

3 Answers 3

2

It is good practice not to expose contained collections directly to clients. There is a list of "standard" methods that you typically provide on the containing class to manage the relationship (get all, add, remove, etc.).

In theory, it's advised that you don't ever return the actual collection to the client, rather an immutable copy of it containing the same objects. This way the client can't modify the collection directly, but has to go through your delegate methods.

Bi-directional relationships are not a problem, but slightly more tricky; use them where needed, but avoid the additional complexity if you don't. You have to make sure that the bi-directionality is maintained correctly in the model, and not rely on client code to do it. The complexity will depend on which mutations are possible after construction, but generally:

  • If you add a Message to a Command, that Command must always be the one set on the Message (and vice versa)
  • If you remove a Message from a Command, the Command reference of the Message must be set to null (and vice versa)
0

I will take the risk and assume that you have modeled the data as close to the source as possible.

In this case:

The List messages is just a structure, and yes it has a lot of method that you can use, but this methods are technical methods, normal operations on a List class.

You want to create methods in the Command class that are more human readable by using a clear name, you could get some interesting things from this approach. F for instance:

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

I have some, easy to read articles about similar topics in my blog: CodeJoy.blogspot.com and particularly What is Good Code

0

Depending on your scenario, you either would expose your collection as a ReadOnlyCollection (or the like, depending on your programming language), or you would use an ObservableCollection (that has events for add, remove, etc), which will allow you to react to changes. Consider if the latter is really necessary though. In most scenarios you would go the first route. If a downstream developer is allowed to make changes to the collections you manage, then make this an explicit API.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.