April 25, 2008
@ 12:35 PM

Based on my last post, I have decided my course of action should be to attempt to override the _ResolveReferences target supplied to me by Web Deployment targets build file.

A quick Google search lead me to Jomo Fisher's blog post titled "Hack the Build: Target Overriding Step-by-Step". A quick read through and I was ready to proceed.

First I opened the Microsoft.WebDeployment.targets file provided by they Web Deployment project. The default location of this file is C:\Program Files\MSBuild\Microsoft\WebDeployment\v8.0\. I copied the target xml for resolving references to the clipboard.

Next I opened my solution, right clicked on my web deployment project and selected Open Project File. This opens the MSBuild script file for the specific project I wish to override a target in. This is an important distinction because placing the override in the main TFSBuild.proj file is to late in the build process and will net you nothing.

I then pasted my new target into the project file near the end. My new target looks like this:

    <Target Name="_ResolveReferences" 
            DependsOnTargets="_PrepareForBuild;GetFrameworkPathAndRedistList">
        <Message Text="Overriden in NAMESPACE.Service Web Deployment Project." />
        <CreateItem Include="$(_FullSourceWebDir)\Bin\*.refresh">
            <Output TaskParameter="Include" ItemName="References_RefreshFile" />
        </CreateItem>
        <ReadLinesFromFile File="%(References_RefreshFile.Identity)" 
                           Condition=" '%(References_RefreshFile.Identity)' != '' ">
            <Output TaskParameter="Lines" ItemName="References_ReferenceRelPath" />
        </ReadLinesFromFile>
        <CombinePath BasePath="$(_FullSourceWebDir)" Paths="@(References_ReferenceRelPath)">
            <Output TaskParameter="CombinedPaths" ItemName="References" />
        </CombinePath>
        <Copy SourceFiles="@(References->'%(FullPath)')" 
              DestinationFolder="$(_FullSourceWebDir)\Bin\" 
              Condition="!Exists('%(References.Identity)')" ContinueOnError="true" />
        <ResolveAssemblyReference Assemblies="@(References->'%(FullPath)')" 
                                  TargetFrameworkDirectories="$(TargetFrameworkDirectory)" 
                                  InstalledAssemblyTables="@(InstalledAssemblyTables)" 
                                  SearchPaths="{RawFileName};{TargetFrameworkDirectory};{GAC}" 
                                  FindDependencies="true" 
                                  FindSatellites="true" 
                                  FindSerializationAssemblies="true" 
                                  FindRelatedFiles="true" 
                                  Condition="Exists('%(References.Identity)')">
            <Output TaskParameter="CopyLocalFiles" ItemName="References_CopyLocalFiles" />
        </ResolveAssemblyReference>
        <Copy SourceFiles="@(References_CopyLocalFiles)" 
              DestinationFiles="@(References_CopyLocalFiles->'$(_FullSourceWebDir)\Bin\%(DestinationSubDirectory)%(Filename)%(Extension)')" />
    </Target>

Note that this is the exact logic from the web deployment targets file. I also added a message node to alert others to the fact that I have overridden this target and given the location of the override.

For this specific project the list of @(References) that is generated by this script incorrectly maps my two messaging libraries. I have *.refresh files for them, but they point to a common folder on the developers machine that does not exist on the build server. To remedy this I added the following code just after the call to CombinePath that generates the @(References) list and just prior to the Copy element:

<CreateItem Include="D:\Build\Build Common\Binaries\Release\Lib.*.dll">
  <Output TaskParameter="Include" ItemName="Messaging_Libraries"/>
</CreateItem>
<CreateItem Include="@(References);@(Messaging_Libraries)">
  <Output TaskParameter="Include" ItemName="NewReferences"/>
</CreateItem>

This allowed my build to successfully complete on the build server. Oddly enough, in the Build steps list the Compiling sources line item has a red X icon even though the compile had no problems. Trolling through the BuildLog I found that the Copy node was throwing errors that were converted to warnings, because the original list of references contains incorrect paths for the messaging DLLs and it fails to copy them.

The copy node seems to be redundant logically, so I commented it out and my build script is complete and working again.

Next on the agenda, getting Team Build to not download my entire source tree to build a single solution. As I add things to source control my build times are getting a bit crazy.


 
Categories: Development | MSBuild

Over the course of the last week or so I have been working on migrating our source code over to TFS. In the process, I am reformulating our solutions, cleaning up garbage and creating automated build scripts.

Our application has five website projects and a hand full of supporting libraries. Using the Web Deployment Project addon, I was able to automate the build of these sites into a clean reproducible deployment.

My application is set up in source code in such a way that frameworks are separated from the actual application code. From the Main branch I have a Framework folder and an Application folder. The Framework folder contains the source code for the Enterprise Library Application Blocks, a vendor supplied library and a Lib folder for interop assemblies and various other compiled resources.

The Frameworks branch has its own build script. The idea is a developer opens up TFS finds the latest successful build of the framework and copies those assemblies to his local machine @ D:\Common. The goal being we are all using the same build of the framework libs and the developer doesn't need to worry about the source for frameworks unless a bug is identified. All applications that use framework assemblies have references set to the common folder.

After successfully migrating our web application over to TFS and getting the build working successfully, I moved on to migrating the applications windows services. These services are in their own solution and I plan to locate them into the application folder in TFS.

While reviewing the windows services solution, I noticed several applications that use messaging libraries that live in the web application solution. I decided to pull these two libraries out into their own solution and add them to the Framework build.

This is where the problems started. I was able to pull the libraries out and add them to the Framework build, but now any website project that references these libraries fails to build on the build server. The solution builds fine locally as I have *.refresh files that point to the Common folder.

Trolling through the BuildLog.txt it is pretty obvious why my build is failing. Target _ResolveReferences which is defined in Microsoft.WebDeployment.targets installed by the Web Deployment Project addon is not able to locate my two messaging assemblies.

My master build script has an AdditionalReferencePath defined, but the Web Deployment project targets seem to ignore this. I have attempted to copy the assemblies to the proper location at various points in the process (AfterGet, BeforeBuild) and have not had success. The libraries are in the proper place but because they reference other assemblies that need to be resolved the build fails.

I need to modify my build script so that it copies the libraries to the correct location and then resolves all references prior to build. This is my task for the day.


 
Categories: Development | MSBuild

The closer your documentation gets to a static Microsoft Word Document, the farther away from current it becomes.


 
Categories: Random

I recently laid my hands on a copy of DevExpress' Code Rush and Refactor! Pro. They have a section on their site that allows you to watch training videos about these products. I wanted to watch them all but at my own pace and on my main TV in the living room.

Using  my new toys I whipped up the following code to download all of the movies from their site. Now I just need to convert them to AVI so I can watch them on the Xbox.

Code included just because I want to:

using System;
using System.Text.RegularExpressions;
using System.Diagnostics;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Net;

namespace SnagDevExMovies
{
    class Program
    {
        private static WebClient client = new WebClient();
        private static Uri site = 
                new Uri(@"http://www.devexpress.com/Products/NET/IDETools/CodeRush/Training.xml");
        private static UriBuilder siteResource = new UriBuilder(site);
        
        static void Main(string[] args)
        {

           string content = getContent(site);
           MatchCollection URLs = getMatches(content, 
                new Regex(@"bWatchExpanded.*LessonNewWindow\('(?<URL>.*)'\)"));
           processMatches(URLs);
        }

        private static void processResource(Uri uri)
        {
            Debug.Assert(uri != null, "uri is null.");
            Debug.WriteLine(String.Format("Processing: {0}", uri));

            string content = getContent(uri);

            MatchCollection URLs = getMatches(content, new Regex(@"(?<URL>\w*\.swf)"));

            if (URLs.Count > 0)
            {
                siteResource.Path = getResourcePath(siteResource.Uri) 
                        + URLs[0].Groups["URL"].Value;
                downloadFile(siteResource.Uri);
            }
        }

        private static MatchCollection getMatches(string content, Regex expression)
        {
            Debug.Assert(!String.IsNullOrEmpty(content), "content is null or empty.");
            Debug.Assert(expression != null, "expression is null.");

            MatchCollection matches = expression.Matches(content);
            Debug.WriteLine(String.Format("{0} matches found.", matches.Count));
            return matches;
        }

        private static void processMatches(MatchCollection relativePaths)
        {
            Debug.Assert(relativePaths != null, "relativePaths is null.");

            foreach (Match item in relativePaths)
            {
                siteResource.Path = item.Groups["URL"].Value;
                processResource(siteResource.Uri);
            }
        }

        private static void downloadFile(Uri uri)
        {
            Debug.Assert(uri != null, "uri is null.");

            Debug.WriteLine(String.Format("Downloading: {0}", uri.ToString()));
            try
            {
                client.DownloadFile(uri, getFileName(uri));
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
            }

        }

