Sunday, May 30, 2010

Exception formatting

public StackFrame ExtractPrimaryFrame(
  Exception exception)
{
  if (exception.InnerException != null)
  {
    return ExtractPrimaryFrame(exception.InnerException);
  }

  return ExtractPrimaryFrame(new StackTrace(exception, true));
}

public StackFrame ExtractPrimaryFrame(
  StackTrace stackTrace)
{
  if (stackTrace == null ||
    stackTrace.GetFrames() == null)
  {
    return null;
  }

  foreach (var frame in stackTrace.GetFrames())
  {
    if (frame.GetFileName() != null)
      return frame;
  }

  return null;
}

public string FormatException(Exception exception)
{
  StackFrame primaryFrame = ExtractPrimaryFrame(exception);
  return string.Format("{0} || {1}",
    FormatFrame(primaryFrame),
    exception);
}

public string FormatFrame(StackFrame frame)
{
  if (frame == null)
  {
    return string.Empty;
  }

  return string.Format(
    "FileName: {0}; Line: {1}; FilePath: {2}; Full info: {3}",
    ExtractFileName(frame.GetFileName(), "src") ?? "(none)",
    frame.GetFileLineNumber(),
    frame.GetFileName() ?? "(none)",
    frame.ToString());
}

private static string ExtractFileName(string filePath)
{
  if (string.IsNullOrEmpty(filePath))
    return null;
  FileInfo fi = new FileInfo(filePath);
  return fi.Name;
}

public string ExtractFileName(string filePath, string folderStart)
{
  if (string.IsNullOrEmpty(filePath))
    return null;
  FileInfo fi = new FileInfo(filePath);
  DirectoryInfo dir = fi.Directory;
  while (true)
  {
    if (dir.Parent == null || dir.Name == folderStart)
      break;
    dir = dir.Parent;
  }

  if (dir.Parent == null)
    return ExtractFileName(filePath);
  return fi.FullName.Replace(dir.FullName + "\\", "");
}

Saturday, March 20, 2010

Testing multiple implementations

Challenge: Run automated tests of multiple implementations of an interface, for example one repository for Sql Server and another for MySql.

A solution: Have one test class for one of the implementations, and create a derived test class for the other implementation, which injects the proper implementation in the constructor of the first test class.

Example with NUnit:

[TestFixture]
public class CustomerRepositoryTests
{
   private ICustomerRepository _repository;

   public CustomerRepositoryTests() :
      this(new CustomerRepository())
   {
   }

   public CustomerRepositoryTests(ICustomerRepository repository)
   {
      _repository = repository;
   }

   [Test]
   public void Add_ValidCustomer_Ok()
   {
      // Arrange:
      var customer = new Customer();

      // Act:
      _repository.Add(customer);
   }

}

[TestFixture]
public class MySqlCustomerRepositoryTests :
   CustomerRepositoryTests
{
   public MySqlCustomerRepositoryTests() :
      base(new MySqlCustomerRepository())
   {
   }
}

Wednesday, March 17, 2010

Manual definition of dependent tables with LinqToSql

The following is a code example of how to declare dependent tables in C# and generate and populate them with LinqToSql [it will generate the tables Parent(Id, Name, ChildId) and Child(Id, Name)]:

using System;
using System.Data.Linq;
using System.Data.Linq.Mapping;

namespace ManualLinqToSql
{
   class Program
   {
      static void Main(string[] args)
      {
         const string connectionString =
            @"Server=.\SqlExpress;Database=LinqTest;Integrated Security=true;";
         TestRepository repository =
            new TestRepository(connectionString);
         try
         {
            repository.CreateDatabase();
            repository.Add("A", "A1");
            repository.Add("B", "B1");
            Console.WriteLine("OK");
         }
         catch (Exception ex)
         {
            Console.WriteLine(ex);
         }
         Console.ReadKey();
      }
   }

   public class TestRepository
   {
      private readonly TestDataContext _dataContext;

      public TestRepository(string connectionString)
      {
         _dataContext = new TestDataContext(connectionString);
      }

