Sergio and the sigil

IE6 still haunts me

Posted by Sergio on 2009-10-21

Oh, the woes of supporting IE6 (or, better put, IE666 — the browser of the beast.)

Halloween is definitely upon us. Today I spent a good chunk of time trying to identify the source of a problem in my application. Right now I'm in the process of jQuery-fying some legacy JavaScript, which includes Ajax calls and error handling logic.

At some point I needed to pop-up a DIV that was supposed to look like a modal message box, reporting some error that happened during the Ajax call. That was not hard at all. I used the SimpleModal plugin and got the message box up in not time at all.

Not so fast, you have IE6 users

As with many web developers out there, I don't have the luxury of ignoring IE6 users because they are upwards of 60% of our user base (corporate users that for some reason can't easily upgrade their browsers.)

I thought it wouldn't be a problem because the SimpleModal plugin handles a number of IE6 issues, including the insertion of an IFrame to overcome the bleedthrough of Select tags. But of course it couldn't be that easy right?

In some of my tests IE6 was simply crashing when I tried to open the "modal" message. After a lot or hair pulling, I saw this suspicious HTML in one of my messages:

<table style="font-size: expression(parentnode.currentstyle.fontsize);" >
    <!-- rest of the table is normal -->
</table>

Sure enough, moving that hack to a proper CSS rule in the external .css file made the error go away. We shouldn't be using dynamic CSS expressions anyway, since they were removed from IE8, so I went ahead and ditched that kind of usage wherever I could find it.

This is just to keep us on our toes regarding IE6 support. Even though the modern JavaScript libraries go to great lengths to support IE6 and make our coding transparent, nothing substitutes good old manual testing to make sure IE6 doesn't play pranks on us in production.

JavaScript and its love for zeroes

Posted by Sergio on 2009-09-19
This post is part of a series called JavaScript Demystified.

Answer quick. Do you know what date is being created here?

var year = '2009', month = '09', day = '01';
var date = new Date( 
             parseInt(year),
			 parseInt(month),
			 parseInt(day)
			 );	

At first glance, it wouldn't surprising that someone guesseed September 1st 2009. However, I'd not be writing this post if that was the correct answer, right?

There's an interesting and tricky thing with the JavaScript parseInt function: it can parse strings with a numeric value in the decimal radix, but also in other radices. See the following examples.

//passing the radix explicitly
parseInt('1011', 10); // ==> 1011
parseInt('1011',  2); // ==> 11
parseInt('1011',  8); // ==> 521
parseInt('1011', 16); // ==> 4113

Maybe you thought that if you didn't pass the radix, then it would default to 10 because it's the obvious behavior. Well, no. In JavaScript the default behavior is to try to identify one of the literal formats and interpret that. So here's that in action:

//leaving JavaScript on its own
parseInt('1011'); // ==> 1011 (decimal literal)
parseInt('0x12'); // ==> 18   (hexadecimal literal)
parseInt('0511'); // ==> 329  (octal literal)
parseInt('0182'); // ==> 1    (whaaaa?!?!)

If you are familiar with the literal notation for integer numbers in JavaScript, and after I explained the default behavior of parseInt, then you probaly understood the results shown above. Well, maybe the last one deserves some comments.

When JavaScript is parsing the string, if it finds a digit (number or alpha) that is invalid in the chosen radix, it stops right there and parses only the portion of the string that comes before that digit. So, since we started '0182' with a leading zero, the octal radix is assumed. Then, because 8 is not a valid octal digit, only '01' will be parsed, which becomes 1.

Tip #1: If there's any chance the string value you plan to parse into an integer number has a leading zero (or a less likely 0x,) then be safe and pass the radix parameter to your parseInt call. If you're extra paranoid, then always pass the radix.

Back to our original question

Armed with the clarification made above, we can expand our example like this:

//given:
var year = '2009', month = '09', day = '01';
// then the following statement:
var date = new Date( 
         parseInt(year),
         parseInt(month),
         parseInt(day)
         );	
//...is equivalent to:
var date = new Date( 
         2009,
         0,  // ===> oopsie
         1
         );	

Hmmm, a zero in the month parameter. Will we have an error here? No, here comes the second potential surprise of this post.

Tip #2: When creating a new date using new Date(year, month, day), the month parameter, and only the month parameter is zero-based (0 to 11).

So, in case the tips and the picture in this text were not enough to help you guessing the date being created, here goes another completely gratuitous one with the answer.

Taming Firebug with Profiles

Posted by Sergio on 2009-09-01

This is a tip for anyone using Firefox and Firebug for web development that is not leveraging the Profiles feature of that browser.

Recent versions of Firebug (after v1.3 I think) removed the ability to enable Firebug panes on a per-domain basis. Now it's kind of all or nothing. And you know that you don't want to have Firebug enabled when using Ajax-intensive applications like GMail, for example.

The end result is that you are stuck in this annoying dance of of enabling/disabling, open/close Firebug when switching tabs.

