I was trying to install the Application Block Software Factory, part of Enterprise Library 3.1, the other day, and I ran into a problem. During the installation, I got a failure stating that the necessary installer types could not be found in "c:\program files\Microsoft Visual Studio 8\common7\ide\Microsoft.Practices.EnterpriseLibrary.BlockFactoryInstaller.dll". I was instructed to see the LoaderExceptions property of the exception for details.
Huh? How in the world was I supposed to see this property of an exception that I didn't even have access to?????
Powershell to the rescue
Hmmm, I thought. Based on a previous blog posting, I remember that I found a way to load an assembly from a file, and I knew that I could inspect the types in an assembly once it was loaded. Maybe I could follow this process to learn something about what was happening.
So, I fired up powershell, and typed in the following command (note that I'm at home and not at work in front of the PC where I did this. The paths are as close as I can remember...)
$assembly = [System.Reflection.Assembly]::LoadFile("c:\program files\Microsoft Visual Studio 8\common7\ide\Microsoft.Practices.EnterpriseLibrary.BlockFactoryInstaller.dll")
Once I had the assembly loaded like this, I used its GetTypes() method to inspect the types in the assembly, and that's when I got the same exception as before.
After a little investigation, I came across the $Error special variable, which seems to hold an array of the last exceptions through during powershell execution. I was able to get to the exact exception I saw at the command line through this variable by typing $Error[0].
I investigated further by using the get-member cmdlet, as
$Error[0] | get-member
which told me that the object returned from $Error[0] had an Exception property on it. I followed on a bit, and looked at the members of the exception I could get to using $Error[0].Exception. Here, it turned out, there was a property called LoaderExceptions, which was the exact property that I had been instructed to see by the error message.
Looking at that property as:
$Error[0].Exception.LoaderException[0]
gave me the exact right answer. It was looking for Microsoft.Practices.Recipes.dll, an assembly loaded by GAX, but it couldn't find it. I searched for that assembly, and I did eventually find it, but it was installed beneath Orcas, not Whidbey, both of which I had installed on my machine.
The solution
So, to make a long story short, I reinstalled GAX, this time installing it for VS.Net 2005, and all was well. I was able to install the Enterprise Library in its entirety, and I was able to proceed.
But, without the ability of powershell to let me iteratively understand what was happening, and explore the objects involved, I don't know how I would have otherwise solved this problem.
-- bab
I had what was probably an obvious insight the other day while I was working on my project alone. I'm a team of one, which kind of gets in the way when it comes to pairing. This, unfortunately, has an effect on my final code.
Good pairs are adversarial
When you find yourself pairing with someone really good, it can almost feel adversarial. What I mean by that is that you can get into a rhythm where one person writes a test, intending to lead his partner down the road of writing a particular piece of code. His partner, however, can write something entirely different that still causes the test to pass.
This back and forth dance between tester and implementer forms the basis of good micro pairing sessions. In these sessions the tester/driver intends to lead the implementer down a particular path, but the implementer has the option of following another way, forcing the test writer to write another test, trying to drive the implementer down the intended path, and so on.
This leads to particularly good code, as the code that is written is usually the least code possible to implement the functionality, and the tests that are written thoroughly cover the functionality that was intended. It's really cool to watch this work.
If you're a pair of one...
If you happen to be working by yourself, it is very difficult to simulate this tension between test authoring and application implementation. At least, from my point of view, what happens is that I do write the code I want to test to lead me to, regardless of whether or not there is a simpler way to get the test to pass. I think it is natural to do this, since you're trying to play both sides of the partnership.
I think code I write without a pair is inferior to code I create with a partner, for this exact reason. We didn't fight over the minimal implementation, which leads to still good code, but not the glory that is fully paired/TDD code.
There ain't nothing better.
-- bab