As we work with ASP.NET MVC on Stack Overflow, I find myself violently thrust back into the bad old days of tag soup that I remember from my tenure as a classic ASP developer in the late 90's. If you're not careful bordering on manically fastidious in constructing your Views, you'll end up with a giant mish-mash of HTML, Javascript, and server-side code. Classic tag soup; difficult to read, difficult to maintain.
I don't mean tag soup in the sense of badly formed HTML, or the malformed world we live in. I mean tag soup in the sense of mixing HTML markup and server-side code. Now you can double your pleasure: badly formed HTML, meet badly written code.
The tag soup problem seems to be endemic to all modern web development stacks. I see that Ruby on Rails apps have the same problem; here's a slice of representative RHTML from Typo, a Ruby blogging engine.
Do you find this readable? Can you see where the code begins and the markup ends? Are you confident you could change the code structure without breaking the HTML, or change the HTML structure without breaking the code?
Sometimes editing this stuff makes me feel like I'm playing Operation. I have to ever so carefully maneuver my metal tweezers into one tiny slice of code or HTML and make my changes without touching the edges and setting off that blasted electrical buzzer.
I'm not trying to single out Rails or Typo here; I could easily show you a ASP.NET MVC view that's just as confusing (or as "clear", if you think that's perfectly readable, I guess). Tag soup is everywhere; take a look at the Python Django framework templates:
<h1>Archive for {{ year }}</h1>
{% for date in days %}
{% ifchanged %}<h3>{{ date|date:"F" }}</h3>{% endifchanged %}
<a href="{{ date|date:"M/d"|lower }}/">{{ date|date:"j" }}</a>
{% endfor %}
Perhaps when it comes to mixing HTML and server-side code, some form of soup is unavoidable, a necessary evil. The soup can be quite palatable; maybe even delicious. It's certainly possible to write good tag soup and bad tag soup.
But I have to wonder: is there a better way? Is there something beyond RHTML, Views, and Templates? What examples would you point to of web development stacks that avoided degenerating into yet more hazardous, difficult to maintain tag soup? Is there anything truly better on the horizon?
Or is this year's newer, fancier, even-more-delicious iteration of tag soup as good as it ever gets for web development?
Shameless plug on this topic: http://rassie.org/archives/178 , Lisp has the power to make this bearable.
Brev is worth a look: http://breve.twisty-industries.com/ if you are writing Python.
Nikolai on July 21, 2008 7:49 AMGreat post keep up the Great work!!!!
Miguel on July 21, 2008 7:51 AMSo basically to code in sane looking HTML, you have to abandon HTML. Great.
JMJ on July 21, 2008 7:52 AMDjango templates are very restrictive when it comes to adding logic and other functions. You have just as much in the templates as needed for the presentation.
I'm a bit puzzled that you present it as tag soup on the same level as other templates...
I thought MVC was supposed to eliminate that sort of thing - you know, all that separate the code from the data stuff.
Chuck on July 21, 2008 7:55 AMNow this takes me back. The good ol' days.
funbytebitstop on July 21, 2008 7:56 AMOne technique I've seen and like is Ruby's stock CGI library. For each supported HTML element, there's a trivial function:
CGI.HTML {
CGI.HEAD {
CGI.TITLE { print Pagetitle }
}
CGI.BODY {
#output page stuff
}
}
The only problem I saw with it (other than the naming) was that It needed badly to be updated to support cleaner, nicer HTML 4. (As it is, I think it outputs some ugly HTML 3.2 transitional.) I thought it was a really cool idea, as it basically just outputs a new open/close tag pair with each block. Of course, this can result in nesting getting arbitrarily deep, but that can be mitigated somewhat.
greyfade on July 21, 2008 7:56 AMSeriously, why are you mixing up the code like this. Testability goes right out the window, readability is thrown out with the bath water and maintainability is completely AWOL.
If you are expecting to go back to your code at anytime AND understand what is going on, then you have to eliminate that sort of mess. Code reviews are a great way to highlight these sort of problems. If you can't stand up explain this code clearly and concisely, then rewrite it.
I'm a keen advocate of the Presenter First (MVP) pattern; it gives you testability right up to edges of your application and removes a great deal of complexity from your UI layer.
The MVC pattern mixed with the ASP.Net model is not a good enough fit to work well, so I avoid that using that.
A little bit of architecture goes a long way. One complaint about Presenter First (MVP) is that is means masses of extra code - not true.
Try it, you might like it.
I don't get it. You're using ASP.NET. Why would you ever use %= %? That's just unnecessary. Any modern web framework should allow for the pages to be nothing but markup, using custom tags to replace all of that tag soup mix-and-match. There were several popular frameworks that allowed for custom tags all the way back in 2000, maybe earlier.
Emitting HTML from pure code, with no markup pages, feels nice to a software engineer, but it's useless in the real world, where designers (who can actually make your UI not suck) need something that looks like HTML to open with their own development tools.
ASPX + ASCX (+ Composite Controls, used very sparingly) give you everything you need to avoid tag soup, if you're using MSFT products.
Eric on July 21, 2008 8:16 AMAs someone admittedly way behind the web-dev curve, I just try and think about what I need beforehand and put as much in one place (in this case the server side ASP.NET code as possible.
If I have to use some tag/soupiness on the HTML side, I make sure I comment it clearly, and perhaps even document that in the code behind file of the page.
N on July 21, 2008 8:16 AMWow, I guess you must be really used to it... all the examples people showed here for code that is more readable seems even less readable to me :LOL:
I think the idea to do it all diagrammatically is not a good idea. Why would I want to have a program *DYNAMICALLY* create a *STATIC* piece of HTML? This makes little sense to me. That is like writing a Word (or OpenOffice) document, where you have static text, you just type and dynamic macros (inserting names, dates, page numbers, headlines, whatever). Why would I want all text to be such a macro? How does this make things any better to read.
I rather want the opposite, having everything static, but having everything static means no dynamic pages. Not a way to go either. I never did much else than PHP, that is when intermixing HTML and code (never used ASP or JSP or Ruby, ...) and here I can only add some tips:
1. Make as much static as possible. The page should not be a big PHP script with some tiny HTML elements inside. It should be a webpage (HTML) with some tiny PHP elements inside. Most parts of a webpage are pretty static, keep them static (this also speeds up processing enormously and keeps server load low).
2. Re-use your code. Don't put that the same PHP code that generates a menu on top of every PHP page. Instead create a script that only renders the menu and use it from everywhere. That way the menu is totally dynamically, but it won't break tip one, as including it makes it look like a static piece of code.
3. Only place PHP code interleaved between HTML code, that really renders the page. If you need functions, declare them in an external PHP (that is pure PHP only).
4. When you switch to PHP, make this PHP block self-contained. That is, don't use static HTML to open a table tag, then a tr tag and now have PHP code create a line of data (TD tags). If you remove the HTML code around (e.g. the table tag), your PHP code produces garbage! And if you remove the PHP code, the page is broken (okay, not in this case, I guess HTML spec allows a table to contain zero TD elements). If you have a dynamically generated table, for that you need PHP code, let PHP generate the whole table (even if this contradicts tip 1). That way you can easily alter all HTML code surrounding the PHP code (the code generated by the PHP will always be valid) and you can easily kick out the whole PHP block, the rest of HTML left over will stay valid (there simple won't be a table any longer on the page).
Mecki on July 21, 2008 8:22 AMI don't write tag soup.
Probably the best explanation of a the helper partials concept, as used in a language which is well-matched to the web but not particularly hi-tech is the manual for the symfony framework in PHP:
http://www.symfony-project.org/book/1_0/07-Inside-the-View-Layer
When I code PHP I don't normally use symfony, but I do use an internal templating system which is remarkably similar.
ASP.NET, at the fundamental level, has one of the best systems for generating HTML. Microsoft has hobbled it with bad ideas and bad implementations (such as tying events to buttons, the specific implementation of the web controls, etc.)
The helper and partial concept can be brought to ASP.NET by creating user-defined controls. Start by defining a 'master template' that describes the HTML shell (the exterior chrome) of your application. The master template should have a few placeholders in it: at least one for the title of the page, and another for the 'body'; perhaps you have slots for sidebars, menus, and other variable concepts.
Your ASP.NET 'controller' then is responsible for selecting user controls that get fill in these placeholders. Ultimately you follow the same strategy all the way down.
Looping isn't bad, but conditionals are generally a 'bad smell' in template code. Some can be pushed into the model/controller (called entirely before the template code.) If it involves something really small, like the date handling code, it should get pushed into a helper (a function that draws a date.) If a conditional involves a significant chunk of HTML, the branches of the conditionals should be pushed into partials and the conditional logic restricted to the selection of which partial gets displayed. If a conditional involves most of the template, there should be more than one template, and the template should be chosen by the controller.
As for the web controls, the basic idea and interface of them is pretty cool. All this guff about attaching event handlers has got to go: that makes people all too confused about what happens on the server and what happens on the client. It ought to be possible to build something similar that uses hidden form variables to keep state instead of the broken 'viewstate' mechanism. (Lots of vendors tried that back around 1997... It didn't work back then... Why did Microsoft revive it?)
Paul Houle on July 21, 2008 8:25 AMI found the RHTML (html.erb now) syntax to be easy to read. What I find funny is that the MVC paradigm is touted as the best way to do web applications, but MVC lends itself to tag soup by its very existence and how it separates things.
I much prefer the old WebForms model of designing applications because there is no tag soup involved, its all tags (well, controls) and any soup happens behinds the scenes, so you don't have to worry about it. Honestly I never got why WebForms was seen as so bad, provided you used something like Model-View-Presenter.
I'm not knocking MVC, as I find it very useful, just that ASP.NET was supposed to get AWAY from tag soup and mixing HTML and code, and now it's going back to that because of MVC.
Wayne M on July 21, 2008 8:27 AMHi Jeff,
I actually started when I saw that rails, beig touted as really hi-tech and quite rocking *still* had a finger up its nose. The server-side templating was a major reason I never really took up rails, after fiddling with it a bit.
Server-side templating is an anti-pattern. The only way to get a clean web based application is to realize that there is a client. It's in the browser. It's suppsoed to communicate with the server through a well-defined protocol. End of story.
That way you get a way simpler server-side, and you need no magic or bizzare canned logic from xml files or what have you, to create a dynamic client.
I call it Thin Server Architecture, but it's nothing new, in principle. A friend of mine has a similar concept called SOFEA (Service Oriented Front End Architecture).
And as how to write a client in JavaScript, well, it's 2008, you know. Quite a lot has happened to Dojo, for example, with data stores, message buses, offline storeage (with gears support), client side Django Templating and RPC stubs autogenerated from SMD (SImple MEthod Description) files.
Cheers,
PS
I think that Mako (the current default templating system for Pylons) has some features that help avoid some of the complexity. Some of them are features that other template languages have, but I suppose it's the recommended usage patterns that make a difference.
Generally what I like about Mako is template inheritance, defined functions (that are defined in templates) that you can namespace and call inside your templates for output, and an extremely limited number of tags that yet make up a fully complete template language.
I personally have found all my Mako templates very readable, until I start using gettext and have to put ${_( )} around all my i18n strings.
-Max
Max Kanat-Alexander on July 21, 2008 8:31 AMYes. I can.
But it's harder to read than code that comes from a better design.
Practicality on July 21, 2008 8:34 AM@ John B
I looked at WebObjects and granted you can avoid tag soup in simple/medium-complexity situations. That’s not saying much though because even old VBscript-based ASP with some kind of tacked-on templating can do the same to a limited degree (I know firsthand because I wrote DataTemplate class in VBscript emulating ASP.NET’s ListView with varying success).
However to completely eliminate tag-soup/spaghetti-bowl problem you need something like server-side DOM where every component on the page (be it plain html or control/template) can be traversed referenced by id/index programmatically changed.
Those changes should be done in event handlers corresponding to this component's lifecycle. For instance: for some kind of data-repeating control you should be able to have row created event inside of which you can use findControl method to find the row's first td cell. Then you can change, let’s say, this “td” cell’s background or hide it, or widen it, or whatever. Clean and simple.
You can also bind to objects in ASP.NET as you can in WebObjects (actually you don’t need .wod files because you assign properties directly in the markup or codebehind). However ASP.NET’s capabilities go well beyond that as I pointed out already because you have full server-side DOM seamlessly integrated with event-driven framework.
using HAML, that code is: (http://pastie.textmate.org/private/khz08x2rwnmqawsoncrmmq)
Still needs more refactoring, but better than erb.
- @pages.each do |page|
- css_class = cycle('', 'alt_row')
- css_class += ' inactive' unless page.is_active
- css_class += ' first_row' if page == @pages.first
%tr{ :class = css_class.strip }
%td.first_col= page.created_at.strftime('%d %b, %Y')
%td= link_to (page.title == '' ? '[Untitled]' : page.title), Site.full_url + '/admin/pages/edit/' + page.id.to_s
%td= truncate(Post.strip_html(page.body), 50)
%td.del_col= link_to 'X', Site.full_url + '/admin/pages/destroy/' +page.id.to_s, :confirm = You are about to delete this page. This is permanent.\n\nAre you ABSOLUTELY sure?
- unless pages.length 0
%tr.first_row
%td.first_col{:colspan = 5}
%span.gray There are no pages at this time
- if @page_pages
%tr.header
%th{:colspan = 5}
.pagination
.prev
= link_to 'laquo; Previous page', { :sort = params[:sort], :page = @page_pages.current.previous } if @page_pages.current.previous
nbsp;
.next
= link_to 'raquo; Next page', { :sort = params[:sort], :page = @page_pages.current.next } if @page_pages.current.next
nbsp;
Jeff, others having tag soup does not mean that you have to have it as well. Using helpers instead of embedded logic can take away all the soup, and leave just the tags.
Your example below can be rewritten like this: (with haml and helpers)
http://pastie.org/237861
The point is not really to use HAML instead of HTML, but the main point is to have enough helpers that you can re-use in your code that having that soup is no longer a requirement. And I don't think that it ever was a requirement ... some people just don't know better.
And yes, you can write an article showing bad-code, there is enough of that on thedailywtf.com. When you post something like this, it would be nice if you could show some alternatives - and not just drop a piece of code that you don't like and expect miracles. (just imho)
I'm going to have to side with the folks that mention server-side asp.net controls. I realize this doesn't help standard Ruby or other languages/technologies that allow for mixing code and mark-up but addresses the problem well. I wonder if ReSharper will ever add a Move to Code-Behind option :-)
JMinadeo on July 21, 2008 8:40 AMThere have been a few mentions of Seaside (http://www.seaside.st/) which completely (and deliberately) eschews standard templates and relies on coded html builders and CSS.
There is a very good tutorial showing this in action - see: http://www.swa.hpi.uni-potsdam.de/seaside/tutorial and read the section on components - essentially you create code like the following:
renderContentOn: html
html heading: 'ToDo-List'.
html div
class: 'menu';
with: self menuComponent.
html div
class: 'list';
with: self listComponent.
Notice how there is a deliberate component model going on which allows for great refactoring and representing the problem in code.
For more UI things, there is Scriptaculous (and other UI tools) support which essentially spits out the relevant javascript from the builder.
This feels a bit like GWT - but with the power of the Smalltalk environment they do some very cool things that keep your model very straight.
I'm sure other frameworks could borrow some of the ideas from this - (e.g. its a shame that Groovy and Grails doesn't lift some of these ideas instead of adding to the soup with their GSP's) although the clever things done elegantly in Smalltalk might be hard to replicate exactly.
There is also some other neat things happening in Smalltalk on the back of Cincom's webvelocity: http://www.cincomsmalltalk.com/userblogs/mls/blogView?showComments=trueprintTitle=WebVelocity_Behind_the_scenes_of_the_enhanced_Debugger,_Inspector_and_Code_Editorentry=3392858654
Tim
TimM on July 21, 2008 8:40 AMThis seems a little risky using ASP.NET MVC at this stage. Its not even in beta1 yet and your using it for a major project. I can see some major re-writes down the road.
Now speaking of tag soup. I hated...hated the classic ASP way of doing that. It drove me crazy. I just don't believe any logic belongs in the presentation tier. If you do need some logic, that's what javascript is for.
Donny on July 21, 2008 8:41 AMIn Java you have a pretty rich JSTL tag library. If you don't find the specific tag you need, you can write your own in Java and reference in HTML with a simple tag. It keeps the code out of the markup nicely.
However, you can also go completely to the dark side and embed all the java code you want in your JSP (HTML) markup. JSPs will allow it, but no one really does that anymore. Tags are the way to go for cleaner markup.
Charles on July 21, 2008 8:46 AMHi Jeff,
If you have a chance check out GWT. You basically abstract out all the html and Javascript.
The short version is that you write a Java application (much like a desktop application in Swing) and it will convert the application to server code, Javascript, etc. for you.
Very very handy because the code is completely written in one language, it's all statically typed, and you get the full benefits of the IDE tools!!!
Stephane Grenier on July 21, 2008 8:46 AMHere's another vote for better attention to architecture. Fix the problem where it begins rather than obscuring the real issue with abstracted markup that destroys HTML's ease of use.
As a JavaScript/CSS/HTML/JSP developer whose's ramping up on Ruby on Rails, I, too, find the tag soup of ERB to be annoying. But it's silly to eliminate all the HTML from your ERB templates just so the code looks cleaner to Ruby developers.
In most shared development environments, you're going to have view-layer experts for whom coding in HTML and CSS is second nature. Forcing them to work with code in which their native languages have been replaced by obtuse helper methods is counterproductive.
Brian Dillard on July 21, 2008 8:50 AMThough my experience is limited to PHP and Django (and a bit ASP .NET), I really like the Django approach. It's a bit difficult to get used to it (the template language doesn't really allow much code; so basically everything has to be calculated in the Python View file, and the template only accesses the created data structure, mainly using for-each loops). The primitiveness of the template language forces separation of Python and HTML.
Also, I think having a template that is basically HTML has the advantage that non-developers can edit it. I suppose HTML-based templates could even be edited with WYSIWYG editors like Dreamweaver (this is probably difficult when using HAML).
Oliver on July 21, 2008 8:59 AMIn webforms asp.net I break up most pages into user controls. Each control is pretty dumb, with a number of events and properties that are handled and set by the parent aspx page(s).
When you get this right you end up with a set of user controls that contain a lot of clean html and very little code, combined with an aspx that contains very little html and a lot of clean code (separated in the codebehind of course).
So I basically consider the problem solved for asp.net, at least since asp.net 2.0. It's more a matter of dicipline than anything else.
Back in Javaland, JSTL enforced some discipline -- if you restrict yourself solely to property access and control structures, it'll look pretty clean, and if you start pressing the % key, it's a sign you're doing something wrong.
In Microsoftland, just use WebForms already. This ASP.NET MVC stuff is just ridiculously undercooked at this point.
Mike Kozlowski on July 21, 2008 9:09 AMIsn't this just another case of You Can Write FORTRAN in any Language? You can create an unmaintainable mess in WebForms, ASPNET MVC, Rails, whatever. People that either don't know how or don't care to write maintainable code will take any framework you give them and build a shanty town.
No framework is a silver bullet. You just have to pick the one whose drawbacks cause you the least amount of problems.
Sean Scally on July 21, 2008 9:15 AMWhat Miika said. Check out Amrita for Ruby (http://amrita.sourceforge.jp/). I've used it on the job with great success. It's not the most polished library in the world, but it definitely does separate the model from the view in a way that the example you show does not.
Amrita does things the way a template engine should. It is very smart about a lot of stuff, too. Like you can put elements in your HTML template, and if there is no corresponding element in your data model, the HTML element gets zapped. It will automatically expand lists which is great for building out tabular data dynamically.
I found that occasionally I'd want to build a little widget in my code and plop that into the template, but in general you get a very clean, complete template that can be previewed directly in a browser with no data or server processing. You also get a very clean way to build up the data separate from the template.
Michael on July 21, 2008 9:17 AMBack in the 90's - classic ASP was supposed to be better than CGI because MS uses threads We quickly scrapped this mix of code and devised a template for new development that broke up a page into HTML, server scripts and client javascript sections. Oh - the horror whenever somebody has to dive into some old mix-style code that is still in use s
john on July 21, 2008 9:23 AMPsst...here's a hint - switch to Java - use custom tags -- use struts - it comes with everything you need to make clean, elegant web apps...
.NET has this idea of custom server side components, but they aren't generalized enough to defeat code-soup.....they're neat if you have simple problems to solve (kinda' like RoR)....but if you need to do anything half-way innovative - they're going to be trouble...
yes - soon .NET MVC will be available -- though, this stuff has been around in the java environment for a number of years -- if you can manage to switch to java...you would do much better. :)
Funny you mention Django, since the template language is very restrictive just to avoid the tag soup. The default Django kinda _forces_ you to write code in your code, not in the templates. Always a Good Thing.
tabo on July 21, 2008 9:32 AMThis brings back horrible memories for me. Back in the very early days of JSP, we saw a lot of this in the view. JSTL solved a lot of it. Having a standard set of iteration/logic/formatting tags mixed with a solid expression language is very helpful.
Mike on July 21, 2008 9:32 AMWow, talk about a coding horror. And I should know, I use Typo. :-/
(N)Haml is your answer. It makes it very painful (not impossible) to put any code in your view. It's excellent at content structure, and mixes very very well with css and jQuery in a very web 2.0 fashion. You can call helper functions for coded web output instead of trying to put server-side code in your view.
Kevin on July 21, 2008 9:41 AMTAL ftw.
dnm on July 21, 2008 9:45 AMDump the ASP.NET MVC. Stick to ASP.NET Web Forms. It works and there is a separation of business logic and presentation. Done.. easy.
Steven Rogers on July 21, 2008 9:48 AMI think tag soup will always a problem with web-based development. The problem lies in the fact that, fundamentally, we are only allowed a few markup tags to express the visual panoply that is a well-functioning web app. The only real answer to the tag soup question at this time is to go back to client-server desktop-app programming. That's the only place that the presentation layer was configurable enough to be truly divorced from the rest of an app's structure, and still provide WYSIWYG screen layout. Flash and Silverlight seem to echo this functionality, but I think we haven't seen either platform provide a compelling enough solution for all the markup gurus to give up their and signs and make the jump en masse. I don't know if we ever will, given the current web standards and protocols.
Kelly on July 21, 2008 9:51 AMJust add a Tag Soup Nazi on your team.
Robert S. Robbins on July 21, 2008 9:53 AMThere is something fundamentally better.
It's called Drupal.
I've never ever written tag soup like this when using Drupal. All your logic contains virtually no HTML. Whenever code generates output, you write a theme function for it, which contains the actual HTML. This function is overridable on a theme-by-theme basis.
This means your HTML is nicely separated and can easily be changed. The only logic you'll find there is for zebra striping.
See http://drupal.org/node/171188.
The most painful thing in web sites/applications, by far, is creating and maintaining forms. I'm sure most of you would agree with that. It's often one of the places where the most distasteful tag soup of your web app lives.
Drupal solves that too.
It has, by far, the most comprehensive Forms API there is. It allows modules to alter each other's forms, makes it easy to keep your forms secure, allows you to create your own (reusable) widgets, and so on.
And then you've only scratched the awesomeness of Drupal.
I'm obviously biased. But really, give it a try.
Wim Leers on July 21, 2008 10:06 AMI'm doing PHP. I write classes for most of the HTML controls that I would need and reuse. So, most of the time, I'll be using my own classes only.
On some minor cases, I'll let PHP to print out the HTML codes.
As for the header, footer or other files without much programming, I'll write them in separate files, then include into the files with lots of programming. I think separating them is good to make your programming source code readable.
Eng Lee on July 21, 2008 10:09 AMThe indentation could be better, but at the risk of sounding blasphemous, I think that this is perfectly fine. It isn't doing any real complicated business logic, just iterating over, escaping, and echoing out some variables. The Django example looks especially sane to me.
If I need to re-format this page 5 months from now, this representation is going to be a lot clearer to me than some control or function which generates HTML behind the scenes. It is amazing to me the complexity that we reach to in the effort to simply output a string to a browser.
There is nothing wrong with mixing code and HTML as long as that code is presentation-oriented, not business-oriented. (Separating presentation code from HTML through some other templating system or control framework isn't really separating it all, just obfuscating it IMHO.)
Nicholas Piasecki on July 21, 2008 10:10 AMAssuming you need to home grow these things, what about...
1. Creating a row generator method that returns a string with the proper tr code for your css class and such. I'd say have it generate your cell data as well, but that looks a little more complex and it might be nice to have each cell rendered with a different method.
2. This is where my ignorance of .NET MVC is at, but aren't ListView objects pretty flexible under MVC? You can use your databinding event to render all your code on the back end page, but don't have the weighty DataGrid object to work with.
Just a couple of thoughts. I've been seeing more and more online examples of fancy datagrid work lately where they are escaping the code as opposed to using some of code behind binding/rendering methods. I'm wondering if there is some kind of programming shift going on...
Sean Patterson on July 21, 2008 10:23 AMThis really is more a question of good development practices.
The danger in getting too soupy in your templates, comes from putting too much logic into your templates. More logic = more soup = more for a developer to decipher and parse and understand. To that end, it really doesn't matter what templating language or MVC framework is being used -- if your developers don't understand (and execute) the concept behind keeping concerns separated, you're going to end up with a hunk of unmaintainable spaghetti.
I like the approach the Django developers have taken -- they *deliberately* kept their templating language simple, to encourage developers to keep the presentation free of all but the essential logic needed to display the content. Templates can output variables (with some filtering), do equality tests, for-loops... and that's about it. Anything beyond that, and the developer ought to be asking himself if it's really necessary to do in the template.
Matt Howell on July 21, 2008 10:27 AMThough I haven't had a chance to play with it yet, I think Paul Graham's ARC might get it right by integrating the html generation right into the language.
http://arcfn.com/doc/html.html
Jeff T. on July 21, 2008 10:29 AMquote
Welcome to Apache Wicket
With proper mark-up/logic separation, a POJO data model, and a refreshing lack of XML, Apache Wicket makes developing web-apps simple and enjoyable again. Swap the boilerplate, complex debugging and brittle code for powerful, reusable components written with plain Java and HTML.
/quote
@ Wim Leers
The most painful thing about web/applications is ... maintaining forms
We are currently evaluating some implementations of XForms, and they seem to provide a *really* neat way to abstract various concerns. The standard itself recognizes a 'model' that each form uses, and you can do all sorts of XPath wizardry to do pretty advanced stuff without any tag soup or even JavaScript. E.g. hiding parts of the form that are dependent on the value of some other input, create neat 'wizard' forms, client side validation and alerts.
The only problem is that people seem to have lost interest in the whole idea, and the main people pushing the implementations seem to have moved on to other things .. But the technology itself is very promising.
Donny Daniel on July 21, 2008 10:37 AMI think this is closely linked to the question of still representing everything in text. In doing so, there's no hard boundry between the view and control contexts.
James L on July 21, 2008 10:39 AMAbout five and a half years ago, I found an interesting alternative to tag soup in the wt (Web Templates) module of the jonpy package (short for Jon's Python modules). You can find documentation here:
Too bad this package doesn't seem to be maintained anymore.
Matt on July 21, 2008 10:41 AMThe key, as other commenters have pointed out, is to use a templating system that deliberately limits what you can put in your views/HTML templates. For me using Perl, that's HTML::Template, which can do only four things: include a variable, include another template, if/then/else logic, and looping over a list. Anything else belongs in the controller.
Mark Gardner on July 21, 2008 10:46 AMhttp://code.whytheluckystiff.net/markaby/
luke on July 21, 2008 10:53 AMThere is some religion that says mixing HTML and code is bad, ostensibly so we can separate the work of developers from the work of graphic designers, but after taking various approaches over the years I'd say mixing HTML and code can actually be a lot more straigtforward an productive. If I can have something like this pseudocode:
% if show_list %
table
% for each list_item %
tr.../tr
% /for %
/table
% /if %
I'd take that any day over having to tease out the logic into a code-behind and then figure out when to run as we basically do with ASP.NET.
The idea that we need to separate tasks between designers and developers is a bit of a red herring. Maybe it's a real concern for some people, but I've never worked on a project where there was someone responsible for creating production-quality HTML for a web application that wasn't a developer, so I don't that's a real end in itself. The goal is to have well-structured code and HTML in the appropriate places to support the application; some people may be more UI-focused than other but everyone working on production UI code (procedural or markup) ultimately needs to work together.
Marc on July 21, 2008 10:57 AMI'm using asp.net, and the aspx-Pages are clean from code.
You have to use runat=server intensively, though.
div id=divShow1 runat=server
show this or not?
/div
...
divShow1.Visible = loDocument.IsVisible;
or
a id=divLink1 runat=server/a
...
divLink1.Href = ....;
divLink1.Title = sLang(translate_this);
And of course, massive use of Controls and self-written grids or other data-consuming elements.
Only in some seldom cases:
span id=xx runat=server/span
...
xx.InnerHtml = string.Format(you have [0} points, lnPoints.ToString(n0));
you could live with code-free templates, but it's not an very easy way. But it pays off for multinational sites, where every sentence has to be translated and some content is country- or market-dependant.
tittrat on July 21, 2008 10:58 AMtype code =
string * attrib list *
the asp.net model allows for quite nice separation, if people just actually learned how to use it...
Eber Irigoyen on July 21, 2008 11:09 AMMixing tags and code (the standard PHP way) is the worst possible way to develop a web app, that applies to templating like Smarty also.
I do everything as objects. The page is an object with methods like addContent and addJavascript. Every input type is an object and it knows how to draw itself. A form is an object, which is just a collection of input objects. And it's all based on objects generated from tables automatically.
Objects that know how to draw themselves, e.g. return html, is the best way to develop Web apps.
Steve on July 21, 2008 11:19 AMPersonally, I've been using template systems for the last few years.
Sure, you'd still need to battle the template language but I find it to be the lesser of two evils.
It is very easy to let forms degenerate into this kind of cacophony using any web framework. Meeting a deadline often means having to declare something as done when it's really just a rough draft.
You can take the low road and say and use the intellectual crutch, hey, it works!, and stop there. Or, you can try minimizing where you repeat yourself and attempt to make the code elegant. After all, wasn't Knuth who asked, Programs must be written for people to read, and only incidentally for machines to execute.?
Also, to be fair to Rails, Typo was written originally written in the pre-Rails 1.0 days. Most people who wanted a decently performing Rails blog platform moved to Mephisto since then. A mountain of improvements with respect ERb, partials, pagination, and form generation have slowly been added as Rails has gained adoption.
Tony Perrie on July 21, 2008 11:23 AMJeff,
Take a look at the Eclipse RAP project at http://www.eclipse.org.rap. You can take a Java project that runs on a desktop and run it over the web with the minimal of fuss, because the API is the just about the same.
It currently renders widgets using Javascript but there is support for it to render widgets using flavour-of-the-month-framework.
A most distinctly different and interesting perspective.
Paul Norrie on July 21, 2008 11:28 AMThis is exactly why I prefer ASP.NET over ASP, JSP, PHP, and other similar languages. You can still do the inline stuff when you want to, but for larger pages with more stuff in them, all of the server logic is tucked away nicely in code-behind. It's always better to have a choice.
Joe Enos on July 21, 2008 11:29 AMDamn, that link should be a href=http://www.eclipse.org/raphttp://www.eclipse.org/rap/a">http://www.eclipse.org/rap/a">http://www.eclipse.org/raphttp://www.eclipse.org/rap/a
Paul
Paul Norrie on July 21, 2008 11:29 AMThe way your code is presented (that is, with syntac colourization) it looks fine, if a little busy. If I were pressed to make it easier to read, I would add vertical whitespace (uh, blank lines) to delineate the different languages, and I'd also keep tags on one line (the span tag, for example, below).
% end -%
% unless @pages.length 0 -%
tr class=first_rowtd class=first_col rows=5
span class=grayThere are no pages at this time/span
/td/tr
% end- %
% if @pages_pages -%
Great column, keep up the good work.
Alex / talexb
In order to put data into the output format you have to have some form of tag soup because that's the only way to put information and display logic into HTML.
The question in my mind is more, are you a developer or web sites or a developer of tools.
Something like .net components or JSP taglibs allows the developer to off load data/widget to a tool developer by just calling a widget.
The two problems I see with that a) historically the people building a lot of those widgets produced markup that _sucked_ b) it's kinda inflexible
Tom Hughes-Croucher on July 21, 2008 11:33 AMJeff, I'm a little surprised at you on this one. You complained similarly about tag soup on the stackoverflow podcast, but it was you who recently championed languages inside languages (http://www.codinghorror.com/blog/archives/000989.html) and isn't that exactly what rhtml is??
The example you threw up on this post is horrendous, leaving WAY too much processing to the template (I think another of your readers mentioned that more could be done in the model to clean this up) I think it would be very very easy to write something that looked almost as ugly in plain old html.
Also just to throw my 2 cents out there, I think django templates are a particularly clean way of doing this code-embedded-html. (The django snippet you included in the post is clean and readable, isn't it??)
Justin Standard on July 21, 2008 11:43 AMYour tag soup example could be rewritten to be a lot more palatable. Just a few small refactorings would go a long way:
1) Change 'for page in @pages' to '@pages.each_with_index do |page, row|' and use the row index instead of f and c.
2) Change that strftime to 'page.created_at(:short_date)' -- with :short_date defined in ActiveSupport::CoreExtensions::Time::Conversions::DATE_FORMATS)
3) 'unless @pages.length 0' could just be 'if @pages.empty?'
4) Extract the tr class code into a helper method: css_class(page, index)
5) Extract the edit delete URL code into a separate helper method. I think you could further clean this up by changing it to something like 'page_url(:page = page, :action = 'edit', :host = Site.host)'
You chose a horrible sample RHTML file, perhaps on purpose?
1) Rails 2.1 RESTful link helpers clean up some of the tag soup
2) Using counter variables in the views? Not the right way to alternation.
3) The example used no partials.
4) The example used table layouts rather than table-less semantic CSS.
And if, with all that, it's still too soupy, you can always learn HAML, but that introduces a new level of abstraction. I prefer to shorten the page using a mixture of custom helpers + partials, when the page gets too busy looking.
-Ryan
Ryan Walker on July 21, 2008 11:57 AMCode like this snippet typically comes out of some of the finest Global Development Centers. And when I say finest, I am not talking creme de la creme finest. I am talking Creme Brulee finest. The talent in those shops is just unbelievable and they work for nothin'.
Readability of the code directly reflects clarity of the programmer's mind (about the problem at hand). Code/tag soup tells us that little Johnny was a bit confused (and probably scared) when he wrote this.
BugRree on July 21, 2008 12:17 PMNow imagine that you have to localize this.
The localizable text is allover, in code and in HTML, most likely with different escaping conventions.
How do you put it back? How do you keep 30 languages updated with any code change you might have to do?
Then try going beyond text changes: fonts, font sizes, colors, right-to-left, etc. Total junk!
Anybody looked at DTML that Zope3/Plone/Zope2 uses?
It's kinda good actually, everything is still a mess. But hey, you cant have it all.
http://www.zope.org/Documentation/Books/ZopeBook/2_6Edition/DTML.stx
html
body
p
This is b tal:replace=template/titlethe Title/b.
/p
/body
/html
Another vote for HAML. Its structured syntax (esp. indentation) is a huge win when it comes to readability.
Cody Caughlan on July 21, 2008 12:25 PMDitto on using ASP.NET Webforms!
MVC doesn't appeal to me and I wish Microsoft would stick with improving ASP.NET proper instead!
Ben on July 21, 2008 12:31 PMNice peace of work man, I liked it. Please tell me if you can guide me further for such a good work. Well, I saw similar brilliant stuff on dreamworltech.com few weeks back. please check it and give me your remarks.
John Wade on July 21, 2008 12:34 PMHi Jef,
The problem with that soup code is that it has too much logic in it.
You shouldn't use % for % or % if % logic in your views.
On the other hand server controls are not worth it. They simply add a lot of complexity in the codebehind trying to solve their own problems without solving anything for you. The only interesting use for server controls is to show/hide things.
I think that the secret is to balance rendering logic between asp and codebehing.
Although it is a different example, how about something like this:
div id=containerPanel
div id=ordersList%= this.RenderOrdersList() %/div
div id=paginator%= this.RenderPaginator() %/div
/div
and in the codebehing:
protected string RenderOrdersList()
{
return Html.Table(this.Model.Orders,
new HtmlColumnOrder(Id, order = order.Id.ToString()),
new HtmlColumnOrder(Customer, order = order.Customer));
}
protected string RenderPaginator()
{
return Html.Paginator(Model.CurrentPage, Model.PageCount, Url, Resources);
}
where Html.Table() and Html.Paginator() are just helper methods that concatenate text.
Santi on July 21, 2008 12:40 PMWebObjects (which inspired Tapestry) solved the server-side tag soup problem by introducing a server-side webobject tag that had an id attribute which mapped to a .wod file that contained the name and paths of the server-side class and attributes. The server would see the webobject tag, look up its id in the pages corresponding .wod file and instantiate and execute the class with the correct attibutes.
WebObjects is pretty-much free now.
mj1531 on July 21, 2008 12:44 PMI think the problem that everyone seems to be missing here is that the browser and HTML were never meant to be a platform like this. All of the technologies that have been added to HTML (CSS, JavaScript, etc.) are all bolted onto the outside of a (somewhat poorly designed) markup language.
The fact that we even have to mix so many different technologies to get a working site is quite ridiculous.
I only saw one reference to Flex, and no mention of Silverlight, but I believe our only hope is that these next generation technologies can free us from the chains of our real enemy, the browser environment itself!
Seriously though, the GWT might offer some relief in the short-term, but as soon as MS or Adobe get a REAL fat-client-feeling engine working and accepted by the mainstream, the old HTML web apps will start to fall by the wayside. Then before too long, they'll come up with some great toolkits that let people build their own sites in the richer environment, and that's when it'll really hit the fan.
It might take a few years, but HTML is doomed, and it'll be gone sooner than most people think.
Chris on July 21, 2008 12:53 PMWe have our own template system developed over the past 6/7 years that doesn't allow for any logic in the views.. Just recently ported it to MVC as well, works pretty nicely.
Though it's a potentially different situation here, in that our developers don't touch a line of html/css and our implementation crew doesn't touch a line of 'real' code.. think it ends up for the best that way.
I never considered asp.net webforms / jsp tags to be particularly helpful, they only seemed to move the problem around a bit.. Tried having XSLT templating for a while, but by the xslt specification, it doesn't seem capable of really outputting functional html. (for example, at least .net's xslt parser will close div/div to div /)
Daniel Pihlstrm on July 21, 2008 1:05 PMIf you like tags, it's cleaner just to take it all the way!
http://www.adobe.com/products/coldfusion/
It actually works out pretty well in terms of using server side logic to structurally output your HTML in an easy to read syntax that is also tag based.
M on July 21, 2008 1:16 PMSomeone's mentioned Zope's Template Attribute Language (TAL) already. I'll second that heartily. In all my experience with templating systems, I haven't seen anything more fastidious about separating logic from markup, while keeping the template GUI-editable.
It's a pity it's not used more widely (which is unsurprising because all of us are tag soup aficionados at heart, until it comes to editing someone else's template).
Kiran Jonnalagadda on July 21, 2008 1:18 PMNot sure how you solve the tag soup problem aside from just encapsulating it using something like ASP.NET server/user controls. I don't think going with tag-based constructs is the answer either. ColdFusion has that and it just feels too verbose.
One a side note, the lack of controls support in ASP.NET MVC is kind of a deal breaker for me. I've invested a lot of time/energy in learning ASP.NET Web Forms, page lifecycle, and control development. It just stinks that (at least for now) most of that doesn't play well with ASP.NET MVC. I wonder what the 3rd-party control vendors (like ComponentArt and Telerik) must be thinking!?
Craig on July 21, 2008 1:28 PMThis reminds me of Bourne Shell Server Pages (.shit, Shell-Interpreted Template) at http://www.hyperrealm.com/wtfd00d/shsp/
Quote:
The basic idea behind all server page technologies is this: rather than writing code that generates an HTML document on-the-fly by writing it out as a series of print statements, you start with a skeleton HTML document and embed the code right inside it. Voila! Instead of having a tangled, unreadable, unmaintainable mess of HTML embedded in source code, you have a tangled, unreadable, unmaintainable mess of source code embedded in HTML.
You can remove all logic out of views via template languages like Liquid, but at the end of the day, you're spending more time trying to make it clean than just getting the job done.
It also doesn't help you picked the most crusty Rails code possible (Typo). There are a number of ways to clean up the snippet you pasted.
PJ Hyett on July 21, 2008 1:42 PMI second (or rather, third/fourth/...) the TAL suggestion. TAL-compatible template systems exist for all important development platforms (Python, Perl, PHP, probably more), it ensures well-formed HTML (+X if you desire), and force you to separate logic and presentation by supplying only a very limited set of operations. foreach-equivalent loops exist (they are too essential), but counting loops don't. Likewise, there are no expressions except a boolean negation -- if you need to evaluate some complex boolean expression, do so in your code. No calculating, no string manipulation, just inserting pre-calculated placeholders.
Actually, most implementations allow some kind of custom extension, so if you are sure you know what you are doing, it's possible to add the missing capabilities yourself.
The person who wrote that code has deeply missed the point of MVC. He's put parts of his controller in his view.
I'm going to cause lots of screaming here, by mentioning the original (now unfashionable) P-word, but Perl has an excellent solution in Template Toolkit.
In the normal way of working, your Perl puts your data into whatever data structure is convenient and the template works with that. There's a simplified set of loops and conditionalsfor the design folks to work with, which do not resemble Perl at all.
It is possible to break the separation, even have the template driving the code if you must, but that sort of nonsense is strongly discouraged.
@Jeff Pants, I must admit that's a very elegant way to split hairs. I approve this method when it comes to produce data-oriented documents, like RSS feeds, data exports in XML, and the like. When you need real-world HTML you'll be needing to add conditional attributes, javascript events, and when it comes to tweak that HTML code to please all browsers, that level of abstraction is just going to be plain nightmare.
I agree with Bloodboiler, in the real world you want to be picky about you HTML output. Like @hombre said, HTML is the problem. And you can try as hard as you want, that problem isn't going to vanish because you hide it below your carpet. A designer absolutely needs to see what the HTML output will look like and anything trying to hide that HTML is going to fail once you need to refactor the HTML to change the layout or please all the browsers. You don't want to dig around generator functions to see where is that tag id you use in your ajax processing.
Atwood sees 20 lines of code he can't read and immediately concludes everything must be thrown in the wastebasket, without even wondering if it can be refactored, only a few guys mention we can use helper functions to tidy up that code, while about everyone else suggest square wheels so they can climb up stairs. Amazing.
Vincent on July 22, 2008 2:14 AMGWT + java servlets + hibernate + mysql is a GREAT stack to use to avoid stuff like this.
GWT on July 22, 2008 2:49 AM@GWT - hibernate and mysql should have nothing to do with tag soup. Or does mysql now suddenly make my presentation layer that much easier to work with.
chico on July 22, 2008 3:22 AMThis was solved in the nineties. It was called enhydra xmlc.
The html didn't contain any markup other than html. Dynamic elements were marked with id-tags and then the DOM was manipulated.
With good helper libraries creating eg. tables was a snap.
There was also the added benefit that the template could contain mock data for the visual developers and demos, and it was then removed when used through the code.
Shame that it didn't go anywhere, the modern equivalent solution seems to be xslt, which is orders of magnitude more horrible, and visual designers can't use it.
Okay, I must be over-reacting and mixing OP with the soup of over-agreeing comments \o/.
That good spaghetti code metaphor is clever, like Jeff's mention to Operation was quite entertaining. But that's way beside the point.
Okay, so Jeff is just asking what we think, wondering if there is good tag soup, and I completely forgot that when I read following comments.
I got quite angry when I read that post about the subject :
http://paraesthesia.com/archive/2008/07/21/tag-soup.aspx
Some folks argue they want that tighter control over the HTML that the tag soup provides. I, personally, am much less interested in hacking HTML. Let the framework do it for me. I'm more concerned with the business logic anyway.
1) promoting just-hide-it-under-the-carpet techniques
2) let the framework do it for me - doesn't work. a) either your pages are trivial and you don't need such a framework in the first place b) when you try fancy stuff the framework gets in the way so you miss the whole point having such a framework.
3) That classic I, personally, am much less interested in hacking HTML making the whole article absolutely pointless, basically saying : your bike sucks, I don't like you pedals, the saddle is uncomfortable, I don't want to use gears ... Oh, and by the way, I don't even like biking.
For the record, I liked RoR, using helper functions and partials. I'm now on turbogears ( python + cherrypy + genshi), not my choice, but not so bad. Toscawidgets is quite elegant to isolate html components, grouping the html template, required css, javascript and validating code in one place, and still having solid control of what the ouput looks like. With some tweaking, one can easily provide form validation after a submission or through ajax ( allowing real-time checks like username availability, etc. ) with the same validation code. genshi is more a template system than a tag soup, and I guess we have the best of two worlds since it's XML ( so it can be validated ) with python inside special attributes. With cherrypy's append_variables you can easily provide helper function from outside the template.
But really, if you want so much custom stuff your framework has to give you A LOT of control over the produced HTML, and that doesn't prevent you from keeping things tidy. I guess I'd like django if I had a chance to try someday.
Vincent on July 22, 2008 4:17 AMI think tag soup is development lag.
A big advantage of ASP.NET Web Forms on Ruby, JSP, PHP and ASP is the code behind, that separates the logic view of HTML.
The power of web controls in ASP.NET doesn't compare with tag soup approach.
We are step back (maybe until 90's) to bad old days and write ourself basic features that are provided (native) by ASP.NET web controls.
Hi Jeff,
I'm quite curious to know WHERE in Typo you found that piece of code, because I wasn't able to find it anywhere. And you can trust me on this point, I've writen most of the current views code. That's the reason why.
Cheers
Frdric de Villamil on July 22, 2008 5:06 AM@Santi:
The problem with that soup code is that it has too much logic in it.
You shouldn't use % for % or % if % logic in your views.
This is utter nonsense. That's exactly the kind of logic that SHOULD be in the view - logic relating to the presentation of the content. What shouldn't be in the view is actual business rules (e.g. if an account is overdue any changes must be approved by a manager). Formatting and presentation logic SHOULD be in the view.
Wayne M on July 22, 2008 5:20 AMI am a fan of Eclipse RCP (SWT) and I think in web development GWT would be really helpful here. Once I had to write a web app in PHP. I hadn't known CakePHP framework back then so I wrote a tiny GUI framework which usage resembled say.. SWT or Swing. You could create views and buttons and tables as PHP objects, set their properties and then render them producing HTML output (something like this):
function onCreate() {
$table = new Table();
$table-addColumn(Name, name);
$table-addColumn(Age, age);
$table-addColumn(Credit card number, card);
$table-setModel( $data );
$window-addWidget($table);
$window-addWidget( new SumbitButton() );
}
However all render() methods had to produce HTML and in case of more sophisticated widgets the code was quite messy. Lots of quoted HTML in there.
When I learned CakePHP I never used my framework again.. I guess dealing with tag soup is a lesser evil than trying to reproduce SWT/Swing-like design in PHP5. It didn't work for me.
mantrid on July 22, 2008 5:31 AMAfter skimming through the vast array of comments containing new and fancy ways of trying to avoid tag soup, some of which seem to make the problem even worse, I feel that one should just embrace tag soup and look at a much simpler option of formatting your code to make it more readable.
This is how I would have written the example Jeff showed us:
(I have replaced tabs with 4 underscores)
% c = 1 -%
% f = 1 -%
% for page in pages -%
____tr class=c% if !page.is_active %inactive % end %%= (c%2 == 0 ? 'alt_row'') %%= (f == 1 ? 'first_row' : '') %
________td class=first_col
____________%= page.created_at.strftime('%d %b, %Y') %
________/td
________td
____________%= link_to (page.title == '' ? '[Untitled]' : page.title),
____________Site.full_url + '/admin/pages/edit/' + page.id.to_s %
________/td
________td
____________%= truncate(Post.strip_html(page.body), 50) %
________/td
________td
____________%= page.permalink %
________/td
________td class=del_col
____________%= link_to 'X', Site.full_url + '/admin/pages/destroy/' + page.id.to_s, :confirm =
____________You are about to delete this page. This is perrnanent.\n\nAre you ABSOLUTELY sure? %
________/td
____/tr
____% c = (c == 1 ? c+1 : c = 1) -%
____% f = f+1 -%
% end -%
% unless pages.length 0 -%
____tr class=first row
________td class=first_col colspan=S
____________span class=gray
________________There are no pages at this time.
____________/span
________/td
____/tr
% end -%
% if page_pages %
____tr class=header
________th colspan=S
____________div class='pagination
________________div class=prev
____________________%= link_to 'laquo; Previous page', { :sort = params[:sort], :page =
____________________page_pages.current.previous } if page_pages.current.previous %
________________/div
________________div class=next
____________________%= link_to 'Next page raquo;', { :sort = params[:sort], :page =
____________________page_pages.current.next } if page_pages.current.next %
________________/div
____________/div
________/th
____/tr
% end %
I'm surprised by the amount of this is cool/should work'
BUT I'VE NEVER TRIED IT.
wonderful that you are providing links to stuff you find interesting,
but if you have never tried it, than can you really say how well it works?
Jeff, should the same kind of posts appear on stackoverflow, it could be handy to flag those as suggestions rather than experience talking.
They still have value, but just not 1st hand experience....
Or so my best friend's sister's boyfriend's brother's girlfriend heard from this guy who knows this kid who's going with the girl who says so .... [paraphrased]
Eric on July 22, 2008 6:25 AMYou need some proper tools.
Try JSP 2.0 custom tags to modularize presentation components, and use a proper MVC architecture. Spring framework is good.
Struts has been obsolete for 4+ years now, btw. Don't both learning or starting any projects with it. Avoid JSF as well, same guy who was responsible for Strut's design flaws. (Sorry Craig.)
In the Java world, we actually have the technology to build clean, modular, reusable scalable OO applications. For the first time in history. Check it out.
Spring framework,
Log4J,
Eclipse IDE,
Tomcat,
Hibernate..
Correct me if I'm wrong but the few examples I've seen of asp.net's MVC look pretty much like a ruby on rails ripoff : the controller, view and routing syntax are very much alike. Which is great, by the way.
Vincent on July 22, 2008 7:12 AMThe comments to this entry are closed.
|
|
Traffic Stats |