        private static string getResourcePath(Uri uri)
        {
            Debug.Assert(uri != null, "uri is null.");

            string resourcePath = uri.AbsolutePath.Substring(0,
                                uri.AbsolutePath.LastIndexOf("/") + 1);
            return resourcePath;
        }

        private static string getFileName(Uri uri)
        {
            Debug.Assert(uri != null, "uri is null.");

            return uri.Segments[uri.Segments.Length - 1];
        }

        private static string getContent(Uri uri)
        {
            Debug.Assert(uri != null, "uri is null.");

            string content = client.DownloadString(uri);
            return content;
        }
       
    }
}

 
Categories: Development | Random

April 15, 2008
@ 05:26 PM

I recieved a fully licensed copy of Office Ultimate 2007 (Retail $454.99) last night at the Olympia Code Trip event. I would like to trade it straight across for a copy of Code Rush (Retail $249.99).

If you are interested please, feel free to contact me.

UPDATE: Trade made to Dylan in Issaquah. Thanks Dylan.
 

Categories: Local | Random

Map image
Come out to the Thurston County Fairgrounds on Monday night and get 3 hours of great information on new and exciting technologies from Microsoft and other sources.

Adam Kinney will present information on Silverlight 2.0. Woody Pewitt will talk about Internet Explorer 8 and the Code Trip Bus Cam. Jason Mauer will take us Under the Hood of the code Trip, explaining the technologies used on the bus and on the website.

Thousands of dollars worth of software will be given away from Infragistics (NetAdvantage for .NET), Telerik (RadControls for ASP.NET AJAX, RadControls for WinForms, Telerik Reporting,Sitefinity CMS), Identity Mine (Blendables Essentials Mix) and copies of CodeRush by Devexpress. Along with all of that goodness, there will be some foam Code Trip Buses and Code Trip Laptop sleeves given away. Free stuff and free high quality presentations -- you don't want to miss this.

To answer a question posed by some of you, sorry, no food this time, but grab something on the way out to the fairgrounds and stuff your face while while Jason, Woody and Adam stuff our brains full of new and shiny information.

Monday, April 14, 2008
6:30 PM to 9:30 PM
Olympia is the last stop for the Code Trip before the end of the line in Seattle. In partnership with the South Sound .NET User Group, they'll be pulling out all the stops and unleashing a technical tour de force at the Thurston County Fairgrounds.

Location

Thurston County Fairgrounds
Expo Hall
3054 Carpenter Rd SE


 
Categories: Development | Events | Local

The Liskov Substitution Principal (LSP) is a concept in Object Oriented Programming that states:

Functions that use pointers or references to base classes must be able to use objects of derived classes with out knowing it.

At it's heart LSP is about interfaces and contracts as well as how to decided when to extend a class vs. use another strategy such as composition to achieve your goal.

The most effective way I have seen to illustrate this point was in Head First OOA&D. They present a scenario where you are a developer on a project to build a framework for strategy games.

They present a class that represents a board that looks like this:

Board

All of the methods take X and Y coordinates as parameters to locate the tile position in the two dimensional array of Tiles. This will allow a game developer to manage units in the board during the course of the game.

The book goes on to change the requirements to say that the game frame work must also support 3d game boards to accommodate games that have flight. So a ThreeDBoard class is introduced that extends Board.

At first glace this seems like a good decision. Board provides both the Height and Width properties and ThreeDBoard provides the Z axis.

Where it breaks down is when you look at all the other members inherited from Board. The methods for AddUnit, GetTile, GetUnits and so on, all take both X and Y parameters in the Board class but the ThreeDBoard needs a Z parameter as well.

So you must implement those methods again with a Z parameter. The Z parameter has no context to the Board class and the inherited methods from the Board class lose their meaning. A unit of code attempting to use the ThreeDBoard class as it's base class Board would be very out of luck.

Maybe we should find another approach. Instead of extending Board, ThreeDBoard should be composed of Board objects. One Board object per unit of the Z axis.

This allows us to use good object oriented principals like encapsulation and reuse and doesn't violate LSP.

LSP is a good method for discovering if you are using inheritance poorly. Try it next time you go to extend a class.


 
Categories: Development | Fundamentals

Please join us on Thursday, April 10th for a presentation on NHibernate by Fred Hirshfield from Sierra Systems, Inc.