      public void Add(string parentName, string childName)
      {
         var parent = new Parent(parentName, childName);
         _dataContext.ParentTable.InsertOnSubmit(parent);
         _dataContext.SubmitChanges();
      }

      public void CreateDatabase()
      {
         _dataContext.DeleteDatabase();
         _dataContext.CreateDatabase();
      }
   }

   public class TestDataContext : DataContext
   {
      public TestDataContext(string connectionString)
         : base(connectionString)
      {
      }

      public Table<Parent> ParentTable
      {
         get { return GetTable<Parent>(); }
      }

      public Table<Child> ChildTable
      {
         get { return GetTable<Child>(); }
      }
   }

   [Table]
   public class Parent
   {
      private EntityRef<Child> _child;

      public Parent()
      {
      }

      public Parent(string name, string childName)
      {
         Name = name;
         Singleton = new Child { Name = childName };
      }

      [Column(IsPrimaryKey = true, IsDbGenerated = true)]
      public int Id { get; set; }

      [Column(CanBeNull = false)]
      public string Name { get; set; }

      [Association(Storage = "_child", ThisKey = "ChildId", IsForeignKey = true)]
      public Child Singleton
      {
         get
         {
            return _child.Entity;
         }
         set
         {
            _child.Entity = value;
            ChildId = value.Id;
         }
      }

      [Column(UpdateCheck = UpdateCheck.Never)]
      private int ChildId { get; set; }
   }

   [Table]
   public class Child
   {
      [Column(IsPrimaryKey = true, IsDbGenerated = true)]
      public int Id { get; set; }

      [Column(CanBeNull = false)]
      public string Name { get; set; }
   }

   public void Detach()
   {
      _child = default(EntityRef<Child>);
   }
}

Sunday, March 7, 2010

MSBuild: Passing arrays between targets

In MSBuild, if you have a target that operates on a list of items of a specific type, and you want to call that operation several times with different lists, here is a way to do that using the DependsOnTargets attribute:

<Target Name="UserInterface">
  <MSBuild Projects="$(MSBuildProjectFile)" Targets="Service"
    Properties="ServiceDependsOn=PersonRepository-1" />
  <MSBuild Projects="$(MSBuildProjectFile)" Targets="Service"
    Properties="ServiceDependsOn=PersonRepository-2" />
</Target>

<Target Name="Service" DependsOnTargets="$(ServiceDependsOn)">
  <Message Text="Persons: @(Persons->'%(Name) (%(Identity))')" />
</Target>

<Target Name="PersonRepository-1">
  <ItemGroup>
    <Persons Include="Al"><Name>Al Omaha</Name></Persons>
    <Persons Include="Ben"><Name>Ben Patterson</Name></Persons>
  </ItemGroup>
</Target>

<Target Name="PersonRepository-2">
  <ItemGroup>
    <Persons Include="Adrian"><Name>Adrian Quist</Name></Persons>
    <Persons Include="Britta"><Name>Britta Ruud</Name></Persons>
  </ItemGroup>
</Target>


and here is sample output:

Project "C:\Projects\MSBuildItems.xml" on node 0 (default targets).
Project "C:\Projects\MSBuildItems.xml" (1) is building "C:\Projects\MSBuildItems.xml" (1:2) on node 0 (Service target(s)).
 Persons: Al Omaha (Al);Ben Patterson (Ben)
Done Building Project "C:\Projects\MSBuildItems.xml"
(Service target(s)).

Project "C:\Projects\MSBuildItems.xml" (1) is building "C:\Projects\MSBuildItems.xml" (1:3) on node 0 (Service target(s)).
 Persons: Adrian Quist (Adrian);Britta Ruud (Britta)
Done Building Project "C:\Projects\MSBuildItems.xml"
(Service target(s)).

Done Building Project "C:\Projects\MSBuildItems.xml" (default targets).

MSBuild with dependency injection

I am about to start refactoring a MSBuild file with around 1000 lines of xml, and I find that the targets are heavily dependent on each other.

Maybe dependency injection can help here?!