There are some workarounds for that but I think the best solution for this problem is through Profiles, which is also a very nice approach for web development overall.

Firefox Profiles

Firefox stores all your preferences (add-ons, state, saved passwords, history, etc) inside profile directories. It installs a default profile and that's perfectly enough for the casual browser user. Web developers, add-on developers, and power users in general, on the other hand, can find handy uses for extra profiles.

You can see your profile directories in %APPDATA%\Mozilla\Firefox\Profiles (or, on the Mac, ~/Library/Application Support/Firefox/Profiles).

Development profile

The suggestion I'm giving is to create a separate profile just to be used during web development work. That way you can exclude some of the add-ons (like ad blockers, bookmarking extensions like Delicious, and any other non development-related extensions.) The opposite applies to your default profile — you can now remove all the development stuff from that profile and keep your browser a little lighter. In addition to that I use a different skin/theme in each profile, just to make it screaming obvious which one I'm looking at.

Here's how we create a new profile. First close all your Firefox windows and make sure there's no Firefox process running in the background. Now go to the command line and enter this:

(on Windows)
%ProgramFiles%\Mozilla Firefox\firefox.exe -ProfileManager
(or on the Mac)
/Applications/Firefox.app/Contents/MacOS/firefox -ProfileManager

This will bring up the Profile Manager, where you can easily create a new profile. Create one named Development and start it.

Once started, you'll notice that Firefox will open looking just like it did the first time you installed it. You can now install your favorite extensions for web development (like Firebug, YSlow, Web Developer Toolbar, User Agent Switcher, etc)

To launch Firefox using the the Development profile you can create a shortcut that passes some arguments to Firefox, like firefox.exe -P Development -no-remote. For example, I added that shortcut to my Desktop, Quick Launch, and Launchy. (Firefox will remember which profile you started last using the Profile Manager, and use that one next time you start Firefox without explicitly choosing a profile. You may want to leave the default profile selected in the Profile Manager.)

More uses for Profiles

Besides creating a profile dedicated to web development work, I can very well see myself eventually creating extra ones for different activities, like a Presentation profile and a NoAddons profile, for example.

Circular Refactoring

Posted by Sergio on 2009-08-14

One of these days I was chatting with Derik and we were talking about refactoring and when to stop refactoring. We thought it was funny (and embarrassing) how sometimes, after a few consecutive refactorings, we are back at the starting point.

This type of Circular Refactoring is a real productivity enemy. In our genuine desire to improve the code, and wishing to dive into an interesting task, we sometimes lose sight of the code history and the real need for this change. It reminds me a lot of this funny comment (second part).

How do you tell when you're being a victim of this variation of the premature optimization monster? Well, here's a start:

Top 10 signs you've fallen into circular refactoring

9 - Code gets eerily familiar by the minute.
8 - Your git repository doesn't seem to grow.
7 - Work feels too much fun to be real.
6 - Your code metrics trending charts look like Bart Simpson's hair.
5 - You're never breaking any of your unit tests after each change.
4 - You've created macros in the IDE to help with almost all the steps.
3 - You're refactoring your macros.
2 - Clippy is asking if you've heard about the "svn merge" command.
1 - TFS, on the other hand, still can't offer you much help.
0 - Your Find/Replace drop-downs seem to read your mind.

A Craftsman sometimes has to create his own tool

Posted by Sergio on 2009-06-28

Today I was reading the latest one of the many excellent blog posts Patrick Smacchia has put out on the topic of code metrics and caring for your code's quality.

The passion this guy has for that topic is such that he has created the best tool for analyzing your code. But he doesn't stop there. He wants to make sure we understand what is going on behind the seemingly magic CQL queries that ship with NDepend. He wants you to understand your code's DNA; with the added bonus that you can actually improve that DNA.

That's Science with capital S.

  1. First you understand the problem that you are trying to fight (code complexity/unmaintainable software,)
  2. you research ways to quantify it (the metrics,)
  3. you create some tool or device to extract that information from your subject,
  4. you extract the metrics from a familiar subject,
  5. you apply your knowledge of how #2 relates to #1 and improve the subject under analysis,
  6. you use the tool to verify the metrics have improved,
  7. time shows you that the changes you made indeed reduced the problem at #1

I simply hate when someone criticizes Patrick's posts as being just marketing material for his product. Let me tell you this. If I had that much dedication for software quality, to the point that I had created a great product to empower everyone, I'd also be trying to explain the problem to you using the tool I wrote. Heck, I'm pretty sure if someone else had written NDepend Patrick would still be writing about these things and using the tool in the process.

I like code metrics and static analysis a lot as well, not nearly as much as Mr Smacchia though. I'm very excited that very soon I'll get to use it in our code base, in our CI server. I can't wait to learn more about this science and inflict positive changes in our code. Like everybody else, we know there's dirt and bad smells in our code and it's just awesome that there's a tool that can help us clearly identify, mitigate, and track it.

My hope is that I'll be able to come back here and share what I've learned about my code and how the process we went through to improve it.