Aug 30 2008

Hug a developer today

Category: IT RelatedRory Primrose @ 21:22

This is absolutely gold. I think every developer can relate to this.

 

Via Scott Watermasysk.

Tags:

Aug 28 2008

Example of coding for testability

Category: .Net | Software DesignRory Primrose @ 07:40

I have done it again. In order to work on a particular project, I have been sidetracked into writing a utility to help me continue with what I am actually trying to do. In my defense, I did look around the net for an application that would do what I needed so I didn't have to write it, but no application seemed appropriate.

In essence, I need an application to resolve all the links internal to a website and check their status. This will give me an initial view of the state of the site. I then want to take all of those links and replay the analysis of those resolved links using a different base address. The reason I am doing this is because I am looking at migrating my Community Server based blog to use BlogEngine.Net instead. As part of that migration, I want to maintain as much of the Community Server url formats as possible so I don't lose my existing audience.

Given that this application is going to chew a lot of bandwidth (my entire site) along with the need for accurate results, I want to make sure that this utility is doing the right thing. Unit testing is critical for this to be successful. I quickly found however that my initial cut is not very testable.

Here is a simple example of how to take untestable code and make it testable. In the following examples, there is some logic in the ResourceResolver.GetResourceContents method that we want to test.

The untestable example

using System;
using System.Diagnostics;
using System.IO;
using System.Net;
 
namespace ConsoleApplication1
{
    internal class Program
    {
        private static void Main(String[] args)
        {
            ResourceResolver resolver = new ResourceResolver();
            Uri location = new Uri("http://localhost");
            String content = resolver.GetResourceContents(location);
 
            Debug.WriteLine(content);
        }
    }
 
    internal class ResourceResolver
    {
        public String GetResourceContents(Uri location)
        {
            HttpWebRequest request = HttpWebRequest.Create(location) as HttpWebRequest;
 
            request.Credentials = CredentialCache.DefaultCredentials;
 
            HttpWebResponse response = request.GetResponse() as HttpWebResponse;
 
            using (Stream contentStream = response.GetResponseStream())
            {
                using (StreamReader reader = new StreamReader(contentStream))
                {
                    String content = reader.ReadToEnd();
 
                    // Do something with this value 
 
 
                    return content;
                }
            }
        }
    }
}

This is untestable as a unit test. To write a test for this code will require an integration test as requests are being made to an external resource (http in this case). What if that resource is not available or produces unknown or unmanageable results? Unit testing normally requires more flexibility as the same code paths need different data thrown at them.

This code is a classic example. The HttpWebRequest class is not easily testable. Converting this code so that mocks and stubs can be used will allow unit tests to be supported.

The testable example

using System;
using System.Diagnostics;
using System.IO;
using System.Net;
 
namespace ConsoleApplication1
{
    internal class Program
    {
        private static void Main(String[] args)
        {
            HttpResourceLoader loader = new HttpResourceLoader();
            ResourceResolver resolver = new ResourceResolver(loader);
            Uri location = new Uri("http://localhost");
            String resourceContent = resolver.GetResourceContents(location);
 
            Debug.WriteLine(resourceContent);
        }
    }
 
    public interface IResourceLoader
    {
        String GetResourceContents(Uri location);
    }
 
    public class HttpResourceLoader : IResourceLoader
    {
        public String GetResourceContents(Uri location)
        {
            HttpWebRequest request = WebRequest.Create(location) as HttpWebRequest;
 
            request.Credentials = CredentialCache.DefaultCredentials;
 
            HttpWebResponse response = request.GetResponse() as HttpWebResponse;
 
            using (Stream contentStream = response.GetResponseStream())
            {
                using (StreamReader reader = new StreamReader(contentStream))
                {
                    return reader.ReadToEnd();
                }
            }
        }
    }
 
    internal class ResourceResolver
    {
        public ResourceResolver(IResourceLoader loader)
        {
            Loader = loader;
        }
 
        public String GetResourceContents(Uri location)
        {
            String content = Loader.GetResourceContents(location);
 
            // Do something with this value
 
            return content;
        }
 
        private IResourceLoader Loader
        {
            get;
            set;
        }
    }
}

By abstracting an implementation that actually gets the resource contents (with a bit of Dependency Injection thrown in), we now have a ResourceResolver.GetResourceContents method that can be unit tested. The unit testing involved now needs to pass in either a stub or a mocked instance of IResourceLoader and we can safely test the logic of this method without requiring http requests.

When you develop code, please think about how it is going to be tested. Even better, write unit tests when you develop the code. You will quickly find out how flexible your code is for unit testing.

Tags: , , , , ,

Aug 27 2008

Visual Studio Tip: Escape without fear

Category: .NetRory Primrose @ 08:07

I read the Visual Studio Tip: Disable F1! post a few weeks ago and was very tempted to take the advice to remove the F1 keyboard mapping in Visual Studio. I kept it because sometimes I do actually want to open help. The problem is I keep missing ESC and hitting F1.

I've finally cracked. It is just too annoying, especially when you haven't opened help yet and it takes a long time to come up. I've got a different take on the solution though. Because I still want access to help, rather than removing the F1 keyboard mapping, I've changed it to F1, F1. A double tap on the F1 key is much more deliberate.

 

Kudos to Andrew Stevenson who inadvertently provided the title to this blog in his comment in the above mentioned post.

Tags:

Aug 21 2008

Red Gate picks up Reflector

Category: Applications | .NetRory Primrose @ 03:46

Read the 'official' interview here.

I really don't know what to think about this. I definitely don't like the phrase "free for download" because it can be very misleading. James Moore has been more explicit in other posts by saying that existing functionality will remain free for download and use. I'm supportive of this move if this is the case and I hope that Red Gate can add value to this product. While it is one of the best .Net tools around, it isn't perfect.

I think this brings great risk to Red Gate. Any serious developer has Reflector as their #1 tool and I am confident that the percentage of good developers out there is substantial. It will be really bad publicity for Red Gate if they tick off that number of people in the industry. Everyone wins if they make the right moves though.

On that point, Red Gate is spending the next couple of months asking the community about what they should do with Reflector. Want to be heard by Red Gate? Flood the forum and let them know how you want this to play out.

I hope that Lutz was well paid for this product. He deserves every cent for how he had supported the industry for so many years.

Tags:

Aug 15 2008

Trojan in VS2008 SP1?

Category: .NetRory Primrose @ 04:53

Hmmm, not sure about this one. I was installing VS2008 SP1 this morning and this came up.

VS2008SP1Trojan 

Updated: Microsoft have responded here.

Tags:

Aug 14 2008

Things to look at when tracing does not output data

Category: .NetRory Primrose @ 10:45

There are several issues that can prevent trace data being written. Here are a few of that you might encounter.

TraceSource names

If using TraceSource, the name provided to the TraceSource constructor is case sensitive. If the string doesn't match your configuration exactly, a default TraceSource instance is created rather than the configured one you were expecting.

TextWriterTraceListener

If using TextWriterTraceListener (or XmlWriterTraceListener that derives from it), there are several more issues that can occur.

The following code is the code in TextWriterTraceListener that causes the issues.

public override void WriteLine(String message)
{
    if (EnsureWriter())
    {
        if (base.NeedIndent)
        {
            WriteIndent();
        }

        writer.WriteLine(message);

        base.NeedIndent = true;
    }
}

internal Boolean EnsureWriter()
{
    Boolean flag = true;

    if (writer == null)
    {
        flag = false;

        if (this.fileName == null)
        {
            return flag;
        }

        Encoding encodingWithFallback = GetEncodingWithFallback(new UTF8Encoding(false));
        String fullPath = Path.GetFullPath(this.fileName);
        String directoryName = Path.GetDirectoryName(fullPath);
        String fileName = Path.GetFileName(fullPath);

        for (Int32 i = 0; i < 2; i++)
        {
            try
            {
                writer = new StreamWriter(fullPath, true, encodingWithFallback, 0x1000);
                flag = true;
                break;
            }
            catch (IOException)
            {
                fileName = Guid.NewGuid() + fileName;
                fullPath = Path.Combine(directoryName, fileName);
            }
            catch (UnauthorizedAccessException)
            {
                break;
            }
            catch (Exception)
            {
                break;
            }
        }

        if (!flag)
        {
            this.fileName = null;
        }
    }

    return flag;
}

When writing a record, it ensures that the writer is ready. The biggest problem with this implementation is that the logic in EnsureWriter() swallows any exception. If an exception is encountered, a second attempt is made which is likely to fail for the same reason as the first attempt. This causes WriteLine() to skip out without throwing an exception.

I find this code very poor. If there is a problem with using the configuration values, the developer (or operations staff) need to know what the problem is so they can fix it. This implementation simply just ignores the request to write the trace record when an exception is encountered. This is the primary reason that troubleshooting tracing problems is so difficult.

Some of the problems that can be encountered with the TextWriterTraceListener and derived classes are:

  • The configured directory doesn't exist. I would have expected that this code would ensure that the directory is created, but unfortunately it doesn't.
  • Lack of permissions. If the identity running the trace methods doesn't have permissions to write to the configured location, this will obviously fail.
  • The path is too long. The .Net framework doesn't support paths more than 260 characters. See here.
  • The drive specified in the path doesn't exist

