Tuesday, June 21, 2011

Browser Session Management

First off, I admit I have a problem. I typically have 5-6 browser windows open with 10-15 tabs per window and that's just with one brand of browser. I sometimes have that many tabs/windows with two of the big three (IE, Firefox or Chrome) browsers going at the same time.

There are many reasons why I end up with so many open tabs:
  • I open a new window to search on something and open the links in tabs
  • I get easily distracted. I start to reading a page then switch to something else and don't want to close the tab knowing I will come back to it.
  • There are some tabs that are semi-permanently open (like gmail, Facebook, Twitter, Amazon Cloud Player).
  • I use open pages as a todo list.
Usually this isn't that big of a problem but it can become one. The biggest problem is memory usage. Over time all three browsers seem to leak memory (some worse than others - Firefox I'm looking at you) forcing restarts (and occasionally Windows wants to install updates and reboot). Having the browser re-open without losing all of my open tabs is a big selling point. 

Here is my take on the big three and session management.

Internet Explorer

IE is the worst of the three when it comes to session management. IE8 and 9 added a link to 'Reopen last session' (accessible on new tabs) but as far as I can tell it assumes all of your previously open tabs were in one window. If you do have multiple windows open and restart your computer only the last window closed is restored (which always seems to be the one with the fewest tabs). If your computer hard crashes and you restart IE it does ask if you would like to restore the previous session and this does reopen all windows and tabs. So full session information does seem to be stored somewhere just not surfaced to the end user.

Firefox

Early on Firefox itself did not have great session management but it had good add-ons like "Session Manager". If I noticed things running slow or saw Firefox memory usage spiking in Task Manager I could kill the browser and with Session Manager reload all of the tabs when it restarts. Firefox has now built this in as option to restore all open tabs.

Chrome

With Chrome I ended up having on of those 'doh' moments. I knew Chrome tracked all of the opened windows and tabs because if I restarted from a hard shutdown it would offer to Restore all of them. The problem was that if I noticed Chrome eating up a lot of memory there didn't seem to be a clean way to close all of the windows and completely restart the browser session. Since each tab spawns its own process there was not a single process I could kill like Firefox in the Task Manager. And if you clicked on the X in each browser window like IE the last window became the only one restored. Then I don't remember where I read it but I found out if you use the 'Exit' menu option from the Wrench icon it will close and remember all of your open windows and tabs. It was one of those 'aha' moments that made live easier. 

Friday, June 17, 2011

Scratch and Squeak

Some of my first programming experiences were typing BASIC programs into my TI-99/4A home computer copied from computer magazines. The whole process was madly frustrating. There was no editor, you had to exactly copy the lines into the console and then you could save the program to an analog cassette. If you were lucky you could reload your program from the cassette at a later date. I remember trying to create a Star Trek game and gave up after taking 2 weeks just to create the logo screen. Despite all of this there was something about programming and I was hooked.

Now many years later I am a father of three and hoping to pass along some of that love of programming to my kids. Looking around its amazing the options out there to get them started . When I was starting out the options were either BASIC or Logo. Logo had some neat ideas and I played with it a bit, but moving the turtle around never got me hooked. Now this Wikipedia page lists 71 educational programming languages.

As a past Smalltalker, the most interesting to me of these appear to be Squeak and Scratch. Squeak is a modern, open source implementation of the Smalltalk programming language and environment. Scratch is built using Squeak under the covers but is a visual programming language where programs are built by snapping together blocks. I think my daughters will like the ability to quickly create an animated story and control the action. I also have a first generation Lego Mindstorms kit but I think Scratch will be a good starting point.

Thursday, June 16, 2011

Smalltalk Extensions

In a previous lifetime I worked for a Smalltalk vendor and my last two posts (here and here) got me thinking about all of the ways that you could hack the Smalltalk environment. In Smalltalk, except for a few primitives, all of the base libraries source code is present and editable in your environment. You can edit the default implementations or easily add additional functionality to base classes. This can lead to all sorts of interesting side effects.

I remember working with one customer that had occasional lock-ups in their development environment which they were blaming on us. These lock-ups were intermittent and hard to reproduce. Well one day while in their environment I was able debug right after a lock-up. I started stepping through some code in the base collection class that I didn't recognize. Turns out they had overridden the inherited Sort function and implemented their own (might have been a quicksort I can't remember) along with a very subtle bug. Given the right list size and starting conditions the code would enter an infinite loop. Fixing their sort function fixed their lock-ups and contributed to my reluctance to ever touch base libraries.

Wednesday, June 15, 2011

Extension methods strike back

In my previous post I showed how static utility functions that extend base library functionality can be rewritten using extension methods. Now I will explain why I don't think it is a good idea to do so.

Extension methods were added primarily to allow LINQ functionality to extend base level classes without changing the spec of the base classes. You can see this in action by adding a reference to the System.Linq namespace to your code and suddenly arrays have methods like OrderBy in the intellisense list.