Presentation Summary:
"Relational databases and Object Oriented design sometimes conflict with each other making it somewhat difficult to make use of each technology the way they were intended. NHibernate is the *bridge* between these two technologies so that DBA's can manage and tune their database effectively and OOP designers and developers can manage their object model they way they need to and then use NHibernate to map these together.

This session will be an introduction to NHibernate and some of its features for mapping the object model to the database model. The demonstration solution will be made available after the session for those that would like to play around with it. We will explore the tool using a well known domain: Bug Tracking!

NHibernate (www.nhibernate.org):
NHibernate handles persisting plain .NET objects to and from an underlying relational database. Given an XML description of your entities and relationships, NHibernate automatically generates SQL for loading and storing the objects. Optionally, you can describe your mapping metadata with attributes in your source code.

NHibernate supports transparent persistence, your object classes don't have to follow a restrictive programming model. Persistent classes do not need to implement any interface or inherit from a special base class. This makes it possible to design the business logic using plain .NET (CLR) objects and object-oriented idiom."

Bio:
Fred is a Technical Lead with Sierra Systems Inc. and head of their in-house Microsoft Solutions Development group. He advises clients on Microsoft Development approaches and best practices and has been working in the industry for more than 10 years with varying technologies (Java, .NET) and roles from Developer to Architect. Fred has been active with the local community presenting at South Sound .NET User Group and the IPMA conferences.

Meeting Specifics:
April 10th, 7 - 9 pm
Olympia Center (222 Columbia NW)
All attendees are eligible for the prize drawings. Past prizes have included technical books, passes to Devscovery, copies of Visual Studio, Vista, Office 2007 and more.


 
Categories: Development | Events | Local

I just wrapped up a three day training class on Software Testing taught by Dale Emery of Quality Tree Software. Dale was the IT Process Improvement Manager for Sun Microsystems from 1999 to 2002. His insights as a developer made the class an awesome opportunity to pick up new tools for the tool box.

One of the more interesting concepts he discussed was the Wideband Delphi Estimation method. WDE is a slight variant of the original Delphi Estimation method developed by the RAND Corporation at the beginning of the cold war to forecast the impact of technology on warfare.

The original method works like this. A set of domain experts are sent a request for an estimate on a specific subject. For example, I send a request asking developers for estimates on how long it would take them to develop a web based message board from scratch.

Each response is then anonymized and added to a chart showing the variability of the estimations. The chart can then be sent out to the estimators and they are offered a chance to revise.

The median value of the estimates is then selected as the final estimate. The median value has a unique nature because it represents a better estimate than 50% of the other estimates regardless of the actual outcome.

An added benefit is that people with strong personalities are not allowed to dominate the estimation process (or weaker personalities for that matter) and skew the results. Each person gets a balanced representation in the estimating process.

Wideband Delphi Estimation differs in that it expands the amount of information being exchanged by the estimators. Estimators provided their considerations as well, which are then presented back to the group. The group can then review the considerations of their peers and adjust their estimations accordingly.

An interesting concept that I stored away in my toolbox. I hope I can drag that one out in the future and find a use for it. Thanks, Dale.


 
Categories: Development

Head First Object-Oriented Analysis & DesignI have recently taken an interest in firming up some fundamental skills in development. I have been so focused on the my current brownfield project, I have been neglecting to sharpen the saw. I picked up a copy of Head First Object-Oriented Analysis & Design at my local B&N. I had read Head First Design Patterns a couple years back and was really impressed with the style the book uses to keep the topic interesting.

OOA&D uses the same tried and true style as the other Head First books. The examples are witty and illustrate the point well. The code is very java focused but should be no problem for anyone with some C# or even JavaScript under their belt.

The book handles the analysis and design process from a simple to understand 3 step solution:

  1. Make sure your software does what the customer wants it to do.
  2. Apply basic Object Oriented principles to add flexibility.
  3. Strive for a maintainable, reusable design.

This simple recipe for great software is then examined in great detail. Topics covered include gathering requirements, effective use case diagramming, textural and domain analysis and various other tools to help the developer understand the problem space. The book starts out very simplistic and works it's way to more and more complex topics. By the time the book was discussing design principals like Open Closed Principal, Don't Repeat Yourself Principal, Single Responsibility Principal and the Liskov Substitution Principal  was really into the book and devouring the content.

If you are looking to bone up on some fundamentals or to take that first step from programmer to architect, this is a great starting point.


 
Categories: Books | Development