Well here we are on Thursday and I am finally posting Tuesday’s video. When I started doing this I had no idea how long it would take to produce one of these videos. I have a pretty good idea now. ;)

In this installment I cover conventions, both ClassMap conventions and AutoMap conventions. I slowly convert the ClassMap implementation over to AutoMap by leaning on default convention and then adding my own as needed. This demonstration should give you a firm understanding of how conventions work in Fluent NHibernate.


 
Categories: Development | Fluent Interface | NHibernate | Tools

Hello Tuesday! Wait a minute this is Monday’s video. That’s right I spent so much time on Monday producing the Introduction video and planning the ClassMaps video, I didn’t get around to making Monday’s until Tuesday. But hey I am on vacation what are you expecting from me really?

So, today I am covering the topic of ClassMaps in Fluent NHibernate. I used Steve Bohlen’s Summer of NHibernate code from session 9 as a starting place. In this video you will see me get the code running on my machine, upgrade it to NHibernate 2.1.0 GA and then convert it over to using ClassMaps. The video clocks in at just over 30 minutes. Enjoy.


 
Categories: Development | Fluent Interface | NHibernate | Tools

Inspired by Steve Bohlen’s Summer of NHibernate screencast series, I thought I would spend some of my vacation creating an addendum to it called Vacation of Fluent NHibernate.

Links from the Screencast:


 
Categories: Development | Fluent Interface | NHibernate | Tools

October 22, 2009
@ 05:04 PM

While at Alliance, a couple team members and I got the bug to do Code Katas. We picked up on Roy Osherove’s TDD Kata and started doing it as a team every morning time boxing ourselves to half an hour.

The three of us would hit a conference room and throw an IDE up on the wall with a projector. One person would write tests, another would implement and the third would be the “Business” representative by reading the requirements and making judgment calls on any questions we had. Every morning we switched positions.

This worked out really well, one person would do something interesting one day and the others would pick up on it and start doing it as  well. For example, when creating a list of delimiters we all started out using a List<char>() because we couldn’t remember how to add a element to an array and didn’t want to take the time out of our thirty minutes to look it up. But then John, started using a string to hold our delimiters simply appending any extra ones on that were need. He then performed the split by using “delimiters.ToCharArray()”.

Terry, sick of writing the same setup code for the unit tests for each test, implemented a extension method that wrapped it up nicely so that all our tests were a single clear line.

This was a great way to practice TDD and to learn from my peers. I’ve moved on now from Alliance, but I am going to miss those guys. Hopefully, I’ll be able to get something similar going at the new gig. And, eventually recruit Terry and John… Just kidding, Craig. 8)

This video is just me, but it represents all the things we came up with to improve the design of our earlier solutions. It is also a great demonstration of using ReSharper and xUnit. Be sure to watch it in full screen, so that you can actually see what is going on. Next time, I’ll try some thing bigger. Anyone have tips?

And before you ask, yes you can have my crazy color scheme. 8) Oh I used Camtasia Studio 6 to produce the video. Great tool easy to use. Wish I had $300 to buy a license. 8) Well I’ll try to produce as many as I can in my 30 days.


 
Categories: Development | Unit Testing

Kata Potter is an interesting problem intended to be used as a learning exercise in TDD. The problem is described like this:

Once upon a time there was a series of 5 books about a very English hero called Harry. (At least when this Kata was invented, there were only 5. Since then they have multiplied) Children all over the world thought he was fantastic, and, of course, so did the publisher. So in a gesture of immense generosity to mankind, (and to increase sales) they set up the following pricing model to take advantage of Harry's magical powers.

One copy of any of the five books costs 8 EUR. If, however, you buy two different books from the series, you get a 5% discount on those two books. If you buy 3 different books, you get a 10% discount. With 4 different books, you get a 20% discount. If you go the whole hog, and buy all 5, you get a huge 25% discount.

Note that if you buy, say, four books, of which 3 are different titles, you get a 10% discount on the 3 that form part of a set, but the fourth book still costs 8 EUR.

Potter mania is sweeping the country and parents of teenagers everywhere are queuing up with shopping baskets overflowing with Potter books. Your mission is to write a piece of code to calculate the price of any conceivable shopping basket, giving as big a discount as possible.

I have been working on solving this kata over the last couple weeks. One goal I had was to understand how Machine.Specifications (MSpec for short) fits in to the BDD development process. MSpec is a framework written by Aaron Jensen that sits on top of your current unit testing framework (as long as you happen to be using NUnit or XUnit). You can read Aaron’s introduction to MSpec here where he does a much finer job at explaining it that I can.

My goal with MSpec was to be able to define the acceptance criteria for Kata Potter before writing a single line of implementation code. MSpec also has the added benefit of allowing me to execute my acceptance criteria on the code as it evolves and report back on my progress. With MSpec I can express what the system under test must do to satisfy all the requirements.

So given MSpec’s utility I started out to write a set of requirements based on the Kata Potter description.

  • Given a cart containing a single book when the price is calculated it should return the full price of the book.
  • Given a cart containing two different books when the price is calculated it should return the price of both books with a 5% discount applied.
  • Given a cart containing three different books when the price is calculated it should return the price of all books with a 10% discount applied.
  • Given a cart containing four different books when the price is calculated it should return the price of all books with a 20% discount applied.
  • Given a cart containing five different books when the price is calculated it should return the price of all books with a 25% discount applied.

This covers the full set of books, but the kata gives us another example:

  • Given a cart containing four books where two are the same title when the price is calculated it should return price of three books discounted by 10% and the full price of the fourth.

Using MSpec I can express these requirements in an executable fashion like this:

using Machine.Specifications;

namespace Kata.Potter.CoreTests.Specifications
{
    [Subject("calculating discount prices")]
    public class when_calculating_the_price_of_a_book
    {
        It should_return_the_full_price_of_the_book;
    }

    [Subject("calculating discount prices")]
    public class when_calculating_the_price_of_two_different_books
    {
        It should_apply_a_five_percent_discount;
    }

    [Subject("calculating discount prices")]
    public class when_calculating_the_price_of_three_different_books
    {
        It should_apply_a_ten_percent_discount;
    }

    [Subject("calculating discount prices")]
    public class when_calculating_the_price_of_four_different_books
    {
        It should_apply_a_twenty_percent_discount;
    }

    [Subject("calculating discount prices")]
    public class when_calculating_the_price_of_five_different_books
    {
        It should_apply_a_twenty_five_percent_discount;
    }

    [Subject("calculating discount prices")]
    public class when_calculating_the_price_of_four_books_where_two_are_the_same
    {
        It should_apply_a_twenty_percent_discount_to_three_of_the_books;
    }
}

With out a single line of code implementing these specifications, I can even execute my tests. I get the following display in the ReSharper test runner:

KataSpecs

Notice that the runner ignores all my tests currently returning the message that the specifications are “Not implemented”. As I write code to satisfy the requirements, the tests will being to go red and then green as each specification is implemented.

The next step in this process is to begin identifying collaborators in the system. Based on the requirements I know that I need objects that represent a Book, a Shopping Cart and a Calculator that calculates the price of all the books in the cart. I’ll begin by creating shell classes that I can use to wire up my specifications to implementation code.

public class Book
    {
        public Book(string title, decimal price)
        {
            Title = title;
            Price = price;
            IsDiscounted = false;
        }

        public string Title { get; private set; }
        public decimal Price { get; set; }
        public bool IsDiscounted { get; set; }
    }

    public class Cart
    {
        public Cart()
        {
            Books = new List<Book>();
        }

        public IList<Book> Books { get; private set; }

        public void AddBook(Book book)
        {
            Books.Add(book);
        }
    }

    public class PriceCalculator
    {
        public decimal CalculatePriceFor(Cart cart)
        {
            return 0;
        }
    }

With this simple implementation, I can now modify my MSpec specifications to exercise these objects. I’ll start with the first one to give you the feel of what it looks like.

[Subject("calculating discount prices")]
    public class when_calculating_the_price_of_a_book
    {
        private static Cart cart;
        private static PriceCalculator calculator;
        private static decimal price;

        Establish context = () =>
                                {
                                    cart = new Cart();
                                    cart.AddBook(new Book("Book 1", 8M));
                                    calculator = new PriceCalculator();
                                };
        Because of = () => price = calculator.CalculatePriceFor(cart);               

        It should_return_the_full_price_of_the_book = () => price.ShouldEqual(8);
    }

First, I establish my specification’s context by newing up my Cart and PriceCalculator classes and adding a single book to the cart. This establishes the environment that the test will run in which matches the name of the class pretty closely. I am calculating the price of a single book. Next, I clearly call out what action is performed to test against. I tell the calculator to calculate the price for the given cart. Finally, I make assertions on the state of my context objects. For this specification, all I need to do is validate that the calculated price is equal to the price of the book.

If I execute my specifications now, this spec will turn from ignored to red. I have now implemented the collaborators and weaved them into specifications to be validated. Here is what shows up in the ReSharper runner:

kataspecs2

The next thing we need to do is fill in the rest of the specifications and make them all turn red as well. If I do this following the pattern of the test we already have I am going to create a lot of duplicated code. Each specification class will have the same private members and most of the context as well. So first I am going to pull those elements out into a base class and refactor my first specification like so:

    public class with_price_calculator
    {
        protected static Cart cart;
        protected static PriceCalculator calculator;
        protected static decimal price;
        protected static decimal correctPrice;

        Establish context = () =>
                            {
                                cart = new Cart();
                                calculator = new PriceCalculator();
                            };
    }

    [Subject("calculating discount prices")]
    public class when_calculating_the_price_of_a_book : with_price_calculator
    {
        Establish context = () =>
                                {
                                    cart.AddBook(new Book("Book 1", 8M));
                                };
        Because of = () => price = calculator.CalculatePriceFor(cart);               

        It should_return_the_full_price_of_the_book = () => price.ShouldEqual(8);
    }

One of the cooler features of MSpec is the way it chains delegates together during execution. Notice that my base class has an Establish statement and my specifcation class has one as well. The specification class inherits from the base class but it does not override the Establish statement. Instead MSpec will execute all the Establish statements in the inheritance chain from the “base-ist” to the “descended-ist”. I can now implement the remaining specification quickly like this:

    public class with_price_calculator
    {
        protected static Cart cart;
        protected static PriceCalculator calculator;
        protected static decimal price;
        protected static decimal correctPrice;

        Establish context = () =>
                            {
                                cart = new Cart();
                                calculator = new PriceCalculator();
                            };
    }

    [Subject("calculating discount prices")]
    public class when_calculating_the_price_of_a_book : with_price_calculator
    {
        Establish context = () =>
                                {
                                    cart.AddBook(new Book("Book 1", 8M));
                                };
        Because of = () => price = calculator.CalculatePriceFor(cart);               

        It should_return_the_full_price_of_the_book = () => price.ShouldEqual(8);
    }

    [Subject("calculating discount prices")]
    public class when_calculating_the_price_of_two_different_books : with_price_calculator
    {
        Establish context = () =>
        {
            cart.AddBook(new Book("Book 1", 8M));
            cart.AddBook(new Book("Book 2", 8M));
            correctPrice = 8*2 - (8*2*.05M);
        };

        Because of = () => price = calculator.CalculatePriceFor(cart);

        It should_apply_a_five_percent_discount = () => price.ShouldEqual(correctPrice);
    }

    [Subject("calculating discount prices")]
    public class when_calculating_the_price_of_three_different_books : with_price_calculator
    {
        Establish context = () =>
        {
            cart.AddBook(new Book("Book 1", 8M));
            cart.AddBook(new Book("Book 2", 8M));
            cart.AddBook(new Book("Book 3", 8M));
            correctPrice = 8 * 3 - (8 * 3 * .1M);
        };

        Because of = () => price = calculator.CalculatePriceFor(cart);

        It should_apply_a_ten_percent_discount = () => price.ShouldEqual(correctPrice);
    }

    [Subject("calculating discount prices")]
    public class when_calculating_the_price_of_four_different_books : with_price_calculator
    {
        Establish context = () =>
        {
            cart.AddBook(new Book("Book 1", 8M));
            cart.AddBook(new Book("Book 2", 8M));
            cart.AddBook(new Book("Book 3", 8M));
            cart.AddBook(new Book("Book 4", 8M));
            correctPrice = 8 * 4 - (8 * 4 * .2M);
        };

        Because of = () => price = calculator.CalculatePriceFor(cart);
        It should_apply_a_twenty_percent_discount = () => price.ShouldEqual(correctPrice);
    }

    [Subject("calculating discount prices")]
    public class when_calculating_the_price_of_five_different_books : with_price_calculator
    {
        Establish context = () =>
        {
            cart.AddBook(new Book("Book 1", 8M));
            cart.AddBook(new Book("Book 2", 8M));
            cart.AddBook(new Book("Book 3", 8M));
            cart.AddBook(new Book("Book 4", 8M));
            cart.AddBook(new Book("Book 5", 8M));
            correctPrice = 8 * 5 - (8 * 5 * .25M);
        };

        Because of = () => price = calculator.CalculatePriceFor(cart);

        It should_apply_a_twenty_five_percent_discount = () => price.ShouldEqual(correctPrice);
    }

    [Subject("calculating discount prices")]
    public class when_calculating_the_price_of_four_books_where_two_are_the_same : with_price_calculator
    {
        Establish context = () =>
        {
            cart.AddBook(new Book("Book 1", 8M));
            cart.AddBook(new Book("Book 2", 8M));
            cart.AddBook(new Book("Book 3", 8M));
            cart.AddBook(new Book("Book 3", 8M));
            correctPrice = (8 * 3 - (8 * 3 * .1M)) + 8;
        };

        Because of = () => price = calculator.CalculatePriceFor(cart);

        It should_apply_a_ten_percent_discount_to_three_of_the_books = () => price.ShouldEqual(correctPrice);
    }

Note that I have added another member to the base class to capture what I think the correct price should be to then use as an assert later on. Executing my specifications now show all red. I can continue implementing functionality using traditional TDD or by writing more specifications for each collaborator using the same techniques.

Next time, I will cover the actual implementation that solves the kata potter that I arrived at through this process.


 
Categories: Development | Tools | Unit Testing

The South Sound .NET Users Group is pleased to present Microsoft’s Eric Lee on the evening of November 12th from 7:00 PM – 9:00PM at Olympia Center in downtown Olympia. This presentation promises to be an enlightening evening with not only an outstanding member of the .NET community offering sage advice, but also honest upfront discussion from a developer with over 15 years of experience working in the belly of Microsoft’s most successful divisions.

About Eric’s presentation “Common Anti-Patterns in Legacy Code”:

One of the most dreaded phrases in software engineering are the words “legacy code”.  You know what that means: old, nasty code that gives you ulcers and makes you tear our your hair.  In this presentation we’ll swap horror stories, discuss ways to make legacy code a little more manageable, and learn some principles that will help you avoid writing legacy code of your own.

About Eric Lee:

I’ve worked for Microsoft for over fifteen years as a developer of testing tools and other applications in the Office division and in Microsoft Game Studios.  I’ve inherited multiple legacy systems during my career and have had to suffer through the resulting pain.  I’m sad to say I’ve probably also written a legacy system or two.  As a result I have some opinions about the sorts of things that makes code either maintainable or a legacy nightmare.

 


View Larger Map


 
Categories: Development | Events | Local

Jeremy Miller has been commissioned by Addison Wesley to write a book on Presentation Patterns. He has chosen to do this the Martin Fowler way by using a wiki engine and making it available to the public as he writes it. This book is targeted directly at the “How”s of writing  desktop applications and rich clients using WPF and Silverlight. Here is a brief description from the site:

Inside of an enterprise application, the user interface layer can be very complex in its own right and is a huge source of potential bugs because of the element of human interaction. This book will present the design patterns that can be used to manage the complexity of user interface code. The book will discuss patterns for organizing the responsibilities of a single screen, coordinating the activities of multiple screens within an application, and architecting a structure that allows a desktop application to be efficiently extended over a longer lifecycle.


 
Categories: Development | Fundamentals

I love me some S#arp Architecture! I subscribe to the mailing list where users ask questions about it’s usage and I try to help when I can. Recently, Paul Hinett of UK Creative Designs asked the following question:

Hi Everyone.

I’m very new to NHibernate, Fluent & S#arp but I’m very keen to learn and have an idea of how OOP and DDD works.

One question I have though is if it’s possible to some way extend the IRepository class, at the moment it provides some basic CRUD functions such as Get, GetAll etc...

However, for this project I am creating for virtually every call to the database i need to pass  a SiteId to filter the data, i thought it would be easier to extend the IRepositroy class itself rather than creating 15-20 interfaces which inherit the IRepository class (like the Northwind example project has done for a couple of classes) and add my own functions.

Sorry if any of my terminology is incorrect, hope you understand what i mean!

Regards,
Paul Hinett

