Woah, Nellie.NET!

From my simple mind to… mine…

Simple NHibernate Example utilizing various xDD Techniques, Part 1

with 4 comments

I wanted to present a simple NHibernate example utilizing some techniques I’ve learned along the way. This first post will provide some domain level background.

Let me know if you have any feedback, so that I can correct or extend this example.

Domain Driven Design

From Eric Evan’s “Domain-Driven Design: Tackling Complexity in the Heart of Software,” I will use the concept of the Ubiquituous Language to derive a Model-Driven Design. That is, begin by taking a common language between the domain experts and developers. Then translate the language into an abstract representation, the domain model.

As developers, we can derive our implementation from the domain model and still converse with domain experts and users in terms of the ubiquitous language and not through technical “mumbo-jumbo”. Well, most of the time.

Starting with a very, very simple example, we might have the following conversation between a domain expert and developer:

Domain Expert: “I would like the system to take in a lead.”

Developer: “You mean store a person’s information in the database?”

Domain Expert: “A database? Sure, if that makes sense. All I really need is for you to save the lead’s information somehwere; first name, last name, and email address. Can you do that?”

And that’s it for now. Yes, I know that’s pretty dang simple. I’ll break this down a little.

The domain expert refers to two Domain-Driven Design (DDD) concepts. I will not into great detail regarding these two concepts since the DDD book does a great job (or have a look at this good introductory book, “Domain-Driven Design Quickly”):

  1. The first concept is that of an Entity, which in this case, I only have one. I will refer to the known entity as a Lead.
  2. The second concept is that of the Repository. The Lead will be saved “somewhere.” I will use a LeadRepository to save the Lead. Repositories allow for the storage and retrieval of entities.

I would also note that there is the concept of a Factory implied in this story, but I will not go into that for now. Also, I am not going to draw any UML models as this example is ridiculously easy and because I’m lazy.

Test Driven Development

I am not familiar enough with Behavior-Driven Development (BDD) to fully utilize the technique in this example. I will stick to Test Driven Development (TDD). I am going to assume that you know enough about TDD, so I’ll begin by implementing the Lead entity.

We know that we have to capture the Lead’s first name, last name and email. So I’ll write some very simple, yet necessary, tests.

Here are the tests (UPDATED: 3/11/2007):

using Foo.Domain;
using NUnit.Framework;
 
namespace Tests.Foo.Domain
{
    [TestFixture]
    public class WhenSettingUpANewLead
    {
        private Lead lead;
 
        [SetUp]
        public void SetUpContext()
        {
            lead = new Lead();   
        }
 
        [Test]
        public void ShouldAllowFirstNameToBeCaptured()
        {
            lead.FirstName = "Foo";
            Assert.AreEqual("Foo", lead.FirstName, "First Name was not captured.");
        }
 
        [Test]
        public void ShouldAllowLastNameToBeCaptured()
        {
            lead.LastName = "Bar";
            Assert.AreEqual("Bar", lead.LastName, "Last Name was not captured.");
        }
 
        [Test]
        public void ShouldAllowEmailToBeCaptured()
        {
            lead.Email = "baz@test.com";
            Assert.AreEqual("baz@test.com", lead.Email, "Email was not captured.");
        }
    }
}

And the resulting entity class:

namespace Foo.Domain
{
    public class Lead
    {
        private string firstName;
        private string lastName;
        private string email;
 
        public string FirstName
        {
            get { return firstName; }
            set { firstName = value; }
        }
 
        public string LastName
        {
            get { return lastName; }
            set { lastName = value; }
        }
 
        public string Email
        {
            get { return email; }
            set { email = value; }
        }
    }
}

Simple enough! The interesting repository stuff will come in the next post, I promise. 🙂

Advertisements

Written by Nelson

March 4, 2007 at 6:12 am

4 Responses

Subscribe to comments with RSS.

  1. Excellent post Nelson!
    Just one comment as always. 😉

    Your BDD approach was sound but there was something lost a little in my opinion.

    Lets imagine that the context “ANewLead” and the specification “ShouldRetrieveFirstNameFromProperty” failed. The error message would read (should read but NUnit can’t do it YET)

    “A New Lead Should Retrieve First Name From Property” failed because “First name was not retrieved.”

    As you can see the context and specification was lost not because of the test fixture but because of the error message displayed by the Test Runner. But the context doesn’t neccearly give you the “why” you need the first name property.

    Maybe a more elegant approach to the context spec would have been the following.

    Given: A new lead (Context)
    When: Saving a new lead (Event)
    Then: The first name should be filled in (ensure some outcome)

    The most important part of this context is the “event” since it signals business value. The “why” of what you are doing.

    So the failure message should read.

    “When saving a new lead the first name should be filled in”

    Context “SavingANewLead”

    Specify “the first name should be filled in”
    End

    Specify “the last name should be filled in”
    End

    Specify “the email address should be filled in”
    End

    End

    Hope this makes sense.

    Joe

    March 5, 2007 at 4:38 am

  2. Let’s talk. I had a bit of an epiphany about BDD while writing this, but I could sure use a good discussion on the topic. 🙂

    Nellie

    March 5, 2007 at 1:20 pm

  3. I’m sorry but your tests here are a little too simplistic. I started tdd this way, but found that simple property setting/getting should all be wrapped up in one test. I.E., CanInitCustomer(). within that test case, I would define all the getters/setters. Testing each individually is a tdd anti-pattern.

    Anonymous

    April 9, 2007 at 11:12 pm

  4. Yes, they are simple. My point was to show how the entity came to be (test first). Also, it’s more from a BDD point of view and I think in that case, the context makes testing properties significantly more relevant.

    You can test or not test properties. It’s up to you, based on your context. As of this example, my context requires me to have them.

    The point of this BDD style testing is that when the business context says, “I need to store this new thing,” then you show that in single, more refined spec.

    I think you’ll find that context based testing creates many more smaller test fixtures (contexts) and more refined individual tests (specs).

    Nellie

    April 9, 2007 at 11:41 pm


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: