Archive for the ‘All’ Category

a generic one-to-one mapping class

Wednesday, September 17th, 2008

Another “tip/trick” style post, but thought it may prove useful to someone (or so I can find it again later!)…

Sometimes I find myself needing to map instances/values of one type to another.  For example, on my current project we have an enumeration in our communications layer, and a VERY similar one in the domain layer.  The reason for this is so we don’t have to be referencing the communications layer version all over in the domain code.  So, there is naturally a one to one mapping between these enumerations.

Consider the following enumerations:

enum Polygons
{
    Triangle,
    Rectangle,
    Pentagon,
    Other
}

enum NumSides
{
    Three,
    Four,
    Five,
    More
}

This is the code I usually write to solve this problem:

private Polygons MapShapes( NumSides sides )
{
    switch( sides )
    {
        case NumSides.Three:
            return Polygons.Triangle;
        case NumSides.Four:
            return Polygons.Rectangle;
        case NumSides.Five:
            return Polygons.Pentagon;
        case NumSides.More:
            return Polygons.Other;
        default:
            throw new NotSupportedException(
                string.Format( "Mapping to Polygons from NumSides value {0}
                    is not supported", sides.ToString() ) );
    }
}

private NumSides MapShapes( Polygons polygon )
{
    switch( polygon )
    {
        case Polygons.Triangle:
            return NumSides.Three;
        case Polygons.Rectangle:
            return NumSides.Four;
        case Polygons.Pentagon:
            return NumSides.Five;
        case Polygons.Other:
            return NumSides.More;
        default:
            throw new NotSupportedException(
                string.Format( "Mapping to NumSides from Polygons value {0}
                    is not supported", polygon.ToString() ) );
    }
}

It turns out we had 3 said enumerations.  So picture the above, copied 3 times.  This thing was just begging for abstraction!

I came up with a Generic (proper) Map class that you can add mappings to and retrieve the corresponding mapped value of the other type… both directions.  Here is the implementation:

public class Map
{
    private Dictionary _oneToTwo;
    private Dictionary _twoToOne;

    public Map()
    {
        _oneToTwo = new Dictionary();
        _twoToOne = new Dictionary();
    }

    public Map Add( Type1 value1, Type2 value2 )
    {
        _oneToTwo.Add( value1, value2 );
        _twoToOne.Add( value2, value1 );
        return this;
    }

    public Type1 this[Type2 value]
    {
        get
        {
            if( !_twoToOne.ContainsKey( value ) )
            {
                throw new NotSupportedException(
                    string.Format( "Mapping from type {0} to type {1} with
                                    value {2} is not defined",
                        typeof( Type2 ).Name,
                        typeof( Type1 ).Name,
                        value.ToString() ) );
            }
            return _twoToOne[value];
        }
    }

    public Type2 this[Type1 value]
    {
        get
        {
            if( !_oneToTwo.ContainsKey( value ) )
            {
                throw new NotSupportedException(
                    string.Format( "Mapping from type {0} to type {1} with
                                    value {2} is not defined",
                        typeof( Type1 ).Name,
                        typeof( Type2 ).Name,
                        value.ToString() ) );
            }
            return _oneToTwo[value];
        }
    }
}

And, here it is in action:

Map<NumSides, Polygons> shapeMap = new Map<NumSides, Polygons>()
                                    .Add( NumSides.Three, Polygons.Triangle )
                                    .Add( NumSides.Four, Polygons.Rectangle )
                                    .Add( NumSides.Five, Polygons.Pentagon )
                                    .Add( NumSides.More, Polygons.Other );

// shape1 value is Polygons.Rectangle
Polygons shape1 = shapeMap[NumSides.Four]; 

// shape2 value is NumSides.Three
NumSides shape2 = shapeMap[Polygons.Triangle];

This not only works with enumerations, but any type.  I see an extension to this possibly allowing for a default mapping, and possibly constraining Type1 and Type2 to be IComparable or something like that as well, so you can have more control over your matching than whatever the default matching behavior that the Dictionary uses is.

That’s it… enjoy!

looking for a better switch/case statement?

Thursday, September 4th, 2008

I find myself sometimes wishing I had a better switch/case construct in C#.

My requirements of “better” are:

  • Case statements are automatically scoped
  • I can switch on more than simple types
  • I can have custom logic for my matching criteria

But why not just use if/else if/else…?

Good question, I’m glad you asked! However, I don’t have an excellent answer other than personal preference. if/else if/else is okay sometimes, but other times I have a deterministic set of conditions, and a switch type construct feels more symmetrical to me. I loves me some symmetric feeling code, it just feels cleaner somehow.

So I’ll present a somewhat contrived example just so you can see what the usage looks like, then we’ll see the code.

Usage


public void DoSomething()
{
	object foo = new object();
	object bar = new object();
	object baz = new object();

	Switch<object>.On(baz)
		.Case(x => x.Equals(foo), () =>
		{
			Console.WriteLine("came into foo case");
		})
		.Case(x => x.Equals(bar), () =>
		{
			Console.WriteLine("came into bar case");
		})
		.Default( () =>
		{
			Console.WriteLine("came into default case");
		})
		.Go();
}

The output from the above, is as you’d expect, the default case, since baz wasn’t equal to foo or bar.

Implementation


public class Switch<T>
{
	private T _target;
	private List<KeyValuePair<Predicate<T>, Action>> _cases;
	private Action _default;

	public static Switch<T> On(T target)
	{
		return new Switch<T>(target);
	}

	public Switch(T target)
	{
		_target = target;
		_cases = new List<KeyValuePair<Predicate<T>, Action>>();
	}

	public Switch<T> Case(Predicate<T> @case, Action action)
	{
		_cases.Add(new KeyValuePair<Predicate<T>, Action>(@case, action));
		return this;
	}

	public Switch<T> Default(Action action)
	{
		_default = action;
		return this;
	}

	public void Go()
	{
		foreach(var @case in _cases)
			if (@case.Key(_target))
			{
				@case.Value();
				return;
			}
		if (_default != null)
			_default();
	}
}

The only part I don’t really like is having to kick it off with the Go() at the end. Any ideas for a better way to kick it off, or at least a better name for it (instead of Go).

Feedback? Ideas?

Update

Paul had a great idea a couple great ideas (see comments) on how to get rid of the Go() at the end, and to force Default to only appear at the end. Here is the new implementation. Usage is the same, just remove the Go().


public class Switch<T>
{
	private T _target;
	private bool _alreadyMatched;

	public static Switch<T> On(T target)
	{
		return new Switch<T>(target);
	}

	public Switch(T target)
	{
		_target = target;
		_alreadyMatched = false;
	}

	public Switch<T> Case(Predicate<T> @case, Action action)
	{
		if (!_alreadyMatched && @case(_target))
		{
			_alreadyMatched = true;
			action();
		}
		return this;
	}

	public void Default(Action action)
	{
		if (!_alreadyMatched)
		{
			_alreadyMatched = true;
			action();
		}
		return this;
	}
}

tfs - using winmerge as your merge/diff tool

Tuesday, August 26th, 2008

If you’re used to using something like winmerge with your SCM of choice, if you wind up using TFS, the built-in diff/merge tools can leave much to be desired.

Here is how to change the tool VS 2kX uses to do diffs/merges when hooked up to TFS (note that these are my settings for using winmerge for ALL file types):

Go To: Tools/Options/SourceControl/Visual Studio Team Foundation Server/Configure User Tools

Click “Add…”
Extension:  .*
Operation: Compare
Command: C:\Program Files\WinMerge\WinMergeU.exe
Arguments: /e /wl /dl %6 /dr %7 %1 %2
Click “Add…”

Extension:  .*
Operation: Merge
Command: C:\Program Files\WinMerge\WinMergeU.exe
Arguments: /ub /dl %6 /dr %7 %1 %2 %4

The winmerge command line reference can be found here.

tfs - error exporting queries to excel

Tuesday, August 26th, 2008

Starting my new project in a new role, as project lead, I need to be managing things in TFS.  The UI for batching these things up is nonexistent, but there is Excel integration so you can do it all in Excel, hit save, and it all goes back to the TFS server… pretty slick I must say (I was actually in the midst of writing such a tool when I realized this functionality already existed OOB).

However, the first time I tried to use this functionality… BLAM, I get smacked with this:

TF80042: The document cannot be opened because you do not have Microsoft Excel 2003 or later, or one of its components installed. For more information, see the Team Foundation Installation Guide.

Isn’t that teh suck?

Anyways, there is a sweet write-up on how to fix it here: http://blogs.microsoft.co.il/blogs/srlteam/archive/2007/07/17/Error-when-trying-to-export-queries-to-Excel.aspx.

Thanks Elad!

Going Medieval on Your App with Castle MonoRail - Indy ALT.NET

Friday, August 22nd, 2008

So last night I gave a talk at Indy ALT.NET on Castle MonoRail.  It was really just a sort of intro to MonoRail type of deal, but the cool part was that we held a Dojo after I got done jabbering.

We ended up building a Poll Generator for our dojo activity.  We almost got done in the 45 minutes or so that we dojo’d.  It was a pretty fun activity, and I’d like to do it again sometime soon.

Also, this was really my first public speaking engagement to our technical community, and let me say it was a blast.  Everyone had great things to say, and many great questions were asked too.

I set up a google code repository so you can grab my slidedeck and grab the source for our dojo activity and my demo app.

Maybe next time I’ll post before the talk, so I can let people know about it.

Thanks guys for all the great feedback, and thanks to my wife for understanding why I wasn’t spending any of my evenings with her this week!

singly implemented interface… addendum

Friday, August 22nd, 2008

Wowza!  So I’ve begun reading LosTechies (tons of great content, highly recommended!), and came across a passage today from Jimmy Bogard, who says what I feel, but what I couldn’t get out of my head:

On a sidenote, it always bothered me when people say that an interface with one implementation is a design smell.  No, an interface is used to expose a contract.  Interfaces communicate design intent, far better than a class might.

Exactly!

indy alt.net

Friday, May 16th, 2008

The inaugural indy alt.net meeting was last night!

The group appears to be led up by jaxidian/Shane Milton of Leaf Software Solutions.  Many thanks to Shane for getting this group together!  I think this is an awesome opportunity for our community to learn how to be more receptive to alternative thinking in a .NET world.  I have heard of so many shops that have their blinders on and won’t even consider working with frameworks/etc. other than those provided by Microsoft.  This can only be a true blessing to our community and where we are going as craftsmen.

Don’t get me wrong, I’m not dissing Microsoft, they make world-class software.  The problem is that we need to be careful to always use the best tools that serve us in any given situation, rather than using only the tools that we are told to use via the mothership.

Last night’s discussion was led by one of the co-founder’s of Entity Spaces.  Their product, Entity Spaces, is a code generation based ORM tool.  I’m very familiar with the concept, but haven’t had much of an opportunity to use many ORM’s other than ActiveRecord in a Rails project I worked on, so I’m not sure how the usual suspects (NH/ActiveRecord, Linq2Sql, Linq2Entities, SubSonic) add up in a real implementation scenario, but it’s at least worth thinking about.  Maybe I’ll do a write up or try to find a comparison.

Also, many thanks to Tridge Alliance for their financial support of the group.

All-in-all, it was a great inaugural meeting.  I am sure we’ll only continue to grow and get better.  If you’re reading, and are in the area, and feel like you’re missing something (sort of like Neo, ya know?) please come and see what we’re all about!  We meet the third Thursday of every month.  Check the website for more info.

I’m stoked!  Let’s make our tech community a better place!

singly implemented interface… why/why not

Friday, May 16th, 2008

So one of the things I’ve noticed since I’ve been at my new place of employment, is that people are passionate about their code!  I love it!  I have always been, and its great to be in a place where everyone else is as passionate about it as I am.

Onto the issue at hand.  Along with passion, comes strong opinions (of course).

Statement: I always want to create an interface for any service or class that collaborates with other services or classes.

Why? 

Testability.

IMO (I’ve got one too!), testability is THE first class citizen (second only to working, value-adding software).

Having an interface on any collaborating service provides me the ability to (at least):

  • TDD
  • Test after the fact
  • Swap in a new implementation later
  • Low-friction

Why not? (my response to each in red)

  • YAGNI - "Why do you need an interface if there is only one implementer?  We’ll create the interface or base class when there is a second implementer".
    There already is a second implementer… the tests!  Nuff said. (which is a nice segue into the next point…)
  • Testability should not affect the design.
    Ahem, isn’t our goal working software?  How do I know it works if I can’t write tests for it?  This directly opposes the entire idea of TDD.  TDD is not so much about testing, as it is about it being a design tool.
  • Just "subclass and override".
    Have you ever read Working Effectively with Legacy Code?  This is the epitome of a legacy code technique

Dear reader (I doubt there are any),

What do you think?  Are there things I missed on either side of the equation?  I want your opinions.

Audience

Monday, January 15th, 2007

It is funny how ‘a-ha moments’ happen at random times and on random topics.  The other day I was walking back from the water cooler at work, and doing some critical thinking as I was (yes!  I can do two things at once, even though Sandi doesn’t think I can!).

Anyways, I had a realization of how when my English teachers in high school (thank you Mr. Stephens and Mrs. Baldwin) harped on the taget audience for a particular essay, that the topic audience isn’t really specific to writing essays, it lends itself to many walks of life…  especially writing software. 

Many people talk about Microsoft always catering to the LCD (even Mark recently did!) and how the *nix community is usually the opposite.  The conversation usually (at least with tech-types) is that the level of control given by *nix is the right mix of simplicity and control.

Ahem… I beg to differ… or do I?

Maybe you’ll think I’m just trying to walk the line (because you’re mine?), but I don’t think so.  I think it all depends on who you’re trying to reach as to what ‘denominator’ you cater to.  Obviously its hard for Microsoft to hit it right, for example, with the Vista shutdown menu, when their target audience is EVERYONE.  That includes me, you, Grandma’s, 5-year olds and anyone else.  It’s easier for *nix to get it ‘right’, because they have a much more narrow audience.

I’ll be the first to confess I have a heck of a time when designing the front-end of an app, and that is mostly due to audience.  Part of my job requires that I lay out new UI’s when I add new functionality to our product.  Believe you me, I am no graphical designer or usability expert.  I usually want to lay it out and build as if I were using it… however, apparently engineers aren’t the typical user-base of debt-collection software.  However, when I write tools (I am often times the Toolsmith for my team as well) that are meant for engineers, I have a completely different audience and an entirely different set of assumptions when laying out the UI that is much more native to my own.  It’s a learning process, and I am definitely still on the climb up the curve.

Mock Objects… Firing Events

Monday, December 4th, 2006

UPDATE: I finally am posting the source here!

It has been long enough since I’ve made my last post, but with the recent posting from Eli’s blog about TypeMock on Firing Events when mocking/testing, I thought I would throw out my solution to this problem for those of us using NMock2.

If you’re not familiar with mock objects, there is some great content out there, just google it (you didn’t think I was actually going to explain them here did you?!)

First off, I love NMock2.  It does what I need and stays out of my way.  The syntax is terse and flows like prose.

On with the content!

Part 1: Ready

It seems obvious to me, that if you’re using mock objects, you’re most likely going to run across a mock that needs to fire an event.  It’s almost like the NMock2 guys completely skipped over this use case (but I’m not knocking them, this is a great product).  After digging around in reflection trying to figure how to do what I wanted and discussing it with a colleague of mine, I was turned on to the idea of using Custom Actions to catch the event add’s and remove’s [part 1] and store them off for invocation later (when the event is actually fired) [part 2].

Part 2: Aim - Catching the Event Add’s and Remove’s

The great thing about a custom action (type IAction), is that you get all sorts of information about the thing that actually got invoked.  In our case, the adder or remover of an event.  Similar to properties, the add/remove ‘accessors’ are compiled into methods just like the get/set accessors.  The naming of these generated methods is also similar.  For a property’s get/set, the names look like:

get_<PropertyNameHere>

set_<PropertyNameHere>

Likewise, for the add/remove ‘accessors’ for an event get names:

add_<EventNameHere>

remove_<EventNameHere>

Armed with this information, we can tell if the method being called is an event adder/remover.  The syntax for catching an event add is as such:

Expect.Once.On(mockButton).EventAdd("Click",

 Is.Anything).Will(Catch.EventAdd);

Similarly, event removal looks like:

Expect.Once.On(mockButton).EventRemove("Click",

 Is.Anything).Will(Catch.EventRemove);

Part 3: Fire!

Great!  We know when events are added!  But wait, it still seems like we haven’t gotten anywhere (but really we have).  The Catch.EventAdd takes the method that got called (add_Click), and grabs the single argument from the method call which happens to be an EventHandler type delegate (in this case), and stores it off to be invoked later when the event gets fired.

Event.Fire("Click").On(mockButton).With(this,

 EventArgs.Empty);

This call invokes all of the methods that were caught when being added to the mockButton’s Click event with the given parameter values.

Often times it is useful for an event to be fired when some other mocked method gets called.  For this case, a custom action should suit just fine; simply pass it into the Will portion of your expectation/stub setup for that particular method.  That means, as soon as the mocked method gets called, the event will fire just as if the above line of code was executed.

Expect.Once.On(mockButton).Method("PerformClick").

Will(Event.Fire("Click", mockButton, this,

  EventArgs.Empty));

Here is a complete example that pulls it all together:

   interface IButton

   {

      event EventHandler Click;

 

      void PerformClick();

   }

 

   class ButtonTester

   {

      private bool clicked;

 

      [SetUp]

      public void Setup()

      {

         clicked = false;

      }

 

      [Test]

      public void TestButtonFire()

      {

         Mockery mocker = new Mockery();

         IButton mockButton = mocker.NewMock(typeof(IButton)) as IButton;

         Expect.Once.On(mockButton).EventAdd("Click", Is.Anything).Will(Catch.EventAdd);

 

         // Normally exercise domain code here,

         // but we’ll keep it simple and inline.

         mockButton.Click += delegate(object sender, EventArgs args) { clicked = true; };

 

         Event.Fire("Click").On(mockButton).With(this, EventArgs.Empty);

 

         Assert.IsTrue(clicked);

         mocker.VerifyAllExpectationsHaveBeenMet();

      }

 

      [Test]

      public void TestPerformClick()

      {

         Mockery mocker = new Mockery();

         IButton mockButton = mocker.NewMock(typeof(IButton)) as IButton;

         Expect.Once.On(mockButton).EventAdd("Click", Is.Anything).Will(Catch.EventAdd);

         Expect.Once.On(mockButton).Method("PerformClick").Will(Event.Fire("Click", mockButton, this, EventArgs.Empty));

 

         // Normally exercise domain code here,

         // but we’ll keep it simple and inline.

         mockButton.Click += delegate(object sender, EventArgs args) { clicked = true; };

 

         mockButton.PerformClick();

 

         Assert.IsTrue(clicked);

         mocker.VerifyAllExpectationsHaveBeenMet();

      }

   }

Thats it.  This stuff is currently unreleased, but feel free to send requests, I’ll gladly send a copy.