Monday, October 25, 2010

IE9 first impressions

IE9's first beta has been out for more than a month, and I haven't written anything about it yet.This was in part because of lack of time, and in part because I did not want to say what can be said after using it for half an hour. Anyway, I'll give you some links if you really want to know that the Acid 3 score is 95/100, that on Windows 7 you can pin a site on the taskbar, that the user interface is cleaner than previous versions, that IE9 won't install on Windows XP.
What I want to focus on in this post is the feeling with this browser when used on a daily basis.
First, some background: my favourite browser is Chrome, I like it because it's simple, quick, clean.
So, I appreciate that IE9 has evolved in the same direction. In fact, I like IE9's minimalistic look, taken even beyond the level we've seen in Chrome: the tabs are on the same line as the address/search box.
This makes the space taken up by the browser above the page content as slim as Chrome in maximized mode (see image below), when tabs are allowed to use up all the space of the application 'title' bar (when Chrome is not maximized, it uses more space above the tabs, so that the user has always some blank space to drag around the application window). 
Browsing with IE9 is also simple, all essential features are at hand, all advanced features are one mouse click farther away.
As for speed, IE9 now seems to be able to compete with Chrome, some sites look quicker in IE9, some others (more) look quicker in Chrome. Anyway, speed differences are no more a clear argument against IE9. I'm talking about speed in general, not in any particular phase of the rendering process: there are very few fish tank sites in the Internet, I think as few as sites running ray tracing in JavaScript...
When it comes to using a browser daily, everything has to be smooth, and I think this is still not the case with IE9 beta 1.
First of all, autocompletion of login forms with data entered in previous sessions does not save as much mouse clicking and typing as in other browsers. Though annoying, this seems to be a minor issue that later releases are likely to fix.
More serious is the compatibility issue. You might expect that I'm talking about standards not yet implemented. Yes, there are many areas in Css3 where implementation is completely missing, and even some tests from the beta CSS2.1 Test Suite are failing (other browsers don't do better here, though). But for daily browsing these glitches won't have great impact.
I'm talking instead of standard implemented correctly in IE9 and sites that still treat IE9 like IE8 and its predecessors had to be treated... The Internet is full of pages that use clever tricks to have IE6+ behave the same way as other browser that implemented correctly web standards. Many of these are commonly used sites, Blogger, Facebook... There are many sites with styling issues, other with problems in scripts... Even if a relatively small percentage of sites has blocking issues, having to switch to a different browser is a pain that I'm not going to face. In some cases compatibility modes help resolve the issues, in other cases there is nothing to do. For these problems we cannot expect fixes from Microsoft. Fixes must come from site developers, that incorrectly include IE9 among the bad browsers from Redmond. For active sites this is likely to happen as sites are tested with the new versions of the browser, for sites that are published and not actively maintained this won't happen anytime soon, maybe never (a negligible loss, though).
The bottom line is that I find IE9 still not suitable for daily browsing, and it's a pity, because when navigating on sites where it does not have issues the experience is really smooth. IE9 is a nice browser, but it has to pay for its fathers' sins...

Monday, September 13, 2010

Browser war for good

There's quite much excitement for the coming beta version of Internet Explorer 9, due to be shown on the Beauty of the Web event in San Francisco.

IE and all other browser are all touted as the quickest, the most powerful, the nicest, the first in many areas of the browsing experience: hardware acceleration (IE9 here, FireFox here, Chrome here), javascript speed (IE9's figures here, FireFox's new engine here, Chrome's celebrations here), standard compliance (IE9 here).
IE9 is going to be a major release that puts Microsoft's browser on track to follow existing web standards; what's more important, it looks like Microsoft has abandoned the 'I'm the standards' position that made IE win the first browser war against Netscape, and was making it lose the second one.
Trying to maintain that position any longer would have made the world progressively shift to other browsers, as in fact is happening in the past few years.

Standard compliance is not going to make quick shifts in browser share: I, as a user, am not using Chrome for writing this post because it is more standard compliant than IE8, I'm using it just because it's quicker and cleaner. If IE9 is as quick and clean as Chrome I think I'll make it again my default browser.
It's when I wear my web developer hat that I feel the pain of having to test what I write on different browsers. And finding that most of the hacks are for one browser clearly explains why the developers/editors community cannot be happy with that browser. This sentiment can erode market share, because developers and editors do have some weight in directing users' choice.
During the first browser war standard compliance was not a must: competition was essentially between two competitors on one platform (Windows) based on features. This competition made available some rich features that are the ground for today's web applications: javascript, innerHTML, xmlHttpRequest... There was no space for standards, no time to wait for their definition before shipping new features.

Well, the first browser war was decided by features (probably an important role was played by the now much hated ActiveX technology) and by the inclusion in Windows so that anybody purchasing a windows box also had installed a copy of Internet Explorer.

If the first browser war had a clear winner, the 'peace' time that came after had a clear loser: the user. Subsequent versions of IE were more aimed to stabilize the codebase than to ship new features. Other minor browsers grew, also due to the fact that IE ceased support for Mac, and healthy web standard got developed, but very few new features got widespread.


Developers and editors could not make use of new features of browsers that accounted for small fractions of audience, if no alternatives were available in IE. Let's take for example Svg: a promising language, made soon available in IE through a plugin from Adobe, bur never supported with energy by Microsoft or Adobe. The result is that it could not be adopted as a widespread technology for producing rich content. If one had to deliver rich interactive content the only option was Flash. Now, with native support from IE9 (and from all the other major browsers, of course, but IE makes the difference) Svg can become a widely used platform to deliver rich content. The same can be said of Html5 and Css3. Unless support from IE is provided, you cannot adopt a new technology to give the user vital parts of the intended experience, or you lose most part of your target audience.

From the features IE9 is going to deliver, it looks like most IE users on Vista and Windows 7 are going to make the switch very soon after IE9's release to web. XP users should instead make the switch to another browser (IE8 is still good for the current web, but I bet new content will soon make it appear outdated).


With many different platforms out there (take into account also smartphones) a plurality of browser vendor is there to stay, and with Microsoft change in attitude they are all going to compete on standard compliance, and not against each other. That plurality will keep browser war going on. Whatever happens to browser market shares, I bet this time the winner is going to be the web.

Saturday, August 28, 2010

IE9 user interface leaked?

A screenshot of a user interface leaked is something of very little importance, but I'l take this as an opportunity to talk about the great news of IE abandoning a roadmap of halfway support of web standards vs existing sites designed for older versions of IE. As a web developer I am happy to see how in Microsoft they have finally changed their mind in deciding to support web standards. A 'I'm the standard' approach might have had some justification when there was no standard, and the web could only be viewed from a pc or a mac, but nowadays there are also other platforms (smartphones) that are becoming commonly used to surf the net, so the new approach of trying to be the best platform implementing and promoting good standards is the only viable.

Just to make life easier to those of you who are trying to guess where this guy writing stands in Browser War II (comments in today's blogs remind me of the first one between Netscape and IE), I'll tell you I have been using Chrome as my default browser, since its release, as I find it quicker and more modern than IE. I have installed and use also Firefox and Safari, to test the sites I work on. I have never been a fan of Firefox: I find it as ugly as IE, from a user's standpoint - though as a developer, I agree that nothing stinks like IE. I prefer Safari over Firefox. I have never taken Opera into account (I'm interested in browsers that users *are* using). As a browser user, I am falling back to IE only when Chrome lacks some features (no, I'm not missing ActiveX support!). And at last, I do not blame Microsoft for IE6 and its lack of standard compliance, I think they're to blame for not making today's shift in standard compliance back in IE7 days. I have seen what IE9 platform previews have delivered, and I think that if the user interface is going to be more Chrome-like I'm going to make the switch back to IE.

Coming back to the topic, another supposed IE9 user interface has leaked, as you can see from this image. Other supposed user interface screenshots that circulated earlier this year showed an oldstyle user interface, but this image seems to confirm other statements published recently in the blogs that anticipated how the user interface should look like. If this screenshot is real, it seems that at Microsoft they have followed the minimalistic design of Chrome that I really love, taking it a step further: they seem to leave more room to the content by putting all the browser's user interface in one single line (the tabs), using less space for inactive tabs (just the icon?). Another thing I hope to see in the new user interface is Chrome's 'status bar': in Chrome you see the status information while the page is being loaded, or a link destination as you hover over the link, then the status bar goes away to leave room to the content. In IE8 you still have to choose whether you want to see the status bar (and lose its space) or you do not want it (and lose the information).

Anyway, the user interface is not what I am eager to see. What I am really waiting IE9 for is standard support: in this area the technology previews have shown Microsoft is doing well. Microsoft is instead advertising the speed increases brought by GPU support, the only area where IE9 has a clear advantage, even over browsers running on a much more powered mac, as shown in the test published by Chris Foresman. In its IE9 Test Drive page Microsoft seems to suggest that browser speed is determined mainly by image intensive processing, as one could notice in the speed tests proposed in IE9 site. Ironically, IE9 might not be the first browser to implement GPU accelerated rendering in a release version: Chrome seems to follow suite later but more seriously than Firefox and Safari, and may ship before IE9 is RTM.

I think Microsoft is also doing well in browser speed: rendering engine, javascript speed, reuse of cached items are all areas that show significant improvements over IE8. But I think that rendering speed is still not so important as standard support: the good news with IE9 is that in the not so distant future we are going to see sites made for Html5, with no IE hacks, and at last write code once for all browsers. At first, we'll see many sites that do only skin-deep browser detection and treat any IE version the same way will render wrong in IE9 because now IE is standard compliant! But at the end the web will be a better place for everyone.


Wednesday, June 30, 2010

Control.Invoke and exceptions - part 2

This post is the second and last of a small series about Control.Invoke and its use when exceptions are thrown and handled. In the previous post we have seen that an exception loses its original stack trace and if you handle it in the background thread you cannot see any reference to the location where the exception was originally thrown.

Here is the same stack trace shown in the previous post:

at System.Windows.Forms.Control.MarshaledInvoke(Control caller, Delegate method, Object[] args, Boolean synchronous)
at System.Windows.Forms.Control.Invoke(Delegate method, Object[] args)
at System.Windows.Forms.Control.Invoke(Delegate method)
at TestForm.DoTheWork(Object sender) in C:\TestInvoke\Program.cs:line 36

Why does this happen? The stack trace only shows methods that run in the background thread... Well, this makes sense, because the exception is travelling through two stacks of calls: the first was the main thread, and the implementation of the Invoke() method rethrows the same exception so its original StackTrace property is cleared and only the stack of calls made in the background thread remains.

But the exception type remains the same, so why bother? Is the original stack trace so important? Well, in this case, not particularly... there's only one point in the application where a DivideByZeroException could be thrown. But what if our application and the call to the invoked method were more complex? What if the exception was a NullReferenceException? That stack trace information would be of much value, so let's try to figure out a way to preserve it. If we wrap the DivideByZeroException in another exception, in the method invoked, the stack trace of the InnerException (our DivideByZeroException) should be preserved. Let's give it a try: here is the example of the previous post, modified in the ThrowWithNiceStackTrace() method (the invoked method) so that the original exception is wrapped in a new ApplicationException:

using System;
using System.Windows.Forms;
using System.Threading;

static class Program {
[STAThread]
static void Main() {
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new TestForm());
}
}

public class TestForm : Form {
private Button btn;
public TestForm() {
// Just add a simple button with a Click handler
btn = new Button();
btn.Text = "Click me";
btn.Click += new EventHandler(btn_Click);
this.Controls.Add(btn);
}

void btn_Click(object sender, EventArgs e) {
// We are creating a WorkItem to be run
// on a thread from the thread pool
WaitCallback wc = new WaitCallback(this.DoTheWork);
ThreadPool.QueueUserWorkItem(wc);
}

void DoTheWork(object sender) {
// This code is run in a background thread
try {
// We are using Invoke so the call
// to ThrowWithNiceStackTrace() runs in the main thread
this.Invoke(new MethodInvoker(
this.ThrowWithNiceStackTrace));
}
catch (Exception ex) {
Type ext = ex.GetType();
string stackTrace = ex.StackTrace;
}
}
private void ThrowWithNiceStackTrace() {
// This code is run in the main thread;
// calling Control methods is legal
this.btn.Text = "Clicked";
try {
this.ThrowWithLongStackTrace();
}
catch (Exception ex) {
throw new ApplicationException(
"Exception caught in invoked method", ex);
}
}
private void ThrowWithLongStackTrace() {
this.ThrowDivByZero();
}
private void ThrowDivByZero() {
int i = 1 / string.Empty.Length;
}
}

Now we run the sample and in the breakpoint inside the DoTheWork() method we see... the same result??

Yes, the exception thrown by Invoke() is still the DivideByZeroException. Not what you might expect, right? And obviously our precious stack trace information is lost again.

It turns out that Invoke() always throws the innermost exception. Digging through the System.Windows.Forms.dll assembly we can find that a call to Exception.GetBaseException() is made to retrieve the exception that will be rethrown. So not only the stack trace is lost, but also other exceptions we might have thrown to enclose the original exception and add context to it. How bad... this seems to be a bug in the Framework, and googling around we can find that we're not alone, and that at least there is some sort of confirmation of this being a bug in the Invoke method (see here, here and here).

What should we do, if we were interested in that information? Should we implement our Invoke strategy?

Hopefully not... the GetBaseException() method is defined virtual: let's try to fool this behavior, overriding the GetBaseException() method:

using System;
using System.Windows.Forms;
using System.Threading;

static class Program {
[STAThread]
static void Main() {
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new TestForm());
}
}

