DiffPlex 1.2 Released

I released version 1.2 of the DiffPlex library on both CodePlex and Nuget. This new version contains a few notable changes.

  1. A new class called InlineDiffBuilder which makes it easier to build inline diffs (the same way the existing SidebySideDiffBuilder enables side by side diffs).
  2. A new argument on the IDiffer interface which causes the diffing algorithm to ignore letter casing. (See work item)
  3. DiffPlex 1.2 now targets .NET 4.0 and Silverlight 4.0

 

You can download the new version at the DiffPlex home page as well as contribute code/ideas to the project.

Posted in DiffPlex, Open Source | 1 Comment

Refactor now, not later

Imagine this situation (one I’ve been in too many times): you have been working on a piece of code and have created a complicated/intricate function. You look over your work and realize it is an ugly mess; the function is over 100 lines long and a tangled jumble of logic. However, it works and is tested; you are tired of working on this function since you have already spent so much time on it. At this point you consider two options: refactor the code or leave a comment indicating that this code should be refactored.

// This code needs refactoring

// Refactor this later
void SomeoneRefactorMeSinceMyCreatorHatesMe()
{
 // Save me
}

It is tempting to leave a comment to refactor and move on, but this decision is supported by some problematic assumptions.

1. I will fix it later

You won’t.

Once a developer puts the comment “refactor this later” on a function and checks it in he has already washed his hands of the function. I often see comments like this. Sometimes they stay in the code base for years without anyone ever addressing them. Often the original developer has long left the project but these comments remain. When asked about them, the author usually responds, “OH YEA! I forgot about that…”.

Not surprising; that comment expresses the developer’s disdain for the job that needs to be done. It follows that this developer will “forget” to come back and fix it. Is this cognitive dissonance rearing its ugly head? The developer knows he doesn’t want to work on it and thus conveniently forgets to return to it.

2. Someone else will fix it

They won’t.

If the author is unwilling to clean up his mess it seems unlikely that anyone else will jump at the opportunity. Plus, code that needs refactoring will be much harder for another developer to comprehend. (Even the author’s understanding of the code will wane the longer he waits to fix it.)

Leaving a comment to refactor is also disrespectful to other developers on the project. Instead of taking my garbage to the curb I carry it into work and dump it on another developer’s desk. If you realize your code is bad you should respect other developers enough to not force them to deal with it.

3. My time is better spent increasing functionality

It isn’t.

“Because this function works and there are other features to complete, refactoring now is a waste of time.” This thought devalues code quality in favor of functionality, which may seem like a good idea now but in the long term will hurt the project. When a function like this is left in the code it causes the entire code base to slowly creep towards an unmaintainable state. This is a concept called software rot. When the next developer needs to work with this function it will take him longer to understand and update, resulting in future features which take longer to complete. Pieces of code exist that developers *dread*. Work is delayed because developers avoid the messy code.

Refactor Early, Refactor Often

Quality of code is vital to a healthy software project. It may be scary to tell your project manager you will not ship functionality because of refactoring needs, but a good manager will appreciate that doing so now is better in the long run, and relying on a future fix is detrimental to the project. While it may feel more productive to move away from one piece of laborious code, in the end take pride in clean and easily understood code. Your team will thank you.

Posted in Software Development | Leave a comment

Regex Hero: Free online regular expression tester

A regex tester is one of those tools developers often need. I used many different ones over the years and  have never settled on one that I really like.  I have seen some paid ones that looked promising but I hoped to find a good free one. A few months ago I came across Regex Hero which is an online Silverlight based regex tester for .NET.  It has both a free and a paid version ($15) . I have not used the paid version so my description is based solely on the free version.

Regex Hero has all the standard features you expect with a regex tester.

1. Syntax highlighting

2. Syntax checking

3. Real time matching, replacing and splitting against a target string

Regext tester

4. Group matching

image

 

In addition to these pretty standard features Regex Hero has a couple really nice additional features.

1. Context sensitive completion menus

image

 

