Why Are We Still Using Internet Explorer 6? – Part Two

Nearly a year and a half ago I wrote this post about why many large organizations are still using Internet Explorer 6. Every now and again, the post is re-discovered and is re-circulated and I get some great feedback about it. I’ve decided that it is time for a bit of an update on the subject, so here goes.

I’m going to assume that you’ve read my original post, but in one line, the reason many large organizations still use Internet Explorer 6 is application compatibility. My employer (a large government department) has recently experienced this first-hand, having had to postpone deployment of Internet Explorer 8 after discovering compatibility issues (mid-deployment) with some important business applications. I have no idea how come they only discovered the issues after starting to deploy. Either someone didn’t do due diligence and test before-hand, or worse, they were completely clueless about the risks of incompatibilities. Either way, as a fellow IT employee in the same organization, it’s down right embarrassing.

One of the most frequent comments I receive as feedback on my original post is that folks get the compatibility issues, but they believe that we wouldn’t be in this situation if these incompatible applications had been written using web standards. It’s the fault of the application developers that their applications only work properly with Internet Explorer 6.

Continue reading

Why Are We Still Using Internet Explorer 6?

There has been some discussion online recently between public servants about how the public service is still overwhelmingly using Microsoft Internet Explorer 6. I got involved when someone tweeted a link to this site: http://hey-it.com/download.html. The site provides cute posters asking the IT folks to basically get off their arses and give us a newer web browser. I responded back that there are other issues involved when upgrading web browsers, such as legacy application compatibility, and that things aren’t as clear cut as it may seem from the perspective of someone outside IT.

Well, responses to that included “don’t punish users for your deployment issues” and “are you afraid of losing your job if I upgrade my own browser”? Oh, and the term “visionless IT geeks” was tossed around. My response to this was a flurry of tweets quoting other folks rhyming off reasons why large organizations all over still use Internet Explorer 6. I then signed off Twitter and did not log back in for two days.

I essentially had a hissy-fit.

Continue reading

My Current Thoughts on the OC Transpo Bus Strike

The union is doing what it has to do. They are being asked to give up certain benefits (i.e. the ability to control their scheduling). From the union’s perspective it’s a dangerous precedent if they start giving stuff up so they HAVE to hold their ground.

The problem I think is that the majority of Ottawa residents (myself included) believe that the drivers don’t deserve to have control of the scheduling (in part because, true or false, we hear that they abuse it). The residents who most want this strike settled at any cost are those who are suffering the most because of it. Therefore the union needs as many people as possible suffering, so that the strike gets settled at any cost, most likely in the union’s favour. That is why the union had to strike just before Christmas, in the dead of winter. Maximum pain = union’s best chances of getting/keeping what it wants.

The union and drivers are prepared to see this through, because we’ve heard them say that they banked up their overtime in the summer (presumably by abusing their scheduling privileges) so they can afford to keep fighting.

For highlights of their last contract, Google “oc transpo collective agreement” (should be the first result, a PDF).

Their starting salary is more than what mine would be if I was starting out today. They start earning 6 weeks of vacation 4 years before I will. The most senior drivers will get 7 weeks, which isn’t even possible for me. They have just as many paid holidays as I do.

I’m a federal civil servant working in the Information Technology (IT) field, for goodness sakes. I thought I had one of the cushiest jobs in the world, but apparently OC Transpo bus drivers do.

I am in my early 30s and don’t have a drivers license. I’ve lived in Ottawa all my life, and my reasoning has always been that I don’t need a license because we had an awesome bus system. I’ve defended the bus system.

I’m beginning to change my mind.

I’ll either be getting my drivers license soon, or leaving Ottawa.

Seriously.

Working from Home

In case you weren’t aware, we are on day 8 of a transit strike here in Ottawa. I don’t drive (at all) so I normally rely heavily on the bus system here (which, in my mind, is top notch, when it’s running). Fortunately the nature of my work (and my manager) has allowed me to work from home on most of the strike days so far.

I was a little worried about working from home. I wasn’t sure how productive I’d be. But as it turns out, I am more productive at home than I am in the office. Here is a quick pro and con list of my experience working from home so far:

Pros:

  • I control the work environment (temperature, lighting, etc.)
  • Quiet! I am all by myself all day (heaven for an introvert like me)
  • More screen real-estate. At the office I have dual 17″ monitors (both @ 1280×1024). At home I am using a laptop (@ 1600×1050), plus the laptop is hooked into my 2nd monitor via the KVM (@ 1280×1024) PLUS I have my 24″ monitor (@ 1920×1200) connected to my home PC, which I can use for web browsing, media, etc). That’s over 5 million pixels in all!
  • Quiet! I can get focused and stay focused (again, for an introvert, getting focused, or getting back into focus, can be difficult)
  • Lunch and snacks are closer, and cheaper.
  • I have full access to the office network (via VPN) and my office PC’s hard drive.
  • Better chair than the one in my office.
  • I can play my music as loud as I want!

Cons (both relatively easy to resolve):

  • The laptop only has 1 GB of RAM!
  • I haven’t been able to get the laptop to share my mouse and keyboard (the mouse works, but it’s laggy. No wonder though: USB Mouse -> USB to PS/2 adapter -> KVM -> KVM Cable -> PS/2 to USB adapter -> laptop). Update: Resolved via laptop docking station borrowed from the office.

Here’s my home office setup:

IMG_2150 IMG_2151

Investigating a .Net Web Application’s Performance Issues

Yesterday my boss and I meet with a group that has been having some significant performance issues with one of their web applications.