This is great for Microsoft which can co-ordinate between the Linq and core library teams but what happens when an extension method you've written conflicts with a change in the base library. Well this is documented here, you lose:
You can use extension methods to extend a class or interface, but not to override them. An extension method with the same name and signature as an interface or class method will never be called.
For example, say you create an extension method named WordCount that looks for spaces to count words. Then in a new .NET release Microsoft also adds a WordCount method to the String class but their version counts hyphenated words as separate words. Your application may suddenly change its output or crash. Even good unit tests may not catch all of the edge cases.

Granted there is probably a remote chance of this happening and you could safety against it by prefixing all of your extension methods with something non-standard. However I just don't feel there is enough gain to be had with using extension methods over static utility classes.

Tuesday, June 14, 2011

Extension methods

In my previous post I talked about convenience functions and their usefulness in wrapping base level functionality. .Net 3.5 added a new feature called extension methods that allows methods to be added to a base class then called on instances of that class.

For example say you have an existing StringUtils class and method named OccurencesOf:

/// <summary>
/// StringUtils provides a collection of static functions for string manipulations.
/// </summary>
public static class StringUtils {

    /// <summary>
    /// Returns the number of occurences of the match string in the source string
    /// </summary>
    public static int OccurencesOf(string sourceString, string matchString) {
      return Regex.Matches(sourceString, EscapeRegEx(matchString)).Count;
    }
}

For example:
    StringUtils.OccurencesOf("the quick brown fox jumped over the lazy dog", "the");

With extension methods this can be rewritten like:
public static class StringExtensions {
 
    /// <summary>
    /// Returns the number of occurences of the match string in the source string.
    /// </summary>
    public static int OccurencesOf(this String sourceString, string matchString) {
        return Regex.Matches(sourceString, EscapeRegEx(matchString)).Count;
    }
}

And called like:
    "the quick brown fox jumped over the lazy dog".OccurencesOf("the");

Definitely a neat feature but in my next post I will explain why you shouldn't use extension methods.

Monday, June 13, 2011

Convenience functions and utility classes

Convenience functions are a favorite category of mine. The core libraries provide great functionality but (by necessity) operate at an atomic level. You might want to call A,B and then C and I just want C then A. This flexibility is great but can lead to a lot of duplicated code in your application.

Enter a convenience function. This is what I call code that wraps several calls to base level functions that can be reused throughout the application. We group similar ones into a static class with a Utils suffix (e.g. StringUtils or XmlUtils).

Here is an example of one that we use:
/// <summary>
/// Convert either a predefined color name or an ARGB value into a Color object.
/// </summary>
/// <param name="colorString">Either a predefined color name or an ARGB number 
/// value represented as a string./// <returns>Color
public static Color FromColorString(string colorString) {
  // Color will throw an exception if the string is null.
  if (string.IsNullOrEmpty(colorString)) return Color.Empty;

  // Translate HTML color strings.
  if (colorString.StartsWith("#")) {
    return ColorTranslator.FromHtml(colorString);
  } 

  // See if the passed in value is a named color string.
  Color color = Color.FromName(colorString);
  if (color.IsKnownColor) return color;

  // If the string is not a named color and not a number return the empty color.
  if (!StringUtils.IsInteger(colorString)) return Color.Empty;

  // Otherwise convert the string to a number and return a color based on that.
  return Color.FromArgb(Convert.ToInt32(colorString));
}

It neatly wraps several ways to create a color object from an HTML string, named color or argb value. Create a bunch of unit tests for this and you have a nice piece of reusable code.

Monday, June 6, 2011

DateTime serialization issue within a DataSet

For most of our SOAP-based web services we return either simple strings or manually created XmlNodes. We did this to try and make the web services as easy to use with languages other than .NET as possible and because early on we had run into some issues with the built-in serialization code. The built-in serialization is nice when you control both endpoints but if you don't, I've found they can have some unexpected behaviors like below.

For a handful of web services we have a huge variable set of data that needs to be returned. Rather than write a blob of custom serialization code we took the easy way out and return a .NET DataSet (letting the built-in serializer to the work). Things were good until we started to get reports of DateTimes being off when the client-code was calling from a different timezone than the server's timezone. There are two options for the times we return they can be either in UTC or adjusted to a user specified timezone. Neither option was using the server's local time but when the DataSet was unserialized in the client it was being adjusted by the delta between the client and server's timezone.

For example a value in the DataSet might look like the following before serialization:
<date_time>12:19:38</date_time>
In the client it would come with a offset specified:
<date_time>12:19:38.0000000-04:00</date_time>

The client code would adjust this to its local time (much like Outlook when you schedule an appointment with someone in a different timezone).

This was a particularly tricky issue to deal with because the delta was between the two different timezones and not some known value like UTC. Since we didn't know what timezone the calling code was in how were we to account for it. This Microsoft KB article suggests as a workaround creating a new web service that the client can call to adjust the times in the DataSet. This seemed to be a really bad idea and knew their had to be a better way.

Thankfully one of the developers on the team found it. The DataColumn objects in the DataSet have a property called DateTimeMode which controls the serialization of times. UnspecifiedLocal is the default which was causing our issues. Switching this to Unspecified allowed the serialization to happen without an offset to be applied. Hooray!

foreach (DataColumn column in table.Columns) {
    if (column.DataType == typeof(DateTime)) {
      column.DateTimeMode = DataSetDateTime.Unspecified;
    }   
  }