In MSBuild this could look something like this:

UserInterface.xml:
<Import Project="ApplicationService.xml" />
<Import Project="Repository.xml" />
(or <Import Project="FakeRepository.xml" />)
<Target Name="UserInterface-Action">
  <CallTarget Targets="ApplicationService-Action" />
</Target>


ApplicationService.xml:
<Target Name="ApplicationService-Action">
  <CallTarget Targets="IRepository-Action" />
</Target>


Repository.xml:
<Target Name="IRepository-Action">
  <Message Text="Repository action" />
</Target>


FakeRepository.xml:
<Target Name="IRepository-Action">
  <Message Text="Fake repository action" />
</Target>


For comparison, here is the corresponding structure in C#:
public class UserInterface
{
  private readonly IRepository repository;

  public UserInterface(IRepository repository)
  {
    this.repository = repository;
  }

  public void Action()
  {
    var service = new ApplicationService(this.repository);
    service.Action();
  }
}

public class ApplicationService
{
  private readonly IRepository repository;

  public ApplicationService(IRepository repository)
  {
    this.repository = repository;
  }
  
  public void Action()
  {
    this.repository.Action();
  }
}

public interface IRepository
{
  void Action();
}

public class Repository : IRepository
{
  public void Action()
  {
    System.Console.WriteLine("Repository action");
  }
}

public class FakeRepository : IRepository
{
  public void Action()
  {
    System.Console.WriteLine("Fake repository action");
  }
}

Sunday, September 20, 2009

Home Computer Setup

Recently entropy caught up with the Home Computer, and resulted in a reformatting and a replacement of the old 32 bit operating system with a new 64 bit operating system.
The strategy has changed to use virtual machines for specific purposes instead of installing everything on the physical machine.
So, now, this is the setup:

  • Physical machine: 64 bit laptop with 64 bit operating system, with:

    • 7-zip

    • AVG Anti Virus

    • Emacs

    • Google Chrome

    • MiKTeX

    • Mozilla Thunderbird

    • TortoiseSVN

    • VisualSVN Server

    • WinDirStat



  • Virtual machine for development, with:

    • AnkhSVN

    • Firefox

    • FxCop

    • NUnit

    • SqlServer

    • TortoiseSVN

    • Visual Studio



  • Virtual machine for tests and games.


Is it better? No.
Is it smarter? No.
Is it new? Yes, for me it is!

Thursday, July 9, 2009

History Based Estimation

Recently I started on a new programming project in my spare time. I call it History Based Estimation. It features a website to handle recording the elapsed time for tasks and using that to estimate future completion dates.

It is inspired by Joel Spolsky's Evidence Based Scheduling, which I've wanted to use since I read about it more than a year ago.

On my job we started using BugTracker.NET half a year ago, but that doesn't fill my need for the scheduling/estimating part. I started to write a web site in ASP.NET (web forms) three weeks ago, and open sourced it on SourceForge.net when I had something that looked like a start.

Features of History Based Estimation are currently:

  • Recording of projects, issues and tasks.

  • Prioritizing issues.

  • Recording estimates and time spent on tasks.

  • Chart with probability of completion dates.

  • Analysis of statistical average remaining time per issue.

  • Download of analysis in Word, Excel, and Latex formats.

  • Choice between English or Danish user interface.

  • Chart with historical task statistics (estimated time versus elapsed time).

  • Tracking of 'days off' when the person will be on holiday etc.



I think it is lacking in, at least, the following: There is no notion of person in the system. I.e. although it is possible for more than one person to use it, there is no authentication required and thus the system does not know who does what, who estimates what, and who has spent the time recorded.

Therefore, I hope to get more time to implement these features:

  • More than one person: I.e. record who is working on what and extract estimates per person.

  • Authentication linked to persons.



A technical note:


  • the web site is written in ASP.NET Web Forms

  • the business logic is written in C#

  • data is stored in a SQL Server database



As mentioned, the code is open source:

so if you would like to take a look at it, please follow the links. If you would like to give me feedback, or maybe even work on the code, please contact me.