Monday, May 12, 2008

A couple years ago a was in a computer book club located in Philadelphia and participated remotely. The experience was great by unfortunately the group lost funding from Microsoft and disbanded.

After gauging a little bit of interest around town I have decided to try and start one here in Edmonton with the possibility of people being able to participate remotely.

If you are interested in participating, please join the discussion at the Google group mailing list.

Monday, May 12, 2008 4:43:28 PM (GMT Standard Time, UTC+00:00)  #    Comments [2]  | 
Friday, March 28, 2008
Last night I tried installing Visual Studio 2008 and the .NET 3.5 Framework. I kept getting the error: "Error: Installation failed for component Microsoft .NET Framework 3.0a. MSI returned error code 1603".

Not very informative. I eventually ended up getting it installed by temporarily uninstalling IIS. Hope this helps someone else out who is having the same problem.

Friday, March 28, 2008 5:25:21 PM (GMT Standard Time, UTC+00:00)  #    Comments [0]  | 
Wednesday, March 05, 2008

Sweetness!

booishMac.png


Wednesday, March 05, 2008 5:51:55 AM (GMT Standard Time, UTC+00:00)  #    Comments [0]  | 
Friday, February 08, 2008

Today I was creating a test data builder for a unit test. I am fairly new to test data builders, on the last project I was on I relied on the ObjectMother pattern which became fairly tedious over time. Both the ObjectMother pattern and the Test Data Builder are Test Helper patterns:

"We define a helper class to hold any Test Utility Methods we want to reuse in several tests." 

If your objects aren't immutable and all you really care about is getting sensible test data without having to repeat yourself, you can use the Rhino Mocks GenerateStub feature to provide sensible test data and deal with invariant test data:

 

[TestFixture]
public class InvoiceTests
{
    [Test]
    public void ShouldCreateInvoiceWithNoPostalCode()
    {
        Invoice invoiceWithNoPostalCode =
                new InvoiceBuilder()
                .WithRecipient(new RecipientBuilder()
                    .WithAddress(new AddressBuilder()
                        .WithNoPostalCode()
                        .Build())
                    .Build())
                .Build();
 
        Assert.AreEqual(string.Empty,
            invoiceWithNoPostalCode.Recipient.Address.PostalCode);
    }
 
 
}
 
public class InvoiceBuilder
{
    private Invoice invoice;
 
    public InvoiceBuilder()
    {
        invoice = MockRepository.GenerateStub<Invoice>();
    }
 
    public InvoiceBuilder WithRecipient(Recipient recipient)
    {
        invoice.Recipient = recipient;
        return this;
    }
 
    public Invoice Build()
    {
        return invoice;
    }
}
 
public class RecipientBuilder
{
    private Recipient recipient;
 
    public RecipientBuilder()
    {
        recipient = MockRepository.GenerateStub<Recipient>();
    }
 
    public RecipientBuilder WithAddress(Address address)
    {
        recipient.Address = address;
        return this;
    }
 
    public Recipient Build()
    {
        return recipient;
    }
}
 
public class AddressBuilder
{
    private Address address;
 
    public AddressBuilder()
    {
        address = MockRepository.GenerateStub<Address>();
    }
 
    public AddressBuilder WithNoPostalCode()
    {
        address.PostalCode = string.Empty;
        return this;
    }
 
    public Address Build()
    {
        return address;
    }
}

Once again be warned that this does not work for immutable objects, I don't recommend making value objects mutable just to implement this pattern so i'm not sure if it actually provides any real value. Maybe if it is combined with a mutable entity and a custom builder for a value object that preserves that value object's immutability. 

If anyone that reads this blog has a way to make Test Data Builders easier I would be glad to hear it.

 

[Currently Listening To: Young Galaxy- Young Galaxy - Wailing Wall]

Friday, February 08, 2008 6:56:17 AM (GMT Standard Time, UTC+00:00)  #    Comments [3]  | 
Saturday, December 01, 2007

