Wednesday, April 23, 2008

Iterating Through "My.Resources"

The "My" namespace in VB.NET is indispensable. Settings and resources among other things can be easily accessed by using it. You can place items such as files or images in "My.Resources" and access them in your code in a very simple manner: 

Dim MyObject As Object 

MyObject = My.Resources.ObjectName

However, iterating through My.Resources is another issue. You might think you could do it this way:

For Each Object In My.Resources 
   'more code here 

You can't. "My.Resources" is a namespace and not a collection that implements IEnumerable. So what do you do? You have to enumerate the objects in "My.Resources" if you want to iterate through them. I started out on the MSDN forums looking for a starting point and I came up with this implementation:

Public Function GetMyResourcesDictionary() As Dictionary(Of String, Object) 
  Dim ItemDictionary As New Dictionary(Of String, Object) 
  Dim ItemEnumerator As System.Collections.IDictionaryEnumerator 
  Dim ItemResourceSet As Resources.ResourceSet 
  Dim ResourceNameList As New List(Of String) 

  ItemResourceSet = My.Resources.ResourceManager.GetResourceSet(New System.Globalization.CultureInfo("en"), True, True) 

  'Get the enumerator for My.Resources 
  ItemEnumerator = ItemResourceSet.GetEnumerator 

  Do While ItemEnumerator.MoveNext 

  For Each resourceName As String In ResourceNameList 
    ItemDictionary.Add(resourceName, GetItem(resourceName)) 

  ResourceNameList = Nothing 

  Return ItemDictionary 
End Function 

Public Function GetItem(ByVal resourceName As String) As Object 
  Return My.Resources.ResourceManager.GetObject(resourceName) 
End Function

The reason I did it this way was so that I could call GetMyResourcesDictionary once and I'd have a Dictionary object that I could iterate through.

Tuesday, April 15, 2008

Unit Testing (Part 2)

Our team aims for at least 70% code coverage with our unit tests.  I've read that quite a few people only test public methods as the private methods will eventually be reached this way. From my experience this isn't always the case.

We use Visual Studio 2008's built in unit testing framework.  The nice thing about this framework is that it's integrated into the IDE and simply right-clicking on a method or class will bring up options to create unit tests.  Along with this, accessor classes are created so that you have access to private fields and methods.

I test both public and private methods just to be exhaustive. Sometimes I run into conditional statements that I can't test fully without the class accessors.  I've hit 80%+ code coverage on my current project, but I will be looking into white to test the UI in my project as well. This will certainly boost code coverage.

Order matters in unit tests.  For example, I have classes that depend on other classes to work.  The unit test stubs that get inserted by the IDE do not account for this, it merely gives you a very trivial skeleton.  It is up to you to make sure that you have all of the dependent classes instantiated before testing the class that you actually want to test.

Monday, April 14, 2008

Unit Testing (Part 1)

I've heard about unit testing before I started here at KPMG, but had zero experience with it.  My software developer friends have experience with unit testing because most of them are part of huge development teams and deal with mission critical software.  I understood the concept, but really didn't understand its value... until I added unit testing to my current project.

I'll be honest, I don't find writing unit tests fun.  I'd much rather be developing new stuff or even fixing bugs, but I found numerous bugs that I wouldn't have found without unit tests. Users would most likely have found these bugs while using the application which would require tracking the issue, fixing the problem, testing the solution, and finally releasing a new version.  This is a lot of time (and money) wasted.

Thursday, April 10, 2008

Generic Lists and LINQ

When LINQ was introduced I was pretty uninterested. I thought to myself, "what's the point?" Well, after using it I think it's an invaluable part of the .NET Framework.

Ever since our team was given the go to update our environment to VS 2008 and .NET 3.5, I've been including LINQ in my current project. Granted I'm only using LINQ to objects, but I see myself using LINQ to XML when I come to that point.

I use Generic Lists all over the place in my project. Today I ran across something I found interesting while I was doing something that required copying of a List. Copying List contents to another List without LINQ is pretty simple.

Dim CopyList As New List(Of Object)


Now with LINQ, you can use the ToList extension method and you don't have to create a New CopyList up front.

Dim CopyList As List(Of Object)

CopyList = OriginalList.ToList

Also, from my testing (admittedly light and crude) the ToList extension method is faster at completing the copy.

Tuesday, April 8, 2008

MS Team Foundation Server / Team Build (Part 2)

Creating a stand alone setup.exe/msi wasn't as easy for me as it should have been. Following Microsoft's suggestion of adding the .vdproj file to my "AfterCompile" target in my TFSBuild.proj file did not work; I got a compile error.

<Target Name="AfterCompile"> 
    <Exec Command="&quot;C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\devenv&quot;&quot;$(SolutionRoot)\HelloWorldTest\HelloWorldTestInstaller\HelloWorldTestInstaller.vdproj /Build &quot;Debug|Any CPU&quot;"/> 
    <Copy SourceFiles="$(SolutionRoot)\HelloWorldTest\HelloWorldTestInstaller\Debug\HelloWorldTestInstaller.msi" DestinationFolder="$(OutDir)" /> 
<Copy SourceFiles="$(SolutionRoot)\HelloWorldTest\HelloWorldTestInstaller\Debug\setup.exe" 
DestinationFolder="$(OutDir)" /> 
What I ended up doing was replacing the .vdproj file with the entire .sln file. Then I copied the setup.exe and .msi files out to the specified drop directory.
<Target Name="AfterCompile">
    <Exec Command="del &quot;$(OutDir)*&quot; /q" />
    <Exec Command="&quot;C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\devenv&quot; &quot;$(SolutionRoot)\Project.sln&quot; /Build &quot;Debug|Any CPU&quot;" />
    <Copy SourceFiles="$(SolutionRoot)\ProjectSetup.msi" DestinationFolder="$(OutDir)" />
    <Copy SourceFiles="$(SolutionRoot)\setup.exe" DestinationFolder="$(OutDir)" />

MS Team Foundation Server / Team Build (Part 1)

I've had to setup my current project at work so that it uses TFS's build automation. "F5 is not a compile solution" as I've been told by my boss. I completely agree with this because I've run into the whole "well it works on my machine" syndrome many times.

Having a dedicated server to compile my solution gives me a better grasp of how things would work on a machine that didn't have all of my development tools on it (aside from what's required by Team Build).

I also had the pleasure (more like pain) of upgrading my TFS 2005 build script to 2008 when we upgraded. This in itself is really simple to do, you just simply move it on over and TFS 2008 just runs the 2005 version in compatibility mode.

However, I didn't want to just run an older version so I just copied out the part that I wanted from the 2005 version, re-ran the wizard to build a 2008 version, and pasted the chunk of text. Much to my disappointment, the build script didn't work anymore.

I looked at my file over and over again. I and others on the MSDN forums found nothing wrong with it. Finally, it was suggested I just delete the TFSBuild.proj file on the build server so that TFS copies it to the build server again... it worked.

Lesson learned: be sure to check out the TFSBuild.proj file when making edits and don't modify in memory if that message box comes up. I spent a good part of a whole week trying to figure out why it wasn't working.

Monday, April 7, 2008

My first post...

My boss suggested I share my software development experiences (aka trials and tribulations) from work. This blog will be my medium to do that. I will share things that I've learned and gone through to possibly ease someone else's pain.