a companion discussion area for blog.codinghorror.com

When Object-Oriented Rendering is Too Much Code


#41

Card
Suit datatype="Suit"Clubs/Suit
Pip datatype="Int32"3/Pip
/Card

Rather.


#42

Jeff, the issue here is more with “Java’s OO” than with “OO” in general.

Ruby for example has (as others already pointed out) the very nice Buider module that allows you to build XML through the use of nested blocks:

In this case, your example would be rendered as

xml = Builder::XmlMarkup.new(:target=STDOUT, :indent=2)
xml.status(:code = 1)
xml.data do
nbsp; xml.usergroup(:id = “usr”)
end

the result?

status code=“1”/
data
usergroup id=“usr”/
/data


#43

ouch. Was meant to say:

The result?

status code=“1”/gt;
data
nbsp;nbsp;usergroup id=“usr”/
/data


#44

It’s a tradeoff.

If you compose XML documents out of strings,
you’re eventually going to make an invalid XML
document. Either because you do something silly,
like forget to close an element, or because you’ll
get bad input and not validate it correctly. (Look at how endemic XSS is, and I haven’t seen a practical web toolkit that eliminates it.)

I suppose you could invent a language that statically checks XML chunks in code and has $-substition for text with correct escaping.

“Too much code” isn’t the problem with “proper” XML interfaces (OO or not.) The problem is maintainability – you can look at an XML chunk and immediately visual the XML it generates. Even Masklinn’s Ruby example involves a conceptual jump between representations. With Java or .net, people can compose the DOM objects in many different permutations, even spread the work across tens of methods, scattered across as many objects. (i) you have to (re)learn the XML API if you don’t use it every day, and (ii) understand the right place to change it if you need to make a little change.

I’m a pretty good maintainance programmer, and I’ll probably make the change right… After a while. I’ve worked with a lot of guys who would (a) just give up and go home, or (b) make a bad change and manage to screw up the version control system so it takes a few hours to back the bad change out.


#45

in Common Lisp + cl-who, it’s easy. Just do:

(with-output-to-string (s)
(with-html-output (s)
(:status :code (- 3 2)) ; you can use code here, too.
(:data
(:usergroup :id “usr”))))

i love it.


#46

Maybe a new VS refactoring option here would be nice. Highlight the string and convert to XMLWriter calls. Or highlight the XMLWriter calls and see it displayed as XML.


#47

Agree with wioota and others above. Jeff, the “fully O-O” code you posted is to my mind anything but.

Here’s what a (statically typed) O-O API to XML looks like: http://www.xom.nu/

Specifically: the level of O-O abstraction matches that of the XML document model. To use it, you would construct objects for elements and data matching that of the desired output and then (as a final operation) serialize it.

This level of abstraction sounds even more important when you are dealing with XML fragments like the one posted above. In this case you simply wouldn’t serialize it, just return the objects to the caller.

Deferring the serialization till the last minute gives practical benefits: Most importantly it decouples the decision of which character encoding to use from the code that will generate each individual XML fragment. Instead of requiring every part of your application to standardize on a given character encoding, you can now support all of them.

In addition it lets you do pretty-printing which is always nice, if not essential.


#48

I think the main point for this post is “there is no universal hammer, you need to use the right tool for the job”, which isn’t really what the example (and the title) says. The problem isn’t with object-orientation. The real battle we have to keep an eye on is between procedural and declarative code.

The object-oriented code on the original post is very much procedural, imperative. This isn’t what we want. For this particular problem a declarative approach is much more appropiate. It simply is the right tool for the job, although the purely template-based solution is not (like many already pointed out).

The Ruby + Builder solution that some already brought to the table illustrates this point: it uses an object-oriented approach, but one that is much more declarative than procedural.

This post inspired me to write one of my own on my blog (in Portuguese): http://thiagoarrais.blogspot.com/2006/06/os-objetos-esto-te-matando.html


#49

Someone replied that most commenters were missing the forest for the trees. So I’ll start with the trees first:

  • The example code using XmlWriter is typical procedural code. The fact that there are objects involved doesn’t mean that the code is OO. Of course, you could argue that the problem is really in the overhead of too-structured code in cases where there are more simple, albeit less “pure”, solutions.
  • Better OO xml libraries (and arguably better languages) lead to more readable code. And, as the Ruby example mentioned above, sometimes to more terse code, as well.