It’s a basic .Net web forms application (in C#). Their issue was that they had one page that was taking upwards of 75 seconds to load! Seriously. 75 seconds! They said they were using NHibernate and they had tracked the issue down to one method that was taking up the majority of those 75 seconds. They also said they had tried some direct database (Oracle) queries that returned MUCH faster than the NHibernate.

We suggested that they look at caching the results of the database queries and that they confirm exactly what queries NHibernate is making on their behalf (I think they assumed it would execute the same query they had tested directly, which may or may not be the case).

Now I am a fan of NHibernate, and I have done some things with it that resulted in less than stellar performance, but I’ve always found tweak things to near direct database performance levels without much effort by changing/correcting some basic assumptions I had about the data and model. So when I left the meeting I felt that NHibernate had unfairly been labelled as the source of the performance issues, so I decided to have a look at the code for myself.

After grabbing a local copy of the code from their source control repository, I ran the code in debug mode and quickly came to the conclusion that the method they had identified as taking a long time to execute was in fact really taking a long time to execute. So I had a closer look at that method, and here (essentially) is what I saw:

/* ... */
IQuery query = CreateQuery("SELECT ...");

for (i = 0; i < query.List().Count; i++)
{
    if ((!((object[])(new ArrayList(query.List())[i]))[0] == null)
       && (!((object[])(new ArrayList(query.List())[i]))[2] == null))
    {
        String value = (((object[])(new ArrayList(query.List())))[2]).ToString();
    }
}
/* ... */

I am “paraphrasing” a bit (the real code was worse).

The query.List() call returns an IList instance containing all the results of the SQL query. I don’t know if each call to query.List() actually executes the database query again (there may be some caching involved somewhere) but each call to query.List() did involve some database activity (according to my network sniffer). You notice that query.List is being called 3 times per loop (in the real code it was more like 6 times per loop)!

Changing this code to make one call to query.List, storing the results in a local IList variable and subsequently re-using that local variable shaved nearly 50 seconds of the response time.

On top of that there would also be improvements by removing the code that creates 3 ArrayLists per loop (again in the real code, 6 ArrayLists per loop), copies the IList of database results into each ArrayList, uses each of those ArrayLists to access only one single item and them discards the ArrayLists (only to recreate them again on the next loop).

NHibernate wasn’t the source of their problem…

A Day Spent Refactoring Code

I spent a good part of today refactoring some code I’ve inherited. It’s a VB.Net wrapper around some commercial address verification software. Two examples of the type of functionality the software provides are address correction and address formatting.

Here is a simplified version of three of the classes I was given to work with: Address, CorrectedAddress and FormattedAddress. An Address is what you would provide to the verification software and the other two classes would be returned from either the address correction or address formatting functionality.

Public Class Address
    Public AddressLine As String
    Public City As String
    Public Province As String
    Public PostalCode As String
    Public Country As String
End Class
Public Class CorrectedAddress : Inherits Address
    Public Status As CorrectedAddress.Status
    Public Message As String

    Public Enum Status
        Valid
        Invalid
        Corrected
        [Error]
    End Enum
End Class
Public Class FormattedAddress
    Public AddressLineOne As String
    Public AddressLineTwo As String
    Public AddressLineThree As String

    Public Status As FormattedAddress.Status
    Public Message As String

    Public Enum Status
        Valid
        Invalid
        [Error]
    End Enum
End Class

Note that CorrectedAddress inherits from Address, but FormattedAddress does not. Both CorrectedAddress and FormattedAddress have a Status and Message properties (implemented as public fields above only for brevity). The Status properties both return similar, but not identical enumerations. In the actual code there were six classes like these two, but I am focusing only on these two for simplicity.

The whole thing didn’t seem quite right to me, and I struggled a bit to put my finger on how this should have been implemented. But then it hit me. CorrectedAddress isn’t really an Address. It’s a result of an address correction (that happens to have an address). “Is A” versus “Has A”. Remember the oft quoted Object-Oriented design principle:

Favour Composition over Inheritance

So I pulled the Address class out of the inheritance hierarchy, renamed CorrectedAddress and FormattedAddress to CorrectedResult and FormattedResult respectively and even threw in some Generics stuff to deal with the similar but different Status enumerations.

The result (the Address class was left as-is):

Public MustInherit Class Result(Of T As Structure)
    Public Status As T
    Public Message As String
End Class
Public Class CorrectedResult : Inherits Result(Of CorrectedResultStatus)
    Public Address As Address

    Public Enum CorrectedResultStatus
        Valid
        Invalid
        Corrected
        [Error]
    End Enum
End Class
Public Class FormattedResult : Inherits Result(Of FormattedResultStatus
    Public AddressLineOne As String
    Public AddressLineTwo As String
    Public AddressLineThree As String

    Public Enum FormattedResultStatus
        Valid
        Invalid
        [Error]
    End Enum
End Class

Much better!

I Survived a Busy Long Weekend

Went up to Quebec City with the family this past weekend. The wife and I both have family up there so we try to go up at least once a year (this was our second trip this year).

We leave Friday night after work and drive as far as Trois-Rivieres, which after a full day of work and several hours in the car with the little one is far enough. We crash overnight in a hotel, then cover the last couple hours to Quebec City on Saturday morning. We spend most of Saturday with my family, then Saturday night we crash at the in-laws place. Sunday is time spent with the wife’s family, and some touristy activities. Then Monday we head back home. This time we stopped in Montreal and spent a few hours at the Bio-Dome. It’s a pretty cool place, but a little on the expensive side.

We got home Monday night and did nothing but unpack and watch a little TV. I spent last night and most of tonight getting caught up on 5 days worth of emails (approximately 1600, 75% spam) and my Google Reader feeds (1000+ articles). I’ve still got 900+ unread items in Google Reader.

First Impressions: Rogers Video Direct (aka Zip.ca)

I’ve been a subscriber of Rogers Video Direct (a Rogers branded version of Zip.ca) for about a month now and so far it’s working out for me.

Basically how it works is that you sign up for an account, choose a plan which dictates how many DVDs you can have out at once and how many you can have shipped to you for free each month. I started out with 3 at a time, unlimited per month, but have switched to one at a time, unlimited per month after getting a feel for exactly how long it actually takes me to watch a DVD given my schedule. Even on the 1 at a time plan there is a ‘Refill’ feature which you can use to indicate that the DVD you’re returning is in the mail. They’ll basically send out your next DVD before before they receive the last one. In my experience I receive my next DVD the same day that they receive to previous DVD return.

Anyways, once you’ve signed up, you browse their selection of DVDs and add the ones you’re interested in to you ZipList. You can rank the DVDs on your list and what they do is send you the highest ranked DVD on your list that is available.

I am currently on my 4th DVD. I find the DVDs in my mailbox within 2 days of receiving notification that they’ve shipped and the return trip seems to take about the same time (2 days after I mail the DVD back it disappears from my current rented DVD list.

I’ve got years of movies to get caught-up with!

Feed Me… RSS

image

I’ve become a hard-core Google Reader user lately. It has gotten to the point where I have all the RSS feeds of my (former) daily-visit web sites plugged into Google Reader.

Google Reader is setup as my start page in my browser and as a result I rarely visit any of the sites I used to visit several times per day.

My Slashdot and CBC news stories all appear in Google Reader, as do my daily comics, my friends sites and blog. I receive Facebook updates there too. The Globe and Mail, MySQL product releases, Stack Overflow, Wired top stories, Woot one day deals! You name it!

If it interests me, I will probably hear about it via Google Reader!