Tuesday, February 27, 2007

NHibernate reference app

Billy McCafferty has created a really nice NHibernate sample app on CodeProject using good ol’ Northwind. If you’re interested in NHibernate, you ought to take a look at it. Billy watches user comments on the article, and gives good help with questions.

His project shows a really nice example of using NHibernate.Generics, and creates a many-to-many bidirectional relationship between Customer and Order. I was interested in extending his domain just to play around a bit, so I decided to create an OrderDetail class. Specifically, I wanted to create a one-to-many one-way relationship from Order to OrderDetail – in other words, I just want the Order to keep track of its own OrderDetails, and I don’t think I really care about being able to see the Order from an OrderDetail. In order to get that working, I had to do the following:

1) Change the OrderDetails table definition in Northwind to include an integer field called OrderDetailID, and make that field the primary key.

2) Create an OrderDetail class like so:


using System;
using NHibernate.Generics;

namespace NHibernateSample.Core.Domain
{
public class OrderDetail : DomainObject
{
public OrderDetail()
{
}

public int ProductId
{
get { return productId; }
set { productId = value; }
}

public decimal UnitPrice
{
get { return unitPrice; }
set { unitPrice = value; }
}

public int Quantity
{
get { return quantity; }
set { quantity = value; }
}

public float Discount
{
get { return discount; }
set { discount = value; }
}


private int productId;
private decimal unitPrice;
private int quantity;
private float discount;

}
}

3) Add an OrderDetails collection to the Order class:

public IList<OrderDetail> OrderDetails
{
get { return _orderDetails; }
}
.

.
.
private EntityList<OrderDetail> _orderDetails = new EntityList<OrderDetail>();


4) And then map everything:
---- order.hbm.xml ----


<bag name="OrderDetails" lazy="true" table="OrderDetails" inverse="false"
access="NHibernate.Generics.GenericAccessor, NHibernate.Generics" >
<key column="OrderID" />
<one-to-many class="NHibernateSample.Core.Domain.OrderDetail, NHibernateSample.Core" />
</bag>


---- orderdetail.hbm.xml ----

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0">
<class name="NHibernateSample.Core.Domain.OrderDetail, NHibernateSample.Core" table="OrderDetails">
<id name="ID" column="OrderDetailsID" unsaved-value="0">
<generator class="identity" />
</id>


<property name="ProductId" column="ProductID" />
<property name="UnitPrice" column="UnitPrice" />
<property name="Quantity" column="Quantity" />
<property name="Discount" column="Discount" />


</class>
</hibernate-mapping>


One thing that threw me initially was the WireUpEntities() method he calls in the Customer and Order classes. Here's the one he has in the Customer class:

private void WireUpEntities() {
// Implement parent/child relationship add/remove scaffolding between Customer and Orders
_orders = new EntityList<Order>(
delegate(Order order) { order.OrderedBy = this; },
delegate(Order order) { order.OrderedBy = null; }
);
}


Since I’ve never used NHibernate generics, I apparently decided it would be a good idea to put my brain out to pasture for a little while, and not to actually dig in and understand what’s going on here before trying to use it for my OrderDetails collection. I tried some goofy similar stuff in the OrderDetails class, but it turns out that this code is for enforcing the bi-directional relationship – not needed at all for one-way relationships, I can just relax and let NHibernate do the work for me. The only difference is that I have to do this in my Order class:

private EntityList<OrderDetail> _orderDetails = new EntityList<OrderDetail>();

instead of this:

private EntityList<OrderDetail> _orderDetails;

In the bi-directional relationship between Customer and Order, WireUpEntities() instantiates the EntityList, but since you don’t need WireUpEntities() for one-way relationships you have to instantiate the EntityList yourself. NHibernate will only work with an existing list...it won't initialize _orderDetails to a new EntityList itself. So if you don't call "new" in a wire-up method, then it needs to be done when declaring the member.

Thursday, February 22, 2007

Reference App for lots of cool stuff

I want to create a .NET reference app to be made available on CodeProject (or some other such site) which will demonstrate the following:
  1. Test Driven Development - full set of unit, integration, and acceptance tests
  2. Domain Driven Design - entities, value objects, services, aggregates, repositories, the works
  3. ORM using NHibernate - I want to explore issues that arise using DDD repositories with an EntityDataGateway to control the NHibernate session.
  4. MVP (maybe MonoRail)
  5. Continuous Integration - set of build scripts to build, test, and report on coverage.

Does a publicly available reference project that covers all these areas currently exist?

Tuesday, February 20, 2007

Random Rules Monday, Except That It's Actually Tuesday

Like many of the developers I've worked with over the years, I listen to music while I work. The Onion AV Club has a semi-regular feature called Random Rules where they get a celebrity to hit shuffle on their iPod, and then reveal all the embarrasing details that come up in the first ten selections. Here's mine for today:

  1. Just Another Night, Ian Hunter
  2. Road, Nick Drake
  3. A Star Is Bored, Paul Westerberg
  4. Mandolin Wind, Rod Stewart
  5. Beat on the Brat, The Ramones
  6. Wild Wild Lover, Flat Duo Jets
  7. Walkin' to My Baby, Fabulous Thunderbirds
  8. To Here Knows When, My Bloody Valentine
  9. Stiff Competition, Cheap Trick
  10. Vaseline, Elastica

Glad all the ABBA stuff didn't come up.

Monday, February 19, 2007

A test-driven chocolate cake?

Are there disciplines other than software development that implement something like Test Driven Development? And how effective would this approach be in other disciplines?

  • Can I know before my cake batter is ever mixed up what my cake is going to taste like?
  • Can I know before my dress design hits the runway that Milan will be absolutely beside itself?
  • And it would be really nice next season when hemlines rise or fall to be able to change the hem without worrying about whether or not you were going to pop another seam and ruin the whole dress.
  • Can I know before I cut my ear off and send it to a woman in an act of rage and desparation, and eventually take my own life in a lonely wheat field, that my paintings will one day be considered among the best ever created?
  • etc.

It would be really nice to know ahead of time that things are going to turn out ok, or at least like you planned them. We can achieve a measure of that in software development with discipline. And using a solid infrastructure of tests, we can have the confidence to make changes to our applications as the business demands it.

But how do other disciplines do it? We've been making things since the dawn of history. How have we historically tackled the problem of quality assurance?

Sunday, February 18, 2007

Jeff Atwood is filled with poo

Jeff Atwood sez programmers are born, that you can't become a great programmer if you aren't born one. He asserts that, "A mediocre developer can program his or her heart out for four years, but that won't magically transform them into a good developer." To Mr. Atwood, I offer this humble rebuttal (quoting Col. Potter): Monkey muffins! I'm not being fair to Jeff, after all a text without a context is a pretext. But it's my blog and I'll cry if I want to.

No one comes into this world knowing how to do anything except cry, poop, eat, and sleep. However, our Creator graciously endows some with talents for various things: there are those who are naturally bent towards music, others who can see an object and render an image of it on the page, still others who can work their way through the abstract logical problems we encounter in programming, etc, etc. Talent is raw material, useless without honing it into skill. Redmond wasn't built in a day: show me one application that has shipped in the history of computing that was entirely produced by a newbie approaching a keyboard (or a breadboard for that matter) for the first time.

Peter Norvig has a great little article about the determination it takes to build skill in any discipline:
http://norvig.com/21-days.html

Good stuff.