In more general terms, I don’t think that object orientation per se implies in much overhead all of the time… For example, look at this post by James Robertson using smalltalk to extract info abot his feeds ( http://www.cincomsmalltalk.com/blog/blogView?showComments=trueentry=3318232350 ).
Or take a look at Martin Fowler’s post showing a small OO faade he created for driving a graph plotting utility: http://martinfowler.com/bliki/ .
Both are simple one-off tasks nicely written in OO fashion.

My point is that structural overhead is always bad (and as an “enterprisey” Java developer I saw my fair share of overengineering…), but we cannot blame object orientation in general for bad design.


#50

Someone replied that most commenters were missing the forest for the trees. So I’ll start with the trees first:

  • The example code using XmlWriter is typical procedural code. The fact that there are objects involved doesn’t mean that the code is OO. Of course, you could argue that the problem is really in the overhead of too-structured code in cases where there are more simple, albeit less “pure”, solutions.
  • Better OO xml libraries (and arguably better languages) lead to more readable code. And, as the Ruby example mentioned above, sometimes to more terse code, as well.

In more general terms, I don’t think that object orientation per se implies in much overhead all of the time… For example, look at this post by James Robertson using smalltalk to extract info abot his feeds ( http://www.cincomsmalltalk.com/blog/blogView?showComments=trueentry=3318232350 ).
Or take a look at Martin Fowler’s post showing a small OO faade he created for driving a graph plotting utility: http://martinfowler.com/bliki/ .
Both are simple one-off tasks nicely written in OO fashion.

My point is that structural overhead is always bad (and as an “enterprisey” Java developer I saw my fair share of overengineering…), but we cannot blame object orientation in general for bad design.


#51

Firstly did anyone else notice that this is not well formed XML? I can only assume that this is part of a larger xml document since there is no root element.

In any case, the easiest way to do this OO would be to simply serialize it as stated above. You wouldnt even have to write the code, since the .net framework comes with a handy little tool called XSD.

So the OO code effort pretty much becomes defining the schema and typing:

xsd myschema.xsd /c

and the code to consume the serializable object is something like:

    Dim serializer As New XmlSerializer(GetType(myClass))
    Dim _myClass As New myClass()

    With _myClass
        .status = 1
        .usergroup = "usr"
    End With
    
    Dim writer As New FileStream(filename, FileMode.Create)
    serializer.Serialize(writer, _myClass)
    writer.Close()

It never ceases to amaze me how people knock what they dont understand.

SB


#52

Write an XSD for it. You can do this by building a DataTable for it. That calling the Write Schema Method. Afterwhich the code looks like this:

DataTable MyDataTable = new DataTable();
MyDataTable.ReadSchema(@“c:\my.xsd”);
//Pull Data in from user input here
//Use DataAdapter or pull values off the Form
MyDataTable.WriteXML(“output.xml”);

Using a StringBuilder is overegineering the issue.


#53

A little late to step up to the table maybe but here are my thoughts:

http://www.thejoyofcode.com/XmlWriter_or_string_concatenation.aspx


#54

I didn’t quite get this:

“I’ve worked with developers who insisted that everything had to be generated through an object model”

How is the string class that you use NOT an object model?

Also in both examples you are solving this problem in a function (judging from the return statement) so how is this solution a

“fully object-oriented way of building it”

Functions are used in procedural programming and if you really tried a more object-oriented way of solving this maybe you would’t write this article in the first place…


#55

I can see your point Jeff, I agree with you 100%; the verbosity is killing the fun. My usual solution to this situation is to create my self some helper methods.

Using the HtmlTextWriter as an example (because I have that on hand now):

private void RenderTag(HtmlTextWriter writer, HtmlTextWriterTag tag, string text)
{
writer.RenderBeginTag(tag);
writer.Write(text);
writer.RenderEndTag();
}

The above method makes it easier to render a simple open-close tag. Then you can create other, more specialised methods.

public void RenderCell(HtmlTextWriter writer, string text)
{
RenderTag(writer, HtmlTextWriterTag.Td, text);
}

Although I think the fact that I have to create such methods outlines a pretty serious flaw in the design of these objects.


#56

When I read this post a month ago I agreed with Jeff, that it does seem to be overkill to write so much code for a few lines of html or xml. Last week a project ended up on my desk that required generating html forms (not asp.net but vanilla html with input boxes and tables) so I happily set off with my System.IO.TextWriter and started spitting out my html strings “div style=“foo:bar;baz:box”” etc.

It all worked quite nicely at first, but as I started adding more complexity to the html the code got more and more unreadable. That’s when the light came on.

All those HtmlTextWriter.RenderBeginTag and AddAttribute methods are designed to work with the asp.net rendering model :
OnPreRender
AddAttributesToRender
Render
RenderChildren
RenderBeginTag etc.
So that when you start subclassing those controls, you can add content in the correct place and be sure that the “new” attribute that you just added isn’t going to get duplicated in the output, or that the css styles get written to the right attribute.

I just spent a day rewriting all of my html writing code along the lines of asp.net and I now have a far cleaner and more robust model to build on.

So for what it’s worth, I don’t agree with your post anymore Jeff. Even though my example is html you can easily apply the same principles to xml creation.


#57

Quote: “If you’re using Response.Write, you’re a dreadful citizen of the ASP.NET world.”

Oh dear, here’a a nice link for anyone who seconds that notion. It’s entitled: “Improving String Handling Performance in ASP Applications” and was written by James Musson Developer Services, Microsoft UK

http://msdn.microsoft.com/library/en-us/dnasp/html/aspstrcatn.asp?frame=true#aspstrcatn_testing


#58

Sorry, but shorter code doesn’t always mean better design. OO is about reusability and maintainability.


#59

Oh yeah, and that first example of generating some
simple xml is so obviously more reusable and maintainable.


#60

Yeah, Its sort of like the ineffectiveness of trying to read a highly threaded forum discussion in a flattened purely linear presentation, it’s quite unmanageable!