public class TestForm : Form {
private Button btn;
public TestForm() {
// Just add a simple button with a Click handler
btn = new Button();
btn.Text = "Click me";
btn.Click += new EventHandler(btn_Click);
this.Controls.Add(btn);
}

void btn_Click(object sender, EventArgs e) {
// We are creating a WorkItem to be run
// on a thread from the thread pool
WaitCallback wc = new WaitCallback(this.DoTheWork);
ThreadPool.QueueUserWorkItem(wc);
}

void DoTheWork(object sender) {
// This code is run in a background thread
try {
// We are using Invoke so the call
// to ThrowWithNiceStackTrace() runs in the main thread
this.Invoke(new MethodInvoker(
this.ThrowWithNiceStackTrace));
}
catch (Exception ex) {
Type ext = ex.GetType();
string stackTrace = ex.StackTrace;
}
}
private void ThrowWithNiceStackTrace() {
// This code is run in the main thread;
// calling Control methods is legal
this.btn.Text = "Clicked";
try {
this.ThrowWithLongStackTrace();
}
catch (Exception ex) {
throw new InvokeException(
"Exception caught in invoked method", ex);
}
}
private void ThrowWithLongStackTrace() {
this.ThrowDivByZero();
}
private void ThrowDivByZero() {
int i = 1 / string.Empty.Length;
}
}
public class InvokeException : Exception {
public InvokeException(string message, Exception innerException)
: base(message, innerException) { }
   public override Exception GetBaseException() {
// Yes, we are lying: the doc says we should return
// 'The first exception thrown in a chain of exceptions'
return this;
}
}
When running this version of the program, if we stop at our breakpoint inside the catch clause of DoTheWork() we find that the exception caught is of type InvokeException, with this stack trace:

at System.Windows.Forms.Control.MarshaledInvoke(Control caller, Delegate method, Object[] args, Boolean synchronous)
at System.Windows.Forms.Control.Invoke(Delegate method, Object[] args)
at System.Windows.Forms.Control.Invoke(Delegate method)
at TestForm.DoTheWork(Object sender) in C:\TestInvoke\Program.cs:line 36

But now there is an InnerException of type DivideByZeroException, with the expected stack trace:

at TestForm.ThrowDivByZero() in C:\TestInvoke\Program.cs:line 60
at TestForm.ThrowWithLongStackTrace() in C:\TestInvoke\Program.cs:line 57
at TestForm.ThrowWithNiceStackTrace() in C:\TestInvoke\Program.cs:line 49

Not an elegant solution: we have to add a try catch in our methods called via Invoke(), at least in the methods where the location and nature of possible exceptions is not obvious. And we have to break the 'contract' of the Exception object: the implementation of GetBaseException of our InvokeException class will deliberately lie to callers. I know that lying is a bad thing (see Marcelo's recent post about this), but if we limit its usage to this workaround, we should be safe. It will also be easy to remove the workaround one day, when the fix to Windows.Forms is available: that day, just remove the InvokeException class and where compilation errors appear, there are the pieces of code to remove.

Less than nothing, anyway. I have used this workaround in error logs that we have in production, and I find it useful.