For everyone that was at my DevTeach presentation thank you for showing up and listening to me. I had my adrenaline flowing and ended up finishing a little to early, if only I could code like that day to day!

If you have svn installed, you can download my presentation from the command line with the following command:

svn checkout http://stevenrockartspresentations.googlecode.com/svn/trunk/ devteachgenericspresentation

I still have to do one more check-in to add my reduce implementation and to clean up the code. I am also going to upload a zipped version of the code to the downloads section located here: http://code.google.com/p/stevenrockartspresentations/downloads/list

 

Here is a list of resources from the presentation:

- Combining Generics, Specifications and Functional Programming Part 1

- Combining Generics, Specifications and Functional Programming Part 2

- Combining Generics, Specifications and Functional Programming Part 3

- Combining Generics, Specifications and Functional Programming Part 4

- Follow up to Generics Presentation Feedback

- Reduce in C#

Saturday, December 01, 2007 5:12:27 AM (GMT Standard Time, UTC+00:00)  #    Comments [0]  | 

I got a couple of emails with great feedback from my last couple of posts. I think I could probably turn this presentation into 2 different presentations but it is curing my blogging writers block so i'll post the responses here for everyone's benefit.

Shane was very quick to point out that the method signature in Customer is kind of misleading:

public bool IsAnActiveCustomer(ISpecification<Customer> activeCustomerSpecification)

We could actually pass any specification that implements the ISpecification interface into this function. We can refactor a little to make it a little more clear to someone consuming the Customer class:

public bool IsAnActiveCustomer()
{
    return this.Matches(new ActiveCustomerSpecification());
}
 
public bool Matches(ISpecification<Customer> specification)
{
    return specification.IsSatisfiedBy(this);
}

Using this approach we supply consumers of our class with a default for an active customer and allow them to specify their own specification for what constitutes an active customer.

One thing that I should have mentioned in my post is that Filter and Map are included in the List class in .NET 2.0. Filter == FindAll and Map==ConvertAll, here is the code from Reflector:

public List<T> FindAll(Predicate<T> match)
{
    if (match == null)
    {
        ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
    }
    List<T> list = new List<T>();
    for (int i = 0; i < this._size; i++)
    {
        if (match(this._items[i]))
        {
           list.Add(this._items[i]);
        }
    }
    return list;
}
 
public List<TOutput> ConvertAll<TOutput>(Converter<T, TOutput> converter)
{
    if (converter == null)
    {
        ThrowHelper.ThrowArgumentNullException(ExceptionArgument.converter);
    }
    List<TOutput> list = new List<TOutput>(this._size);
    for (int i = 0; i < this._size; i++)
    {
        list._items[i] = converter(this._items[i]);
    }
    list._size = this._size;
    return list;
}
Saturday, December 01, 2007 3:39:40 AM (GMT Standard Time, UTC+00:00)  #    Comments [0]  | 

At my DevTeach presentation I showed how you can do Map and Filter from Functional programming right now in C# 2.0. In mathematics Reduce is "the process of manipulating a series of equations or matrices into a desired 'simpler' format". In C# you can think of it as taking a list and reducing it down to one value. 

Here is my implementation of Reduce in C# 2.0:

[Test]
public void ShouldReduceListOfIntegersToTotal()
{
    IList<int> numbers = new List<int>();
    numbers.Add(1);
    numbers.Add(2);
    numbers.Add(3);
    numbers.Add(4);
 
    RecordBook<int> recordBook = new RecordBook<int>(numbers);
 
    Assert.AreEqual(10, recordBook.Reduce<int, int>(numbers, Add));
}
 
[Test]
public void ShouldPrintIntegersAsOneString()
{
    IList<int> numbers = new List<int>();
    numbers.Add(1);
    numbers.Add(2);
    numbers.Add(3);
    numbers.Add(4);
 
    RecordBook<int> recordBook = new RecordBook<int>(numbers);
 
    Assert.AreEqual("1234", recordBook.Reduce<int, string>(numbers, BuildStringFromIntegers));
}
 
