Jeff Atwood of coding horror posted about "tag soup" in web development. I absolutely agree with him on this one: every web development framework currently in existence renders crap HTML code. Remember my HTML wall of shame? Yes, that's a good example of crap HTML being rendered by frameworks. Jeff (Atwood) asks if there's a better solution. Luckily, Jeff (me) has one: it's called writing good HTMLand separation of concerns in rendering. Wow, that's a long phrase. Let's try again: Don't use frameworks because you don't know HTML; the people who wrote the framework don't know HTML either. No, still not good. Let's stick with the old favorite:
It's called HTML and it's not hard
That's right, HTML is not a complex thing and writing clean HTML isn't particularly difficult. In fact, you can leverage a framework and still write good HTML and I'm going to show you how. It's really as simple as using separation of concerns. Let's analyze the various parts of a web page.
What is the HTML for? It's really a place to store content. Your text, your menu bars, your stupid scrolling marquees, your <blink> tags, etc. All of this goes here. The way I think about it is that you're using HTML tags to create containers for content. A <p> tag is a container for some text. A <table> contains some related data in rows and columns. A <span> tag is going to hold some special line of content. A <div> is going to contain some special stuff inside of it. Notice that I haven't said a thing about formatting, style, or actual content yet. The reason would be that it DOESN'T BELONG IN YOUR STUPID HTML!!!!! One more thing I'd like to bring up here is the hell of nested tables. This occurs when someone wants to do some sort of complex formatting and doesn't know how to use the div tag with CSS. Nested tables are an anti-pattern called "Nested fucking tables" and should be avoided. It won't make your formatting better (Firefox and IE sometimes render different table elements differently so often this actually makes things worse). This brings us to:
Formatting and Style
So wouldn't it be nice if there were some sort of "style" thing you could use to store all your styles so you can keep them in one place (DRY, right?). Maybe some sort of "sheet" where your "styles" could go, and then they would "cascade" throughout the whole site for every page that referenced them. Maybe some sort of "cascading style sheet?" Oh wait, that already exists. Let's use it! Now, you can focus on the HTML only be containers for content and let your CSS define how that content is presented and styled. Separation of concerns, right? Now you have only containers and maybe some information in the containers to identify them to your style sheets (ID and Class are the attributes you're looking for). This is good separation of concerns.
So what about behavior?
But the server blah blah blah . . . .
This is where the example that Jeff shows really breaks down. I'm not going to post it up here, but go look at his post and check out the example code. You'll see something really stupidly obvious: YOU'RE DOING LOGIC IN THE DAMN MARKUP!!!! You're concatenating links, you're looping through stuff, you're doing all kinds of crap. Hell, as long as you're at it, why don't you query the database there too just so all your crap is at least in one file?
There is a simple solution to this problem: You already have containers defined by your html. Use them. Expose them to the server side code and let that code render stuff inside them. For example, in ASP .Net one of my favorite tricks is to have a table on my page and actually use the <asp:table> object so that my codebehind can expose it to my controller (You're using MVC, right?) and my controller can populate it with data. Wait, controllers shouldn't populate data, so wtf am I doing? Am I breaking my own rules? No, I don't directly populate tables from the controller; typically I use an intermediary object to do that for me (more about this in a future post, I promise). This way, the controller is able to provide the model to the view via some other object that is responsible for doing complex formatting. I can reuse my formatting objects where appropriate. I can also change the formatting without changing the model or the view itself. I can change the view even if I want to without caring how the formatting is created (as long as the contract between the view and my formatting object is fulfilled, i.e. if the view is expecting a table then the formatter had best be rendering one).
Here you go, Jeff-
A nice, happy, clean solution looks something like this:
1. The HTML provides containers for content and possibly some content as well.
2. The CSS provides style information and formatting for the containers.
4. The server side code populates the HTML containers with content.
5. The server side uses helper objects to populate content that requires more complex rendering (tables with grouping levels I think are a good example here).
The only thing you need in order to pull this off is to know all of these different technologies. This isn't that hard, and as a web developer you really should know all of this stuff anyway. I think Microsoft started a horrible trend with Asp .Net that allowed application developers to write web apps without knowing anything about web technologies. This attitude has brought us the viewstate, page events, chatty controls, and a bunch of other crap that makes your html look like tag soup. Rails and MVC haven't helped this problem at all.