Thursday, August 30, 2007

I was messing around with some unit tests this week and I came across an unexpected benefit while working on code that worked with a COM object. When you add a reference to a COM library in .NET, you'll get an interface as well an implementation of that interface that forwards the calls to the COM objects.

Because an interface is created for the COM objects as well as the implementation, you can mock the COM dependency with Rhino Mocks or some other mocking framework. Just code against the interface instead of the concrete implementation and inject the concrete implementation via dependency injection for the normal scenario.

Let's say you wanted to unit test some code that had a dependency on the Windows Media Player COM object. Here's how you could do it.*

image

// Code to be tested
public class SomeClass
{
   private WMPLib.WindowsMediaPlayer _player;

   public SomeCode(WMPLib.WindowsMediaPlayer player)
   {
      _player = player;
   }

   public void DoSomething()
   {
      _player.enabled = false;
   }
}

// Unit test
[TestFixture()]
public class SomeCodeTest
{
   [Test()]
   public void PlayerEnabledShouldBeSetCorrectly()
   {
      MockRepository mocks = new MockRepository();

      // Mock the WMP interface... note that even 
// though it doesn't start with an 'I', // it is still an interface... WMPLib.WindowsMediaPlayer player = mocks.CreateMock(); // Inject the mocked WMP object SomeClass sc = new SomeClass(player); using (mocks.Record()) {
// Expect player.enabled to be set to false player.enabled = false; } using (mocks.Playback()) { sc.DoSomething(); } } }

I tried this code out and the test runs fine. Note the comment where the mock object is actually being created. For some reason, the interface to the COM object isn't named with an 'I'. It still is an interface, though. And you can create the COM object by saying 'new WMPLib.WindowsMediaPlayer' though I think that is some COM interop magic going on there (I'm guessing the CoClass attribute on the interface has something to do with this magic).

* I'm not actually mocking Windows Media Player in any of my code and I have no idea how well it will work. I do know that I can mock some of our own COM objects without any problems, though.

posted on Thursday, August 30, 2007 3:36:44 PM (Central Standard Time, UTC-06:00)  #    Comments [0]
 Tuesday, August 21, 2007

I found myself writing the following code this evening:

public T GetItem<T>(string name)
{
    string result = node.SelectSingleNode(name).InnerText.Trim();
 
    return (T)GetConverter(typeof(T)).ConvertFromString(result);
}
 
private TypeConverter GetConverter(Type objectType)
{
    if (objectType.Equals(typeof(int)))
        return new Int32Converter();
    else if (objectType.Equals(typeof(bool)))
        return new BooleanConverter();
    else if (objectType.Equals(typeof(string)))
        return new StringConverter();
    else
        throw new ArgumentException("Does not support casting to " + objectType.Name);
}

Don't ever write code like this. Read the documentation which explicitly says that "you should never create an instance of a BooleanConverter". If you follow their advice, your code will become much cleaner. Like so:

public T GetItem<T>(string name)
{
    string result = node.SelectSingleNode(name).InnerText.Trim();
    return (T)TypeDescriptor.GetConverter(typeof(T)).ConvertFromString(result);
}
posted on Tuesday, August 21, 2007 8:39:58 PM (Central Standard Time, UTC-06:00)  #    Comments [0]

I was looking through programming.reddit.com today and discovered that IronLisp now has a website on Codeplex. I haven't coded in LISP since college, but it was certainly an interesting experience.

This got me thinking - how many Iron* projects are there now? This is what I've come up with:

1) IronPython - the original Iron project?

2) IronRuby

3) IronLisp

4) IronXSLT - (thanks Michael!)

5) ...

Hmmm... as I was thinking about this blog post, I seemed to think there were a lot more out there. I know there are a lot of other languages that support the CLR, but I guess the Iron designation seems to be fitting with the languages that are build on top of the DLR. I'm a little curious if the Smalltalk/DLR implementation (Vista Smalltalk) will make the name change to IronSmalltalk or not.

So where did the Iron naming scheme come from anyway? Why not Nython1 or NRuby2? :-)

1 - The Java implementation is Jython.

2 - The Java implementation is JRuby.

posted on Tuesday, August 21, 2007 6:47:02 PM (Central Standard Time, UTC-06:00)  #    Comments [3]
 Friday, August 10, 2007

For your enjoyment, here is some great dialogue from the movie Airplane. Why am I providing this? Because it is funny and because I wanted to.

Roger Murdock: We have clearance, Clarence.
Capt. Clarence Oveur: Roger, Roger. What's our vector, Victor?
Tower: Tower Radio, clearance, over.
Oveur: That's 'Clarence Oveur', over.
Tower: Roger.
Roger Murdock: Huh?
Tower: Roger, over.
Roger Murdock: What?
Capt. Oveur: Huh?

Many thanks to Kaelin for providing this.

posted on Friday, August 10, 2007 7:15:34 AM (Central Standard Time, UTC-06:00)  #    Comments [0]
 Tuesday, August 07, 2007

I work with the WebBrowser control that was introduced in .NET 2.0 (as well as the ActiveX browser it is based on) a lot at work. As a result, I've come to learn a lot about some of the various intricacies that Internet Explorer has as well as the browser control in general.

Because we're not running some of our web pages in Internet Explorer but in a custom web browser, unit testing frameworks like Watir and Watin won't work for us. They make use of the Internet Explorer COM application. Unless we want to fork one of those frameworks as well as provide an automation interface into our custom browser, I don't see either of those frameworks working for us.

However, Selenium will work fine!

Selenium runs in the browser!

image

That's a picture of a little WinForms application I put together that is hosting the WebBrowser control. As you can see, all but one of shipped Selenium tests passed (the only one that failed had to do with opening an XHTML page).

Looks pretty good to me!

posted on Tuesday, August 07, 2007 12:51:25 PM (Central Standard Time, UTC-06:00)  #    Comments [0]
 Thursday, August 02, 2007

(note - if you're reading this in a feed reader like Google Reader, sorry - the code snippets look awful... if anyone has any suggestions on good ways to get code to look good in the webpage and feed readers, I'd appreciate it)

Given this:

    delegate void WorkDelegate();
    interface ISomeInterface
    {
        void Execute();
    }

 

What is the difference between this class

    class TestCaseOne
    {
        ISomeInterface something = Activator.GetObject(typeof(ISomeInterface), "http://some.url.com/") as ISomeInterface;

        public TestCaseOne()
        {
            BackgroundWorker wkr = new BackgroundWorker();
            wkr.DoWork += new DoWorkEventHandler(wkr_DoWork);
            wkr.RunWorkerAsync();
        }

        void wkr_DoWork(object sender, DoWorkEventArgs e)
        {
            something.Execute();
        }
    }

and this class?

    class TestCaseTwo
    {
        ISomeInterface something = Activator.GetObject(typeof(ISomeInterface), "http://some.url.com/") as ISomeInterface;

        public TestCaseTwo()
        {
            WorkDelegate dlg = new WorkDelegate(something.Execute);
            dlg.BeginInvoke(MyCallback, new object[] { dlg });
        }

        private void MyCallback(IAsyncResult iar)
        {
            object[] asyncState = iar.AsyncState as object[];
            WorkDelegate dlg = asyncState[0] as WorkDelegate;

            dlg.EndInvoke(iar);
        }
    }

 

Both classes have a field named something that is a reference to an HTTP remoting proxy that has been published at http://some.url.com. Let's assume that the the HTTP Remoting configuration has already been set up. Both call the Execute method defined on the interface, but one is using a BackgroundWorker for threading and the other is using the BeginInvoke/EndInvoke means of threading. Big deal, right?

There isn't a huge difference just looking at the code -- except that with TestCaseOne, the remoting call will result in a blocked thread whereas TestCaseTwo will not. In TestCaseOne, the background thread will block on the something.Execute() call and wait for it to return. In TestCaseTwo, the WorkDelegate BeginInvokes on the transparent remoting proxy. There isn't any code to block on. Instead, the framework will let you know when your remoting call returns.

