Saturday, January 7, 2012

.NET Collection Runtimes

Each week my department holds a morning tech review. Subjects vary from testing tools, advanced caching mechanisms, to good ol' basic .NET facts. This week the tech review was an "Asymptomatic Analysis of .NET Collections". While most of the material was pretty straight forward, I always find getting back to the basics to be a good thing.

I thought that it was fun to see all of the collection run times aggregated into one table. As several of my coworkers pointed out, it can be a bit of a pain to find all these "simple" facts on the SEO crammed internet...so then why does no one simply blog about it?

In summary: here is some stolen content. Thanks Byron!

List-Like Collections

  List LinkedList SortedList
Add O(1) or O(N) O(1) O(Log N) or O(N)
Remove O(N) O(N) O(N)
Clear O(N) O(1) O(Log N)
Get O(1) O(N) O(Log N)
Find O(N) O(N) O(Log N)
Sort O(N log N) or O(N^2) - Already sorted
Underlying
Data
Structure
Array Dynamically allocated nodes Array

Hash-Like Collections

  Dictionary SortedDictionary HashSet SortedSet
Add O(1)
or O(N)
O(Log N) O(1)
or O(N)
O(log N)
Remove O(1) O(log N) O(1) O(N)
Clear O(N) O(Log N) O(N) O(N)
Get / Find O(1) O(Log N) O(1) O(Log N)
Sort - Already sorted - -
Underlying
Data
Structure
Array + Linked List Dynamically allocated nodes
(Binary Search Tree)
Array + Linked List Dynamically allocated nodes
(Binary Search Tree)

If you would like to see any updates/additions please feel free to leave a comment.

Enjoy,
Tom

Tuesday, January 3, 2012

Why Atwood's Law is a Good Thing

Any application that can be written in JavaScript, will eventually be written in JavaScript.

Jeff Atwood proposed this simple rule way back in 2007. Now, as his predictions come true, we may find ourselves asking "why would anyone want to do such a crazy thing?" Well here are three simple reasons:

1: Because we can!
Software development is an art that requires practice. Why do college students write compilers? Why did John Carmack port Rage to iOS? Why did I port Chrono Trigger to a graphing calculator? Software engineers are artisans, these challenges represent our art form at it's best.

2: JavaScript represents true platform independence.
Windows, Mac, Linux, x86, x64, iOS, Android, the list goes on; frankly, there are just too many platforms out there to develop for. The beauty of JavaScript is that it is a universally recognized spec that is supported everywhere. This level of accessibility is advantageous for developers and consumers alike.

3: It shows the power of modern technology.
The fact that we can run a Java Virtual Machine in the browser shows just how far modern browsers and house hold hardware have come. It was only a few years ago that Virtual Machines were a concept reserved for only the most powerful of server farms. The tower of Dubia was not built out of necessity, it instead stands as a monument to human achievement; that is how I view emulator hardware in a browser, a virtual monument of human engineering.

...also, why wouldn't you want to play NES games in your browser?

Tom

Sunday, December 25, 2011

Happy Holidays

My apologies for the shortage of blog posts recently, but between the new job and some unannounced side projects I've been extremely busy. So here is some best of 2011 filler material...

  • Gizmo of the Year: Asus Transformer Prime
  • Console Game of the Year: Super Mario 3D Land
  • PC Game of the Year: Orcs Must Die
  • Movie of the Year: Troll Hunter
  • Programmer of the Year: Markus "Notch" Persson
  • Gift of the Year: FLYING SHARKS!

Happy Holidays,
Tom

Sunday, November 6, 2011

jQuery UI Modal Dialog disables scrolling in Chrome

Is Chrome becoming the new IE?

As much as I love jQuery, I still cannot escape the fact that jQuery UI leaves a lot to be desired. Yesterday I ran across an issue where the jQuery UI modal dialog acted inconsistently in different browsers. Normally opening a modal leaves the background page functionality unaltered, but in Webkit browsers (I ran into this while using Chrome) it disables the page scroll bars.

The Fix

Yes, this bug has already been reported. Yes, it is priority major. No, it won't be fixed anytime soon. For a feature as widely used as the Modal Dialog, I find that kinda sad.

However, thanks to Jesse Beach, there is a tiny little patch to fix this! Here is a slightly updated version of the fix:

(function($) {
  if ($.ui && $.ui.dialog && $.browser.webkit) {
    $.ui.dialog.overlay.events = $.map(['focus', 'keydown', 'keypress'], function(event) { 
      return event + '.dialog-overlay';
    }).join(' ');
  }
}(jQuery));

Additional Resources

Hope that helps!
Tom

Thursday, November 3, 2011

Configuring MVC Routes in Web.config

ASP.NET MVC is even more configurable than you think!

Routes are registered in the Application Start of an MVC application, but there is no reason that they have to be hard coded in the Global.asax. By simply reading routes out of the Web.config you provide a way to control routing without having to redeploy code, allowing you to enable or disable website functionality on the fly.

I can't take credit for this idea, my implementation is an enhancement of Fredrik Normén's MvcRouteHandler that adds a few things that were missing:

  • Optional Parameters
  • Typed Constraints
  • Data Tokens
  • An MVC3 Library

Download MvcRouteConfig.zip for the project and a sample application.

Example Global.asax

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
 
    var routeConfigManager = new RouteManager();
    routeConfigManager.RegisterRoutes(routes);
}

