Random Thoughts of a Scatterbrain.
 Monday, May 05, 2008

MbUnit And TestDriven.NET On x64

5/5/2008 12:23:45 PM (Eastern Daylight Time, UTC-04:00)

I came across an interesting issue while trying to run some MbUnit RowTests this morning.

Namely, it seemed that the rows being passed in contained all null values.  It left me scratching my head.  I ran the tests using MbUnit console and it worked fine but didn't work as expected from TestDriven.NET in VS2005.

Well, it turns out that (I think) the install for MbUnit does not create the requisite registry keys in an x64 environment.  It properly creates the keys under the Wow6432Node, but it does not create the keys under the path:

HKEY_LOCAL_MACHINE\SOFTWARE\MutantDesign\TestDriven.NET\TestRunners

So to make it work, all you have to do is to copy the string values from the Wow6432Node to the key above and restart VS.

Hope this saves some headaches for other developers working in an x64 environment!

Update: Jeff Brown notes in the comments that this should be fixed with future releases so that x64 environment registry keys are properly generated.

 Thursday, April 24, 2008

Automating Remote GAC Installs On Build

4/24/2008 4:42:15 PM (Eastern Daylight Time, UTC-04:00)

When working with SharePoint, you'll find yourself working with the GAC quite often during development.

If you've seen the light and you're working with SharePoint on a VM, one tricky problem is how to update the GAC using a post-build event.  The following is a little script that I use:

::----------------------- GAC binaries code ------------------------
:: Check if the share is available on the server
IF EXIST "\\server-name\temp" GOTO COPYFILES
GOTO SHOWNOTICE

:: Copy file to the server
:COPYFILES
ECHO Found \\server-name\temp; proceeding to copy files...

SET SN=\\server-name\temp

:: Copy the binary
XCOPY "$(TargetPath)" "%SN%" /Y /I

:: Use PsExec to execute gacutil
PATH=$(SolutionDir)Tools;%windir%\Microsoft.Net\Framework\v2.0.50727;%programfiles%\Microsoft SDKs\Windows\v6.0\Bin;%path%

psexec \\server-name -u Administrator -p password -w "c:\temp" gacutil.exe /i "$(TargetFileName)" /f

GOTO END

:SHOWNOTICE
ECHO Your VM image is not sharing the directory "c:\temp"
GOTO END

:END
ECHO Completed

The batch script makes use of Sysinternal's PsExec.  I've included the binary executable in my solution tree under the directory "Tools".