The entire thread is a good read and I suggest reading the whole thing for context. What Paul is talking about is a Multi-Tenant application. For a great tutorial on what muli-tenancy is check out Ayende’s excellent series on the subject which starts here and ends here. Sadly, Ayende never went back and finished his series on the topic, but he does still talk on the subject at conferences. I was lucky enough to attend his workshop at ALT.NET Seattle this year. He even has a sample application you can look that demonstrates the key concepts.

S#arp Architecture has multiple database support built in at the Repository level. What this means is that I can have a UserRepository that uses the default nhibernate configuration and then a separate ContentRepository using a different configuration. To accomplish this all you need to do is attribute your Repository with a SessionFactory key like this:

  [SessionFactory("content")]
  public class ContentRepository : Repository
  {  }

There is also some other configuration stuff you need to do for this to work, I’ll get to that in a bit.

What Paul wants to be able to do is to have NHibernate talk to different databases based on some bit of the URL. So, if the user accesses the site via http://www.havartirocks.com it talks to the HavartiCheese database, but if they come in using http://www.provaloneowns.com they talk to the ProvaloneCheese database. He ads the extra wrinkle in that he would like a third common database for things like User accounts.

The best way I have found to approach this kind of problem is to start with the domain and let it tell the infrastructure how to react to it. So given the following simple classes, I would like the User class to be persisted to a common core database and the Orders & LineItems classes to be persisted to their respective Tenant databases.

 
namespace CheeseStore.Core
{
  public class User : Entity
  {
    public virtual string Name { get; set; }
  }
  
  public class Order : Entity
  {
    public virtual DateTime OrderDate { get; set; }
    public virtual DateTime ShipDate { get; set; }
    public virtual IList Items { get; set; }
  }

  public class LineItem : Entity
  {
    public virtual string SKU { get; set; }
    public virtual int Quantity { get; set; }
  }
}

All of my domain classes inherit from the S#arp Architecture base class Entity. This gives me a lot of preconfigured persistence support via NHibernate for my domain classes. Next, I need some way in my domain to identify entities that are tenant specific. The simplest way to do this is with a marker interface. A marker interface has no implementation and as it’s name suggests it simply marks a class so that it is easy to detect via reflection. The above domain now looks like this:

 
namespace CheeseStore.Core
{
  public interface IAmTenantSpecific
  {  }

  public class User : Entity
  {
    public virtual string Name { get; set; }
  }
  
  public class Order : Entity, IAmTenantSpecific
  {
    public virtual DateTime OrderDate { get; set; }
    public virtual DateTime ShipDate { get; set; }
    public virtual IList Items { get; set; }
  }

  public class LineItem : Entity, IAmTenantSpecific
  {
    public virtual string SKU { get; set; }
    public virtual int Quantity { get; set; }
  }
}

We can now clearly see that Orders and LineItems are meant to be considered as multitenant objects. Since S#arp’s Repository<T> class doesn’t support switching databases on the fly, I need to create my own implementation class that will do this for me. I can inherit directly from Repository<T> and just override the bits I need.

 
namespace CheeseStore.Core
{
  public interface ITenantContext
  {
    string GetFactoryKey();
  }
}
namespace CheeseStore.Data
{
  public class MultiTenantRepository : Repository
  {
    private ITenantContext tenantContext;

    public MultiTenantRepository(ITenantContext tenantContext)
    {
      this.tenantContext = tenantContext;
    }

    protected override ISession Session
    {
      get
      {
        string factoryKey = tenantContext.GetFactoryKey();
        return factoryKey == null ? base.Session : NHibernateSession.CurrentFor(factoryKey);
      }
    }
  }
}

There are a couple interesting things going on here. First is the interface ITenantContext. You notice that it lives in the CheeseStore.Core namespace in a project of the same name. My application needs some way to determine what the tenant is, at this point I don’t really care how or where. I just want to define the contract that states that something will provide this bit of information for the Repository. Next, we have the MultiTenantRepository<T> it inherits form the S#arp provided Repository<T> implementation and simply overrides its Session property. This property relies on the tenant context to provide the key and then pulls it out of the S#arp provided session factory class. Finally, notice that the tenant context is provided though constructor injection. We will have to wire that up later once we have an implementation.

I can now easily create a Order specific repository like this:

namespace CheeseStore.Core.DataInterfaces
{
  public interface IOrderRepository
  {
    IList GetBySomeCriteria(int count);
  }
}

namespace CheeseStore.Data
{
  public class OrderRepository : MultiTenantRepository, IOrderRepository
  {
    public OrderRepository(ITenantContext tenantContext) : base(tenantContext)
    {
    }

    public IList GetBySomeCriteria(int count)
    {
      ICriteria criteria = Session.CreateCriteria(typeof(Order));
      return criteria.List();
    }
  }
}

This is exactly how the S#arp architecture documents instruct you to create a entity specific repository with a defining interface and implementation that leans on the base Repository class.

Next up we need a way to configure the S#arp NHibernate session factory factory with multiple configurations. This configuration is almost wired up for us already, we simply need to edit the InitalizeNHibernateSession() method in the Global.asax and add a couple tricky tweaks to the AutoPersistenceModelGenerator class to take advantage of our marker interface.

Here is the change to the Global:

    /// 
    /// If you need to communicate to multiple databases, you'd add a line to this method to
    /// initialize the other database as well.
    /// 
    private void InitializeNHibernateSession()
    {
      NHibernateSession.Init(
         new WebSessionStorage(this),
          new string[] { Server.MapPath("~/bin/CheeseStore.Data.dll") },
          new AutoPersistenceModelGenerator().GenerateCore(),
          Server.MapPath("~/Config/CoreNHibernate.config"));

      NHibernateSession.Init(
         new WebSessionStorage(this,"Tenant1"),
          new string[] { Server.MapPath("~/bin/CheeseStore.Data.dll") },
          new AutoPersistenceModelGenerator().Generate(),
          Server.MapPath("~/Config/Tenant1NHibernate.config"));
    }

Notice that I first initialize the default core session factory and then initialize a tenant factory providing an tenant key to identify them by. I could add as many tenants as I want right here. Also note that each factory uses a separate nhibernate.config file so you can tweak all you want. The final thing to notice here is the call to AutoPersistenceModelGenerator.GenerateCore(). This is the additional tweak I mentioned earlier.

We want to be able to configure each session factory with a different set of domain objects. The core needs only core entities and each tenant needs the full set of multi-tenant entities. Here is how I accomplished that:

namespace CheeseStore.Data.NHibernateMaps
{
  public class AutoPersistenceModelGenerator : IAutoPersistenceModelGenerator
  {
    private bool isTenantModel = true;

    public AutoPersistenceModel GenerateCore()
    {
      isTenantModel = false;
      return Generate();
    }

    public AutoPersistenceModel Generate()
    {
      AutoPersistenceModel mappings = AutoPersistenceModel
         .MapEntitiesFromAssemblyOf()
          .Where(GetAutoMappingFilter)
          .ConventionDiscovery.Setup(GetConventions())
          .WithSetup(GetSetup())
          .UseOverridesFromAssemblyOf();

      return mappings;
    }
   ...

    private bool GetAutoMappingFilter(Type t)
    {
      //see if the type is a tenant entity
      var tenantType = t.GetInterfaces().Any(x => x == typeof(IAmTenantSpecific));
      
      return t.GetInterfaces().Any(x =>
           x.IsGenericType && x.GetGenericTypeDefinition() == typeof(IEntityWithTypedId<>))
           && isTenantModel ? tenantType : !tenantType;
    }
    ...
  }
}

Here I have added a private member to indicate if we are generating a tenant model and a new method GenerateCore() that sets that property and calls the default functionality. I have also modified the GetAutoMappingFilter() method to divide my domain objects by the marker interface. Thus providing two totally different persistence models from one domain.

So far we started at the domain model and worked out way down to the data access layer. Next up we need to create a MVC Controller that uses our OrderRepository. No problem. It looks like every other controller with a dependency on a Repository.

namespace CheeseStore.Web.Controllers
{
  [HandleError]
  public class HomeController : Controller
  {
    private IOrderRepository orderRepository;

    public HomeController(IOrderRepository orderRepository)
    {
      this.orderRepository = orderRepository;
    }

    public ActionResult Index()
    {
      return View();
    }
  }
}

Notice that our controller knows nothing about the multi-tenancy work we have been doing. It requests a IOrderRepository and does what ever it needs to do with it completely ignorant of where the objects are being persisted or even how.

There is one thing left to do here. We still haven’t specified where the tenant context comes from. For this example, I will keep it simple and base the tenant id off of a query string parameter. It could just as easily be based on the domain or a sub-domain. Here is what that looks like:

namespace CheeseStore.Web
{
  public class TenantContext : ITenantContext
  {
    
    public string GetFactoryKey()
    {
      return HttpContext.Current.Request.QueryString.Get("tenantId");
    }
  }
}

It is that simple. This class actually lives in the ASP.NET MVC project. This allows the website to define how the tenant context is created.

If you are interested in taking a look at the complete solution you can download it here. A majority of what you see in the solution is auto generated by S#arp Architecture when you create a new project. So all credit goes to Billy and the other devs on S#arp for that. I have outlined my modifications above.


 
Categories: Development | NHibernate

Yo dawg! I have been working on a project with my wife the last few weeks. Since this is a totally personal project I am free to use whatever tools I want to use without having to justify my decisions to a team.

So I have been going nuts with the tooling. I set up a SVN repository on my Windows Home Server. I set up TeamCity and two separate CI builds using UppercuT that run NUnit tests, NCover code coverage analysis and NDepend reports. I am writing my app using ASP.NET MVC and the S#arp Architecture frameworks. Heck, I’ve even setup Selenium tests that get run every night. And I have NHibernate Profiler wired in there too JUST BECAUSE I CAN. It’s a lot of infrastructure set up for one page so far. 8)

So when I couldn’t get my single Selenium web test to pass in the TeamCity nightly build, I was a bit obsessed with figuring out why. Turns out, I had made a modification to a test base class that was causing the problem. I didn’t discover this issue when I created it because I typically don’t run Selenium tests prior to check in. I prefer to let the nightly build do that. So it took me a couple days to figure it out. Which prompted this post to Twitter which made its way to Facebook:

Yo Dawg, I heard your build failed because you refactored your unit tests. So, I wrote some unit tests for your unit tests, so you can...

To which my buddy Drew Welliver, an awesome developer over at L&I, commented:

Code so nice... I refactored it twice, then thrice, then.... At some point ya gotta wonder, wouldn't it have been easier to just run the application yerself and find the friggin' bugs?...

And followed up with:

And code coverage is cool, but scripts running code running scripts running code running scripts running... The users are still gonna break it, SOMEHOW....  And all that testing becomes academic.  The reality SEEMS to be that when I've worked on systems that used testing frameworks, their bug lists never seemed to be any shorter than the ones that didn't.

The Fallacy of Unit Testing Proving Quality

I don't think any TDD-er will say they don't produce bugs because they have tests. I would hope that it makes you think about your code a bit more and help you to discover more bugs prior to them getting out, but you never know if you are testing the right assumptions.

I do know that, if I have a bug and I write a test that demonstrates that bug, I know I have fixed it when that test passes and that that test gets run every time a check in is made to  source control, ensuring that bug never returns.

The value of unit tests is not only the immediate feed back that the code you are working on does what you think it does but also sustained confidence that that code still does what you think it does though out the life of the development effort and beyond.

Spending ten minutes writing a test that gets run thousands of times though out the life of the project and into the maintenance phase of the product lifecycle is value.

Additional Benefits

A tight feed back cycle between change=>flaw=>fix does yield better code. The wider your gap in feedback cycle the longer it will take you to fix the problem because you have to reestablish all that context.

If you have to monkey test over the course of days, how do you know what change might have caused the problem? (no offense to monkeys of course)

The bottom line comes down to this question:

 "Have you ever hesitated to make a change in a large system because you had no idea what effects it might have elsewhere in that system?"

A logical ,well thought out test suit gives you the confidence to make that change. If your tests start failing you simply back the change out right then and there and try something else while you have all the context for what you are working on.

The alternative of waiting days to weeks for unmotivated half qualified monkey testers to find that bug and then wondering which of the 40 change sets checked in during that time might have caused the issue is not one for me.

And Drew, I take you up on that beer offer brother. I am always down for testing out some beer.

UPDATE: And you want hard numbers? Here are some hard number for you.


 
Categories: Commentary | Development | Unit Testing

I was just reading Ayende’s post on coding pitfalls and it’s associated comments. This struck me as less about pitfalls and more about pet peeves. A personal pet peeve of mine is when I discover a block of code that makes multiple calls out to fetch a single value while processing.

For example:

if(Call.ToSomethingByName("Name") != "foo") {
  if(Call.ToSomethingByName("Name") !="bar")
    var something = Call.ToSomethingByName("Name");
    processNonFoos(something);
  else
    var someotherthing = Call.ToSomethingByName("Name");
    processFoos(something);
}

Just seeing this kind of construct tells me the person who wrote it was not thinking about anything other than “make it work”. They were so focused on getting the task at hand done and moving on they didn’t stop to think about the all the possible gotchas and potential failure cases.

This code was most likely tested by hitting F5, plugging some text into a form and clicking submit. As long as no errors were thrown the developer moves on to the next task.

Just looking at this code, how many possible failure points do you see? What happens if Call.ToSomethingByName(“Name”) return null? What happens if Call.ToSomethingByName(“Name”) makes calls to the database? What happens if Call.ToSomethingByName(“Name”) returns something different on each call?


 
Categories: Development | Fundamentals

The Norwegian Developers Conference was held last month on June 17-19th. From all accounts this conf was bordering on epic. The videos of each session have been posted on the website and it might be worth taking a look at them.

Some points of interest:

Michael Feathers

Scott Hanselman

Uncle Bob Martin

Udi Dahan

Ted Neward

Jeremy D. Miller

Roy Osherove

Ayende Rahien


 
Categories: Development | Events

I have been working a lot with JQuery recently. It is rapidly becoming a core library for doing client side scripting in our primary application.

I discovered a great video series last night intended to introduce you to JQuery from the ground up. The first one is located here. They are a great way to learn the basics.


 
Categories: Development | JQuery

During the Olympia Software Craftsmanship Workshop last weekend, Jeff Olsen (@olsonjeffery) demonstrated the use of the web testing framework Selenium. I was really impressed with the Selenium IDE and how easy it was to use in Firefox. One of the menu items of the IDE is to export a test as C#.

Export

This piqued my curiosity and I wanted to find out exactly what it takes for a .NET developer to get started using Selenium. This post is intended to help others get started.

First, a list of the stuff you will want to download:

You can get started right away by simply downloading the Selenium IDE for Firefox. There is a great tutorial here that will guide you through getting started. The other downloads are not required to use the IDE.

If you want to integrate your tests into your build process or write tests as if they were unit tests, you will need the two asterisked items at a minimum. The Selenium Remote Control comes in two parts. There is a server that runs under the Java Runtime Environment and several Client libraries for just about any flavor of programming you may prefer.

SeleniumRC

As, you can see I have added a batch script to launch the server on my local machine. The file contains a single command:

"C:\Program Files (x86)\Java\jre6\bin\java.exe" -jar selenium-server-1.0\selenium-server.jar

If you run the batch script, this is what you will see.

SeleniumRunning

Selenium is now listening on its default port of 4444 for commands from the client library. The server portion of Selenium can run anywhere. It would be fairly easy to set it up to run on a VM or on your build server with minimal effort.

So now let's write some tests. This blog has a built in administrative system. After you authenticate, a link bar is displayed with the various administrative tasks. A simple set of specifications, might look like this:

  1. When authenticating with valid credentials, the configuration menu link should be present.
  2. When authenticating with invalid credentials, the configuration menu link should not be present.

Let's start by creating a new test assembly. I called mine NotMyself.Blog.Specifications. Simply create a new Class Library and call it what ever you want. Next add references to nmock, nunit.core, nunit.framework and ThoughtWorks.Selenium.Core located in the selenium-dotnet-client-driver-1.0 folder in the Selenium Remote Control distribution.

References

I am not sure if there is a direct dependency on nmock or nunit for that mater. ThoughtWorks.Selenium.Core.dll is the meat & potatoes here. In a future post, I'll try getting up and running with MSTest or MBUnit.

To execute against the Selenium Server, we need to do some set up. The following base class demonstrates what is needed.

using System;
using System.Text;
using NUnit.Framework;
using Selenium;

