Monday, October 18, 2010

Why Are Web Frameworks So Bad

I debated what punctuation was appropriate for this post. Should it be a period because I this post will explain the answer? Should it be a question mark because I am trying to understand? Should it be an exclamation point because I am surprised? After a little bit of thought, I think it should be "Why are web frameworks so bad?!?!?!?!?!?!" because I want to rant!

Oh, and as a quick caveat, I am talking about the two environments that are primarily used in the business world today, i.e. .NET and Java.

ASP.NET

ASP.NET tries to just extend Windows Forms programming so that creating a web app is just like creating a desktop app. The promise being that the legion of Windows programmers will suddenly be able to create rich web apps without learning anything new. The reality - programming for the web has different constraints than programming for the desktop, and while ASP.NET tries to hide it reality leaks through. Any time you go off the beaten path you risk getting bitten. Unless you truly understand the seven stages of the page life-cycle, problems can arise like losing user input.

What It Gets Right
Code Behind
An ASP.NET page is actually two files.  There is the .aspx file which is where you put your HTML with a minimal amount of code.  The other file is the .aspx.cs file (assuming C#) which has specific methods that will be called prior to displaying the .aspx.  You can put the meat of your code in this C# file, and populate variables which can be used in the .aspx.  This makes for a good separation of concerns between coding and markup.

Components
It is also easy to create a custom ASP.NET component with its own markup (.ascx) and code behind (.ascx.cs) files.  These components can then be fairly easily embedded into your pages (or other components).  This works fairly well.

What It Gets Wrong
Wow - where to start.  I guess I'll limit myself to the three biggest complaints that I have.

Complexity
When you create a page in ASP.NET you are logically building a tree of Components. The HTML is generated by walking this tree. So far so good. The complication comes in that the HTML form variables that are posted back are specified and accessed via these components. So after the user performs an action, the webserver must be able to exactly recreate the Component tree from before so that your ASP code can access any user modified values. Recreating this tree is no trivial task, and while it just works most of the time, if you do something that causes it to break - understanding and tracking down your bugs can be a nightmare. And dynamically creating components based on user input is likely to cause this breakage unless you *really* understand what is going on. Ugh.

Doesn't fit the web model
ASP.NET really tries to mimic non web GUI programming. A .aspx page is a single Form containing lots of Components. What this translates to is a single HTML form that typically has all its buttons post back to the same page. So if you want to logically have different forms on your web page that go to different places, you can't do it. You can fake it, via redirects after the postback, but this is really a perversion of web semantics. Oh, plus the built in components that try to hide the fact that they really just turn into a <div> or an image tag or what not, don't give you full access to the HTML properties of those tags. i.e. ASP.NET forces (strongly encourages?) you to write web pages in a very specific way whether that makes sense for the end user or not.

Page Bloat
ASP.NET adds a hidden input variable called __VIEWSTATE to the pages it creates. This variable contains serialized data that is used after a post to help it recreate the Component tree exactly. This can be potentially quite large, which slows down page load time. Even though broadband is fairly common, many connections don't have a high upload speed, and this data is both downloaded and uploaded with every page view, often causing website to load slowly. To make matters worse, if you don't really understand how this variable is used (and you can create sites without even being aware of its existence), it is really easy to end up with a lot of extra data in this variable that isn't even needed.

Java

Java provides multiple option. First there were Servlets and JSPs, which are functional but often require you to mix your code and your mark up and write generally ugly code. To solve this a number of frameworks which either sit on top of or replace JSPs have come out like Struts, Facelets, JSF, and Seam. Seam is actually a framework that uses other frameworks, just in case this wasn't confusing enough.  For this conversation I'll be talking about Seam using Facelets since that is what I am currently playing with.

What It Gets Right
Hmm... Well, I guess these frameworks are much better than the original Servlet/JSP approach for separating HTML markup and code.

What It Gets Wrong
Again, I'll pick three complaints to highlight.

Dependency Injection Magic
In Seam you can use annotations to give a Name to your class.  You now have access to a variable of that name in the xhtml front end markup.  Some people would probably feel that this belongs in the "what it gets right" category, however I think it is too much magic for my taste.  When I am reading an xhtml file and I come across a variable, there is no easy way to know what it is.  I have to go to every class to find the one with the appropriate annotation.  This does not make for easy to understand code.

Too Many Config Files
Seam claims to have greatly improved the "too many config files" problem, but my current project has:
  • components.xml
  • faces-config.xml
  • jboss-web.xml
  • pages.xml
  • web.xml
  • Plus a page.xml file for every .xhtml page
As you've probably noticed, in addition to a lot of files every single one of these config files is in XML which means there is also a lot of extra verbosity.

Ugly Syntax
Do you remember back when you learned C?  You write printf("hello world\n"); inside a main and it doesn't compile.  Why not?  Oh, you need to tell the compiler to include the standard i/o library.  Pretty soon you just automatically put #include <stdio.h> at the top of all of your programs.  Similarly, with our facelet code we have includes so that we can have access to the special tags in our xhtml.  Here is an example of the concise and easy to remember way this is specified:

<ui:composition xmlns="http://www.w3.org/1999/xhtml"
  xmlns:ui="http://java.sun.com/jsf/facelets"
  xmlns:h="http://java.sun.com/jsf/html"
  xmlns:f="http://java.sun.com/jsf/core"
  xmlns:a="http://richfaces.org/a4j"
  xmlns:rich="http://richfaces.org/rich"
  xmlns:s="http://jboss.com/products/seam/taglib">


I don't think anything further needs to be said.

What Do I Want
This is probably a topic for a whole other post, but here are a couple quick thoughts.
  • Simple and clear separation of code and markup so I can minimize the amount of code that is intermingled with html
  • A library of useful existing components
  • Easy to write my own html components
  • Makes it easy to do the common web stuff (session management, cookies, parameter passing, url building, security precautions, etc.)
  • Does NOT hide any aspects of the web, just SIMPLIFY it
    • I want to know how and what parameters are passed
    • I want to know how they go in/out of components libraries
    • I want it to be easy to integrate components (e.g. javascript libraries) that were written without any knowledge of this framework.
    • I want to be able to control the specific HTML that is generated.
  • Good documentation - something Java does well is good JavaDoc documentation on the supplied system libraries.  I want my frameworks to have similar quality documentation.
  • Is transparent about what it does, so when I have a bug I can easily find it by reading the aforementioned document, rather than having to do Google searches in the hope of finding a blog post or stackoverflow question which describes *and* answers my problem.

    4 comments:

    Jessica said...

    Speaking of frameworks....

    Today, in between my frustrating moments with our friend Seam, I looked at what was popular out in the wild wild web for frameworks. To get a good metrix, I went to indeed's trending tool. ;)

    http://www.indeed.com/jobtrends?q=jsf,facelets,seam,struts&l=

    Now, let's look at languages...

    http://www.indeed.com/jobtrends?q=php,python,perl,java&l=

    Python is pretty popular. And the favored framework that I've noticed with it is django.

    And if we do this:
    http://www.indeed.com/jobtrends?q=struts,django&l=&relative=1

    There's a clear winner. ;)

    Is it the answer? Dunno. Still exploring.

    Michael Haddox-Schatz said...

    Modifying your indeed queries slightly:
    http://www.indeed.com/jobtrends?q=php,python,perl,java,C%23,ruby,VB&l=
    Java seems to be the dominant language and C# seems to be getting the VB market to make it the second biggest.

    As for framework, since django didn't really exist in '05, of course it has the highest relative growth. A better query is:
    http://www.indeed.com/jobtrends?q=struts,django,rails,asp.net&l=
    ASP.NET is the big winner here, with struts in second, hence my focus on C# and Java in the post. I am quite heartened to see the Rails trend line. Maybe Ruby on Rails really can become mainstream.

    Pete Muir said...

    We agree with your criticisms of Seam. For Seam 3 we are hoping to get the number of config files down a long way.

    We're also going to have GWT (not that this sounds like something you would like!) integration with Seam; this will allows you to use Java code right to the view layer (so you no longer have to search beans for the right EL expression) and doesn't require the namespace declarations.

    It does sound like you might prefer Wicket to JSF (which again you can use with Seam) as it keeps the markup/logic distinction much clearer.

    Pete (Seam lead)

    Michael Haddox-Schatz said...

    Pete, thank you for taking the time to respond. I've had friends tell me that I'll like Seam 3 better, so we'll see. :) And thanks for the tip about Wicket, I'll have to look into that.

    As for GWT, I played around with it when it first came out, but haven't looked at it since. If you can write the entire front end in Java and it all "just works", then I am not opposed to it. My concern is: are there times where you would want to tweak the HTML or JavaScript, and if so how transparent is this process? In other words, I am ok with an abstraction layer (since that's really what all programming languages are already). My complaint is when you have to really know both the abstraction layer and what is being abstracted away to do a good job.