The script only has one assumption: the VM (or remote machine, really) is sharing the c:\temp directory (okay, and that the path to gacutil.exe has been added to the remote machine's PATH environment variable).  Here's a breakdown of the logic:

  1. The first step is to check if the directory exists and can be reached.  If not, we go to the end and show a notice about sharing the directory.
  2. If the directory is shared, the output dll from the build is copied to the shared directory using plain old XCOPY.
  3. Once it's copied over, we use PsExec to execute gacutil on the VM (or remote machine).  The -w argument specifies the working directory on the remote machine.

Enjoy!

 Tuesday, March 25, 2008

Disabling Office 2003 Browser Inline Behavior

3/25/2008 10:21:43 AM (Eastern Daylight Time, UTC-04:00)

There's a unique problem in an Office 2003 environment that may be encountered by add-in developers.  Namely, by default, Office 2003 documents, when opened from a URL (for example, clicking on a link in an email or typing a URL into a browser address bar) will cause the document to open "inline" with the browser.

open-office2003-from-ie7-s.png

The problem with this, for add-in developers, is that while the WINWORD.EXE process is indeed launched, the add-in is not loaded (I'm still not sure why, but I'm guessing it's due to the different security restrictions of being "hosted" in Internet Explorer).  Aside from this, it's generally problematic because the default menu bars and toolbars are not displayed by default...not the ideal behavior.

As it turns out, in Office 2007, the behavior is entirely different: the document always open in a standalone WINWORD.EXE process.  So how can we get Office 2003 to behave the same way?  A series of articles lead the way to an answer:

First, Microsoft actually has a KB (927009) which advises how to enabled Office 2003 behavior in an Office 2007 environment.  This is the first clue that the core of the issue is a series of registry keys.  Knowing which keys to look for, I simply checked the keys in an Office 2007 environment to get the values which would cause an application like Word to launch in standalone mode instead of inline mode (decimal 44 in the case of Word).

The next step was figuring out how to adjust these values in existing deployments.  One option would have been to use a similar registry script as porposed in the KB but I decided to use a programmatic approach instead.  I came across some hints on how to approach this task from a forum posting and MSDN articles.

The outcome was this script:

/*=============================================================================
   This file contains the scripts which are executed after installation of the 
   Office 2003 client update registry keys which would otherwise force Office 
   documents to open in Internet Explorer (inline behavior)
=============================================================================*/
// Key paths
var commonRootPath = "HKLM\\SOFTWARE\\Classes\\";
var commonPath = "SOFTWARE\\Classes\\";
var commonKey = "BrowserFlags";
var HKLM = 0x80000002;

// Instantiate the shell.
var shell = WScript.CreateObject("WScript.Shell");

// Holds the values for the key types
var keyTypes = {
    String:"REG_SZ", 
    Number:"REG_DWORD", 
    Binary:"REG_BINARY", 
    ExpandableString:"REG_EXPAND_SZ"
};

// Holds the array of all key paths (not including the shared "BrowserFlags" 
// DWORD key name) and the value to assign to the key (different for each
// runtime).
var keys = [
    {Class:"Word.Document", Value:44},
    {Class:"Word.Document.6", Value:44},
    {Class:"Word.Document.8", Value:44},
    {Class:"Word.Document.12", Value:44},
    {Class:"Word.RTF.8", Value:44},
    {Class:"Word.DocumentMacroEnabled.12", Value:44}
];

/*-----------------------------------------------------------------------------
    Main method.
-----------------------------------------------------------------------------*/    
function Run() {
    try {
        for(var i = 0; i < keys.length; i++) {  
            var key = keys[i];
            
            if(RegistryKeyExists(key.Class)) {            
                var keyPath = commonRootPath + key.Class + "\\" + commonKey;                              
            
                shell.RegWrite(keyPath, key.Value, keyTypes.Number);
            }
        }   

	    shell.Popup("Updated registry keys.", 0, "Completed", 0 + 64);
    }
    catch(all) {
        // Failures are considered non-fatal.
        var errorMessage = "A non-fatal error occurred while configuring Word 2003\r\n";
        errorMessage += "document handling in IE.\r\n\r\n";
        errorMessage += "You can re-run this script at a later time from:\r\n\r\n";
        errorMessage += "[Program Files]\\[Common Files]\\FirstPoint\";
		errorMessage += "UpdateOffice2003RegistrySettings.js\r\n\r\n";
        errorMessage += "Press OK to continue.";

        shell.Popup(errorMessage, 0, "Error", 0 + 48);
    }
}

/*-----------------------------------------------------------------------------
    Checks to see if a registry key exists.
-----------------------------------------------------------------------------*/
function RegistryKeyExists(className) {
    var registry = GetObject("winmgmts:\\\\.\\root\\default:StdRegProv");   
    
    var path = commonPath + className;       
    
    var value = registry.GetStringValue(HKLM, path, "");
    
    return value == 0;
}

/*-----------------------------------------------------------------------------
    Abstracts Popup()
-----------------------------------------------------------------------------*/
function Alert(string) {
    shell.Popup(string, 0, "Message", 0);
}

Run();

Perhaps the most useful little tidbit in all of this is the RegistryKeyExists method which checks to see a registry path exists.  A return value of 0 from any of the Get[KeyType]Value() method calls indicates that the path was found; it's a very neat little trick to have up your sleeve.

 Saturday, March 08, 2008

Random Rant

3/8/2008 12:32:42 AM (Eastern Standard Time, UTC-05:00)

One of the most awesome pieces of software that I've come across in my career as a consultant and software engineer is Trac.  Among the various awesome features of Trac include:

  • An awesome plug-in system and library for all sorts of add-ons to the core system
  • RSS feeds on available on the timeline which acts as a customizable, almost realtime data feed
  • Integrated source browser...it makes pointing out code isssues so much easier when you can link it to source
  • An awesome wiki system that integrates with the ticket and changeset systems

Did I mention the ticket system?  Sure it lacks a bit in terms of workflow and it is rather simplistic -- being geared almost exclusively towards bugs, but I think the most important aspect that it brings is, well, tracking.

Having worked with it for almost a year, I find it really hard to imagine working on any sizable software project without it (or some other piece of comparable software project management tool).

Perhaps the only thing that I've found frustrating -- surprisingly, it is not with Trac itself -- is the inability to really win anyone else over in my group; you'd think its like pulling teeth to get a ticket created for tracking purposes instead of using email. Let's not even get into wiki editing or proper usage of wiki markup or taking advantage of the integrated wiki syntax for tickets and what not.  It just seems like some old habits are hard to break (much to my dismay).

But don't let this dissuade you! If you haven't given it a look yet, there's no time like the present to download it and give it a go. Oddly enough, if you're looking to get started, VisualSVN Server may be the way to go since it includes an integrated installation of Apache, Subversion, and a mangement console.  Also check out the awesome documentation on installing Trac on a variety of systems, including Windows.

 Thursday, October 04, 2007

Serializing Inheritance Chains With WCF

10/4/2007 1:42:26 PM (Eastern Daylight Time, UTC-04:00)

During a recent code review, I noticed that a colleague was sending me service entities from his WCF service with flags for the data type.  This itself wasn't so bothersome to me, but what did bother me was that the model he was sending back was violating one of the basic rules of object oriented programming: encapsulation (well, inheritence and abstraction, too) by mashing all of the data types into one type differentiated by a property.

Having worked extensively with XML serializers and XSD.exe generated code, I suggested that instead of mashing all of the objects into one definition -- with all of the different properties -- build one abstract definition and define a hierarchy of classes that inherit from the abstract class.

This worked out great since the family of objects all had a very obvious common base, but now the question turned to how to notify the runtime serialization engine to include the concrete types when returning abstract types from an operation.

I had imagined that the .NET 3.0 team would have made the process more "automagic" and use reflection to find inheriting classes instead of requiring the explicit declaration of inheriting classes.  As I soon found out, such is not the case as my proxy classes didn't include any of the inheriting classes; the proxy definition only contained the definition for the base class.

The answer is the KnownTypeAttribute which must be used to decorate the class definition of the base class (in my case, an abstract class).  One attribute must be added for each inheriting type which must be serialized across the wire.  For example:

[DataContract]
[KnownType(typeof(Invertebrates))]
[KnownType(typeof(Vertebrates))]
[KnownType(typeof(Mammal))]
[KnownType(typeof(Reptile))]
[KnownType(typeof(Human))]
public abstract class Animal {
	// Base class definition
}

Notice that the entire hierarchy has to be "flattened" and included in the declaration for the root base type. The DataMemberAttribute only has to be applied once on any property in the base class.

 Saturday, September 29, 2007

Less Painful Windows Service Development

9/29/2007 12:11:08 PM (Eastern Daylight Time, UTC-04:00)

When developing Windows services applications, one of the most painful aspects is testing.

Sure, you can test individual component libraries separately with unit tests, but what about deploying and testing the system in an actual runtime environment?  What if your components are dependent on live communications (for example, two components that communicate via TCTP/IP bindings in WCF)?  You could use mocks, but at some point, testing the interactions of the full system will be necessary.

Typically, this is a painful process of either using installers to install and uninstall the service or manually starting and stopping an installed service to replace component library assemblies. 

The pain can be alleviated by using automated batch scripts on the post-build event.

ECHO Checking for existing deployment...
IF EXIST "
\\<server>\<deployment-target>" GOTO COPYFILES
GOTO SHOWNOTICE

:COPYFILES
ECHO Found deployment; copying output files...
ECHO Stopping Windows Service...
SC
\\<server> STOP <service-name>

:: COPY FILES HERE....

ECHO Starting Windows Service...
SC
\\<server> START <service-name>
ECHO Started Windows Service.
GOTO END

:SHOWNOTICE
ECHO Did not find deployment target...
GOTO END

:END
ECHO Completed build...

In this example, I'm deploying to a remote server on the local network (but it would work just as well on a local deployment).  I came up with the script a while back after I got tired of stopping services, copying binaries over by hand manually, and starting services when testing some appliactions that I was building.  This technique still requires a one time initial install to deploy the Windows service, but on subsequent builds,

  1. It checks to see if the deployment target exists,
  2. If so, it stops the service and replaces the binaries (I've left that script out since it's particular to any given deployment),
  3. It restarts the service.

I find this particularly useful for testing WF applications in custom Windows services based runtimes and for testing WCF applications in custom Windows services based runtimes as it allows me to install the service once and redeploy the component binaries with each build with ease.

 Thursday, September 27, 2007

Dynamic SQL: Yea or Nay?

9/27/2007 2:42:01 PM (Eastern Daylight Time, UTC-04:00)

I've always been on the side of stored procedures in the classic debate over the merits of dynamic SQL.  In reality, I can only think of one good scenario where dynamic SQL at the application layer should be used: programmatic batch inserts.

I won't go into the performance debate, since there are tons of articles that already cover this area, but rather, I'd like to discuss the usability and development and architectural aspect of it.

In almost all other cases, it seems like the best choice is to have the application not generate dynamic SQL and use a stored procedure...always.  There are certainly times when dynamic SQL is necessary, for example, when generating selects against a dynamic table structure, but in those cases, the variable portions of the query can be parameterized into the stored procedure and the procedure should generate the dynamic SQL.

Some would argue that if the underlying data models change, the application layer will usually be forced to change are ignoring other aspects of model changes that don't necessitate application model changes.  These include performance tuning, filtering by table JOINs and reuse of the data logic in nested stored procedures or functions.

When working with compiled code like .NET, the core issue is that fixing query errors involves a recompile and redeploy, which in most cases, is much more difficult than just fixing a completely disconnected (but not completely decoupled since there is a quasi-interface (the return result type and structure)) stored procedure.

For example, if a dataset today contains data from table A and tomorrow it needs to include data from table A and B (let's say they both contain the same elements, but one is used for archives), it would be easy to update the procedure to UNION the results from the two datasets without affecting the application layer.

This isn't the only scenario, for example, let's say the requirement changes and now the data needs to be filtered by another table.  It would be easy to add a new INNER JOIN to the query without affecting the application layer.  Not only that, it also allows for the recombination of fields (for example a user name field today only needs to show first and last name, but tomorrow, it may need to show the middle initial as well - this change can be done at the database level and not affect the application or UI layers).  It can also make it easy to change the underlying table structure so long as the return data isn't expected to change: it provides a layer of decoupling between the application layer and the raw data storage.

In addition, having a stored procedure allows for easier testing of the data layer without the added overhead of having to execute the application runtime and walk through the debugger line by line just to figure out if the return data is correct; it is much more efficient to simply execute the query and simulate the use case to find if the data that is returned is correct.  It becomes much easier and much less painful to simulate data access tests since they can be run, observed, and analyzed nearly instantly.

In larger organizations with dedicated DBAs, stored procedures have the added benefit of allowing SQL experts to add performance tuning to eek out extra performance without requiring the application to be rewritten or recompiled.  Again, we see this decoupling of the application layer from the data layer.  Of course you could always have templated SQL stored in XML files or something that would get rid of that recompile, but it is still likely to necessitate more redeployment if the application in question is distributed.  This key point is not to be taken lightly since -- as an example -- an error in string formatting may require the replacement of binaries and services across dozens of servers.  Not only that, testing in such a scenario still requires interaction with the application layer, adding to the possible failure points, time required, and general development pain.

My own conclusion is that using dynamic SQL (including LINQ) creates too tight of a coupling between the application layer binaries and the underlying data store; it's great for RAD and testing, but in any application of significance (especially in highly distributed environments), dynamic SQL at the application layer seems like it's a maintenance and testing disaster waiting to happen.

 Thursday, September 13, 2007

Double Dispatch To The Rescue

9/13/2007 9:55:42 AM (Eastern Daylight Time, UTC-04:00)

In working out a tricky design issue surrounding the usage of the Visitor pattern, I stumbled upon the related Double Dispatch pattern/mechanism.

In short, double dispatch, when implemented, allows an object - a "dispatcher" - to delegate method calls based on the runtime type or types involved in the interaction.

The two core problems with visitor are that:

  1. You must have access to the visitable object to implement an IVisitable interface.  Often times, when dealing with binary code references, this is not an option.
  2. Each visitor must implement IVisitor, regardless of whether all of the Visit() interactions make any sense.  This means that if there are 10 concrete IVisitable classes, then each IVisitor must implement 10 Visit() methods that support each of the concrete classes, even if the particular IVisitor has no valid operations on a given IVisitable.

I suppose point number 1 is not really a constraint, it's just that it's a criterion for a by-the-book visitor pattern implementation.  But point number 2 is a really sticky situation since in many cases, not all of the IVisitor concrete classes should support all of the IVisitable concrete classes.  Of course we could just add a blank method stub, even for operations that don't make sense, but that just seems like bloat and a maintenance nightmare.

The key in understanding the use of double dispatch is to understand the core issue with the Visitor pattern.  We want the visitor to perform different operations based on the runtime type passed into a call to an abstract Visitor base class.  Unlike method overloading, which relies on compile time types to determine the method to invoke, we want the code to decide which method to invoke based on the runtime type of the object being passed in.

Ideally, we could have a scenario like this:

public class Program {
    private static void Main(string[] args) {
        Collection<AbstractVisitor> visitors 
			= new Collection<AbstractVisitor>();
        Collection<Pet> pets = new Collection<Pet>();

        pets.Add(new Fish());
        pets.Add(new Dog());

        visitors.Add(new Feeder());
        visitors.Add(new Walker());

        // Visit each of the pets.
        foreach (Pet pet in pets) {
            foreach (AbstractVisitor visitor in visitors) {
                visitor.Visit(pet);
            }
        }
    }
}

/// <summary>
/// Abstract base class for visitors.
/// </summary>
public abstract class AbstractVisitor {
    public abstract void Visit(Pet pet);
}

/// <summary>
/// Concrete visitor, a pet feeder.
/// </summary>
public class Feeder : AbstractVisitor {
    public void Visit(Dog dog) {
        // Feed the dog
        dog.Visitors.Add("Fed the dog");
    }

    public void Visit(Fish fish) {
        // Feed the fish
        fish.Visitors.Add("Fed the fish");
    }
}

/// <summary>
/// Concrete visitor, a pet walker.
/// </summary>
public class Walker : AbstractVisitor {
    public void Visit(Dog dog) {
        dog.Visitors.Add("Walked the dog");
    }

    // Fish can't be walked!
}

But this code doesn't work!  Both Walker an Feeder must now implement Visit(Pet pet) like so:

/// <summary>
/// Abstract base class for visitors.
/// </summary>
public abstract class AbstractVisitor {
    public abstract void Visit(Pet pet);
}

/// <summary>
/// Concrete visitor, a pet feeder.
/// </summary>
public class Feeder : AbstractVisitor {
    // Yucky if block...
    public override void Visit(Pet pet) {
        if(pet is Dog) {
            Visit(pet as Dog);
        }
        if(pet is Fish) {
            Visit(pet as Fish);
        }
    }
    
    public void Visit(Dog dog) {
        // Feed the dog
        dog.Visitors.Add("Fed the dog");
    }

    public void Visit(Fish fish) {
        // Feed the fish
        fish.Visitors.Add("Fed the fish");
    }
}

This is a less than desirable situation since for every new pet type we introduce, we need to introduce another entry in the if-else block. Yuck. 

While there were many articles on how to implement double dispatch in C# using various techniques, by far, the simplest implementation that I found was one by Anthony Cowley.

So let's see how our code would look using this technique (I'll omit the implmentation of the abstract visitor class for now):

public class Program {
    private static void Main(string[] args) {
        Collection<AbstractVisitor> visitors 
			= new Collection<AbstractVisitor>();
        Collection<Pet> pets = new Collection<Pet>();

        pets.Add(new Fish());
        pets.Add(new Dog());

        visitors.Add(new Feeder());
        visitors.Add(new Walker());

        // Visit each of the pets.
        foreach (Pet pet in pets) {
            foreach (AbstractVisitor visitor in visitors) {
                visitor.Visit(pet);
            }
        }

        // Check the results.
        foreach(Pet pet in pets) {
            Console.Out.WriteLine(pet.GetType().Name);
            foreach(String note in pet.Visitors) {
                Console.Out.WriteLine("\t{0}", note);
            }
        }
    }
}

/// <summary>
/// Concrete visitor, a pet feeder.
/// </summary>
public class Feeder : AbstractVisitor {
    public void Visit(Dog dog) {
        // Feed the dog
        dog.Visitors.Add("Fed the dog");
    }

    public void Visit(Fish fish) {
        // Feed the fish
        fish.Visitors.Add("Fed the fish");
    }
}

/// <summary>
/// Concrete visitor, a pet walker.
/// </summary>
public class Walker : AbstractVisitor {
    public void Visit(Dog dog) {
        dog.Visitors.Add("Walked the dog");
    }

    // Fish can't be walked!
}

/// <summary>
/// Base class for pets.
/// </summary>
public abstract class Pet {
    private readonly Collection<string> visitors;

    public Collection<string> Visitors {
        get { return visitors; }
    }

    protected Pet() {
        visitors = new Collection<string>();
    }
}

/// <summary>
/// A pet fish.
/// </summary>
public class Fish : Pet {}

/// <summary>
/// A pet dog.
/// </summary>
public class Dog : Pet {}

When I run this program, I get the following output:

As expected, the dog was walked and fed, but the fish was only fed. Now we can go about adding pets to our heart's content and we won't be forced to add another Visit() method declaration. If there is no Visit() method implemented for a particular pet type, then nothing happens and the default implementation of Visit() on the abstract class handles it. The magic all happens in Cowley's implementation of AbstractVisitor:

/// <summary>
/// Abstract base class for visitors.
/// </summary>
public abstract class AbstractVisitor {
    private static readonly Dictionary<long, MethodInfo> dispatch;

    static AbstractVisitor() {
        dispatch = new Dictionary<long, MethodInfo>();

        foreach (Type t in Assembly.GetCallingAssembly().GetTypes()) {
            if (t.IsSubclassOf(typeof(AbstractVisitor))) {
                foreach (MethodInfo mi in t.GetMethods()) {
                    if (mi.Name == "Visit") {
                        ParameterInfo[] pars = mi.GetParameters();
                        if (pars.Length == 1) {
                            Int64 code = ((Int64)t.GetHashCode() << 32) +
                                pars[0].ParameterType.GetHashCode();
                            dispatch.Add(code, mi);
                        }
                    }
                }
            }
        }
    }

    public virtual void Visit(object pet) {
        Int64 hash = ((Int64)GetType().GetHashCode() << 32) + 
            pet.GetType().GetHashCode();
        if (dispatch.ContainsKey(hash)) {
            dispatch[hash].Invoke(this, new object[] { pet });
        }
        else {
            // This is our fallback functionality
            Console.WriteLine("Visiting object " + pet.ToString());
        }
    }
}

You may have spotted an issue here: since the Visit() method is virtual, the subclasses of AbstractVisitor aren't strictly forced to define a Visit() method of any sort nor is there a constraint that forces any implementation to have only one argument.  But this is just fine, since all of the classes must inherit from AbstractVisitor to participate in this pattern, it will also inherit the default implementation of Visit() which, conveniently, contains a fallback do-nothing behavior.

You can download the full source here: SimpleDoubleDispatchSample.zip (4.08 KB)

I also have a second sample that I modified from Cowley's code that uses singleton instances of the visitors and improved encapsulation of the dispatch lookup table.  I also modified the catch all virtual Visit() method to a call to another virtual method to allow subclasses to change the default implementation of the case that no specific Visit() is found: SimpleDoubleDispatchSample.2.zip (4.12 KB)

Once again, credit goes to Anthony Cowley for an excellent and simple implementation of double dispatch in C#. There were two others that I examined, namely one by Max Hajek (which actually generated IL) and one by Steve Love using Generics.  In both cases, I thought the solutions were far more complex than the actual problem that they tried to solve, though Max's solution seems far more powerful and may be more useful in some scenarios.

 Friday, September 07, 2007

Code Complete: Chapter 31

9/7/2007 1:50:37 PM (Eastern Daylight Time, UTC-04:00)

I've recently picked up my copy of Code Complete - 2nd Edition again after a long hiatus from it.  It's such a massive book that I think if you plan on reading it from front to back, it'll bore you to death and put you to sleep.  Of course, this is not to say that the book is bad - quite the opposite, the book is filled to the brim with knowledge that will benefit any level of developer - but that you have to approach it in a more "leisurely" manner.

The book itself is one of those that you can really just kind of jump in and out of the chapters (except for some of the early ones that should be digested together).

Some bits from Chapter 31 that I think really capture the essence of the book. 

McConnell opens with an excellent statement that succintly summarizes my infatuation with proper code structure, naming, and other seemingly "non-development" coding activities: it is a matter of personal pride in my work and the effort that I put forth to make the code legible:

“The visual and intellectual enjoyment of well-formatted code is a pleasure that few nonprogrammers can appreciate.  But programmers who take pride in their work derive great artistic satisfaction from polishing the visual structure of their code.” (P.729)

The chapter covers the importance of good formatting and layout, the psychological effects of good layout and formatting (such as easier to memorize code structure), and techniques to achieve good layout.

McConnell introduces the idea of “The Fundamental Theorem of Formatting” which says “good visual layout shows the logical structure of a program” (P.732)

He quotes Elliot Soloway and Kate Ehrlich in their studies:

“…there is a psychological basis for writing programs in a conventional manner: programmers have strong expectations that other programmers will follow these discourse rules.  If the rules are violated, then the utility afforded by the expectations that programmers have built up over time is effectively nullified."  (P.733)

This is in alignment with the ideals of best practices.  The core concept is to have a codebase that exudes familiarity even to first time readers.  McConnell emphasizes the importance of the human aspect of coding:

“The smaller part of the job of programming is writing a program so that the computer can read it; the larger part is writing it so that other humans can read it.” (P.733)

Indeed, writing code so that the machine can read it is easy: the compiler, IDE, and development tools like ReSharper will tell you when the machine can’t read it.  Writing code so that other humans can read it is a true challenge since there is no one to confirm your view of the code or structure (without a well defined code review practice or pair programming). 

In that sense, writing code is not so different than writing in general.  Using shorthand is always the fastest ways to write little notes for oneself, but when composing a written work that others must consume, there are certain conventions that people come to expect: proper spacing, proper usage of punctuation, proper grammar, and the usage of paragraphs to delineate discrete bodies of text – these details all help to make the text more readable from a mechanical perspective.

While code is certainly not literature (well, not to most normal people anyways ;-)), there are similar traits in elegant code structure and elegant prose: it is simple, clear, concise, and expressive.  It might follow a pattern (rhyming, iambic pentameter, etc.) that gives it a flow.

Soloway and Ehrlich’s studies concluded that:

“The results point out the fragility of programming expertise: advanced programmers have strong expectations about what programs should look like, and when those expectations are violated—in seemingly innocuous ways—their performance drops drastically.” (P.735)

They cite examples where advanced chess players showed a marked increase in ability to memorize chess pieces arranged in “standard” or common scenarios over novice players, but demonstrated no increased ability when the pieces were arranged in a random fashion.  The conclusion is that familiarity increases the ability to internalize and process an otherwise abstract structure (or in this case, arrangement of chess pieces).

Of course, it’s not all just fluff and “nice to haves”, right?  McConnell raises an interesting observation that:

“The information contained in a program is denser than the information contained in most books.  Whereas you might read and understand a page of a book in a minute or two, most programmers can’t read and understand a naked program listing at anything close to that rate.  A program should give more organizational clues than a book, not fewer."

This makes the argument clear for commenting, proper and consistent application of white space, and using descriptive rather than short names (see Framework Design Guidelines for more coverage on that).  For example (and I’ve never understood this one), the use of “itm” instead of typing “item” or “tsk” instead of “task” or the use of “d” to declare a local variable instead of “document”.  One letter makes the code much more readable and much easier to process for another human reader of the code.

McConnell also makes a very good case for how code should be structured to reduce the complexity of the visual layout.  He gives a good abstract comparison on page 747.  These are small items which increase the readability of the code in very subversive ways; you probably never think about such details actively, but when processing a page of code, little details like indentation probably have a strong effect on your ability to understand the purpose and nature of the code.  More importantly, when other humans have to process your code, these little details, taken in cumulative, could mean the difference between a day of ramp up and a week of ramp up time.

Of course, McConnell does acknowledge that in many cases, such matters of style are borderline “religious”.  But from an objective perspective:

“…it’s clear that some forms of layout are better than others.  Good programmers should be open-minded about their layout practices and accept practices proven to be better than the ones they’re used to, even if adjusting to a new method results in some initial discomfort.” (P.735)

Definitely a book that deserves some shelf space on any developer's desk (edit: or nightstand ;-)).

 Tuesday, August 21, 2007

Working With SQL Server Compact Edition 2005

8/21/2007 6:05:02 PM (Eastern Daylight Time, UTC-04:00)

One interesting issue that I just solved involved how to specify the location of the database file for a SQL Server Compact Edition 2005 connection string in a .Net add-in for Microsoft Office.

You see, when the add-in starts, it sets the context directory as the user's documents directory, which of course, makes it impossible to enter a configuration string for the data source of the connection string.

It works fine if the directory is hard coded - which is what I did for testing purposes initially, but of course, when I switched over to XP64, this broke as on XP64, the program is installed to "Program Files (x86)".

The solution lies buried in Microsoft's SQL CE documentation: there's a note that you should use a special token with the connection string like so:

<connectionStrings>
	<add name="ClientDatabase" 
		connectionString="Data Source=|DataDirectory|\data-file.sdf"
		providerName="Microsoft.SqlServerCe.Client" />
</connectionStrings>

The token needs to be included exactly as entered "|DataDirectory|". So how is this token replaced? In the static constructor of my Connect class that was autogenerated by Visual Studio, I added the following code:

/// <summary>
/// Initializes the logging subsystem for the <see cref="Connect"/> class.
/// </summary>
static Connect() {
	string path = Assembly.GetExecutingAssembly().Location;
	path = path.Substring(0, path.LastIndexOf('\\'));

	// Set the DataDirectory for the SQL Server CE connection string.
	AppDomain domain = AppDomain.CurrentDomain;
	domain.SetData("DataDirectory", path);
}
 Thursday, August 16, 2007

Book Review: Framework Design Guidelines

8/16/2007 4:30:48 PM (Eastern Daylight Time, UTC-04:00)

I originally came across a title Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries after perusing the documentation on the Subtext site.

For the most part, I had been following the guidelines outlined by Scott Bellware in his handy dandy style guide, but this text - FDG - takes it to another level and formalizes it in a way that it must be accepted by development teams since it was born from the source itself: the .NET Framework development teams.

I've reviewed it on Amazon, but here is the transcripted text:

I don't personally think that all developers will find this book useful. In fact, I have a feeling that some may find it highly useless and disruptive as it is abstract in a sense (one must apply the lessons to each library and scenario independently, taking into consideration many different aspects of usability and readability) and it does require some "retraining" of bad practices which have been long since ingrained due to years of usage.

But whether this book deserves a five star rating or a one star rating - whether this book is for you - can be answered by asking yourself the following question: are you obsessed with quality? Quality in the sense of creating a library that is:

- Easily reused by others, even first timers encountering the library or even first timers to .Net
- Well thought out with well designed classes
- Consistent within itself and consistent with the base libraries from Microsoft

The importance of the little things like naming classes, properties, methods, using one type of construct over another, using one type of accessor over another, etc. cannot be stressed enough in the overall picture of creating a library to a higher standard of quality, usability, and extensibility.

As Confucius is to have said:

"If names be not correct, language is not in accordance with the truth of things. If language be not in accordance with the truth of things, affairs cannot be carried on to success.

"When affairs cannot be carried on to success, proprieties and music do not flourish. When proprieties and music do not flourish, punishments will not be properly awarded. When punishments are not properly awarded, the people do not know how to move hand or foot.

"Therefore a superior man considers it necessary that the names he uses may be spoken appropriately, and also that what he speaks may be carried out appropriately. What the superior man requires is just that in his words there may be nothing incorrect."

As I wrote in an e-mail to my team, I think that digesting this book will lead to: higher quality public facing APIs for our customer development teams seeking to extend the functionality, increased readability and more consistency internally in our teams, increased usability and decreased maintenance costs for the support teams as well as new developers on our team, and of course, increased skill, knowledge, and competency as developers of each of the team members.

The title of this book is perhaps a bit misleading.  In reality, this book is applicable for anyone doing .Net development since it will lead to better quality code construction irregardless of whether you happen to be working on a "framework".  What I also like about the book is that the authors, architects, and various developers who worked on the .NET Framework admit error and inconsistency in some design and shows that this book is truly a work of the men in the trenches and intended for those of us who work on the front line of software development.

While the book does not delve into architecture or design, I think it still has value in enhancing the skill and mastery of any developer that takes the time to read it.  Definitely pick up this book if you are serious about becoming a better developer in the sense of being a more refined craftsman.

 Wednesday, August 15, 2007

Running Trac, Subversion, And Apache On Ports 80 And 443

8/15/2007 8:41:15 PM (Eastern Daylight Time, UTC-04:00)

If you are proxying Subversion through Apache, chances are you are probably using a non-default port since Apache won't start if you configure it use port 80 and 443 for SSL if you have IIS installed.  IIS uses socket pooling which binds port 80 and 443 on all IPs -- even ones not use by IIS -- to IIS.

To disable this behavior, you need the httpcfg.exe utility.  For Windows Server 2003, this can be found in the SP1 32-bit Support Tools download.  For Windows XP, the utility is available as part of the SP2 Support Tools download.

You can find a good overview of how to use this tool at neowin.net.

Some tips:

  • I didn't have luck running net stop http /y alone; I had to stop IIS first by running net stop iisadmin.
  • Assuming you have two or more IPs, the key is that you are actually telling IIS which IPs are okay to bind to.  If you are proxying Apache over IIS, you are likely (or should) use SSL.  This means that you have to make sure that you explicitly force IIS to bind to 80 and 443 for a specific IP and leave the other IP available for Apache.
 Tuesday, August 14, 2007

Normalizing And Denormalizing SharePoint Field Names

8/14/2007 11:45:29 AM (Eastern Daylight Time, UTC-04:00)

Frequently, when working with Office, SharePoint, and SharePoint web services, it is necessary to convert between the "normalized" (hex escaped string) version of a field name.

To that end, I found a useful JavaScript tool for normalizing strings into SharePoint's "static name" format.

In .Net, we can simplify this using Regex and Uri.

    private static readonly Regex specialCharactersPattern
        = new Regex("[\\[*($%&)<>!?\\/\"{}\\s+-='@~`#\\\\:;^\\]]", 
            RegexOptions.Compiled);

    private static readonly Regex encodedCharactersPattern
        = new Regex("_x00(\\d{2})_", RegexOptions.Compiled);

    /// <summary>
    /// Normalizes the name of the SharePoint property name.
    /// </summary>
    /// <param name="key">The "human readable" key/property name.</param>
    /// <returns>
    /// The string with hex representation in place of special ASCII
    /// characters.
    /// </returns>
    private static string NormalizeSharePointPropertyName(string key) {
        return specialCharactersPattern.Replace(key, ReplaceSpecialCharacter);
    }

    /// <summary>
    /// Custom match evaluator to replace special characters within the input
    /// string.
    /// </summary>
    /// <param name="match">The pattern match.</param>
    /// <returns>The formatted version of the string.</returns>
    private static string ReplaceSpecialCharacter(Match match) {
        string replacement = string.Format("_x00{0}_",
            Uri.HexEscape(match.Value[0]).TrimStart('%'));

        return replacement;
    }

    /// <summary>
    /// Denormalizes the name of the SharePoint property.
    /// </summary>
    /// <param name="key">The normalized key/property name (static name).</param>
    /// <returns>
    /// The denormalized form of the input string ("human readable"
    /// with hex patterns replaced).
    /// </returns>
    private static string DenormalizeSharePointPropertyName(string key) {
        return encodedCharactersPattern.Replace(key, DecodeSpecialCharacter);
    }

    /// <summary>
    /// Custom match evaluator to replace the hex characters with special characters.
    /// </summary>
    /// <param name="match">The pattern match.</param>
    /// <returns>The ASCII format of the special character encoded in hex.</returns>
    private static string DecodeSpecialCharacter(Match match) {
        int start = 0;

        string replacement =
            Convert.ToString(
                Uri.HexUnescape(Convert.ToString(match.Value[0]), ref start)
            );

        return replacement;
    }

Download the sample console project to test it out.

SharePointNormalizationConsole.zip (4.35 KB)

 Tuesday, July 31, 2007

Finding An Application Runtime By Extension

7/31/2007 12:38:53 PM (Eastern Daylight Time, UTC-04:00)

So a recent item that I've been tasked with is programmatically finding the application that is required to open/load a file of a given file extension.  One would think that this would be a straightforward task and quite easy to accomplish with .Net.

My first thought was to check the System.Environment namespace for any mappings of file extensions.  Nada.  My next instinct was to check System.Runtime.InteropServices to see if there was a chance that some object (maybe Marshal) had access to such a table.  No go.  I also stopped by Microsoft.Win32...nothing as well.

I did come across an interesting method in System.Drawing.Icon, ExtractAssociatedIcon() which would be useful if that was what I was after.  Unfortunately, I didn't find anything that would resemble this functionlity in System.IO.

So it would seem that for the time being, the only way that I can get at this data is to read registry keys.

What I've found is the following algorithm:

  1. Open HKEY_CLASSES_ROOT\<extension>\(Default). This gives us the class name that handles the file extension.
  2. Open HKEY_CLASSES_ROOT\<class-name>\CLSID\(Default). This gives us the GUID class ID of the application that handles the file extension.
  3. Open HKEY_CLASSES_ROOT\CLSID\<class-id>\InProcServer32|LocalServer32\(Default). This will yield the path to the executable which handles the file extension.

In some cases, it is enough to open the first key (the extension key) and you will find a subkey called OpenWithList with the first subkey being the name of the executable of the application (but this isn't always available).

I'm thinking there has to be a better way to do this programmatically, but I haven't come across it yet.

 Wednesday, July 18, 2007

CAB, Model View Presenter, Passive View, and Humble Dialog

7/18/2007 10:24:03 AM (Eastern Daylight Time, UTC-04:00)

In trying to wrap my head around how solutions should be designed and componentized in SCSF/CAB, I've spent a bit of time trying to study up on Model View Controller (MVC) and Model View Presenter (MVP).

The packaged documentation, in my opinion, doesn't necessarily do a good job of covering these two topics and the variations of MVP that really make sense in CAB.

One of the best resources for discourse on these two topics is Martin Fowler's article on GUI Architectures, which provides a broad view of three of the most common underlying architectural choices for many of the GUIs that we work with today.

Of note is that Fowler's entry for MVP has been retired; instead, replaced with Passive View (PV) and Supervising Controller (SC).

What I've observed is that PV is more "aligned" with the design of the components in CAB than SC, which Fowler summarizes:

The separation advantage is that it pulls all the behavioral complexity away from the basic window itself, making it easier to understand. This advantage is offset by the fact that the controller is still closely coupled to its screen, needing a pretty intimate knowledge of the details of the screen. In which case there is a real question mark over whether it's worth the effort of making it a separate object.

In my opinion, since the CAB generated presenter isn't coupled with a concrete implementation of the view, PV is the way to go since this will allow a lower level of coupling with the concrete implementation of the view.  I went about this by adding interface methods to return Control (one could go as generic as Object as well) instances from the view which would then be rendered, wired, and databound by the presenter.  In other words, it's not really Model View Presenter as the documentation would have you believe.

Regardless, this allows a great deal of flexibility in the design of the module as a whole as the view can truly be replaced completely independently of the presenter since the presenter is only coupled with the interface class.  In addition, it allows for easy replacement of data visualization types using the adapter pattern to connect data to the control type (for example, having one adapter if the returned control is of type TreeView and another when the control is a DataGridView).

However, an even better description of the architectural intent of CAB modules is Humble Dialog, a pattern formalized by Michael Feathers.  What Feathers terms "smart object" is congruent to the presenter, which "pushes data onto the view class" through a view interface.  The view, of course, is the actual UserControl derived view class.  Now this leaves a key question: what is the place of the model in such a pattern?  Does it have a place?  With SCSF (but not necessarily with CAB when used with desktop applications), the classic sense of the model almost has no place in such an architecture; the model is but a dumb container for data.  It leaves you with what Fowler terms an Anemic Domain Model, an "anti-pattern":

The basic symptom of an Anemic Domain Model is that at first blush it looks like the real thing. There are objects, many named after the nouns in the domain space, and these objects are connected with the rich relationships and structure that true domain models have. The catch comes when you look at the behavior, and you realize that there is hardly any behavior on these objects, making them little more than bags of getters and setters. Indeed often these models come with design rules that say that you are not to put any domain logic in the the domain objects. Instead there are a set of service objects which capture all the domain logic. These services live on top of the domain model and use the domain model for data.

While Fowler views this pattern with disdain, I can't help but wonder whether it is the most natural choice for a smart client style application which should rely heavily on service layers to handle the data models.  Otherwise, it would seem that one would end up writing a great deal of domain objects which were nothing more than shells (well, perhaps this is still useful if complex service interactions are necessary) which make the calls through the service proxies.

 Tuesday, July 17, 2007

Tuesday Morning Thoughts

7/17/2007 10:50:01 AM (Eastern Daylight Time, UTC-04:00)

Some random stuff and some not so random stuff.

First, the Oral-B CrossAction Vitalizer is possibly the best damn (non-electric) toothbrush ever made.  It's comfy on the gums, it gets to the back teeth, and the handle is just right for control of pressure and angle.  The "soft" bristle isn't very soft at all, but I've found that it doesn't cause any pain or damage to my gums...it's just right.

Second, in reorganizing some of our code, I jumped headfirst into Microsoft's Smart Client Software Factory (SCSF).  While the verdict is far from conclusive, I have to say: I like it.  It implements several ideas I was tossing around in my head for a Windows Forms client but is obviously much, much more well developed and thought out.

I do find it annoying that it is somewhat difficult to visualize the relationships.  That is the one advantage to using an XML based object configuration system as opposed to the attribute based system used by the Composite Application UI Block that SCSF is built on: it's quite easy to wrap your head around the relationships and see how the pieces fit simply by reading the XML.  To be honest, it wouldn't be too terribly difficult to build similar (but certainly much less refined, given the amount of time I have) facilities with Spring utilizing the dependency injection, loosely coupled events, expression evaluation, and other components of Spring.

However, I think that the entire package, including the GAX pieces make this too compelling of a package to pass up.  There is surely a huge learning curve for the framework and library itself, but I think it will be made up for with the gain in development and deployment speed.

It's kind of cool that it also supports WPF modules.  I spent quite some time last night (up until 2 AM) trying to replicate some of the existing UI components that we have into WPF UIs.  I think I'm starting to "get it".  Not in the sense of why XAML is great for UI developers (I've always preferred declarative markup), but in the sense that I've kind of aligned myself with some of principles of XAML (i.e. layout, grids/tables, applying styles, backgrounds, etc. - which are of course slightly different than HTML) and I can now really appreciate how much easier it will be to create snazzy UIs in the future.

cab-hosted-wpf-UI.jpg

While I have Expresison Blend, I found it much more constructive to actually go into the raw XAML and write it by hand (well, not to mention that I find the UI hideous and unusable or perhaps I'm just way too Adobe-ized).  It was quite slow going at first, but once it clicked, it picked up very quickly.

Ultimately, however, I don't think that I can use WPF for our next release.  There seems to be some runtime instability with the current Visual Studio 2005 extensions (the November 2006 CTPs) to support WPF and WCF...I was only able to run my application once last night; subsequently, it would crash immediately.  The problem was only fixed by rebooting my machine.

But in any case, there are some great SCSF resources out there.  I would start from Cabpedia.com as CAB itself is really what presents the challenge in the Smart Client.  Cabpedia has a list of great resources which helped me at least grasp some of the conceptual ideas behind CAB.  In particular, a series of articles by Szymon Kobalczyk.

 Tuesday, July 10, 2007

Software, Artistry, and Frustration

7/10/2007 10:52:46 PM (Eastern Daylight Time, UTC-04:00)

In describing my approach to software development, I like to use the term practical artistry.  What does this mean exactly?

Well, the practical part of it is that the class libraries, interfaces, and components have to work the way that tey were designed.  They should also be easy to use, easy to understand, easy to integrate with.

The artistry portion of this term is much harder to quantify.  Just what is artistry when used in the context of software development?

Art Tatum offers a very compelling definition:

Art is a method of communication which unifies surface details and form while taking both the intended meaning and aesthetics into account. This requires significant amounts of problem solving. The artist is constantly asking, "How can I best express this idea without ruining the proportions of the work as a whole."

This ties in with Fred Brooks' principle of conceptual integrity for it is the artist alone who sees the proportions of his work and the artist alone who shall ensure that the work abides by the guidelines of the orginal design intent.

Another term that I like to use is exemplary craftsmanship.  This concerns the little details that make code aesthetically pleasing, readable, and well crafted.  Many small details affect this quality of code such as consistent naming schemes, using extra keystrokes and not abbreviating non-standard terms, ensuring that spacing is consistent, formatting code in a consistent manner so as to make it more readable, and commenting public APIs.  On a higher level, it concerns the organization of code and the clear separation of domains (not in the Fowler sense, but in a more abstract sense) in a manner that enhances the extensibility and orthogonality of the code.

It's not just code, it's any trade.  A panel and house wired by a master electrician will certainly be different than a panel and house wired by an apprentice.  The cabling will be neat, the runs will be well thought out, the circuits will be well labled, the panel will be well organized, little details will have been considered, and the artistry of the finished work is apparent even to laymen.

With this in mind, I consider myself to still be an apprentice; I still seek to learn the trade from a master craftsman and I still seek to hone my skills and develop my artistry so that I may also craft software of a high caliber.  But I work hard to ensure that some sense of practical artistry and exemplary craftsmanship is apparent in everything I do.  From simple tasks like ensuring proper indentation in my source files, selecting the right margins in my documentation, and using the right fonts to more complex design issues like organizing libraries in proper dependency chains, achieving orthogonality in modules, and organizing objects in consistent and well defined fashions (i.e. utilizing design patterns).

Unfortunately, in my short career, my interactions with other developers have left me disappointed on this front for the most part except for three individuals whom I didn't have nearly enough time to interact with (this is not to say that I haven't worked with many fine developers, but three stand out as practicing these principles of craftsmanship).  These three were true craftsmen in the sense that the little details mattered to them.  Improving their skills as developers was an important aspect of everyday development.  Writing good code and following well known guidelines and principles meant something.  The naming of every class, of every variable, required at least some passing thought so as to ensure that each construct was congruent and aligned with the whole.

Of course, such discussion of artistry as it applies to software is not just frivolous academia, Maarten Boasson writes in The Artistry of Software Architecture:

Designing software is not very different from designing any other complex structure: Few people are good at it; no single recipe always produces a good product; and the more people involved, the smaller the probability of success.  On the other hand, a design produced by someone who is good at design provides an excellent basis for long, reliable service.

Software engineers consider the artistry of the design not only evaluating aesthetics but also the practical results of such a design such as orthogonality and added extensibility.  Boasson further comments:

In exceptional cases, a good software design is no less valuable than the great masterpieces that have been created throughout our rich history.  Examples of both bad and good designs can be found all around us, in almost every engineering field; practically everyone recognizes a piece of art when they see it.

So I often wonder why it is the case that I encounter and, of much greater concern, find high degrees of tolerance for bad design.  Not just bad design, but bad development practices like inconsistent usage of formatting elements (spacing, newlines, tabs), naming namespaces and classes against well established guidelines and practices, and other details like inconsistent casing.  Leadership just doesn't seem to care for the most part and it requires the rare and truly inspired individual project manager to understand the long term value of encouraging practical artistry and exemplary craftsmanship.

Bear in mind: it's not that I approach writing software with any sort of artistry or snobbery in mind...indeed, a good portion of it is the grunt work - simply putting the hammer to the nail, or putting the brush to the canvas, so to speak.  But at the end of the day, there is a personal satsifaction that is achieved from not just writing any code, but writing good code.  There is a satsifaction that comes from recognizing and implementing a superior system design.  Of course, it goes beyond personal satisfaction, good design, as Boasson writes, can provide long term value in the form of extensibility, maintainability, and reusability.

In almost all cases, as the majority of developers are not self motivated to write such code, it takes strong leadership, clear definitions or design guidelines, and enforcement of the policies to ensure that quality software - not just working software, but quality software - is crafted.

To me, it is the little details that go towards creating a better product.  There is certainly a time and place for prototyping and RAD - and certainly, I utilize these techniques all the time, but there is also a time to formalize the lessons learned from such exercises and to create a masterpiece...to write code that you would find have no qualms about showing to the world and exposing it to critique.

It is with this in mind that I find myself currently flustered.  Is it just me?  Am I being too uppity about all of this?  It's hard to say...I am truly conflicted about this as I cannot see how I can work productively and cooperatively in a team with people who do not honor the same sense of craftsmanship and artistry.  I awake and find that someone has scribbled on my canvas in a weak imitation of my style using colors that clash with the existing palette.  Analogously, I open the electrical panel to find that someone has stuffed some low grade wire haphazardly into the panel without any clear labeling.  I cannot help myself but cringe at the thought of integration - yes cringe.  I don't want to deal with ugly code and yet the leadership doesn't seem to care one way or the other and I am powerless to affect change (partly because I am a blunt edge and possess no sense of finesse whatsoever in dealing with these situations)...*sigh*

I can only hope that some of my desire to achieve practical artistry in code and design inspires others on my team, otherwise this will be painful to endure.

 Friday, July 06, 2007

WCF Configuration Intellisense

7/6/2007 4:06:38 PM (Eastern Daylight Time, UTC-04:00)

Hmm...I thought it was kind of odd that Visual Studio didn't support intellisense for WCF configuration elements (but then again, I've kind of become intimately familiar with the core elements without having the schema).

Turns out that you have to take care of it manually by updating the schema file for configuration.

Blogger Govind has a post with the necessary file and instructions.

Helps configuration go much more smoothly until Orcas arrives.

I'm surprised that this hasn't been posted across more blogs since it seems like a big, big bonus to have this for developing WCF applications.  Is it common knowledge?  Was there an SP that updated the schema files?  I know that installing .Net 3.0 didn't change the configuration files on my system at least.

 Friday, June 22, 2007

Software Engineering 101....ARGH!

6/22/2007 5:23:40 PM (Eastern Daylight Time, UTC-04:00)

Some days, I just can't handle the aggrevation...

I thought it was generally known that binary build output does not belong in source control, so I was quite dismayed when I grabbed an update to our source tree today and found myself downloading a 2MB .msi file (the output of one of our installer projects).

After discussing this with the other developers on my team, it became apparent that what I thought was a common, well known practice regarding source control is in fact, not so well known.

After presenting my arguments with little avail, I started to scour the web to find evidence support my stance: