Search code examples
javamodel-view-controllertostringpresentation

toString() and MVC


The API documentation for toString() states:

Returns a string representation of the object. In general, the toString method returns a string that "textually represents" this object. The result should be a concise but informative representation that is easy for a person to read. It is recommended that all subclasses override this method.

(emphasis mine)

With that in mind, I wrote a toString() for a Building type class that was essentially (some implementation stripped)

@Override
public String toString(){
Stringbuilder sb = new StringBuilder("<p>");
sb.append (this.getDesc());
sb.append ("which contains: <br> <ul>"); 
for (Room r: this.getRooms()){
    sb.append("<li>");
    sb.append(r.getDesc());
    sb.append("</li>");
}
sb.append("</ul>");
return sb.toString();
}

Giving something like:

A self contained student flat which contains:

  • A basic study
  • A basic living area
  • A basic bathroom
  • A basic bedroom

I think this is a "concise but informative representation that is easy for a person to read" but it seems to fly in the face of MVC as I understand it. The Building and Room class are both in the Model and surely that sort of output formatting belongs in the view?

I'm not certain whether I'm overthinking this, whether the Java API isn't written with MVC in mind or whether there's something I haven't understood. Can presentation matters go in the toString()? Would I be better having a seperate displayBuilding() or similar?


Solution

  • IMHO Object::toString is very useful in logs and debugging, So, I'd use plain text to render its output.

    My suggestions are:

    • Use libraries such as Apache Commons Lang and method ReflectionToStringBuilder::toString to quickly get a plain text output.
    • Create a functional interface (e.g. HtmlRepresentable) with one method toHtmlString implement such method in your classes you want to have an HTML object representation.

      public interface HtmlRepresentable {
          String toHtmlString();
      }
      

      Then

      public Building implements HtmlRepresentable {
      
          @Override
          public String toString() {
              StringBuilder sb = new StringBuilder("<p>");
              sb.append (this.getDesc());
              sb.append ("which contains: <br> <ul>"); 
              for (Room r: this.getRooms()) {
                  sb.append("<li>" + r.getDesc() + "</li>");
              }
              sb.append("</ul>");
              return sb.toString(); 
      }