2. Generate C#/VB code from your regular expression

image

 

3. Save your regexes online and access from any computer

image

 

This tool is definitely a steal for a price of $0.  If anyone has tried the “pro” features of Regex Hero I would love to hear what you think about it but for now I am more than satisfied with the free version of this great tool.

Posted in Regular Expression, Tools | Leave a comment

Converting from RTF to HTML and HTML to RTF

A while back I posted Converting RTF to HTML which showed how to convert RTF text into HTML markup using the WPF RichTextBox control.  Since then I have noticed many posts on forums asking for a free and easy way to go the other way: convert from HTML to RTF. This is actually a very straightforward modification to my original code.

I posted an updated article and the complete sample code for this at Converting between RTF and HTML on the Code Samples Gallery.

Posted in C#, HTML, RTF, WPF, XAML | 3 Comments

The problem with the EnvDTE ItemOperations.NewFile method

During my work on the latest version of the Snippet Designer I was struggling with solving an issue with the EnvDTE method ItemOperations.NewFile. The purpose of the NewFile method is to create a new file in the same manner as if you created it from the File->New->File  dialog in Visual Studio. I used this method as part of the Snippet Designer’s Export as Snippet feature. The NewFile method was working fine (I thought) until I started receiving some bug reports from French and German users. After looking into it deeper I learned that the way I was using the NewFile method would not work in non-English installations of Visual Studio. To understand why you need to know a little bit more about ItemOperations.NewFile.

The NewFile method is define as:

Window NewFile(
	string Item,
	string Name,
	string ViewKind
)

When I would launch a new snippet file I would call the method like:

 Dte.ItemOperations.NewFile( @"General\Text File", "SnippetFile1.snippet");

The MSDN documentation for the first argument of this method is

The virtual path to the item based on the tree nodes from the left pane of the dialog box and the item name from the right pane.

This is where the problem was, the virtual path is language dependent! So while in English the correct path is  “General\Text File” in Spanish it is something like “General\Archivo”.  At this point I looked into this further to see if anyone else has this issue with no luck.

This left me with two options:

  1. Figure out each language specific virtual path
  2. Find a different way to have Visual Studio launch the file

Option 1 is an annoying and fragile solution so I started looking for alternate methods. Eventually I got the idea to try to send the command directly to the Visual Studio shell’s IOleCommandTarget::Exec method. The IOleCommandTarget interface helps define the command design pattern which VS uses. Many components in VS implement this interface (explicitly or implicitly) so that they can handle commands from the user.

Getting the IOleCommandTarget for the Visual Studio shell is pretty simple once you know that there is a service for this called SUIHostCommandDispatcher

private IOleCommandTarget GetShellCommandDispatcher()
{
    return GetService(typeof (SUIHostCommandDispatcher)) as IOleCommandTarget;
}

Then looking through the VSConstants.VSStd97CmdID list I found the FileNew command id

FileNew     Command id:”File New” on File menu.

With the both the command target and the command id I was able to execute the command:

private bool LaunchNewFile(string fileName)
{
    IntPtr inArgPtr = Marshal.AllocCoTaskMem(200);
    Marshal.GetNativeVariantForObject(fileName, inArgPtr);

    Guid cmdGroup = VSConstants.GUID_VSStandardCommandSet97;
    IOleCommandTarget commandTarget = GetShellCommandDispatcher();
    int hr = commandTarget.Exec(ref cmdGroup,
                                (uint) VSConstants.VSStd97CmdID.FileNew,
                                (uint) OLECMDEXECOPT.OLECMDEXECOPT_DODEFAULT,
                                inArgPtr,
                                IntPtr.Zero);
    return ErrorHandler.Succeeded(hr);
}

One thing to note above is that in order to pass the file name for FileNew command into the Exec method you need to marshal the string into a native object since IOleCommandTarget is just a managed interface on top of native COM interfaces.

After all of that I was able to correctly launch a new file through Visual Studio that works regardless of locale.

Posted in Visual Studio, VS SDK | 5 Comments