I'm working on a class that represents an object with multiple representations - one is an XML type representation used by an automatic ordering system, the other is a POJO-based representation used by a monitoring tool.
The problem I'm running into is that I seem to have to make trade-off between encapsulating the object's internal data and designing my application according to the principle of "separation of concerns" or "single responsibily per class".
Let's look at the class in more detail:
public class MyObject {
private Object field1;
private Object field2;
private Object field3;
...
private Object field100;
}
(Yes it's quite a big ugly monster, something I have no control over).
If I follow the principle of separation of concerns (the way I understand it anyway), I will have to add getters for every field in this class and have a separate XMLBuilder class for the XML representation, and a PojoBuilder for the Monitoring tool representation:
public class XMLBuilder {
public XML asXml(MyObject obj) {
return "<tag1>" + object.getField1() + "</tag1>"
"<tag2>" + object.getField2() + "</tag2>"
...
;
}
}
This seems to me to break the principle of encapsulation - I have to expose a lot of the internal data on my class just to provide a representation for it. If I pass my object to other systems, I have no control whether these sub-systems may become dependent on arbitrary fields (i.e. field45), which means that future changes to the structure of this object may become difficult as there are now other possible dependencies on it.
An alternative approach, advocated by Allen Holub (http://www.javaworld.com/article/2073723/core-java/why-getter-and-setter-methods-are-evil.html) for example, is to do the representation inside the class:
public class MyObject {
...
public XML asXml() {
return "<tag1>" + field1 + "</tag1>"
"<tag2>" + field2 + "</tag2>"
...
;
}
public Object asMonitor() {
...
}
}
To me, this solution seems great, as the class never exposes any private fields. The representation generators have access to all the information it needs, and the object itself can be safely passed to other sub-systems without the worry that another module would depend on internals.
Now, when I implement this, my colleagues all raise the issue of "Separation of concerns". The problem, they say, is that the MyObject class now have knowledge of things like XML representations and POJO represantions, which means that if the XML representation changes, you now have to make modifications inside the actual class itself, instead of just updating an "XML ruleset" or some other external configuration.
Holub's solution is to use a Builder pattern:
public class MyObject {
...
public void buildContent(MyObjectBuilder builder) {
builder.setField1(field1);
builder.setField2(field2);
}
}
public class XMLBuilder implements MyObjectBuilder {
...
public void setField1(Object field1) {
content += "<tag1>" + field1 + "</tag1>";
}
public XML asXML() {
return content;
}
...
}
but this seems hardly better than the first approach - instead of exposing data as getters, it is now implicitly exposed via a builder. OK, I understand that with the builder I may have additional control over how my object represents itself, but is that iota of control worth the increased complexity in the code base? Changes to the structure of MyObject will still likely result in downstream dependencies requiring updates, so I'm not entirely sure if much have been gained here (except that there are technically no getters).
Is this a case where you simply have to choose your poison? Or is there a magical middle ground that reduces all these issues? What are the common strategies for dealing with this?