private string BuildStringFromIntegers(int number, string test)
{
    return test + number;
}
 
private int Add(int number1, int number2)
{
    return number1 + number2;
}

and the implementation of the tests:

public delegate TResult Accumulator<TSource, TResult>(TSource x, TResult y);
 
public TResult Reduce<TSource, TResult>(IList<TSource> source, Accumulator<TSource, TResult> accumulator)
{
    TResult result = default(TResult);
 
    foreach (TSource item in source)
        result = accumulator(item, result);
 
    return result;
}

The first test calculates the sum of adding all the integers in the list together using the add function. The second test takes an integer and concatenates it to a string producing a string of all the integers in the list.

The Reduce function introduces the default keyword that you can leverage with generics. This will give you the default value for value types (0 for integers, 0.0 for decimals, null for string).

Saturday, December 01, 2007 1:21:02 AM (GMT Standard Time, UTC+00:00)  #    Comments [0]  | 
Thursday, November 22, 2007

What would you do if your client asked you to find all suppliers in a list that are located in Alberta? We could create a new Supplier record book but by now you should be seeing the pattern. Whenever the type differs, think about creating a generic class that can extract the essence of the algorithm without worrying about the type. Lets create a generic RecordBook class that can filter by any specification:

public class RecordBook<T>
{
    private IList<T> list;
 
    public RecordBook(IList<T> list)
    {
        this.list = list;
    }
 
    public IEnumerable<T> Filter(ISpecification<T> specification)
    {
        foreach (T item in list)
        {
            if (specification.IsSatisfiedBy(item))
                yield return item;
        }
    }
}

Our Filter method is actually a C# implementation of one of the big 3 in functional programming...Filter!

Our client is happy with our work and we as developers are satisfied that we can respond to change quickly and filter by and type and specification our client can dream up. Our client then throws us a curveball, they want to see all the customers in the list formatted with their last name before their first name. Lets drive out what this would look like with a test:

[Test]
public void ShouldFormatCustomerNameWithLastNameBeforeFirstName()
{
    IList<Customer> recordBook = new List<Customer>();
    recordBook.Add(new Customer(new DateTime(2007, 04, 29), "Steven", "Rockarts"));
 
    RecordBook<Customer> customerRecordBook = new RecordBook<Customer>(recordBook);
 
    IList<string> formattedResult =
        new List<string>(customerRecordBook.Map<Customer, string>(recordBook, ReverseFullName));
 
    Assert.AreEqual("Rockarts Steven", formattedResult[0]);       
}

private string ReverseFullName(Customer customer)
{
    return string.Format("{0} {1}", customer.LastName, customer.FirstName);
}

There is a lot going on in this test so let me try and explain it before showing the Map method. The Map method takes an generic input (in our case a Customer object) and an generic output (a string). It then takes the list that it is going to convert (recordBook) and a method that converts a Customer to a string (ReverseFullName). The result is a list of strings with the customer's name reversed. Here is the implementation:

public IEnumerable<TOutput> Map<TInput, TOutput>(IList<TInput> input, Converter<TInput, TOutput> converter)
{
    foreach (TInput item in input)
    {
        yield return converter(item);
    }
}

This is the C# implementation of the Map higher order function from functional programming. I will leave it up to you the reader to implement the last of the big three from functional programming (Reduce or Fold). Also try and think about how you would create a function to reverse all customers names who are active. Maybe once the dust settles after DevTeach I will post the solution.

Thursday, November 22, 2007 10:33:22 AM (GMT Standard Time, UTC+00:00)  #    Comments [0]  | 

Our Customer comes to us and likes what we have done setting up a way for them to find if a customer is active, but now they want to keep track of all the customers. We come up with the concept of a Customer Record Book and our client seems happy with that:

[Test]
public void ShouldBeAbleToCreateACustomerRecordBook()
{
    IList<Customer> recordBook = new List<Customer>();
    recordBook.Add(new Customer(new DateTime(2007, 04, 29), "Steven", "Rockarts"));
    recordBook.Add(new Customer(new DateTime(1965, 04, 29), "John", "McCarthy"));
    recordBook.Add(new Customer(new DateTime(2006, 04, 29), "Doug", "Armstrong"));
 
    CustomerRecordBook customerRecordBook = new CustomerRecordBook(recordBook);
 
    Assert.IsNotNull(customerRecordBook);
}

public class CustomerRecordBook
{
    private IList<Customer> customerList;
 
    public CustomerRecordBook(IList<Customer> customerList)
    {
        this.customerList = customerList;
    }
}

Our record book does its job of storing customers well but our client wants us to add a way to find all the active customers in it. Our first attempt at creating a way to find all the active customers looks like this:

[Test]
public void ShouldFindAllActiveCustomers()
{
    IList<Customer> recordBook = new List<Customer>();
    recordBook.Add(new Customer(new DateTime(2007, 04, 29), "Steven", "Rockarts"));
    recordBook.Add(new Customer(new DateTime(1965, 04, 29), "John", "McCarthy"));
    recordBook.Add(new Customer(new DateTime(2006, 04, 29), "Doug", "Armstrong"));
 
    CustomerRecordBook customerRecordBook = new CustomerRecordBook(recordBook);
 
    Assert.AreEqual(1, customerRecordBook.Filter(new ActiveCustomerSpecification()).Count);
}

public class CustomerRecordBook
{
    private IList<Customer> customerList;
 
    public CustomerRecordBook(IList<Customer> customerList)
    {
        this.customerList = customerList;
    }
 
    public IList<Customer> Filter(ActiveCustomerSpecification specification)
    {
         IList<Customer> list = new List<Customer>();
 
         foreach (Customer customer in customerList)
         {
             if(customer.IsAnActiveCustomer(specification))
                list.Add(customer);
         }
 
         return list;
     }       
}

The Filter method that we just created takes in the ActiveCustomerSpecification, creates a temporary list and then iterates through the customer list adding the active customers to the temporary list, once it is done it returns the temporary list.  Our test passes but there are a couple of improvements we can make to this code. First of all, we don't need to create a temporary list or use an IList<Customer> we can leverage the yield keyword and IEnumerable<Customer> to make our code tighter:

public IEnumerable<Customer> Filter(ActiveCustomerSpecification specification)
{
    foreach (Customer customer in customerList)
    {
        if (customer.IsAnActiveCustomer(specification))
            yield return customer;
    }
}

This change will break our test since IEnumerable does not contain a definition for count. If we look at the available constructors for the List class we can see that List has a contructor for creating a list from IEnumerable. So we can easily fix our test:

[Test]
public void ShouldFindAllActiveCustomers()
{
    IList<Customer> recordBook = new List<Customer>();
    recordBook.Add(new Customer(new DateTime(2007, 04, 29), "Steven", "Rockarts"));
    recordBook.Add(new Customer(new DateTime(1965, 04, 29), "John", "McCarthy"));
    recordBook.Add(new Customer(new DateTime(2006, 04, 29), "Doug", "Armstrong"));
 
    CustomerRecordBook customerRecordBook = new CustomerRecordBook(recordBook);
 
    Assert.AreEqual(1, new List<Customer>(customerRecordBook.Filter(new ActiveCustomerSpecification())).Count);
}

Now we are able to find all active customers in a list.

Thursday, November 22, 2007 9:46:45 AM (GMT Standard Time, UTC+00:00)  #    Comments [0]  | 

Encapsulating Criteria Using Specifications

"Specification provides a concise way of expressing certain kinds of rules, extricating them from conditional logic and making them explicit in the model."

Eric Evans : Domain Driven Design

In our domain model we have a normal Customer object that looks like this:

public class Customer
{
    private DateTime signUpDate;
    private string firstName;
    private string lastName;
 
    public Customer(DateTime signUpDate, string firstName, string lastName)
    {
        this.