Hope this helps.

Tags: ,

Aug 13 2008

Iterators and the yield statement

Category: IT Related | .NetRory Primrose @ 04:57

The yield statement is one of those C# statements that is really powerful but is either not understood or is unknown to most developers. Raymond Chen just posted a very good write up on how the compiler deals with the yield statement.

The Old New Thing : The implementation of iterators in C# and its consequences (part 1)

The great feature that the yield statement brings is delayed execution in iterations. If building a collection of items to iterate through is an expensive operation on either performance or memory, getting individual items as they are requested may be a better design. Using the yield statement means that this is really easy to achieve.

Take the following code for example:

using System;
using System.Collections.Generic;
 
namespace ConsoleApplication1
{
    internal class Program
    {
        private static void Main(String[] args)
        {
            Console.WriteLine("Starting the iterations");
 
            foreach (Entity item in GetItems(10))
            {
                Console.WriteLine("Got item {0} - {1} - {2}", item.Id, item.FirstValue, item.SecondValue);
            }
 
            Console.ReadKey();
        }
 
        private static IEnumerable<Entity> GetItems(Int32 maxItems)
        {
            for (Int32 index = 0; index < maxItems; index++)
            {
                yield return GetItemFromStore(index);
            }
        }
 
        private static Entity GetItemFromStore(Int32 id)
        {
            Console.WriteLine("Getting item {0} from the store", id);
 
            // Simulate getting the item from a data store or service
            Entity item = new Entity();
 
            item.Id = id;
            item.FirstValue = "First" + id;
            item.SecondValue = "Second" + id;
 
            return item;
        }
    }
 
    internal class Entity
    {
        public String FirstValue
        {
            get;
            set;
        }
 
        public Int32 Id
        {
            get;
            set;
        }
 
        public String SecondValue
        {
            get;
            set;
        }
    }
}

This code iterates over a set of 10 items and outputs the details of each item encountered. The interesting bit is that each item is only requested and created for each iteration rather than calculating the entire set up front.

The output of this code is:

Starting the iterations
Getting item 0 from the store
Got item 0 - First0 - Second0
Getting item 1 from the store
Got item 1 - First1 - Second1
Getting item 2 from the store
Got item 2 - First2 - Second2
Getting item 3 from the store
Got item 3 - First3 - Second3
Getting item 4 from the store
Got item 4 - First4 - Second4
Getting item 5 from the store
Got item 5 - First5 - Second5
Getting item 6 from the store
Got item 6 - First6 - Second6
Getting item 7 from the store
Got item 7 - First7 - Second7
Getting item 8 from the store
Got item 8 - First8 - Second8
Getting item 9 from the store
Got item 9 - First9 - Second9

Very powerful, very easy.

Tags: , ,

Aug 12 2008

Thread identity propagation

Category: .NetRory Primrose @ 06:30

I have been writing up some instrumentation documentation where I have been explaining the use of TraceFilter implementations. I gave an example of creating a TraceFilter that filters trace events from the TraceListener based on the identity of the executing thread. The issue here is that a TraceListener implementation may be writing its data on a different thread to the one that invoked the trace event.

I had always assumed that when you create a new thread, the identity of the creating thread is used as the identity of the new thread. There is a lot of danger in assumptions though. While it's just an example, I needed to prove that my TraceFilter code wouldn't be invalid if a TraceListener did use threads for its work.

After firing up Reflector, I poked around Thread.CurrentPrincipal code. As expected, the principal is stored in the context data of the thread (LogicalCallContext via CallContext). What was interesting about the code is that if the call context doesn't contain a principal, it then consults the AppDomain. In the internal AppDomain.GetThreadPrincipal() method, the code runs a switch around a PrincipalPolicy value. I hadn't come across PrincipalPolicy before so this was an interesting discovery.

The policy allows for an AppDomain to determine the default identity to use for threads. This is set by calling AppDomain.SetPrincipalPolicy(), but its value is only valid until an identity is explicitly assigned to a thread. From that point on, that thread and any threads that it creates use the explicitly defined identity. The way to revert this back to using the policy on the AppDomain is to set the identity on the current thread to null.

So my assumption was correct. Identities on threads do get propagated to their created threads.

Here is an example:

using System;
using System.Security.Principal;
using System.Threading;
 
namespace ConsoleApplication1
{
    internal class Program
    {
        private static void Main(String[] args)
        {
            Thread newThread = new Thread(ThreadTest);
            newThread.Start("Default AppDomain");
            newThread.Join();
 
            Console.WriteLine();
 
            AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.NoPrincipal);
            newThread = new Thread(ThreadTest);
            newThread.Start("AppDomain NoPrincipal");
            newThread.Join();
 
            AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.UnauthenticatedPrincipal);
            newThread = new Thread(ThreadTest);
            newThread.Start("AppDomain UnauthenticatedPrincipal");
            newThread.Join();
 
            AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal);
            newThread = new Thread(ThreadTest);
            newThread.Start("AppDomain WindowsPrincipal");
            newThread.Join();
 
            Console.WriteLine();
 
            Thread.CurrentPrincipal = new GenericPrincipal(new GenericIdentity("NewIdentity"), null);
 
            Console.WriteLine("Assigned new identity to thread");
            Console.WriteLine();
 
            AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.NoPrincipal);
            newThread = new Thread(ThreadTest);
            newThread.Start("AppDomain NoPrincipal");
            newThread.Join();
 
            AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.UnauthenticatedPrincipal);
            newThread = new Thread(ThreadTest);
            newThread.Start("AppDomain UnauthenticatedPrincipal");
            newThread.Join();
 
            AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal);
            newThread = new Thread(ThreadTest);
            newThread.Start("AppDomain WindowsPrincipal");
            newThread.Join();
 
            Console.WriteLine();
 
            Thread.CurrentPrincipal = null;
 
            Console.WriteLine("Removed identity from thread");
            Console.WriteLine();
 
            AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.NoPrincipal);
            newThread = new Thread(ThreadTest);
            newThread.Start("AppDomain NoPrincipal");
            newThread.Join();
 
            AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.UnauthenticatedPrincipal);
            newThread = new Thread(ThreadTest);
            newThread.Start("AppDomain UnauthenticatedPrincipal");
            newThread.Join();
 
            AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal);
            newThread = new Thread(ThreadTest);
            newThread.Start("AppDomain WindowsPrincipal");
            newThread.Join();
 
            Console.ReadKey();
        }
 
        private static void ThreadTest(Object value)
        {
            IPrincipal principal = Thread.CurrentPrincipal;
            String name = "null";
 
            if (principal != null
                && principal.Identity != null)
            {
                name = principal.Identity.Name;
 
                if (String.IsNullOrEmpty(name))
                {
                    name = "empty";
                }
            }
 
            Console.WriteLine(value + " - " + name);
        }
    }
}

The results in the following output (with the windows account removed):

Default AppDomain - empty

AppDomain NoPrincipal - null
AppDomain UnauthenticatedPrincipal - empty
AppDomain WindowsPrincipal - [WindowsAccountRemoved]

Assigned new identity to thread

AppDomain NoPrincipal - NewIdentity
AppDomain UnauthenticatedPrincipal - NewIdentity
AppDomain WindowsPrincipal - NewIdentity

Removed identity from thread

AppDomain NoPrincipal - null
AppDomain UnauthenticatedPrincipal - empty
AppDomain WindowsPrincipal - [WindowsAccountRemoved]

Tags:

Aug 11 2008

AOP in .NET

Category: IT Related | .Net | Software DesignRory Primrose @ 16:26

A few months ago I did some research into dependency injection frameworks. One of the interesting features provided by many of the Dependency Injection frameworks was the support for AOP. This is really interesting stuff and great for injecting logging and caching implementations without having to modify existing code.

There are several AOP implementations around (Oren Eini identified seven in this post) and I have always wondered how some of them worked. Unfortunately I never got the time to research it.

Using aspects in .NET - Part 1 is a post by Istvan that just popped up in my feed reader. He describes how to create an AOP implementation using ContextBoundObject and ProxyAttribute classes. I didn't previously know that combining these types in the .Net framework allows you to override the new statement. This is extremely powerful. I had assumed that this was the method that TypeMock used for creating unit testing mocks, but Oren's post identifies it as using a profiling API.

I think the centerpiece of Istvan's implementation is the RealProxy class. This is another one of those .Net classes that is incredibly powerful. I have used RealProxy before to create a wrapper for WCF channel management. Thankfully this helped me to understand Istvan's post quickly. I am looking forward to his Part 2 post.

The only thing I don't like about this style of AOP is that it requires the aspected class to derive from ContextBoundObject and have a ProxyAttribute derived attribute decorated on the class. This has the disadvantage that the aspected class must be not only designed for AOP, but coded for this specific type of AOP. I'm a fan of POCO code design, so at this stage I think the profiling API version of AOP used by TypeMock is so much more powerful and has less impact on the code.

BTW, Castle Windsor was my pick of the dependency injection frameworks as it was the most suitable for my requirements. I also did some research into mocking frameworks about the same time. While TypeMock was certainly the most powerful, its particular implementation isn't very flexible. Oren's RhinoMocks was my pick on that one.

Tags: , ,