namespace NotMyself.Blog.Specifications
{
public class SeleniumTestContext
{
protected ISelenium browser;
protected StringBuilder verificationErrors;

[SetUp]
public void SetupTest()
{
browser = new DefaultSelenium("localhost", 4444, "*iexplore", "http://iamnotmyself.com/");
browser.Start();
verificationErrors = new StringBuilder();

Context();
BecauseOf();
}

public virtual void Context() { }
public virtual void BecauseOf() { }
[TearDown]
public void TeardownTest()
{
try
{
browser.Stop();
}
catch (Exception)
{
// Ignore errors if unable to close the browser
}
Assert.AreEqual("", verificationErrors.ToString());
}
}
}

The above class sets up a couple fields and then news up a DefaultSelenium object. This object takes four constructor parameters; the URL hosting the Selenium Server, the port the server is running on, a string that represents the browser we want the tests run in (in this case IE, but we could use "*chrome" to use FireFox) and finally the root URL of the site we are testing.

Next up let's create a context for our authentication tests.

namespace NotMyself.Blog.Specifications
{
internal class AuthenticationContext : SeleniumTestContext
{
protected string authenticationUrl = "/notreallythe/pathtomy/page.aspx";
protected string badPassword = "reallynotmypassword";
protected string goodPassword = "notreallymypassword";
protected string userName = "notreallymyusername";
}
}

This class simply allow me to share some information across multiple test classes. Finally we are ready to write our tests.

using NUnit.Framework;

namespace NotMyself.Blog.Specifications
{
[TestFixture]
public class When_Authenticating_With_Valid_Credentials : AuthenticationContext
{
public override void BecauseOf()
{
browser.Open(authenticationUrl);
browser.Type("LoginBox_username", userName);
browser.Type("LoginBox_password", goodPassword);
browser.Click("LoginBox_doSignIn");
browser.WaitForPageToLoad("30000");
}

[Test]
public void The_Configuration_Menu_Link_Should_Be_Present()
{
Assert.IsTrue(browser.IsElementPresent("_ctl6_hyperLinkEditConfig"));
}
}

[TestFixture]
public class When_Authenticating_With_Invalid_Credentials : AuthenticationContext
{
public override void BecauseOf()
{
browser.Open(authenticationUrl);
browser.Type("LoginBox_username", userName);
browser.Type("LoginBox_password", badPassword);
browser.Click("LoginBox_doSignIn");
browser.WaitForPageToLoad("30000");
}

[Test]
public void The_Configuration_Menu_Link_Should_Not_Be_Present()
{
Assert.IsFalse(browser.IsElementPresent("_ctl6_hyperLinkEditConfig"));
}
}
}

These tests simply issue commands as if it were interacting directly with the browser telling it to open a URL, type some text into form fields, click a button. Validation works the same way, I interrogate the browser to see if specific elements exist.

Finally, all we have to do is fire up the Selenium Server by running the batch script, load up our test assembly into our favorite test runner and watch the tests execute. If you are running the Selenium Server locally you can sit back and watch the browser fire up and the tests execute right before your eyes. Very cool.

TestResults


 
Categories: Development | Tools | Unit Testing

A few friends and I from ALT.NET Seattle are putting on a software workshop right here in Olympia. Chris did a great job of describing it, so I will quote him:

Some of us folks from ALT.NET Seattle have been working on putting together a workshop for developers in Olympia, WA, focusing on Software Craftsmanship – which, to us, means caring about our craft and applying the principles we know work to what we are doing. The workshop is inspired by some of the discussions started in the much despised, “Why So Mean” session at the recent Seattle ALT.NET conference, as well as discussions in the follow up (and less controversial) “ALT.NET Pedagogy” session, as well as what @briandonahue has been doing in Philadelphia with the “Foundation Series.”

I am hoping this will raise the bar a little bit and get more people walking the walk. My view has always been that we all have to work together, so better to get everyone up to speed on what’s working and what’s not, and for as many people to be passionate and excited about the work they are doing as possible.

And here is the official announcement:

You’re at work and you catch yourself writing another 100 line method that you can’t test and really can’t even understand. You scour the Internet for ideas but there are so many ideas. Some say don’t test, others says don’t test anything, still others say test every keystroke! You just let your head drop to your desk with a solid thud. You think to yourself, “Is this really the best I can do?”

The Olympia Software Craftsmanship Workshop is one day workshop, developed with the intention of increasing the level of awareness of practices and skills that can improve our software.

Any developer interested in improving and learning new skills is welcome. If you can bring a laptop, please do. We will provide the software you need. If you can’t bring a laptop, don’t worry, you can pair up with someone who has one.

 

What: Olympia Software Craftsmanship Workshop

Where: Olympia Center, 222 Columbia St NW, Olympia, WA 98501

When: Saturday June 6, 2009.  10 am to 4 pm

How much does it cost? $25.00 to cover the cost of the facility and lunch. Seating is limited to the first 35 people to both register and submit a payment.

How do I sign up? Go to www.olympiasoftwarecraftsmanship.org

The workshop is hosted by members of the South Sound.NET users group and Alt.Net Seattle who want to help others build better software.

For more information: http://github.com/altnetseattle/olympia_software_craftsmanship_workshop/tree/master


 
Categories: Development | Events | Local

Earlier today, I blogged about a Kobayashi Maru situation I found myself in with the code base which must not be named. I was stuck making the choice between completely destabilizing our code base at the end of a sprint while trying to track down all the possible side effects of fixing the root cause of my problem or putting yet another little hack into our code.

Over lunch, I was describing the situation to Terry, one of our other developers. We came to the conclusion that we needed to go with the hack method to meet our obligations to the Scrum Master, but we should get the root cause of the issue in the backlog so we could resolve it later.

But this means that our hack would be in place in a fairly unobvious place and in 6 months when we get the item into the sprint backlog, we might fix the issue but forget to remove the hack.

Typically this is solved by adding a "TODO:" in the comments right by your hack to remind you to remove it in the future. Our code base is littered with them.

ToDoWTF

Notice the one from 2005. :-( And these are only the comments that happen to have "TODO:" in them. Obviously, we need a better way to remind ourselves to go back and take care of housekeeping tasks when we change the system.

Then Terry said, "Wouldn't it be awesome if we had a test that would fail if this condition changes?" and the light went off. We talked about it some more and as soon as I got back to the office, I created a new utility project called TestTools.HackToDos. I then wrote two specification style tests.

The first test demonstrates the low level call that causes the issue:

[TestClass]
public class When_Cleaning_A_DataTable_With_Null_Dates : GridViewHacksContext
{
protected override void BecauseOf()
{
Tools.Instance().CleanData(dataWithNulls);
}

[TestMethod]
public void The_Nulls_Will_Be_Converted_To_Invalid_Dates()
{
dataWithNulls.Rows[0].Field(0).ShouldEqual(DateTime.MinValue);
}
}

The second test demonstrates what I would like to happen:

[TestClass]
public class When_Binding_GridView_To_DataView_With_Invalid_Dates : GridViewHacksContext
{
protected override void BecauseOf()
{
Tools.Instance().CleanData(dataWithNulls);
grid.BindData(dataWithNulls.DefaultView, layoutManager.Columns);
}

[TestMethod]
public void The_Invaid_Date_Should_Be_Hacked_Out()
{
Assert.IsTrue(String.IsNullOrEmpty(grid.Rows[0].Cells[0].Text));
}
}

Running these tests resulted in the first test passing and the second failing. I then introduced my "hack fix" as a part of my extension methods to GridView:

private static void hackOutBadDates(GridView grid)
{
foreach (var row in grid.GridDataRows())
{
foreach (TableCell cell in row.Cells)
{
if (cell.Text.Contains(@"01/01/0001"))
cell.Text = null;
}
}
}

Now both tests pass. And my lovely jQuery awesome grid now displays null dates correctly.

yagniYAY

Now I can safely check this code in and feel like I performed my boy scout duty today without feeling dirty. In 6 months when someone on the team gets the sprint item to fix our goofy handling of null values in data tables, my first test is either going to fail or even fail to compile. That dev will go look at the test and find himself staring at this comment block:

/// 
/// TODO: this spec demonstrates a low level flaw in our dataaccess layer where
/// DateTime columns in a DataTable are set to a value of DateTime.MinValue
/// after every read. When we attempt to bind a Grid View to the resulting DataTable
/// null dates are displayed as "01/01/0001" which DateTime.Parse throws as invalid.
/// I have added a hack to our grid view extension methods that fixes this problem.
/// If these tests fails, it might be because we fixed the low level issue and
/// the hack should be removed along with these tests.
///

And there you have ToDos that are enforced by unit tests.


 
Categories: Development | Unit Testing

YAGNI, "you aren't gonna need it" (should maybe have a sub-principal of "will prolly come back around to bite you in the ass later"), is a principal that gets tossed around a lot to keep gold plating developers like me in check. I just love traveling down bunny trails adding "wouldn't it be cool if..." features to the code I am working on. I recognize this this fault in myself and routinely stop to ask myself, "why am I doing this?" or "how does this relate to the task at hand?" maybe even a "what effects could this have in other areas of the system?" on occasions where I am feeling extra saucy.

I wish someone had asked those questions of the person who wrote this code that I discovered deep in the bowls of "the code base that must not be named".

public void CleanData(DataRow row, int upperLimit)
{
if ((row == null))
{
return;
}

//Look at each field in this row
for (int i = 0; i <= upperLimit; i++)
{
//If this field is null, change the value of the field to some type of empty value
if ((row.ItemArray.GetValue(i)) == DBNull.Value)
{
// Handle all possible types of data in a datatable
switch (row.Table.Columns[i].DataType.Name)
{
case "Boolean":
row[i] = false;
break;

case "Byte":
row[i] = (byte) 0;
break;

case "Byte[]":
row[i] = 0;
break;

case "DateTime":
row[i] = DateTime.MinValue;
break;

case "Decimal":
row[i] = (decimal) 0;
break;

case "Double":
row[i] = (double) 0;
break;

case "Int16":
case "Int32":
case "Int64":
row[i] = Conversions.ToInteger(0);
break;

case "Long":
row[i] = Conversions.ToLong(0);
break;

case "Short":
row[i] = (short) 0;
break;

case "Single":
row[i] = (float) 0;
break;

case "String":
row[i] = "";
break;

//If a type shows up that is not handled, throw a meaningful exception
default:
throw new ArgumentException(string.Format(CultureInfo.InvariantCulture,
Resources.InvalidConversionDataType,
row.Table.Columns[i].DataType.Name));
}
}
 

Now at first glance, this doesn't seem that bad. A very nice example of gold plating. I can hear the developer now saying to him or herself, "wouldn't it be cool if we never had to check for DBNull? Seriously that would be jalapeno hot!"

I wonder if the developer was thinking about this possible unintended consequence that I am currently working to resolve.

yagnidoh

So, now I have nonsense dates being rendered out to my page. Trying to address this issue at the source, I commented out the line that sets dates to a min value in the clean data method to see what happens.

yagniuberdoh

Well that is interesting. To make it perfectly obvious _StaffMember is a hashtable. And the value of it's Staff_Lockout_Datetime key is and empty string. And this error is being caused by me switching a low level data clean up method to not change a null value to a invalid date.

So how is this hashtable created? Once again, deep in the bowls of the code base is a method called ToHashtable that takes a datarow and returns a hashtable. The interesting block of code is below.

 

For i As Integer = 0 To tableRow.Table.Columns.Count - 1

If tableRow.IsNull(i) Then

'Convert nulls to 0 or "" before putting in hashtable
Select Case tableRow.Table.Columns(i).DataType.Name

Case "Int64", "Int32", "Int16", "Decimal", "Double", "Single"

'Numeric data types
If convertDBNullIntToZero Then
ht.Add(tableRow.Table.Columns(i).ColumnName, 0)
Else
ht.Add(tableRow.Table.Columns(i).ColumnName, "")
End If

Case Else

'String, DateTime data types
ht.Add(tableRow.Table.Columns(i).ColumnName, "")

End Select

Else
'blah blah blah
End If
Next

 

So once again we have some gold plating here attempting to prevent other developers from having to check for null values. The interesting thing is why are we checking for nulls on a row that has already been though the clean process when the dataset was retrieved from the database? It seems to me this block of code has never been hit before today. Maybe our gold plate-ers are not comparing notes on all the filigree they are adorning our objects with.

The icing to this cake is the line of code where it all blows up. Look at it. What are they really trying to do?

If CDate(_StaffMember("Staff_Lockout_Datetime")) <> CDate(Nothing) Then

All they really want to know is if the hash table value is null. Exactly what our gold plate-ers have so desperately been trying to hide from us.

So I am left with two choices:

  1. Attempt to locate all the areas in the entire application where this gold plating has caused assumptions and correct them to let null dates make their way out the UI and hope like hell I don't introduce more bizarre side effects.
  2. Come up with some goofy databinding or prerender hack to work around the invalid dates.

Both options leave a bad taste in my mouth and a strong desire to drown my sorrows with a nice Irish whiskey.


 
Categories: Development | Fundamentals

This just might be the most awesome JavaScript I have written in the better part of a decade.

function sortEnd() {
$('thead th', this).each(function() {

var $className = $(this).attr('class');
var $anchor = $('a', this);
var titleText;

switch ($className) {
case "headerSortUp":
titleText = $anchor.text() + ', sorted acending';
break;
case "headerSortDown":
titleText = $anchor.text() + ', sorted decending';
break;
default:
titleText = $anchor.text() + ', sort by';
}

$anchor.attr('title', titleText);
$anchor.attr('alt', titleText);

});
};

 
Categories: Development

Just in case you missed it the Portland Code Camp is on for May 30th, 2009 at Reed College. It looks to be a great time already and is so far totally dominated by the ALT.NET movement.

Seattle's Justin Bozonier has posted a sessions on Artistic Expression Through Code and Solid Principles in Practice and TDD/BDD. Chris Bilson posted sessions on Client Side Rendering and F# - It's Not Just for Scientists. I personally am planning on doing my Beginning Dependency Injection talk as well as something new that I am working on that is an Introduction to ORM and nHibernate.


 
Categories: Development | Events | Local | Shameless Plug

I am a OSS enthusiast and want to use tools like nHibernate in my daily application development practices. What I am not is a CIO or Architect at my company. There are several roadblocks, misconceptions and valid concerns that are raise when I suggest using an OSS tool in one of our projects. One of the biggest concerns I have heard is that of responsibility. The question usually is phrased like this:


"When we encounter a blocking bug what do we do?"


The overwhelming OSS response to this is: "Fix it yourself and submit a patch." And this is where I lose management. Management doesn't want to take on the responsibilities of fixing platform bugs. In their eyes it is much easier to purchase packages from vendors who take on those responsibilities. The role of tools like nHibernate, Ninject or even Prism in my environment is to allow me to focus on business value and functionality. We are not a platform company.


I want to find a solution to this problem, and I think it falls down to money. My company is willing to pay good money to a vendor for a tool that allows us to deliver business value quickly. I wonder if that same cash flow relationship could be applied to OSS.

Say, I have to make a choice between vendor Product X and nHibernate for ORM. Product X requires a license fee of $1000 per developer. I chose nHibernate and put my $1000 per developer in the bank as a emergency fund.

Six months later, I encounter a bug or blocking problem in nHibernate that is going to prevent me from releasing my product. I can't fix it myself. I do not have the time or the skill needed to do so. I create a test case for the problem and submit it with a portion of my emergency fund to the community for a solution.

My question is, do you think anyone would accept it? What if we wanted them to be contractually obligated to fix the bug upon acceptance? Is anyone out there currently doing this? Would any of the current developers want to do this? Is this a viable alternative to vendor software here?

So here is a list of the OSS tools I would like to use. Anyone out there willing to commit to saying, "Yes, if you can provide me with a test case, I can provide you with a fix for that OSS tool. I charge $X amount per hour or this flat fee."

  • nHibernate
  • Fluent nHibernate
  • Castle Winsor
  • Ninject
  • Rhino.Security
  • Prism
  • MVC Contrib
  • Caliburn

If your particular pet OSS project is not listed, I would still like to hear from you. This list came of the top of my head from what I am currently interested in.


 
Categories: Development | Tools

I have two silverlight assemblies, CaseManager.Applet and CaseManager.Applet.Sample. The Sample assembly has a reference to the base Applet assembly. The sample assembly has an embedded resource png image. The base applet assembly has a view xaml that I wish to display that image programmatically.

In the sample assembly I have a bit of code that creates a Uri like so:

private void RegisterIcon()
{

var icon = new AppletIcon()
{
ImageUri = new Uri("CaseManager.Applet.Sample;component/images/guiness_2.png", UriKind.Relative),
ModuleType = GetType(),
Text = "Sample Module"
};

container.RegisterInstance("SampleModule", icon);
}

 

When I execute this code all the properties of ImageUri throw InvalidOperationException. I am not sure why. I have a hunch that it has to do with the way the assemblies are referencing each other in one direction. Anyone have suggestions?

 

Update: ok I found it by using the googles searching for WPF instead of silverlight info. The following code does the job:

 

ImageUri = new Uri("/CaseManager.Applet.Sample;component/images/guiness_2.png", UriKind.Relative),

Things to note here:

  • The slash at the start of the Uri string.
  • The short name of the assembly containing the resource.
  • the ;component/ section.

From there it is basically the path inside your project to the image. Hope this helps someone else.

For what it was worth I was missing the very first slash. /facepalm
 

Categories: Development | Silverlight

My company is investigating a dramatic shift in our product offering. We are looking at offering a SAAS product delivered via Silverlight. Our current offering is a large scale  classic ASP.NET case management system that is installed on site with the client and heavily customized. Our SAAS application is intended to start as a scaled down version of this application.

One of our main goals was to produce a highly modularized application that has been described as "simple widgets of functionality" that are driven by tasks instead of long menu trees. Our source of inspiration is the iPhone and it's clean interface.

Using the amazing Balsamiq, I generated a couple mock ups of a possible UI. I needed something concrete to work toward while learning WPF & Silverlight and modifying my mind set from stateless web mentality.

Desktop 

Side Note: Balsamiq is AWESOME. If you have not tried it go now and do it this blog post will wait.

These high level vision statements lead me down the path of a component based UI. I have had a copy of the Composite Application Guidance for WPF sitting on my desk for a couple of months, so I thought I would give that a chance. I then created a separate version of my mock up that described the areas and their function with in the context of a "desktop" screen.

areas

I then downloaded Prism & Unity and with a copy of Silverlight 2 in Action, I began my journey into the bowels of XAML and figuring out exactly how layout works. After a day or so of discovery with the Canvas, Grid & StackPanel controls I came up with this. It's a fairly simple layout consisting of five rows and a hidden control for user notifications. Working with XAML was very difficult for me at first as I wanted to resist table based layouts like the plague due to my HTML bigotry. But once I gave in, I started making progress.

One goal I had was to explore Prism's Region types and how they interact with the UI. In my application shell I had defined regions for each of the major areas of the UI and I wanted to create a "Place Holder" view that I could populate each of the regions with that would give me some information at runtime.

Following the Prism sample code, I created a ApplicationModule class which would represents the Applications role in the UI modularity. This module is the first to load and set default values within the application before moving on to interrogate other assemblies for other modules. One thing the application module does is to set all regions to a default place holder view like so:

 

public class ApplicationModule : IModule
{
private readonly IUnityContainer container;
private readonly IRegionManager regionManager;
private readonly IRegionViewRegistry regionViewRegistry;

public ApplicationModule(IUnityContainer container,
IRegionManager regionManager,
IRegionViewRegistry regionViewRegistry)
{
this.container = container;
this.regionManager = regionManager;
this.regionViewRegistry = regionViewRegistry;
}

#region IModule Members

public void Initialize()
{
RegisterTypesAndServices();
RegisterViewsWithRegions();
}

private void RegisterViewsWithRegions()
{
//registering placeholders with current regions
this.regionManager.RegisterViewWithRegion(RegionNames.Branding,
() => this.container.Resolve().View);
this.regionManager.RegisterViewWithRegion(RegionNames.Menu,
() => this.container.Resolve().View);
this.regionManager.RegisterViewWithRegion(RegionNames.Breadcrumb,
() => this.container.Resolve().View);
this.regionManager.RegisterViewWithRegion(RegionNames.Content,
() => this.container.Resolve().View);
this.regionManager.RegisterViewWithRegion(RegionNames.SystemNotification,
() => this.container.Resolve().View);
this.regionManager.RegisterViewWithRegion(RegionNames.UserNotification,
() => this.container.Resolve().View);

}

private void RegisterTypesAndServices()
{
this.container.RegisterType();

}

#endregion
}

I then wanted my place holder view to display a bit of information about its current context. Specifically I wanted the view to tell me what region it belonged to and its current dimensions. The XAML for this is not even worth looking at, it's a user control with a text block. The problem I ran into was getting any kind of information about the current context of the user control. My first attempt lead me to the VisualTreeHelper class and this code:

 

var parent = VisualTreeHelper.GetParent(this) as FrameworkElement;
this.PlaceHolderText.Text = parent.Name ?? "Placeholder";

 

This basically left me with a blank screen. Interesting enough the parent of my user control was not the region that contained it but a stack panel with no name that is not even defined in the XAML. It appears that the region is not a UI element so much as a concept within prism. After a couple hours of working with this I was stumped and hit the twitterverse to see if Glenn Block might offer a suggestion.

Glenn was the PM at Microsoft for the Composite Application Guidance for WPF. Seriously his name features prominently on the Authors page. If anyone could point me in the right direction, it would be this guy. It was somewhat of an obvious noob question, but I was very focused on the application DOM. He suggested that I check out the RegionManager.

After fiddling around with the region manager I came up with this:

public partial class PlaceholderView : UserControl, IPlaceholderView
{
private IRegionManager regionManager;

public PlaceholderView(IRegionManager regionManager)
{
InitializeComponent();
this.regionManager = regionManager;
}


private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
foreach (IRegion region in regionManager.Regions)
{
foreach (UserControl view in region.Views)
{
if (view == this)
{
PlaceHolderText.Text =
string.Format("{0} PlaceHolder : {1}x{2}",
region.Name, view.RenderSize.Width, view.RenderSize.Height);
return;
}
}
}
}
}

 

This almost has me there. For some reason, I get the correct width of the region my user control is inhabiting but the height always reports as zero. I am sure it has to do with how I have structured my application shell and plan to track this one down today.

In the end, I really like Silverlight. Prism allowed me to put something together fast based on a mock up and has DI baked in in a nice way.


 
Categories: Development | Tools

I will be attending the ALT.NET Seattle 2009 Conference this weekend February 27th - March 1st at the DigiPen Campus in Redmond, WA. If any ALT.NET people want to get together for lunch or dinner while I am there feel free to contact me via the plethora of options to the right. I will be in full on geek out mode and happy to talk with you.

Looking forward to seeing everybody.

UPDATE: I just realized I posted this with the wrong date... No wonder no body was looking for me. 8(


 
Categories: Development | Events | Local

I was asked by a few people for access to my slide deck and code samples, so here they are.

The walk though of Dependency Injection by hand and how to use Ninject was directly adapted from the documentation for Ninject written by the amazing Nate Kohari.

To learn more about the SOLID principals check out Robert "Uncle Bob" Martin's original white papers on the subject or pick up the book Agile Principals, Patterns and Practices in C#.

If you are interested in playing with an IoC container, here is the list I discussed last night:

I had a ton of fun last night, thanks for listening to me ramble.


 
Categories: Development | Events | Local

I'll be presenting on the topic of Dependency Injection at the South Sound .NET Users Group on February 12th, 2009. In an effort to beef up my presentation to close to two hours, I decided to give a brief introduction to the S.O.L.I.D. Principals as described by Uncle Bob Martin as supporting material/introduction to Inversion of Control and Dependency Injection.

You can find the the first post in this series here:

S.O.L.I.D. By Example: Single Responsibility Principal

The Single Responsibility Principal demonstrated how to keep classes simple, focused and uncluttered. The Open Closed Principal is about protecting behavior that we know works. OCP states:

You should be able to extend a classes behavior, without modifying it.

Let's jump right into the example to demonstrate the difference. Imagine that we are given a specification for an order service that saves orders to a database. Our initial implementation might look something like this:

 

public class OrderService
{
private readonly OrderRepository _orderRepository;

public OrderService(OrderRepository orderRepository)
{
_orderRepository = orderRepository;
}

public bool SaveOrder(Order order)
{
if (order.IsValid)
{
_orderRepository.Save(order);
}
return true;
}
}

 

We have a simple order service that verifies an order is valid and then saves it to an order repository. Pretty clean and it appears to conform with SRP. Good times!

Two months later we get an addendum to the specification that states the company would like the order service to also send a confirmation email out when the order is accepted and saved to the database.

No problem! We start hacking away and come up with version 2 of our class:

public class OrderService
{
private readonly EmailService _emailService;
private readonly OrderRepository _orderRepository;

public OrderService(EmailService emailService, OrderRepository orderRepository)
{
_emailService = emailService;
_orderRepository = orderRepository;
}

public bool SaveOrder(Order order)
{
if (order.IsValid)
{
_orderRepository.Save(order);
}
if (Configuration.SendEmailConfirmation)
{
_emailService.SendConfirmation(order);
}
return true;
}
}

In our edits we have modified our order service and added a dependency on a new class called email service. We have also modified the save order method to use the new email service. We also added to the complexity of the class by adding additional branching logic in the body of the save order method.

So in essence we took a class that had been written, presumably tested and functioning fine for a couple months and modified its behavior potentially breaking not only the new specification but the original at the same time.

Instead, we could approach the problem a different way to preserve the working functionality of the order service class but add additional behavior to it by extending the class.

All we would need to do is modify the original class like this:

public class OrderService
{
private readonly OrderRepository _orderRepository;

public OrderService(OrderRepository orderRepository)
{
_orderRepository = orderRepository;
}

public virtual bool SaveOrder(Order order)
{
if (order.IsValid)
{
_orderRepository.Save(order);
}
return true;
}

Note that the save order method has been marked as virtual. This allows us to provide an alternative implementation. You can look at this as opening the class up to extension of its behavior.

So to add the new specified behavior we simply inherit from order service and override the save order method like this:

public class EmailingOrderService : OrderService
{
private readonly EmailService _emailService;

public EmailingOrderService(EmailService emailService,
OrderRepository orderRepository)
: base(orderRepository)
{
_emailService = emailService;
}

public override bool SaveOrder(Order order)
{
if (base.SaveOrder(order))
{
_emailService.SendConfirmation(order);
}
return true;
}

 

We create a new emailing order service that inherits from order service. The constructor has a dependency on the original order repository which it passes along to its base class. It also adds a new dependency on email service.

The new implementation of save order delegates the saving of the order to its base class and then uses the email service to send the email confirmation.

So we have effectively added the new behavior in such a way that we are not potentially breaking the original object. We have also prevented the addition of branching complexity and overall lines of code within the save order methods.


 
Categories: Development | Fundamentals

Please join us Thursday, February 12th, to eat pizza and enjoy a informative presentation by Bobby Johnson on Dependency Injection: A Beginners Guild to Why Ninjas Are Awesome


Special thanks to Alliance Enterprises for providing pizza.


Presentation Summary
This presentation will describe the core concepts of  Dependency Injection (DI), first described by Martin Fowler in his article Inversion of Control (IoC) Containers and the Dependency Injection Pattern.


The presentation will highlight the benefits of Dependency Injection including:

  • Creating classes that are easier to unit test in isolation
  • Promotes loose coupling between classes and subsystems
  • Adds potential flexibility to a codebase for future changes
  • Can enable better code reuse


Bobby will also be sharing simple and fun examples on how to use DI along with a real world example of its use in a web-based application.


Speaker Bio
Bobby Johnson is a Senior Software Developer at Alliance Enterprises, a performance management software company based in Lacey, Washington.  As an avid enthusiast of Agile methods and a self proclaimed code monkey, Bobby is currently focused on overseeing the  implementation of Agile techniques like DDD, TDD, CI into Alliance's software and quality engineering processes.  Prior to joining Alliance, Bobby worked at the Washington State Department of Labor & Industries as a  Development Specialist.


To find out more about Bobby and his technical misadventures visit his blog at www.iamnotmyself.com
Meeting Specifics
February 12th, 7 - 9 pm
Olympia Center (222 Columbia NW)


All attendees are eligible for the prize drawings. Past prizes have included technical books, passes to Devscovery, copies of Visual Studio, Vista, Office 2007 and more.


Don't forget to let your friends and co-workers know about this meeting.  Feel free to forward this email and/or direct them to www.ssdotnet.org for more information.

That's right b@#$%es, I'm packing a posse and they are bringing the pizza.


 
Categories: Development | Events | Local

I'll be presenting on the topic of Dependency Injection at the South Sound .NET Users Group on February 12th, 2009. In an effort to beef up my presentation to close to two hours, I decided to give a brief introduction to the S.O.L.I.D. Principals as described by Uncle Bob Martin as supporting material/introduction to Inversion of Control and Dependency Injection.

 

I sat down last night and started writing sample code that demonstrated each of the principals. The first being, the Single Responsibility Principal.

"A class should have one, and only one reason to change."

For example, let's take a look at the following User class:

 

namespace Sample.BigBallOfMud
{
public class User
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }

public string GenerateUpdate()
{
return String.Format(
"UPDATE Users SET FirstName='{0}', LastName='{1}' WHERE Id={2}",
FirstName, LastName, Id);
}

public string GenerateDelete()
{
return String.Format(
"DELETE FROM Users WHERE Id={0}", Id);
}

public string GenrateInsert()
{
if (Id != 0)
throw new InvalidOperationException(
String.Format(
"This user already exists with an ID of {0}",
Id));

return String.Format(
"INSERT INTO Users VALUES ({0},{1})",
FirstName, LastName);
}

public bool IsValid()
{
return !String.IsNullOrEmpty(FirstName) &&
!String.IsNullOrEmpty(LastName);
}
}
}

 

This class represents a user and various functions that related to the concept of user. In the context of SRP this class has three distinct responsibilities:

  1. Uniquely identify and represent a user in the system.
  2. Map the user to various SQL statements for interaction with the database.
  3. Validate that the user is valid based on some business specification.

SRP tells us that each of these responsibilities should be in a separate class. Uncle Bob explains this principal best:

"Because each responsibility is an axis of change. When the requirements change, that
change will be manifest through a change in responsibility amongst the classes. If a class
assumes more than one responsibility, then there will be more than one reason for it to
change.


If a class has more then one responsibility, then the responsibilities become coupled.
Changes to one responsibility may impair or inhibit the class’ ability to meet the others.
This kind of coupling leads to fragile designs that break in unexpected ways when
changed."

Given this principal let's consider the following refactoring of the user class:

namespace Sample.SOLID
{
public class User
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}

public class UserSQLMapper
{
private readonly User _user;

public UserSQLMapper(User user)
{
_user = user;
}

public string GenerateUpdate()
{
return String.Format(
"UPDATE Users SET FirstName='{0}', LastName='{1}' WHERE Id={2}",
_user.FirstName, _user.LastName, _user.Id);
}

public string GenerateDelete()
{
return String.Format(
"DELETE FROM Users WHERE Id={0}",
_user.Id);
}

public string GenrateInsert()
{
if (_user.Id != 0)
throw new InvalidOperationException(
String.Format("This user already exists with an ID of {0}",
_user.Id));

return String.Format(
"INSERT INTO Users VALUES ({0},{1})",
_user.FirstName, _user.LastName);
}
}

public class ValidUserSpecification
{
public bool IsSatisifedBy(User user)
{
return !String.IsNullOrEmpty(user.FirstName) &&
!String.IsNullOrEmpty(user.LastName);
}
}
}

 

We now have three very specific class that are descriptive of what their responsibilities are. The User class has been decoupled from database concerns and validation concerns. It clearly represents a single concept and only needs to change when we redefine what a User is.

Database mapping concerns have been encapsulated in the UserSQLMapper class. It's sole responsibility is to map a user to various sql statements. The only reason for this class to chance is a Schema change in the database. At first glance you might say it has an additional change vector of the User class. But if we add additional properties to User, the UserSQLMapper only needs to care if we are mapping that property to the database. If we are mapping to the database, the schema has changed. So one responsibility there.

Validation of the User class has been broken out into a Specification class called ValidUserSpecification. It's responsibility is pretty clear. It answers the question, "Is this a valid user?". Specifications in this style are a nice way to do validation rules, but I'll save that for another post.

BONUS: One aspect of SRP that is not very clear from this example, is how it can lead to better design through refactoring.

One of the most common complaints about SRP is object explosion. If I am constantly breaking classes down into single responsibilities, won't I trade the complexity of large objects for the complexity of thousands of little objects?

This is a valid concern. But consider our example above. Imagine we now have 10 classes that have been broken down in this same Entity, Mapper, Specification way giving us 30. Would it not be possible to look at the set of 10 mapping classes and reduce them down to some smaller subset of classes that perform the responsibility in a generic fashion?

When things are broken down by concern like this it is far easier to consider the concern in isolation and come up with a better design for that single concern.


 
Categories: Development | Fundamentals

January 30, 2009
@ 01:50 PM

Here is the gist of what I was trying to accomplish. Please excuse the VB.. it's not by choice. 8)

Basically the page I was working on has a set of switch statements based on string literals which annoys me.. So I was messing around with a way to use Enumerations to represent my commands. But the commands come back as strings from the various page controls.. So I was looking at a way to generically re-map back to the command Enumeration.

Private Function GetCommand(Of T)(ByVal commandName As String) As T
Return CType([Enum].Parse(GetType(T), commandName), T)
End Function

Protected Enum GridCommand
CompetencySelect
FormSelect
Sort
End Enum

Public Overrides Sub Grid_Commands(ByVal source As Object, _
ByVal e As DataGridCommandEventArgs) _
Handles CompetencyData.ItemCommand, FormData.ItemCommand
If Page_Save() Then

Select Case GetCommand(Of GridCommand)(e.CommandName)

Case GridCommand.CompetencySelect
NavigateToCompetencySelection( _
CInt(CompetencyData.DataKeys(e.Item.ItemIndex)), _
CompetencyData.ID)

Case GridCommand.FormSelect
NavigateToFormSelection( _
CInt(FormData.DataKeys(e.Item.ItemIndex)), _
FormData.ID)

End Select
End If

End Sub

 
Categories: Development | Random

January 9, 2009
@ 08:15 AM

I was reading Oren's excellent series of posts on Multi Tenancy located here. It seems like he is just building up a good head of steam when the posts stop. Was Multi Tenancy - Approaches and Applicability the last one in the series?

Before you jump on me for not utilizing my google skills, a query of "site:ayende.com Multi Tenancy" does not return anything I have not already read. Did he stop cold turkey in the middle of the series? Or did he switch his post title scheme?


Does anyone have suggestions on other sources for this kind of information? I am specifically interested in multi tenant applications with separate databases with nhibernate as well as DDD approaches to extensible schemas.


A pointer in the right direction would be greatly appreciated.


 
Categories: Development | NHibernate

January 4, 2009
@ 10:26 AM

There are several upcoming ALT.NET Seattle events. Meetings are open to any developer who is passionate about writing software and eager to get better and it. You don't need permission or an invite to show up. Simply show up and participate.

Our meetings are somewhat different from the Olympia .NET Users Group in that we typically don't have a set presenter. We are all presenters. We follow an Open Spaces format. You probably also won't find many demonstrations of Visual Studio RAD tools either. Here are a sampling of topics that I have attended:

  • TDD/BDD
  • Dependancy Injection
  • GIT Source Control
  • ASP.NET MVC
  • NHibernate
  • MEF
  • Continuous Integration/Improvement
  • Agile Adoption

Meetings are held at the Microsoft Westlake Avenue office. The meetings are usually held from 10:00 AM - 5:00PM on a Saturday. The next meeting appears to be on the 17th of January. The February meeting appears to be getting lined up for the 7th but may be postponed to the lager ALT.NET Seattle 2009 Conf.

The ALT.NET Seattle 2009 Conf was just announced this week. It is planned for the weekend prior to the Microsoft MVP Summit, February 27th - March 1st. Registration opens at 6:00PM PST, Tuesday January 6th here. Admission is free, but space is limited to the first 150 people to register.


 
Categories: Development | Events | Local

Please join us Thursday, January 8th for Ade Miller's (twitter) presentation on Continuous Integration and Defense In Depth: Experiences at Microsoft.

Presentation Summary
Continuous Integration (CI) is the practice of building and testing the application under development. Usually right after each and every check-in. CI grew out of the agile software development community but can add value to almost any project. This talk will describe the basic approach to CI and also some other practices teams can adopt to get even more out of their investment in CI. The talk will also cover the Microsoft patterns & practices team’s experience with CI and show some of the likely cost savings of adopting this practice on your team.

Speaker Bio
Ade Miller is currently the Development Manager for Microsoft’s Patterns & Practices group (P&P) where he manages several agile teams executing on a variety of projects. He also lead the development of the P&P Web Services Software Factory: Modeling Edition. Before joining P&P Ade was a developer and then a Development Lead on Visual Studio Tools for Office 2005 and 2008.


Prior to joining Microsoft Ade worked in a variety of development environments including start-ups, consultancy and web publishing. His primary interest is in improving the way people develop software. He spends much of his time trying to figure out what being “agile” really means. Ade is a regular speaker on these topics, he also blogs and writes about his experiences. Ade received his BSc and PhD in Physics from the University of Southampton, UK.


Meeting Specifics
January 8th, 7 - 9 pm
Olympia Center (222 Columbia NW)


All attendees are eligible for the prize drawings. Past prizes have included technical books, passes to Devscovery, copies of Visual Studio, Vista, Office 2007 and more.
Don't forget to let your friends and co-workers know about this meeting.  Feel free to forward this email and/or direct them to www.ssdotnet.org for more information.


 
Categories: Development | Events | Local

It looks like Glenn let the cat out of the bag so to speak. ALT.NET Seattle 2009 is on and I am a part of the organizing committee.

This year's event is planned for the weekend prior to the Microsoft MVP Summit, February 27th through March 1st of 2009. We intend to follow the same Open Spaces format as in previous years with the addition of a keynote speaker on the first day. We have secured the Digipen Institute in Redmond, Washington as our location.

We will be opening registration at the beginning of the month. 130 seats will be made available to the public with an additional allotment reserved for special guests including sponsors.

From Glenn's site here are the details so far:

  • What: ALT.NET Seattle 2009. (The site is still being worked on. Thanks to Justin Bonozier and Shoshanah Bain for getting the site up).
  • Where: Digipen (thanks to Jeff Tucker for lining up the space)
  • When: Evening February 27th through March 1st.
  • Registration: Opens this Tuesday evening at 6PM. We're holding on registration to allow the word to spread. There will be a max of 150 attendees. Check the wiki on Tuesday for details.

I'll be handling organizing sponsors, so if your company is interested and have not been contact by me already shoot me an email to hash out details.

There are three levels of sponsorship:

  • Gold – $1000
  • Silver – $500
  • Bronze – $250

In exchange for being a sponsor, we will offer you the following:

  1. Attendance to the event. We will reserve a seat at the conference for your representative to attend.
  2. Your company banner featured on our web site, and at the event (You will need to supply the banner).
  3. A table at the conference where you can have some promotional material.
  4. Recognition at the event for being a sponsor.

You can reach me at: bobbyDOTjohnsonATgmailDOTcom.


 
Categories: Development | Events | Local

December 12, 2008
@ 04:25 PM
Writing this today completely baked my noodle:
 public class ClassMapTester
{
protected XmlElement currentElement;
protected XmlDocument document;
protected XmlNamespaceManager mgr;


public ClassMapTester ForString(string input)
{
document = new XmlDocument();
document.LoadXml(input);
return For(document);
}

public ClassMapTester For(XmlDocument doc)
{
document = doc;
SetNameSpaceManager();
return this;
}

public ClassMapTester For() where A : ClassMap, new()
{
For(new A().CreateMapping(new MappingVisitor()));
return this;
}

private void SetNameSpaceManager()
{
mgr = new XmlNamespaceManager(new NameTable());
mgr.AddNamespace("urn", "urn:nhibernate-mapping-2.2");
}

//....
}

Which allow me to write a Fluent-Nhhbernate ClassMap unit test like this:

[Test]
public void LanguageMap_Creates_Valid_Mapping()
{
new ClassMapTester().For()
.TestDefaultConventions()
.TestProperty("LanguageName", "8", "true").Exists()
.TestProperty("LanguageDisplayName", "50", "true").Exists();
}

 

Someone linked the Oxide Channel 9 video yesterday either on Twitter or in IRC. I don't quite remember who. I was intrigued  after watching the video and have been wanting a good excuse to seriously play around with ASP.NET MVC. I have been wanting to hop blog engines from dasBlog for a while now and Oxide appears to have all the features I use. So I downloaded the bits and started looking around.

Oxide is a fairly straight forward blog engine built on MVC. All the standard features are there including RSS, Trackbacks, Comments and Windows Live Writer support via MetaWebLog API. Oxide also uses a provider model for most of its major functionality, so building alternatives is pretty easy as well.

By default the data access layer is build on Linq To Sql, which I found an interesting choice considering the recent death bells tolled for it. In order to make the data provider generic and swapable, the Oxide team chose to create interfaces for their entities.

In the main Oxide.Data namespace are a series of interfaces that look like this:

public interface IArea
{
Guid SiteID { get; set; }
Guid ID { get; set; }
string Name { get; set; }
string DisplayName { get; set; }
string Description { get; set; }
string Type { get; set; }
string TypeUrl { get; set; }
DateTime? Created { get; set; }
DateTime? Modified { get; set; }
}

 

The Linq to Sql entities are created using a typical DBML file. Partial classes are then created for each entity and they are set to inherit from the interface:

 partial class oxite_Area : IArea
{
public Guid ID
{
get { return AreaID; }
set { AreaID = value; }
}

//......
}

This design allow the rest of the application to only deal with the interface leaving the persistence concerns hidden and isolated in the data provider class. This seemed really clean to me, so I wanted to take a stab at implementing a data provider using my favorite ORM technology.

So I fired up a new project and imported NHibernate, Fluent NHibernate and Linq to NHibernate and started hacking out some code. The main entry point to the data provider is the IOxideDataProvider interface. This interface exposes a series of repository interfaces:

public interface IOxiteDataProvider
{
IAreaRepository AreaRepository { get; }
IBackgroundServiceActionRepository BackgroundServiceActionRepository { get; }
ILanguageRepository LanguageRepository { get; }
IMembershipRepository MembershipRepository { get; }
IMessageRepository MessageRepository { get; }
IPostRepository PostRepository { get; }
IResourceRepository ResourceRepository { get; }
ITagRepository TagRepository { get; }
ITrackbackRepository TrackbackRepository { get; }
}

I started by implementing stubs for this interface. I wired my new assembly into the Oxide web.config as the data provider and fired up the site. I wanted to see what was the first repository it would attempt to use. I quickly got a lemon meringue screen crying about AreaRepository.

AreaRepository deals with the IArea entity interface. The Oxide data provider defines this entity partially in DBML and an added partial class. I needed my own implementation of it. This is where the entity interfaces come in handy.

public class Area : AuditedEntity, IArea
{
private string description;
private string displayName;


private string name;
private Guid siteId;
private string type;
private string typeUrl;



public string Name
{
get { return name; }
set { name = value; }
}


//.......

}

Here Area is a simple POCO object that implements IArea. I also pushed up some common properties into a base class set of EntityBase which provides identity via a GUID and a AuditedEntity which provides created and modified date tracking.

Looking through the various repository code, it looked to me like the Oxide team had created  one to one repositories like this to get around limitations of Linq to Sql. I decided to try to create a generic repository to handle all entity types' simple CRUD operations. So I created a typical IRepository interface like so:

 internal interface IRepository
{
IQueryable GetList();
T GetById(long id);
void Save(T entity);
void Delete(T entity);
T GetOne(SpecificationBase query);
IQueryable GetList(SpecificationBase query);
}
internal interface IPagedRepository
{
IQueryable GetPagedList(SpecificationBase query, int pageSize, int pageId);
}

This interface defines very basic Create, Read, Update and Delete functionality for a repository. The Specification stuff is a really cool idea that I blatantly ripped off from RossCode. Check out his article on how that works. It is irrelevant to the topic at hand, so I wont go into it now. I may not even need to use it by the time I am done. I also threw in a interface for paging just in case.

Implementing these interfaces are pretty straight forward and once again this is most likely not my code but something borrowed from somewhere else.

public class Repository
: IRepository, IPagedRepository
{
public Repository(ISession _session)
{
this.session = session;
}


private ISession session { get; set; }



public IQueryable GetPagedList(SpecificationBase query,
int pageSize, int pageId)
{
if (pageId == 0) pageId = 1;
return GetList(query).Take(pageSize).Skip(pageId*pageSize);
}


public IQueryable GetList()
{
return (from entity in _session.Linq() select entity);
}


public T GetById(long id)
{
return _session.Get(id);
}


public void Save(T entity)
{
_session.SaveOrUpdate(entity);
}

public void Delete(T entity)
{
_session.Delete(entity);
_session.Flush();
}


public T GetOne(SpecificationBase query)
{
return query.SatisfyingElementFrom(_session.Linq());
}


public IQueryable GetList(SpecificationBase query)
{
return query.SatisfyingElementsFrom(_session.Linq());
}


}

I can now use my generic repository for all simple CRUD operations required by the interface required repositories. I won't show a full implementation but the basics of it look like this:

 public class AreaRepository : IAreaRepository
{
private readonly IRepository<Area> repository;

public AreaRepository(ISession session)
{
repository = new Repository<Area>(session);
}

private IQueryable<Area> getAreas(Guid siteID)
{
return from a in repository.GetList()
where a.SiteID == siteID
select a;
// orderby a.AreaName
}

//......

}

As you can see the area repository implements IAreaRepository which satisfies the IOxideDataProvider interface. Implementing the rest of the class was pretty much a cut & paste job on the Oxide code to get the linq queries all the methods are based on.

One problem I did run into was that the version of Linq to NHibernate I am using does not appear to support orderby. This might not be the case with the actual trunk version, but the one that is in the Flient NHibernate trunk doesn't. I simply commented the item out for now and will return to it later.

I am currently passing in the NHibernate session and newing up an instance of the generic repository. This isn't the cleanest design but I can push the repository creation up when I get to introducing my IoC container of choice Ninject. I am not quite sure how I am going to do that in Oxide, so I am leaving it for another day.

I now have an end to end solution for the Area entity. All that is left is persistence concerns. I need to create a NHibernate mapping for the Area class to my database. Fluent NHibernate makes this incredibly simple.

public class AreaMap : ClassMap
{
public AreaMap()
{
WithTable("oxite_Area");
Id(x => x.ID,"AreaID").GeneratedBy.Guid().WithUnsavedValue(null);
Map(x => x.Name).TheColumnNameIs("AreaName").WithLengthOf(256).CanNotBeNull();
Map(x => x.DisplayName).WithLengthOf(256).CanNotBeNull();
Map(x => x.Description).WithLengthOf(256).CanNotBeNull();
Map(x => x.Type).WithLengthOf(25).CanNotBeNull();
Map(x => x.TypeUrl).WithLengthOf(25).CanNotBeNull();
Map(x => x.Created).TheColumnNameIs("CreatedDate").CanNotBeNull();
Map(x => x.Modified).TheColumnNameIs("ModifiedDate").CanNotBeNull();
}
}

I can even verify this is right in unit tests by using the very awesome PersistenceSpecification class provided by Fluent NHibernate.

       [Test]
public void Can_Add_Area_To_Database()
{
var testDate = new DateTime(2008, 12, 1);
new PersistenceSpecification(Session)
.CheckProperty(x => x.Name, "Name")
.CheckProperty(x => x.DisplayName, "DisplayName")
.CheckProperty(x => x.Description, "Description")
.CheckProperty(x => x.TypeUrl, "TypeUrl")
.CheckProperty(x => x.Type, "Type")
.CheckProperty(x => x.Created, testDate)
.CheckProperty(x => x.Modified, testDate)
.VerifyTheMappings();
}

Now that is hot. James and the gang have done amazing things with Fluent NHibernate. Next up, I plan to map all the entities in my project in an effort to understand the domain model a bit more and flesh out some unit tests around what I have written.

I have not released the source code for this post yet, as I want to get a working Oxide Data Provider first that way people can actually see it working. So look for more posts on this as I work my way though it.


 
Categories: Development | Oxide

The somewhat monthly meeting of the Seattle ALT.NET Open Spaces Group has been scheduled for December 13th at Microsoft's West Lake office. Please feel free to join us as we discuss a wide variety of topics in the software development and process space.

If you are curious what IoC, Continuous Improvement or NHibernate is all about, this is the meeting to come check out. And if finally no one is interested in those topics we might cover Git, Lean, Kanban or other cutting edge practices that you need to know about.

Where: Microsoft, 320 Westlake Avenue, Seattle

When: Saturday, Dec. 13th, 10am-5pm

Go to the 3rd floor once you arrive, and then you'll see a phone number to call to get in.
 

Categories: Development | Events | Local

Since discovering the ALT.NET community and its dramatic effect on my personal outlook on the way I think about and write code, I have been looking for ways to bring this philosophy to my local developer community. This meeting represents the first major achievement in that goal.

Connecting Camey with Glenn Block and Ade Miller was a stroke of divine intervention. If ever there was a time to come down and check out what the South Sound .NET Users Group is all about this is it.

Please join us on Thursday, December 11th for a presentation on MEF by Glenn Block.

Meeting Summary
Today, it is difficult for applications and frameworks to meet an open-ended set of needs. Building in extensibility allows third-party customization, however there are many challenges in doing so. The Managed Extensibility Framework (MEF) is a new extensibility model in the .NET framework that addresses many of these problems. It provides as simple declarative model for application developers and extenders. Come to this session and get an overview on what it is and what it will do for you.

About Glenn Block
Glenn is a PM for the new Managed Extensibility Framework in .NET 4.0. Prior to Microsoft, he worked for 10 years in various startups and ISVs wearing many different hats all related to developing software. Glenn has been writing code practically since the time he learned how to ride a bicycle. When he's not writing code, he's working on ways to build better software through learning good software design principles and methodologies. Glenn is a geek at heart and spends a good portion of the rest of this time spreading that geekdom through conferences, and the community through groups such as ALT.NET. When he's not working and playing with technology, he spends his time with his wife and four year old daughter either at their Seattle apartment or at one of the local coffee shops.


Meeting Specifics
December 11th, 7 - 9 pm
Olympia Center (222 Columbia NW)


All attendees are eligible for the prize drawings. Past prizes have included technical books, passes to Devscovery, copies of Visual Studio, Vista, Office 2007 and more. Don't forget to let your friends and co-workers know about this meeting.  Feel free to forward this email and/or direct them to www.ssdotnet.org for more information.


 
Categories: Development | Events | Local

November 24, 2008
@ 08:14 PM

Well, I finally did it. I went over to the darkside and picked up a 15" MacBook Pro and a copy of VMWare Fusion. I got the box home and had a Bootcamp partition with Windows 2008 Workstation installed within an hour. Install Visual Studio 2008 and I was ready to do some development in one Space while working on Keynote presentations in another.

My journey though Mac software beings. I sit here now typing this up in a very nice blog post editor called Ecto. It's all good.

Look for more post as I explore the developer tools on the Mac.


 
Categories: Development | Random | Tools

November 11, 2008
@ 07:36 AM

Don't forget about Seattle Code Camp v4.0 this weekend in Redmond.  For all the details, go to the Seattle Code Camp website.  This is a free weekend of presentations on a wide variety of software development subjects.  This isn't a 'Microsoft' only event, check out the list of sessions if you don't believe me.

Two South Sound .NET User Group members will be presenting:

Chris Bilson is presenting 'Getting Git'

Git is a distributed version control system. It's a little different than other source control systems you may have used (Subversion, TFS, etc.), and a little more powerful too. In this session we'll talk a little bit about what the big deal is with distributed revision control systems, which ones exist, git, some tools related to git, web sites that work with git, and go through a typical git workflow.

Camey Combs is presenting "What's the Big EFing Deal? Even Newbies can do Entity Framework"

Have you done anything with Entity Framework yet? Have you heard of it? Curious about it? if you're new to EF and want to do some coding utilizing it, this is the session for you. Come and see what a newbie (you and your presenter) can do with EF after only a few short lessons. Bring your laptop loaded up and ready to go and follow along, building your own simple applications using EF.


 
Categories: Development | Events | Local

Please join us on Thursday, November 13th for a presentation on MVC by Chris Tavares.


Meeting Summary:
The ASP.NET Model-View-Controller (MVC) framework is a new web development framework that sits next to the existing ASP.NET WebForms framework. Rather than attempting to abstract away the Web, MVC embraces the web programming model. The result is a very different experience for writing web applications on the .NET platform. In this talk, we’ll look at what the MVC framework is, the basics of how to use it, why it exists, and how to decide whether to use it (or not).

Speaker Info:
Chris is a developer on the Microsoft patterns & practices team. He started his obsession with computers in third grade with an actual teletype taking to a mainframe. The job has gotten rather easier since. He’s worked in embedded systems, shrink wrap software, developer tools, consulting, and as a developer trainer before joining Microsoft. His current projects are as dev lead / architect for Microsoft’s Enterprise Library, and consulting software designer on the ASP.NET MVC framework.

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


Don't forget to let your friends and co-workers know about this meeting.  Feel free to forward this email and/or direct them to www.ssdotnet.org for more information.


 
Categories: Development | Events | Local

I have assembly A with class Z that inherits from class X in assembly B. Now in a completely different solution, I have assembly C, which uses class Z.

The compiler complains unless assembly C has a reference to both assembly A & B. Even though assembly C does not use class Z directly in anyway.

Is this expected?

It seems to me that if assembly B is missing at run time stuff blows up, but at compile time it shouldn't care.

What am I missing here?

My goal is that I can tell my clients to depend on class Z in assembly A, but I can completely reconfigure my assemblies on the other side and have no effect at all on the client when they upgrade.


 
Categories: Development

I have the following solution project structure:

  • Application.Core.Entities
  • Application.Xtend.CustomerName.Entities

In the Core project I have an entity Customer defiend. In the XTend project, I have an entity defined that subclasses Customer named xCustomer (for lack of a better name at this time...).

The idea here is that we have a Core domain model in our application. A customer can then create a new assembly that contains extensions to our core model. When the extension assembly is present a smart IRepository class will return a subclass of the core class instead.

I am attempting to map this relationship in NHibernate. Using Fluent NHibernate I was able to generate this mapping:

 

<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   default-lazy="false"
                   assembly="NHibernate.Core.Entites"
                   namespace="NHibernate.Entites"
                   default-access="field.camelcase-underscore">
  <!-- Customer is located in assembly Application.Core.Entities -->
  <class name="Customer" table="Customers" 
        xmlns="urn:nhibernate-mapping-2.2">
    <id name="Id" column="Id" type="Int64">
      <generator class="native" />
    </id>
    <component name="Name" insert="true" update="true">
      <property name="LastName" column="LastName" length="255"
                type="String" not-null="true">
        <column name="LastName" />
      </property>
      <property name="FirstName" column="FirstName" length="255"
                type="String" not-null="true">
        <column name="FirstName" />
      </property>
    </component>
    <!-- xCustomer is located in assembly Application.XTend.CustomerName.Entities -->
    <joined-subclass name="xCustomer" table="xCustomer">
      <key column="CustomerId" />
      <property name="CustomerType" column="CustomerType"
                length="255" type="String" not-null="true">
        <column name="CustomerType" />
      </property>
    </joined-subclass>
  </class>
</hibernate-mapping>

But NHib throws the following error:

NHibernate.MappingException: persistent class Application.Entites.xCustomer, Application.Core.Entites not found ---> System.TypeLoadException: Could not load type 'Application.Entites.xCustomer' from assembly 'Application.Core.Entites, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'..

Which makes sense xCustomer is not defined in the Core library. I took my quandary to the NHibernate Users mailing list and StackOverflow. After some helpful suggestions and pointers, I discovered that the solution was so obvious that I am somewhat embarrassed that I couldn't see it.

The hibernate-mapping attributes assembly and namespace are convenient short cuts that allow you to not have to fully qualify your class names. This lets you have the nice mark up , but the name attribute of both class and joined-subclass elements can take a fully qualified assembly name as well.

So the above broken mapping file can be fixed like so:

 

<joined-subclass name="Application.XTend.CustomerName.Entities.xCustomer, 
                 Application.XTend.CustomerName.Entities, Version=1.0.0.0, 
                 Culture=neutral, PublicKeyToken=null" 
                 table="xCustomer">
  <key column="CustomerId" />
  <property name="CustomerType" column="CustomerType" length="255" 
            type="String" not-null="true">
    <column name="CustomerType" />
  </property>
</joined-subclass>

This works as I expected it to. So I then took a look at the Fluent-NHibernate source and created a patch complete with working unit tests to resolve the issue and submitted it to the project.

So at the end of the day, I learned something about NHibernate and the Fluent-NHibernate team got a patch to resolve and obscure bug.


 
Categories: Development | NHibernate

Yesterday, my team had a developer forum session to assist one our own get our latest release to build on our build server from a new branch. He had been working on it for a couple days and was getting nowhere. He would follow our documented process to create the new build and when he got to the end of it the build threw the following error:

The path C:\Build\ProductReleases\FullBuildv5.4.2x\Sources is already mapped to workspace BuildServer_23.

We used the Team Explorer IDE and attempted to identify this rogue workspace. Try as we might we couldn't locate it. We tried deleting all the source code on the file system. We tried nuking all the workspaces we could see through the IDE.

In the end we had seven developers in a room shouting out ideas to a frustrated developer sitting the keyboard. So we broke for lunch.

After lunch, I returned to my desk to troll the MSDN Team Foundation Server Developer Center. Using the tf workspaces command, you can get a list of all the workspaces you have created:

C:\>tf workspaces

Server: BuildServer
Workspace Owner          Computer Comment
--------- -------------- -------- --------
BOBBY     work\Bobby 	 BOBBY

But if you add the owner switch, you can get a list of all the workspaces on the server:

C:\>tf workspaces /owner:*

Server: BuildServer
Workspace      Owner      Computer  Comment
-----------    ---------- --------- -------------------------------
BuildServer    Shane      BuildServer
BuildServer    Craig      BuildServer
BuildServer    TFSSETUP   BuildServer
BuildServer    Keith      BuildServer
BuildServer_1  TFSSERVICE BuildServer  Workspace created by Team Build
BuildServer_10 TFSSERVICE BuildServer  Workspace created by Team Build
BuildServer_12 TFSSERVICE BuildServer  Workspace created by Team Build
BuildServer_13 TFSSERVICE BuildServer  Workspace created by Team Build
BuildServer_14 TFSSERVICE BuildServer  Workspace created by Team Build
BuildServer_16 TFSSERVICE BuildServer  Workspace created by Team Build
BuildServer_2  TFSSERVICE BuildServer  Workspace created by Team Build
BuildServer_23 TFSSERVICE BuildServer  Workspace created by Team Build
BuildServer_28 TFSSERVICE BuildServer  Workspace created by Team Build
BuildServer_3  TFSSERVICE BuildServer  Workspace created by Team Build
BuildServer_30 TFSSERVICE BuildServer  Workspace created by Team Build
BuildServer_31 TFSSERVICE BuildServer  Workspace created by Team Build
BuildServer_32 TFSSERVICE BuildServer  Workspace created by Team Build
BuildServer_4  TFSSERVICE BuildServer  Workspace created by Team Build
BuildServer_6  TFSSERVICE BuildServer  Workspace created by Team Build
BuildServer_7  TFSSERVICE BuildServer  Workspace created by Team Build
BuildServer_8  TFSSERVICE BuildServer  Workspace created by Team Build
BuildServer_9  TFSSERVICE BuildServer  Workspace created by Team Build

From this output we can see that our build service user TFSSERVICE has a lot of workspaces defined. Considering we have 3 builds so far. Something is very wrong here.

Our original error message referenced a workspace named BuildServer_23 which does show up in our list. Using the tf workspace command, we can completely remove the workspace:

C:\>tf workspace /delete /server:BuildServer BuildServer_23;TFSSERVICE
A deleted workspace cannot be recovered.
Workspace 'BuildServer_23;TFSSERVICE' on server 'BuildServer' has 0 pending change(s).
Are you sure you want to delete the workspace? (Yes/No) Y

Our build now runs as expected. It's now time to verify what all those other workspaces are and remove them if they are not needed.

Hope this helps someone out there if you are desparately googling for away around this error.


 
Categories: Development | Tools

The application I am currently working on has a hand rolled implementation of Ajax that is somewhat awkward to work with. At the end of our last sprint, I was tasked with spiking what it would take to migrate to the .NET Ajax 1.0 extensions while everyone else was working on release week tasks.

It took a couple days to figure out all the installs, web.config modifications, component vendor compatibility and other various things. But in the end, I had a simple page with two sample Ajaxified controls that worked.

I then turned to the task of unraveling the way the current implementation was wired up and modifying a single page to use the Ajax framework instead. A few minor safe refactorings and quirks later, I had a semi-functional reference implementation with one giant problem.

The page contained a series of drop down lists that filter each other as you make selections. On initial page load, I could select an item any drop down and it would appropriately modify the others. The second selection always returned the following error:

Sys.WebForms.PageRequestManagerServerErrorException: An unknown error occurred while processing the request on the server. The status code returned was: 404

Reguardless of what list I selected from first, the second request would fail. My IIS logs revealed that my request was being sent to server, but for whatever reason the URL changed.

2008-10-17 14:52:14 W3SVC1 127.0.0.1 POST /Aware/Xtend/mParticipant/NewPlannedService.aspx  80 - 127.0.0.1 200 0 0

2008-10-17 14:52:20 W3SVC1 127.0.0.1 POST /Aware/mParticipant/NewPlannedService.aspx  80 - 127.0.0.1 404 0 0

Using Fiddler, I was able to see that a value for formAction was being sent back to the client that was invalid. You can also see that the second request is going to a non-existent page:

FiddlerOutPut

I was able to resolve the issue by explicitly setting the value of my forms action back to the correct path at the end of my call back method like so:

this.Form1.Action = Request.Url.PathAndQuery

But this seemed like a hack in the worst way and smelled somewhat like moldy cheese to me. And I still didn't understand what was causing the issue.

The application makes extensive use of Server.Transfer as a "performance enhancement". I noticed that the form I was working with was one of these cases where Page1.aspx transfers execution to my Ajaxified page.

I decided to try to isolate the behavior and reproduce it in a simple example project.

I fired up Visual Studio and created a new Ajax website. I added two pages; Default.aspx and AjaxPage.aspx. I implemented a simple ajax call back on my ajax page and the default page transfer execution in its Page_Load method.

To my surprise, it worked with no problems. I didn't see the nasty error at all. I verified with Fiddler. I was stumped.

I started thinking about the behavior in my application. The only difference I could think of was that the page that was being transferred to was in a different subdirectory than the original page. So I created a folder in my test project and moved AjaxPage.aspx into it. And this time I got the error. I confirmed with Fiddler that my "Folder" sub directory was being dropped off the second request and that it was missing from the response from the first request.

My smelly cheese hack worked as well for my test project. But I didn't want to solve this issue with a server side hack. So I created the following client side Javascript to hook into the client ajax framework and solve it there in a single place:

var orginalFormAction = null;

//capture the current form action value
function BeginRequestHandler() {
  orginalFormAction = theForm.action;
}

//set the form action value back to the
//correct value
function EndRequestHandler() {
  theForm.action = orginalFormAction;
  theForm._initialAction = orginalFormAction;
}

function RegisterRequestHandlers() {

  if (typeof (Sys) != "undefined") {
  
    Sys.WebForms.PageRequestManager.getInstance().add_endRequest(EndRequestHandler);
    Sys.WebForms.PageRequestManager.getInstance().add_beginRequest(BeginRequestHandler);
    Sys.Application.notifyScriptLoaded();
    
  }
}

//register request handlers after the application 
//has successfully loaded.
Sys.Application.add_load(RegisterRequestHandlers);

I can then add the script to any ajax page, by adding the following code to my Page_Load event handler:

protected void Page_Load(object sender, EventArgs e)
    {
      PageScriptManager.Scripts.Add(
        new ScriptReference("~/Script/Ajax.Server.Transfer.Fixer.js")
        );
    }

Problem solved and I didn't have to rewrite the entire application to get rid of Server.Transfer calls. On to other things.

Fiddler Tip: To get Fiddler to capture traffic when you are debugging on local host, after you hit F5 to begin degugging change the address so that localhost has a "." after it. For instance, you start debugging and the you have the following URL in the Address bar: http://localhost:49573/Default.aspx Change it to http://localhost.:49573/Default.aspx hit enter and Fidder will start picking up your traffic.


 
Categories: Development | Tools

The code base I am currently working with has a collection class that inherits from ArrayList. The purpose of this class is to offer a unique list of objects and to provide case insensitive comparisons when adding a unique item to the collection. The collection does not need to be unique, but we a way to add unique things to the list is required.

My task the last week was to become familiar with the code base and identify possible refactorings. Using NDepend, I was able to determine that this class is typically used with strings. One possible refactoring I suggested was to replace this custom class with List<string>(). An out of sprint hit squad was formed to tackle doing just that. We came in on Saturday morning bright and early and got started.

Doing a global search and replace to change this custom ArrayList class with List<string> turned up thousands of compiler warnings where the method AddUnique() was called.

Our first stab at tackling this problem was to create a helper method that added an item to a given list only if that list did not already contain the item. We wrote a macro to quickly turn the old references into the new helper references. The code looked something like this:

tableList.AddUnique("item_table")

ListHelper.AddUnique(tableList, "item_table")

This seemed to get us around the uniqueness hurdle. It was a bit verbose, but it got the job done and would eventually allow us to get rid of the custom collection class altogether. We started hacking away, taking turns at the keyboard with three sets of eyes making sure we were hitting the right items and evaluating between List<string> and ArrayList where appropriate.

After a few hours of locating problem areas and fixing them with a handy macro we created out of sheer boredom, the hit squad decided this was not working. I mentioned that if we were using Visual Studio 2008, we could write an extension method that would simply attach an AddUnique() method to the List<string> class. We knew that Visual Studio 2008 allowed you to target the 2.0 framework. So we could upgrade the solution to VS2k8, leave all our projects targeting 2.0 and be able to use extension methods.

I left the 8 hour marathon triple-programming session with the goal of playing around with implementing extension methods in Visual Studio 2008. Since I was not familiar with actually writing them, I fired up my IDE and wrote a couple tests for what I wanted to happen.

        [Test]
        public void Can_Add_Unique_String_To_List_Of_String()
        {
            var list = new List<String>();

            list.AddUnique("one");
            list.AddUnique("one");

            Assert.AreEqual(1, list.Count);
        }

        [Test]
        public void Can_Add_Case_Insensitive_Unique_String_To_List_Of_String()
        {
            var list = new List<string>();

            list.AddUnique("one");
            list.AddUnique("ONE");

            Assert.AreEqual(1, list.Count);
        }

I flipped over to my Extensions library and added a ListOfStringExtensions class. To get the code to compile I quickly stubbed out the method like this:

public static void AddUnique(this List<String> list, string item)  {   }

Using the ReSharper unit test runner, I verified that my test indeed fail. The moved on to implementing the method logic. My first attempt at implementing the method looked something like this:

public static void AddUnique(this List<string> list, string item)
        {
            foreach(var s in list)
            {
                if(s == item)
                    return;
            }

            list.Add(item);
        }

This allowed my first test to pass, but not the second. So I modified the implementation like so:

public static void AddUnique(this List<string> list, string item)
        {
            foreach(var s in list)
            {
                if(String.Compare(s,item,true) > 0)
                    return;
            }

            list.Add(item);
        }

Now both tests pass. I continued down this TDD path until I had a nice set of extension methods and unit tests that satisfied all the requirements to get rid of our custom collection class. In the end I created AddUnique, AddUniqueRange, CaseInsensitiveContains, IsUnique and ToUniqueList extension methods which all work nicely together with a full suit of unit tests.

The next task at hand was to get the extension methods working in projects that were targeting the 2.0 framework. I set my unit test class to target 2.0 and verified that they still worked. I got an warning as soon as I set the framework target that I had references to projects targeting a different framework. The tests ran fine.

I then changed the target of my extension library to 2.0 and got this nasty error at compile time:

Cannot define a new extension method because the compiler required type 'System.Runtime.CompilerServices.ExtensionAttribute' cannot be found. Are you missing a reference to System.Core.dll?

Hrm.. ExtensionAttribute seems to be a 3.x feature. But I had started out this adventure reading ScottGu's blog where he says that extension methods are language syntactical sugar and should work fine with the 2.0 framework. So I fired up Chrome and hit google.

The first result for my query happened to be my good friend Nate Kohari's blog. Nate is the creator of Ninject the amazing Dependency Injection framework. He also recently release his new web site IdeaVine. He is an awesome guy  and as usual he already blazed the path I was walking down.

According to Nate, all I needed to do was add an attribute class in a specific namespace to get around the compiler issue.

 
//override the .net 3.5 compiler services for .net 2.0 compatibility
//see: http://kohari.org/2008/04/04/extension-methods-in-net-20/
namespace System.Runtime.CompilerServices  
 {  
   [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]  
   public class ExtensionAttribute : Attribute  
   {  
   }  
 } 

Everything compiles and test run fine targeting the 2.0 framework. In morning I plan to verify this by running sample code on a fresh box with only the 2.0 framework installed. As always you can get my full source code here.


 
Categories: Development | Unit Testing

I will be attending the Wintellect Devscovery conference this week, August 19th - 21st, on the Microsoft campus in Redmond. If any ALT.NET people want to get together for lunch or dinner while I am there feel free to contact me via the plethora of options to the right. I will be in full on geek out mode and happy to talk with you.

Here is my schedule while I am there:

 

Tuesday  
9:00 AM Keynote - I am ASP.NET 3.5 Extensions and So Can You! - Hanselman
10:45 AM Translating Architecture to Technologies - Dahlman
12:15 PM Lunch
1:30 PM An Overview of ASP.NET MVC - Haack
3:15 PM An Introduction to TDD - Haack
Wednesday  
9:00 AM Windows Communication Foundation: Rest with WCF - Mehner
10:45 AM Windows Communication Foundation: Debugging & Error Handling - Mehner
12:15 PM Lunch
1:30 PM Practical Workflow Foundation, Part 1 - Mehner
3:15 PM Practical Workflow Foundation, Part 2 - Mehner
Thursday  
9:00 AM An Introduction to LINQ to SQL - Demsak
10:45 AM An Introduction to LINQ to Entities - Demsak
12:15 PM Lunch
1:30 PM Unit Testing & Code Coverage Best Practices - Robbins
3:15 PM .NET Performance Tips & Tricks - Robbins

 
Categories: Development | Events | Local

 Taken in Blijdorp Michael Feathers, the amazing author of Working Effectively with Legacy Code, posted recently about technical debt.

What happens to code when you don’t refactor?  Anyone with any experience knows the answer.  It gets messy.  It becomes hard to change and the rate at which you can add features slows to a crawl.

I was on a project that inherited a tremendous amount of technical debt. The motivating force for the original team was meeting a hard deadline. As the deadline approached development process crumbled. Hero developers shot from the hip. Corners were cut. Non-critical bugs piled up. Quality was sacrificed to meet the deadline.

The technical debt was put on the American Express.

At the end of the project, the resulting application had a week long eventful launch full of rapid critical bug fix releases. The application was eventually brought up to an acceptable level of performance through Herculean effort of very skilled and talented people.

The technical debt bill was left ignored.

The following project cycle a new team was introduced to the application. A feature set to be added was defined. A deadline was set. A new requirement was added. All new features would have a emphasis on quality. No defects would be added to the already limping system.

The technical debt went into Universal Default and the APR was bumped up to 29%.

The team began moving forward except this time the business actively using the system kept running into critical issues that the team had to quickly deal with. The short cuts taken by the previous team became direct roadblocks to the new features slowing the implementation down. Each new line of code had to make sacrifices to work around quirks in the code base.

The 800 pound technical debt collection gorilla started calling demanding payment.

After a year of use the sheer size of the technical debt in the database caused leaks to spring which cascaded outward through out the application. New releases were viewed with dread by the entire organization. The DBA's were not happy. The help desk was not happy. The users were not happy. Morale on the project was through the floor.

The 800 pound technical debt collection gorilla had frozen all assets and put a lean on the house.

You can put that debt on the card. You can ignore it and buy some time. But eventually that gorilla is going to find you, climb on your back and beat you down.

Photo Credit:  Ruben Bos


 
Categories: Commentary | Development | Random

Introduction

As you may have noticed, I have become interested in the concept of Object Relational Mapping and the NHibernate framework. One of the more painful/tedious aspects of using NHibernate is hand writing the xml mapping files. That is why I got excited when I heard that Jeremy Miller was open sourcing his mapping generation libraries.

FHLogo The Fluent NHibernate project is an effort to create a set of APIs that generate NHibernate mapping files using a fluent interface. I downloaded the source code from the Google Code Repository and quickly found myself adding fluent methods. I submitted my changes to the project and was accepted as a contributor.

One of the tasks identified by the project owner, James Gregory, was to create a quick start guide that easily fit into the NHibernate Quick Start section 1.3 Mapping the cat. I assigned the task to myself and start hacking some code.

Creating the Mapping Class

First, create a new class project QuickStart.Domain to hold  domain model objects that need to be mapped. To this assembly,  add the Cat class from the NHibernate quick start.

namespace QuickStart.Domain
{
    public class Cat
    {
        public virtual string Id { get; set; }

        public virtual string Name { get; set; }

        public virtual char Sex { get; set; }

        public virtual float Weight { get; set; }
    }
}

This is what the class looks like after a little ReSharper Code Clean Up loving.

Then add a second class project QuickStart.Domain.Mapping to hold  domain model mapping classes using the Fluent NHibernate library. Add references to both the FluentNHibernate.dll and the domain model library.

Create a new class in the mapping library called CatMap. This class will inherit from ClassMap<T> where T is the type you are creating the map for, in this case Cat. Create a constructor for the CatMap class. The constructor is where the mappings will be defined.

Because CatMap is an instance of ClassMap, you can begin using the fluent interface in the constructor right away.

public CatMap()
        {
            this.TableName = "Cat";
        }

The TableName property of the ClassMap object specifies the name of the table in the data store that stores the Cat class. This explicit setting of the table name is unnecessary. If one is not provided the API will assume the table has the same name as the class being mapped. So, for the rest of this example, it will be dropped.

The API offers several fluent methods for defining an identifier though the Id method of ClassMap. The Cat example uses the UUID generator which looks like this:

 

public CatMap()
        {           
            this.Id(x => x.Id)
                .GeneratedBy
                .UuidHex("B");
        }
 

An identity column in SQL server would be mapped like this:

public CatMap()
        {
            Id(x => x.Id);
        }

These two examples take advantage of the new C# 3.0 syntax sugar lambda expressions. An explanation of lambda expressions is outside the scope of this article, but  tons of information is available on the topic on the web.

The remainder of the CatMap constructor uses the Map method of ClassMap to define the remaining properties of the class.

public CatMap()
        {
            this.TableName = "Cat";
           
            this.Id(x => x.Id)
                .GeneratedBy
                .UuidHex("B");

            //non-nullable string with a length of 16
           this.Map(x => x.Name)
                .WithLengthOf(16)
                .CanNotBeNull();

            //simple properties
            this.Map(x => x.Sex);
            this.Map(x => x.Weight);
        }

Both the Sex and Weight properties of the Cat class are mapped quickly with a single call to them Map method. You do not need to explicitly specify the type of your properties, Fluent NHibernate will infer it based on the type being mapped. The Name property has an additional two fluent calls to limit the length of the property to sixteen characters and to disallow null values.

Usage of this mapping generates the following XML document:

<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" 
  default-lazy="false" 
  assembly="QuickStart.Domain" namespace="QuickStart.Domain">
  <class name="Cat" table="Cat" xmlns="urn:nhibernate-mapping-2.2">
    <id name="Id" column="Id" type="String" unsaved-value="0">
      <generator class="uuid.hex">
        <param name="format">B</param>
      </generator>
    </id>
    <property name="Weight" column="Weight" type="Single">
      <column name="Weight" />
    </property>
    <property name="Sex" column="Sex" type="Char">
      <column name="Sex" />
    </property>
    <property name="Name" column="Name" length="16" type="String" not-null="true">
      <column name="Name" />
    </property>
  </class>
</hibernate-mapping>

This mapping xml is a bit more verbose than the original example from the NHibernate quick start, but this post is being written using an alpha version of the Fluent NHibernate library. There is a lot of clean up and work left to be done.

Hooking It All Up

So, how exactly did I go from CatMap to generated XML document? There is currently no recommended methodology that I am aware of, but I am happy to share how I accomplished it.

I started by adding an interface to the Mapping library called IMapGenerator that looks like this:

namespace QuickStart.Domain.Mapping
{
    public interface IMapGenerator
    {
        string FileName { get; }
        XmlDocument Generate();
    }
}

 

FileName is defined in the fluent interface on the ClassMap class, I know I added it while writing this code ;). It represents the conventional name for the NHibernate mapping files. For example, We are mapping the class Cat so FirstName would contain the string "Cat.hbm.xml". Generate on the other hand, will be a wrapper around the ClassMap's CreateMapping method.

I then added the interface to the CatMap class. The final CatMap looks like this:

namespace QuickStart.Domain.Mapping
{
    public class CatMap : ClassMap<Cat>, IMapGenerator
    {
        public CatMap()
        {
             Id(x => x.Id)
                .GeneratedBy
                .UuidHex("B");

            Id(x => x.Id);

            //non-nullable string with a length of 16
            Map(x => x.Name)
                .WithLengthOf(16)
                .CanNotBeNull();

            //simple properties
            Map(x => x.Sex);
            Map(x => x.Weight);
        }
        
        public XmlDocument Generate()
        {
            return CreateMapping(new MappingVisitor());
        }
    }
}

 

I now have a way to identify all my mapping classes using the interface. I wanted to be able to automatically get a list of all the classes that implement the IMapGenerator interface, so  created a helper class GeneratorHelper with a single static method GetMapGenerators. The class lives in the Mapping library and looks like this:

namespace QuickStart.Domain.Mapping
{
    public class GeneratorHelper
    {
        private const string GENERATOR_INTERFACE = "IMapGenerator";

        public static IList<IMapGenerator> GetMapGenerators()
        {
            IList<IMapGenerator> generators = new List<IMapGenerator>();
            Assembly assembly = Assembly.GetAssembly(typeof(IMapGenerator));
            foreach (Type type in assembly.GetTypes())
            {
                if (null == type.GetInterface(GENERATOR_INTERFACE)) continue;
                var instance = Activator.CreateInstance(type) as IMapGenerator;
                if (instance != null)
                    generators.Add(instance);
            }
            return generators;
        }
    }
}

This method uses reflection to locate and load the assembly that contains the IMapGenerator interface. It then iterates over the types in the loaded assembly and checks to see if the type implements the IMapGenerator interface. If a match is found, an instance of that class is created and added to the generators list.

Finally, I created a console application, QuickStart.Domain.Mapping.Mapper, and added a reference to my Mapping library. The implementation of my console app is fairly straight forward.

 

namespace QuickStart.Domain.Mapping.Mapper
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            IList<IMapGenerator> generators =
                GeneratorHelper.GetMapGenerators();
            
            foreach (IMapGenerator generator in generators)
            {
                XmlDocument classMapXML = generator.Generate();
                classMapXML.Save(generator.FileName);
            }
        }
    }
}

 

The app calls the generator helper class to get a list of IMapGenerator objects which it then iterates over calling each objects Generate method and saves the result using the conventional name for mapping files. It works fairly well and I can add as many mapping classes as I need to the Mapping library and spin out xml any time I need.

Now where Fluent NHibernate becomes really interesting is when you decide to do away with xml mapping files all together. For a great example of this check out Zachariah Young's post, "Does the Fluent NHibernate create static XML mapping files?".


 
Categories: Development | Fluent Interface | NHibernate | Tools

In a recent post, I discovered a flaw in my world domination plot. I had written a Unit Test to test my expectation that the method GetByID() of the class UserRepository returned the expected User. When UserRepository.GetById() is called, it calls IDataProvider.GetById(), which returns an instance User to the UserRepository which in turn returns it to the caller.

My UserRepository class delegates database access to the interface IDataProvider. This allows me to substitute any implementation of IDataProvider to satisfy this responsibility. In non testing code I use Dependancy Injection to map UserDataProvier to IDataProvider. But in testing code I do not really want to hit a database as it slows the testing process down. So I use Rhino.Mocks instead.

Rhino.Mocks is a framework for creating mock objects for use in Unit Testing. Provide Rhino.Mocks with an Interface and it will give you back an object that implements that interface. You can also tell it to expect certain calls against the interface and how it should respond.

My Unit Test looked something like this:

      [Test]
        public void GetByIdTest()
        {
            MockRepository mock = new MockRepository();

            IDataProvider dataProvider = (IDataProvider)mock.CreateMock<IDataProvider>();
            UserRepository target = new UserRepository(dataProvider);

            Expect.Call(dataProvider.GetById(1)).Return(new User() { Id = 1 });

            mock.ReplayAll();
            User u = target.GetById(1);
            mock.VerifyAll();

            Assert.AreEqual(1, u.Id);
        }

As you can see this test, creates a MockRepository that is provided by the Rhino.Mocks framework. It then declares an instance of IDataProvider but delegates the creation of that instance to the MockRepository's CreateMock method. This tells Rhino.Mocks to create a dummy instance of the IDataProvider interface. Next we new up a UserRepository (the actual target of the unit test) and provide our mocked IDataProvider to it's constructor. Then we tell Rhino.Mocks to expect a call to our mock IDataProvider's GetById method and to return a new instance of User with it's Id property set to 1. Finally, we do our testing and validation.

This test fails to compile. The entity class User has read only properties. Id happens to be one of them. In the domain model for this particular application Id is a unique identifier and once a User instance is returned from the data access layer, it should never be modified.

So this presents a unique challenge, how do I test that UserRepository.GetById(1) returns an instance of User with an Id of 1?

I went down the path of trying to use Ninject (an Inversion of Control container), to inject the value in a newed up instance. But this had code smell for me. Why am I creating a dependency on Ninject to get my Unit Tests to work. That just seemed wrong to me. So I began digging in the Rhino.Mocks documentation wiki to see if it had a method for resolving this.

That was when Aiden Montgomery in the #ALT.NET IRC channel suggested that I use Reflection. He even went so far as to download my source from CodePlex and demonstrate what he was suggesting in my application.

The final test ended up looking something like this:

[Test]
        public void GetByIdTest()
        {
            MockRepository mock = new MockRepository();
            
            Type userType = typeof(User);
            PropertyInfo pi = userType.GetProperty("Id");
            User user = new User();
            pi.SetValue(user, 1, null);

            IDataProvider dataProvider = 
                (IDataProvider) mock.CreateMock<IDataProvider>();
            UserRepository target = new UserRepository(dataProvider);

            Expect.Call(dataProvider.GetById(1)).Return(user);

            mock.ReplayAll();
            User u = target.GetById(1);
            mock.VerifyAll();

            Assert.AreEqual(1, u.Id);
        }

 

This of course passed, didn't add a non-BCL dependency and maintained the original intent of the test and the domain model. With all the shiny new toys, I was forgetting to see the forest through the trees and return to the simplest solution. Thanks to Aiden for bringing me back down from the clouds.


 
Categories: Development | Tools | Unit Testing

Karl Seguin of CodeBetter.com released a 79 page ebook called Foundations of Programming yesterday. Browsing the table of contents, I found a ton of good information is covered here. Some highlights include: YAGNI & DRY principals, Explicitness, Cohesion & Coupling, Domain Driven Design... The list just goes on and on and on.

If you want to read about the stuff that a giant Wrox tomb will never mention, grab this ebook as a great launching point.


 
Categories: Development | Events | Fundamentals

Stephen Bohlen of Microdesk recently posted to the ALT.NET mailing list that he plans to release his internal training material on NHibernate to the world at large. The first two, of a planned  5, are online and ready for consumption.


I have been doing some noodling with NHibernate recently, so I downloaded the screen casts and watched them this morning. The quality is excellent, the material is comprehensive and Stephen's teaching style is top notch.

If you are interested in learning what NHibernate is all about and what you can do with it, I cannot recommend these enough. Grab them here:


 
Categories: Development | Fundamentals | Tools

I have been reading a ton of the ALT.NET bloggers and mailing list lately. They are constantly talking about the methodology of software development and the tools they use. On the concept front Domain Driven Design, Inversion of Control, Separation of Concerns and Test Driven Development are all popular topics that have been stewing in my mind. I also wanted to give some of the tools like Nhibernate, Rhino.Mocks and Ninject a try. I was also itching to get into the new Microsoft ASP.NET MVC code.

For the last couple months, I have been festering in the swamp of legacy VB.NET spaghetti code and haven't had the time or motivation to write something fresh just for the sheer joy of creation. Friday, I kind of snapped, fired up Visual Studio 2008, downloaded the tool stack and started hacking away.

Things seemed to just click on all of the topics I had been reading about. I started out with NHibernate and getting a simple User entity to persist to a SQL Sever 2005 database. I then moved on to implementing the Repository Pattern for my User entity abstracting away the actual persistence to a DataProvider class wrapping NHibernate. By this time I had Factory Patterns all over the place, so I added a reference to Ninject.Core and got rid of those too. I then whipped out a MVC site to consume my new repository.

After an evening of furious experimentation, I had a complete database to web page end to end implementation of my User entity. I was stoked, still am. I am currently working on getting unit tests in place using Rhino.Mocks, integration tests on my data access layer and fully implementing CRUD in the MVC site. It is a hell of a lot of fun.

If anyone is interested in seeing what I am working on or want a simple example of using all these things together in an easily understandable way, I posted my work to CodePlex. If you are new to this stuff like I am, download it and check it out. If you are an old hat and want to give me some pointers or tips, please download it and fill me in.

If you work with me and happen to read my blog and are interested, I would love to talk to you about the project and what I learned and discovered. Hit me up.


 
Categories: Development | Fundamentals | Tools | Unit Testing

I came across an interesting issue tonight exploring the use of Rhino.Mocks in unit tests. I have a class UserRepository that implements my current understanding of the Repository Pattern. My repository uses the interface IDataProvider to persist my User entity. The concrete class UserDataProvider wraps NHibernate.

My goal was to write unit tests that cover the methods of UserRepository. I used Rhino.Mocks to mock away UserDataProvider to prevent actually needing a database.

Things were going fine:

public void SaveTest(){
            MockRepository mock = new MockRepository();

            IDataProvider dataProvider = 
                  (IDataProvider) mock.CreateMock<IDataProvider>();
            UserRepository target = new UserRepository(dataProvider);
            User u = new User();
            
            Expect.Call(dataProvider.Save(u)).Return(1);
            Expect.Call(dataProvider.GetById(1)).Return(u);
            
            mock.ReplayAll();
            User x = target.Save(u);
            mock.VerifyAll();

            Assert.AreEqual(x, u);
        }
 
public void GetListTest(){
            MockRepository mock = new MockRepository();
            IDataProvider dataProvider = 
                 (IDataProvider)mock.CreateMock<IDataProvider>();
            UserRepository target = new UserRepository(dataProvider);

            Expect.Call(dataProvider.GetList()).Return(
                new List<object> { new User(), new User()});

            mock.ReplayAll();
            IList<User> users = target.GetList();
            mock.VerifyAll();
            Assert.AreEqual(2, users.Count);  
        }

Then I hit a snag. My User entity has a property Id that is read only. The users Id comes form the database and should not be able to be modified. So my next test has a bit of a problem and fails to compile.

public void GetByIdTest() {
            MockRepository mock = new MockRepository();

            IDataProvider dataProvider = (IDataProvider)mock.CreateMock<IDataProvider>();
            UserRepository target = new UserRepository(dataProvider);

            //TODO: Interesting Problem here. My actual dataProvider uses NHib
            //and would be able to meet this expectation. But my mock
            //cannot set the read only id property so this test will not
            //even compile.
            Expect.Call(dataProvider.GetById(1)).Return(new User() { Id = 1 });

            mock.ReplayAll();
            User u = target.GetById(1);
            mock.VerifyAll();

            Assert.AreEqual(1, u.Id);
        }

 

NHibernate has no problem injecting the value when I fetch the object from it, but my simple little expectation above chokes on it. I am not sure how to get around this one with out violating the intent of the test. I'll have to dig into the Rhino.Mocks documentation and see what tools it offers to get around this situation.

So far Rhino.Mocks is a great time saver. If I actually had to generate a fake for IDataProvider it would take quite a bit of time. I'll have to work it into my regular work life and see how it fairs there.

I'll update this post when I find a resolution to the issue at hand.


 
Categories: Development | Tools | Unit Testing

Over the course of the last couple months I have been working diligently to migrate the application I inherited from the wild wild west of unmanaged corner cutting contractor land to the happy kingdom of semi-intelligent source control.

I have successfully migrated what we have come to know as "what we think production is built with" source in to Team Foundation Server source control, cleaning up along the way. Why exactly this particular batch of contractors felt it was necessary to include references to both the 2.0 and 3.0 Enterprise Application Blocks, I may never know. I suspect they felt it was 2x more "Enterprise-y".

Next up on my path to Agile Nirvana, I whipped up a set of build scripts that produce a consistent build every time. Imagine that! My server support people are so happy with me.

The system I am working on is somewhat interesting. The application went live last summer and was officially handed over to a group of maintenance developers. A new project was immediately started to add new functionality while the maintenance guys fixed up bugs. I currently work with the New Development group.

The maintenance guys decided they wanted in on all this awesome TFS goodness. So I spun them off a branch and let them go on their merry way. That was until they decided they were ready to start rolling forward into production.

That is when I realized that all of my build scripts no longer worked. I would fire up a build using Team Builds in Team Explorer, it would do it's thing pulling down source code and firing off MSBuild to compile and then throw errors.

I checked on the build server in the location where source is downloaded and Team Build was no longer pulling down the source for my Main branch. The only thing be retrieved from Source Control was my Branches directory. Obviously the dirty maintenance branch hosed by lovely build process.

I checked my build definitions and mapping files. My source tree looks something like this:

$/PROJECT
..Branches
    ..2.0.1.0-APPLICATION-branch
..Main
   ..Framework
   ..APPLICATION
   ..Samples
   ..Utilites
..TeamBuildTypes
The 2.0.1.0 node is a branch of $/PROJECT/Main/APPLICATION. My workspace mapping pretty much looks like so:

<InternalMapping ServerItem="$/APPLICATION" LocalItem="flibbityjibits" Type="Map" />

I have a few cloaked paths as well all related to $/PROJECT/Main/Something. When I execute my Team Builds Branches and TeamBuildTypes are retrieved from source control and Main is ignored.

My buildlog shows that CoreGet is retrieving the latest:

Get Version="T" Recursive=True Force=True Workspace="NinjaWarrior"

There was something I was missing here. I shot off an email to the Seattle ALT.NET mailing list, more in a effort to articulate the issue well than expecting them to solve my issues or anything. Kinda just getting it all out as I understand the issue for the eventual call to tech support.

I went home that night utterly devastated that my painstakingly lovingly crafted system had failed so spectacularly.

At home I was playing some Lego Indy with the wife on the Xbox and letting the subconscious work on it. And finally the light bulb went off.

I have other branches in the Branches folder that caused no problem when they were created. I thought to myself, "Self, it's not the branch that did it.. It must be something that you did at the same time you created the branch."

My assumption about the branch breaking my build came directly from my Jump To Conclusions Mat.
I created this branch for an external group who is adding functionality. In an effort to keep my main pristine, I locked it down so that only members of the group "Tech Leads" could check in to Main.

This had to be the cause.. when I realized it last night I almost went back in to work... but come on its Lego Indy!

So I get to work this morning and checked the membership of "Tech Members" and surprise, surprise... TFSService is a member... The build service uses this account to access TFS...

So I quickly added it to the leads group and verified that my builds worked again and went to repair the dent I put in the wall from beating my head against it.

So Lessons Learned here:
1. Respect the build user, he can make you a very sad panda.
2. I've automated the build, its time to get a nightly build going so these changes are fresh in my mind when stuff breaks.
3. While I am at it might as well look into setting up CI to the Dev environment with the nightly.
4. Indy really can accomplish anything.

So in the end, I created my own problem. Thanks to all the ALT.NET mailing list readers for silently laughing at me while I verbalized (textualized?) the issue on the mailing list and worked through it.

I'll be here all week.


 
Categories: Development | MSBuild | Random

Please join us on Thursday, June 12th for a presentation on Silverlight 2.0 by Erik Mork.

Meeting Specifics:

Erik Mork will be returning to Olympia in June to present Silverlight 2.0 to the South Sound .NET User Group. Our last visit from Erik was in July 2007, when he told us about Silverlight 1.0 and looked forward to what might be in version 2.0. Now, with Silverlight 2.0 released in Beta, he can come back and give us the next chapter in this ongoing story.

Erik was with Tranxition last year and looking toward self-employment. He's made that leap now, founding Silver Bay Labs. In addition, he and with his wife is producing a Silverlight podcast called Sparkling Client. Recent shows featured interviews with Adam Kinney aka The Silverlight Surfer and Jesse Liberty aka Captain Silverlight.

If you're into Silverlight, definitely check out what the Morks are up to and plan to attend the South Sound .NET meeting on June 12th with Erik and Silverlight 2.0.

 

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

Don't forget to let your friends and co-workers know about this meeting.  Feel free to forward this email and/or direct them to www.ssdotnet.org for more information.


 
Categories: Development | Events | Local

April 25, 2008
@ 12:35 PM

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

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

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

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

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

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

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

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

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

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

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

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


 
Categories: Development | MSBuild

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

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

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

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

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

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

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

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

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

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


 
Categories: Development | MSBuild

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

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

Code included just because I want to:

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

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

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

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

            string content = getContent(uri);

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

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

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

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

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

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

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

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

        }

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

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

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

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

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

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

 
Categories: Development | Random

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

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

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

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

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

Location

Thurston County Fairgrounds
Expo Hall
3054 Carpenter Rd SE


 
Categories: Development | Events | Local

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

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

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

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

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

Board

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

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

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

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

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

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

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

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


 
Categories: Development | Fundamentals

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

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

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

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

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

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

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


 
Categories: Development | Events | Local

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

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

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

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

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

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

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

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


 
Categories: Development

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

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

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

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

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

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


 
Categories: Books | Development

I was having a problem printing reports using the ActiveX print mode in the Crystal Reports Viewer control. The problem is described exactly here.

When using the Crystal Reports Viewer for .NET, if the PrintMode property is set to ActiveX reports designed to print landscape will display correctly but print portrait.

There is a bug in the crystalprinthost.html located @ C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\ASP.NETClientFiles\ CrystalReportWebFormViewer3\html\crystalprinthost.html

The following code must be changed in the file:
if (window.dialogArguments.pageorientation) {
objectTag +="<PARAM NAME=\"PageOrientation\" VALUE=\"";
objectTag += window.dialogArguments.pageorientation;
objectTag += "\">";
}

change it to:

if (window.dialogArguments.[b]paperorientation[/b]) {
objectTag +="<PARAM NAME=\"PageOrientation\" VALUE=\"";
objectTag += window.dialogArguments.paperorientation;
objectTag += "\">";
}

NOTE: You are only changing the javascript property name pageorientation to paperorientation, the param needs to stay the same.


 
Categories: Development

March 28, 2008
@ 12:50 PM

I have inherited an application that uses some interesting design choices. I have been tasked with adding functionality. I would like to put my mantra of “improve everything you touch” in this process.

The application uses a standard nTier design pattern based on a collection of domain specific entities contained in a  Buisness.Entities.dll. This library contains two types of objects: a BusinessObjectEntity and a corresponding BusinessObjectEntityCollection. The objects do not really model any real world items, but instead contain all of the data elements needed to render a specific view.

Each object inherits from EntityBase which contains no implementation. Object collection classes inherit from EntityCollectionBase which appears to be a wrapper around List(Of T).

Here is an example of the implementation of one of the collection classes:

WARNING: VB.NET CODE AHEAD

Public Class InboxWorkItemCollection
    Inherits EDF.Entities.EntityCollectionBase(Of EntityBase)

    Public Overrides Function SetValues(
ByVal
DtReader As System.Data.IDataReader) As Boolean While (DtReader.Read()) Dim objWI As New InboxWorkItem objWI.SetValues(DtReader) Me.Add(objWI) End While Return True End Function End Class

There are ninety-one collection classes in the library that follow this pattern of reading from a Data Reader object, creating an instance of a specific class and adding it to the List collection.

Clearly there is an opportunity here to improve the design. I came up with this:

Public Class TypedEntityCollection

    Private entities As List(Of EntityBase)

    Public Sub New(ByVal reader As System.Data.IDataReader, 
ByVal
type As Type)

entities = New List(Of EntityBase) While (reader.Read()) Dim item As EntityBase item = Activator.CreateInstance(type) item.SetValues(reader) entities.Add(item) End While End Sub End Class
This new collection type still wraps List(Of T) but now expects a type parameter in its constructor. It uses this extra parameter to use create an instance of a specific class via reflection.

This appears to eliminate 90 classes and reduce the complexity of the library dramatically. How would you have approached the problem? How would you improve on my solution?

Now on to determine the level of duplication in the entity classes. Do we areally have ninety-one domain objects? I think there might be even more commonality to find yet.


 
Categories: Development

I received the following message from my local DNUG, the South Sound .NET Users Group about The Code Camp coming to our area. I plan on attending and hope to see you there.

"Are you ready for the Code Trip to come to Olympia?  Jason Mauer is coming back to Olympia with a tour bus full of geeks.  They'll be pulling up to the Thurston County Fairgrounds on Monday, April 14th.  There will be giveaways, and great information on the newest technology from great presenters.

Have you been tracking the Code Trip?  They started in Las Vegas at MIX08 on March 7th and headed north.  They've made about 13 stops since then and Olympia will be the last one before arriving at the MVP Summit in Seattle on Tuesday, April 15th.  The capacity of our venue is 288, let's see how close we can get to that total, ok? 

Jason will be sending us a list soon of the roster of geeks we'll see performing on the 14th.  We're going to set up the Expo Hall so that multiple presentations can be happening at one time, to make the most of the time we have.

Other Code Trip events have featured talks on the newest technologies to emerge from MIX08, including Silverlight 2 Beta 1, Internet Explorer 8, SQL Server Data Services, Windows Live.  Some attendees have been treated to talks on the technology powering the Code Trip, both online and on the bus.  We'll update you as soon as we know what the recipe for the Olympia stop will be.

Tell your friends, drag your co-workers along, let's give the Code Trippers a big final event before they get back to the mothership.

For more on the Code Trip, including information on current and past events and where the Bus is now, see TheCodeTrip.com.  You can see profiles of the Roadies -- people who have spent time in the bus.  There's a behind the scenes section called 'Under the Hood' where you can get information on the technologies used on the Code Trip, the use of GPS information in tracking the route and current bus location and other technical goodness being used to keep them in touch with the rest of the world.  The Toolbox provides links to the tools used along the way to keep the Trip running smoothly.

The Travel Log is a blog contributed to by various people, mostly Jason Mauer and Tim Heuer.  Video blogs, info on participants and events gets you right into the action.  It certainly gets me fired up to see them in Olympia.  Makes me more than a little envious really, getting to ride a tour bus full of state of the art equipment and full of other geeks sounds like a lot of fun.

So, you coming or what?  Put it on your calendar, invite some other folks and we'll see you there.

Monday, April 14th, 2008
6:30pm - 9:30pm
The Expo Hall at the Thurston County Fairgrounds
3054 Carpenter Rd SE
for directions"




 
Categories: Local | Development | Events