7 Jul
2009

Fluent Context Builders

Category:UncategorizedTag: :

One thing I?ve been doing more and more of, especially as I use MSpec and context/spec driven development, is using lambdas and fluent-interface style programming to capture the essence of the spec?s I?m working on and keep them separate from the details of the code that implements them.

What the heck does that mean? Well, let?s say I get the following story:

    As a customer of our website
    When I order a medical product
    And I want it shipped to a state with no sales tax on medical products
    I should see that there is no tax for the item
    And no sales tax for that item should be incorporated in the final price

Quite a mouth full, yet completely contrived.

What does my executable specification for this look like? Well, first, let?s name it:

public class when_I_order_medial_products_for_shipment_to_places_where_they_arent_subject_to_sales_tax 
{
}

I changed the wording around a little. I would probably work on this with a business expert to make sure I understood the story right. I might even come up with something more concise and understand the story/business even better from the conversation.

Next, the asserts:

It shows_me_there_is_no_sales_tax_for_the_item;
It doesnt_include_any_tax_for_the_item_in_the_total;

Personally, I prefer writing my specs in active voice. It helps me get in the role of the person that we?re doing this for.

If I run this now, I get the ?pending? behavior we talked about in my last post:

 when I order medial products for shipment to places where they arent subject to sales tax
 ? shows me there is no sales tax for the item (NOT IMPLEMENTED)
 ? doesnt include any tax for the item in the total (NOT IMPLEMENTED)

Before I can implement the assertions, I need to be able to build the context up:

Because of = () => {
// TODO: Shit...I don't know
};

If you are used to test-first design, you are probably familiar with the concept of ?write the code you wish you had.? Increasingly, I am finding, even if just for design purposes, the code I wish I had was wrapped in a fluent builder for the contexts I am testing:

Because of = () => {
var invoice = new Invoice()
.with_some_medical_product()
.shipping_to(new Address().where_medical_products_arent_taxed());
};

That pretty much sums up the scenario I want. I just need to implement these extension methods.

public static class ContextBuilder
{
public static Invoice with_some_medical_product(this Invoice invoice)
{
invoice.Items.Add(new InvoiceItem { });

return invoice;
}
}

So, what makes something a medical product in our system? Is it simply an attribute of a product?

invoice.Items.Add(new InvoiceItem {
Product = new Product { Category = Category.MedicalSupplies }
);

Or is there some service that figures that out?

static IProductCategoryFigureOuter categories = MockRepository.GenerateStub<IProductCategoryFigureOuter>();



public static Invoice with_some_medical_product(this Invoice invoice)
{
Product medicalProduct = new Product { };
categories.Stub(x => x.IsMedicalProduct(medicalProduct)).Return(true);

invoice.Items.Add(new InvoiceItem {
Product = medicalProduct
});

return invoice;
}

We need to ask the SME/business expert more questions to figure out how best to represent this in our system.

How do we make an address where_medical_products_arent_taxed? Another service?

static ITaxInfoService taxInfo = MockRepository.GenerateStub<ITaxInfoService>();



public static Address where_medical_products_arent_taxed(this Address address)
{
taxInfo.Stub(x => x.AreMedicalProductsTaxedIn(address)).Return(false);

return address;
}

We?re starting to get close to where we are going to have to write some real code. Up until this point, all we?ve done is sketch out how it might look structurally, from a high level, but we?ve done this while keeping real business concerns in mind the whole time. Using fluent-style builders to help manage and create the context helped us do that and name the actors that make up the context. The problem is decomposing naturally into smaller problem.

If we?ve gotten good answers to the questions we surfaced during this process, chances are high that our application closely resembles the actual business we?re modeling.

2 thoughts on “Fluent Context Builders

Comments are closed.