Example Web.config

<configuration>
  <configSections>
    <section name="routeTable" type="MvcRouteConfig.RouteSection" />
  </configSections>
  <routeTable>
    <routes>
      <add name="Default" url="{controller}/{action}/{id}">
        <defaults controller="Home" action="Index" id="Optional" />
        <constraints>
          <add name="custom"
              type="MvcApplication.CustomConstraint, MvcApplication">
            <params value="Hello world!" />
          </add>
        </constraints>
      </add>
    </routes>
  </routeTable>

Thanks Fredrik!

~Tom

Update 2/16/2013 - I have added this source to GitHub and created a NuGet Package.

Shout it

Monday, October 17, 2011

Using the InternetExplorerDriver for WebDriver

Are you getting this error when trying to use the InternetExplorerDriver for WebDriver (Selenium 2.0)?

System.InvalidOperationException

"Unexpected error launching Internet Explorer. Protected Mode must be set to the same value (enabled or disabled) for all zones. (NoSuchDriver)"

Don't worry, it's easier to fix than it sounds: Simply go into your Internet Options of Internet Explorer, select the Security tab, and all four zones to have the same Protected Mode value (either all on or all off). That's it!

Sample Code

using NUnit.Framework;
using OpenQA.Selenium;
using OpenQA.Selenium.IE;
 
namespace WebDriverTests
{
    public abstract class WebDriverTestBase
    {
        public IWebDriver WebDriver { get; set; }
 
        [TestFixtureSetUp]
        public void TestFixtureSetUp()
        {
            WebDriver = new InternetExplorerDriver();
        }
 
        [TestFixtureTearDown]
        public void TestFixtureTearDown()
        {
            if (WebDriver != null)
            {
                WebDriver.Close();
                WebDriver.Dispose();
            }
        }
 
        [SetUp]
        public void SetUp()
        {
            WebDriver.Url = "about:blank";
        }
    }
 
    [TestFixture]
    public class GoogleTests : WebDriverTestBase
    {
        [Test]
        public void SearchForTom()
        {
            WebDriver.Url = "http://www.google.com/";
 
            IWebElement searchBox = WebDriver
                .FindElement(By.Id("lst-ib"));
 
            searchBox.SendKeys("Tom DuPont");
            searchBox.Submit();
 
            IWebElement firstResult = WebDriver
                .FindElement(By.CssSelector("#search cite"));
 
            Assert.AreEqual("www.tomdupont.net/", firstResult.Text);
        }
    }
}
Shout it

Enjoy,
Tom

Tuesday, September 27, 2011

Unity.MVC3 and Disposing Singletons

Recently I was having a conversation with a friend where I was able to articulate my thoughts on dependency injection more eloquently than I ever had before. In fact, I may have phrased this better than any nerd in the history of programming. That's a bold statement, so you be the judge:

"I didn't just swallow the inversion of control kool-aid, I went on the I.V. drip."

Unity.Mvc3

I recently starting working on a new project where they wanted to use Microsoft's Unity for their DI framework. It's not the exact flavor of IOC container would have chosen, but I am all for best practices regardless of specific implementation.

Important side note about MVC3: There is a new way to wire up for dependency injection. MVC now natively exposes a System.Web.MVC.DependencyResolver that you can set to use your container. This means that you no longer need to create a custom MVC controller factory to inject your dependencies.

While researching how best to implement Unity in my MVC 3 project, I came across Unity.Mvc3 by DevTrends. (Here is a little overview.) It's a great project for all the right reasons:

  1. It's up to date.
  2. It's lightweight.
  3. It solves pre-existing issues.

Note that last point. There are a lot of wrappers out there, and a lot of simple copy paste code snippets, but I really appreciate when someone goes out of their way to do more than just write their own version of something. To be specific, unlike many of the alternatives Unity.Mvc3 works with IDisposable dependencies, and that just happens to be a requirement of the project that I am working on.

Also, DevTrends get's additional bonus points for deploying their solution as a NuGet package!

Disposing Singletons with Application_End

I did find two small problems with Unity.Mvc3:

First and foremost, singleton dependencies (anything registered with ContainerControlledLifetimeManager) were not being disposed. This was easy enough to fix however, I just wired up a dispose call to my Bootstrapper in the MvcApplication's Application_End method.

Second, the NuGet package's initialize method was spelled wrong. I actually view this is actually a good thing, because it means that I am not the only person who makes spelling errors in code that they opensource! HA HA HA!

Bootstrapper Example

public static class Bootstrapper
{
    private static IUnityContainer _container;
 
    public static void Initialize()
    {
        _container = BuildUnityContainer();
        var resolver = new UnityDependencyResolver(_container);
        DependencyResolver.SetResolver(resolver);
    }
 
    public static void Dispose()
    {
        if (_container != null)
            _container.Dispose();
    }
 
    private static IUnityContainer BuildUnityContainer()
    {
        var container = new UnityContainer();
        // TODO Register Types Here
        container.RegisterControllers();
        return container;
    }
}
 
public class MvcApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();
        RegisterGlobalFilters(GlobalFilters.Filters);
        RegisterRoutes(RouteTable.Routes);
 
        Bootstrapper.Initialize();
    }
 
    protected void Application_End()
    {
        Bootstrapper.Dispose();
    }

Enjoy,
Tom

Real Time Web Analytics