The Demented Ravings of Frank W. Zammetti Visit www.zammetti.com for all things me

29Jul/160

Building web UIs: an unconventional viewpoint (now with surprising supporting evidence?)

For a long time I've been becoming more and more convinced that the approach to developing complex web-based SPA UIs is going in the wrong direction. There is now an incredibly heavy dependency on CSS and markup and it's made modern web development a lot more complicated than it's ever been before (and that's not even talking about all the tooling typically involved). I personally find understanding a UI holistically to be more difficult when it's mixing complex CSS and markup (and then usually some JS too). I know some people love that and think it's the Best Thing Ever(tm) but I respectfully disagree. I think the development of responsive design has been a big driver of this, though not exclusively. You can of course do responsive without CSS, but I suspect it's largely been a case of "this is the first way someone figured out how to do it and now everyone thinks its the right answer" without really considering alternatives very much. Just my opinion of course.

What's interesting to me is that I've spent a few years developing highly complex UIs, SPAs of course, that have taken a different approach: a code-centric approach. It's more like... dare I say it... Java Swing development then web development in a sense. Rather than creating a basic layout in HTML and then styling it with CSS and applying JS for interactivity I've instead done most of my work by writing JS that generates the UI for me. CSS becomes more like it's original intent: just very basic look-and-feel styling. Things like animations and such aren't done in CSS (at least not at the level of me developing the UI). A lot of this work has been done using ExtJS, but not exclusively, so obviously there's a lot of markup and CSS and JS going on at a level below my work, but that's irrelevant to my main point, which is that it's building a UI through code rather than markup and styling directly.

Of course, I've done my fair share of more "typical" UI development at the same time so I've had a great chance to compare and contrast the approaches. I've always felt that the code-centric approach just made more sense. It always seems to me to be easier to understand what's going on (assuming the library used is expressive enough, as I find ExtJS to be). Things like responsive design are pretty easy to achieve with this approach too because now you've got JS making the breakpoint decisions and elements and all of that and that too just works better with my mind than does the HTML/CSS approach.

Of course, a code-centric approach isn't without it's problems. For one, it obviously requires JS be available. However, I frankly no longer see this as a disadvantage. I think JS has become one of the three key pillars of the web (along with HTML and CSS of course) and it's no less natural to expect JS to be available than to expect HTML and CSS to be available. If a user chooses to turn JS off (as I sometimes do) then woe be unto them if things don't work. I'm no longer interested in graceful degradation, not as far as JS goes anyway (and with a code-centric approach, any other GD concern largely goes away as well).

Another pitfall is that the code-centric approach can also be more verbose and overall requires more "stuff" be written. This, again, is something I don't necessarily see as a problem though. There's a drive towards terseness in programming generally today that I find to be counterproductive. Verbosity isn't the measure that matters really, it's expressiveness. Sometimes, short can be very expressive for sure, but often times I find short is the result of laziness more than anything else (programmers REALLY seem to hate typing these days!) and the result is code that's harder to read and comprehend in my opinion. There are of course limits: I'm not a fan of Objective-C and its long names, but one could hardly accuse it of not being expressive.

All of this is highly debatable and I'd be the first to admit it, but it's my blog so let's go with it 🙂 Anyway, I'm not here trying to convince you that I know the One True Right Way(tm) to develop modern webapps or that you're doing it wrong. Philosophical musings are fun, but it's not my purpose here. No, this article is about one specific problem of the code-centric approach that I didn't mention yet.

Or, at least, something I EXPECTED would be a problem: performance.

Let's jump in and look at a bit of code, shall we?

<html>
  <head>
  <meta content="text/html;charset=utf-8" http-equiv="Content-Type"/>
  <meta content="utf-8" http-equiv="encoding"/>
  <script>

    var startTime = new Date().getTime();

    function calcTime() {
      var endTime = new Date().getTime();
      console.log("browser", (endTime - startTime));
    }

  </script>
  </head>
  <body onLoad="calcTime();">
  <form>
    Username: <input type="text"/>
    <br />
    Password: <input type="text"/>
    <br />
    <input type="button" value="Logon"/>
  </form></body>
</html>

It's not getting much simpler than that! One would expect that runs quite fast, and indeed it does: I sat there reloading it off the file system a bunch of times in Firefox (47.0.1) and on my machine (Surface Pro 3 i5 256Gb) it averages around 100ms to display the elapsed time in the console. It fluctuates a fair bit: I saw as low as about 70ms and as high as about 200ms. I'm frankly not certain what the discrepancies are all about, but ultimately it doesn't much matter because they were outliers anyway and we're looking at rough averages here.

Now, let's look at a code-centric approach version of that same example:

<html>
  <head>
  <meta content="text/html;charset=utf-8" http-equiv="Content-Type"/>
  <meta content="utf-8" http-equiv="encoding"/>
  <script>

    var startTime = new Date().getTime();

    function buildUI() {

      var f = document. createElement("form");
      f.appendChild(document.createTextNode("Username: "));
      var i1 = document.createElement("input");
      i1. setAttribute("type", "text");
      f.appendChild(i1);
      f.appendChild(document.createElement("br"));
      f.appendChild(document.createTextNode("Password: "));
      var i2 = document.createElement("input");
      i2.setAttribute("type", "text");
      f.appendChild(i2);
      f.appendChild(document.createElement("br"));
      var b = document.createElement("input");
      b.setAttribute("type", "button");
      b.setAttribute("value", "Logon");
      f.appendChild(b);
      document.body.appendChild(f);

    }

    function calcTime() {
      var endTime = new Date().getTime();
      console.log("js", (endTime - startTime));
    }

  </script>
  </head>
  <body onLoad="buildUI();calcTime();">
  </body>
</html>

Note the paradigm employed here: there is no content on the page initially, it's all built up in code onLoad (no sense doing it sooner since there's no DOM to build up after all!). The loaded page you can think of as a blank canvas that gets drawn on by the code rather than the completed painting that the browser automatically displays as a result of parsing the document. Obviously, the onLoad event is going to fire here sooner than the plain HTML version because there's nothing to render.

But, what's your expectation of how this version compares to the plain HTML version? That code in buildUI() has to do its work, building up the DOM, and then the browser has to render it when it's appended, right? Does your gut say that this will take longer to complete because surely the browser can render static HTML in the body loaded as part of the document faster than it can process JS, build the DOM and render it under the control of JS?

That certainly was my expectation.

BUT THAT DOES NOT APPEAR TO BE THE CASE!

Doing the same sort of "just sit there hitting reload a bunch of times" dirty timing, I got an average of around 60ms (and again, there were a few outliers in either direction, around the same number of them as the plain HTML version, so my guess is those are simple IO delays and in any case we can ignore them in favor of the rough average again).

I mean, it's not just me, right? That's kinda crazy, no?! And, that's not even the most efficient way one could write that code, so there's probably a chance to increase that performance. But what's the point? It's already faster than the plain HTML version!

Now, to be fair, I can't necessarily extrapolate this out to a much more complex UI and assume the same would hold true. That's frankly a test I still need to do, but it's also a much harder test to set up properly. But, just seeing this simple test is frankly eye-opening to me. I always assumed that my favored code-centric approach was sacrificing speed in the name of other benefits, but that may not actually be true.

So, is it just me? Is this common knowledge and it's something I just never realized? Or, is it pretty surprising to you like it is to me? Or, did I just screw up the analysis somehow? That's always a possibility of course 🙂 But, I think I got it right, and I'm surprised (err, by the results, not that I think I got it right! LOL)

Comments (0) Trackbacks (0)

No comments yet.


Leave a comment

No trackbacks yet.