Why does this matter? When you have a blocked thread, you basically have wasted CPU cycles where it is blocking instead of working. This likely won't matter much if you're not working with a lot of threads, but it can cause performance problems if you're working with a lot of threads.

On the other hand, when TestCaseTwo calls back to let you know the remoting call has completed, it will not call back on the calling thread. BackgroundWorker is smart enough to invoke back to the UI thread if needed. Both have their pluses and minuses. The BackgroundWorker component does make the code a little more easy to read and it handles invoking back to the UI thread. However, if you're working with a lot of threads, you might try using the delegate approach instead, so as to avoid any blocked threads.

posted on Thursday, August 02, 2007 9:40:25 AM (Central Standard Time, UTC-06:00)  #    Comments [0]
 Monday, July 16, 2007

I was digging around my old posts and bookmarks and stumbled across my post on the Share Your OPML website from over a year ago. Whatever happened with that site? It quite literally hasn't changed since the service started as far as I can tell. I really like the idea and I wouldn't mind at all if the site added a few services or something. I went ahead and updated my OPML (which has literally doubled) and you can check it out here. If you've got an account with them, go ahead and update your list and then comment with a link to it.

Off-topic, but I wish that Google Reader would start adding some more features. I figure it would be easy to provide a way to subscribe to another users' shared OPML list (as opposed to just items that they mark as shared). Maybe no one else wants that feature, but I think it'd be cool. I already subscribe to a few del.icio.us bookmark feeds and shared feed items. Why not provide a feed that lets me know when someone adds a new feed to their list?

UPDATE:

One small thing to add - Matt brought up the point that there isn't an easy way to get an external link to your own shared OPML list. I've only found two ways to do this so far: 1) Use the "Who Subscribes To..." feature and look for a feed you subscribe to. 2) Google your name and optionally specify the site (site:share.opml.org).

posted on Monday, July 16, 2007 6:26:15 PM (Central Standard Time, UTC-06:00)  #    Comments [3]

I'm pretty excited this year, because I'll be going to my first developer conference. devLink 2007 will be held in Nashville, TN on October 12 and 13. You can't beat the return that you'll get from this conference because, for the low, low price of $50, you'll get to hear from such speakers at Brad Abrams, Scott Bellware, Jean-Paul S. Boodhoo, and Rockford Lhotka just to name a few. All this for $50!!!

Even if you can't get your employer to pay for this conference (I don't know if mine is or not yet), it would still be worth it to check this out. Besides, you can go see the Parthenon while in Nashville. Having seen the original, I'd say Nashville's copy is pretty cool, too.

Evan Hoff posted about the conference and his post already has 13 kicks on DotNetKicks, so excitement about the conference is building. Sign up now!

Leave a comment or email me if you're planning on going. It'd be great to meet some of the other developers out there. 

posted on Monday, July 16, 2007 12:18:35 PM (Central Standard Time, UTC-06:00)  #    Comments [2]
 Friday, July 13, 2007

Visual Basic annoys me because of the way arrays are initialized.

What's the semantic difference between the two lines of code below?

C#

int[] test = new int[10];

VB.NET

Dim test(10) As Integer

Here's a hint - one array has ten items and one does not. The VB.NET array has eleven elements. When you declare an array in VB.NET, you're specifying the upper bounds of the array instead of the length. This drives me insane. We regularly go between C# and VB.NET and I am constantly bit by this one.

I was talking with a guy at work today and we discussed how we'd like to have another option setting (in addition to Option Strict and Option Explicit) available for VB.NET:

Option OperateLikeAllOtherLanguages = True

This setting would allow VB.NET to initialize arrays like all other languages.

NOTE: This post is satire. I still like to program in VB.NET and C#. I do not want to get into which language is better. Both languages have their virtues. Learn them both. Then go learn Ruby.

posted on Friday, July 13, 2007 1:02:19 PM (Central Standard Time, UTC-06:00)  #    Comments [1]