Thursday, October 22, 2009

Sample Application with White,WPF,TDD and DDD

I'm currently thinking about what we could do better on a next project avoiding some technical issues that we have had in our latest project. Some of the issues were

  1. The Passive View implementation for our Win-Form client was too costly. The design of it wasn't intuitive and straight forward at all.
  2. The Passive View implementation didn't allow us to unit-test the UI. Even we were able to test the presenters we still couldn't test the event- and data binding automatically .
  3. Our initial plan to do acceptance- and integrationtesting with TestComplete failed. No tests have ever been written with TestComplete.
  4. Our testing-suite runs too slow. The whole suite was too slow and even running one single test took too much time.
  5. We struggled with Aggregates and domain logic leaked sometimes into the presentation layers.
  6. The application is too slow. This was caused due the fact that we couldn't react appropriately when we were forced to move our 2-tier implementation to a 3-tier implementation.
I've recently written a sample application to find answers to some of those problems. You can download the application from this site (Click 'Save file to your PC' at the end of the site).


I'm going to explain my thoughts in detail maybe later, but the most interesting points in the sample application are:
  • WPF+White: White allows testing the UI right from inside the unit-test runner. Following some basic principals it allows to script the UI right from the c#-code. But I used White just to Unit-Test the UI and to write some basic integration tests. I don't believe that one should use White to do more than that otherwise he might get some serious maintenance issues. For details see OrderExploration.Test\UnitTest\Ui and OrderExploration.Test\Integration
  • Acceptance-Testing: I think acceptance-testing frameworks are a weak point of the .net-world. Either they require a lot of infrastructure (like wiki's) or they can't be used by "none technical's". NBehave is useless because it can't be used by "none technical's" and it doesn't produce readable code at all (That statement is maybe wrong with Version 0.4, but I didn't check). FitNess is far too complicated for a small project like the sample application. I tried StoryTeller as well, but there is not a lot of documentation available yet, so I gave up. So why not using pure old nunit-tests if there are no "none technical's"? For details see OrderExploration.Test\Acceptance
  • Persistence-Ignorance: There is just one test that hits the database (see OrderExploration.Test\Integration). All other tests (UI, unit und acceptance) run against stubs.
  • Test-Setups: To setup Unit- Acceptance- and Integrationtest differently I used SetupFixtures (I didn't know them before!). Lookout for classes with name "SetupFixture"
  • CQS (Command-Query Seperation) inspired by a Ian Cooper: I tried to separate querying data (mainly for displaying on view) and commanding (mainly for updating on aggregates). I'm not sure if I really got it right! For an example see method DataService.GetOrders() that queries data right from the database and see OrderService.Submit() that writes changes through the aggregate to the database.
  • Aggregates: See the class Order that defines an Aggregate-Root. I tried to build an expressive aggregate by separating the aggregate from its persisted structure (see class OrderRow) and its displayed structure (see class OrderDetailData). If there is an interest I would like to discuss that decision later. For now see method Order.AddTag() and think about: 1.) If the class Order were directly bound to the UI, how would you handle the fact that the user can add/remove tags several time but just the last state should be persisted and logged in the history. 2.) If the class Order were persisted directly, how would you handle the fact that tags are persisted as strings? (see Order.Tags in the database-scheme)
  • and StructureMap and AutoMapper ... of course!
Summary
  • White is cool and helps to (Unit)-test UI
  • Persistence Ignorance can be implemented and helps to make Unit-/UI-/Acceptance tests much faster
  • CQS (Command-Query-Separation), ViewModels, DomainModel and PersistenceModel add another layer of indirection that can help to solve tricky problems quite easly. However, these indirections can be a huge overkill for simple applications. I have no doubts that it's worth to have ViewModels (including all kind of MVP,MVC) but I'm not sure when it's worth to separate DomainModel and PersistenceModel. In the sample application, DDD (e.g Repository-Pattern) helped me to answer that question per Aggregate. In the sample application the Aggregate Order has a separated DomainModel and PersistenceModel. For the other Aggregates DomainModel and PersistenceModel are the same. Any thoughts about that?







    Monday, August 3, 2009

    IObservable ... it's so beautiful

    I've just watched Brian Beckman and Erik Meijer - Inside the .NET Reactive Framework (Rx) and it's again a great work of Erik, Wes and their team.

    It's a petty that I couldn't understand all that formalism but i enjoyed it like art and i'm impressed about the beauty and completness of their solution. That's the first mind-blowing feature of .NET 4.0!

    Sunday, July 26, 2009

    Object Role Stereotypes

    I had a short discussions with my college Jürg last week about that classes in object oriented design (especially DDD or RDD) can be classified regarding their responsibility and behaviour. Neither could I remember the name for that concept nor any of those classifications. Jürg mentioned that this is like stereotypes in UML. I looked it up now and he wasn't wrong. They are called 'Object Role Stereotypes'. Not that Object Role Stereotypes are defined by the UML specification but one could use stereotypes in UML to classify classes by their Object Role Stereotype. Here are the stereotypes that I found:

    • Controller – Controls application execution. Makes decisions and delegates to other classes.
    • Service Provider – Provides a service to other classes. Performs a calculation, computation, or executes business rules.
    • Interfacer – Communicates actions to other layers or systems.
    • Information Holder – Holds facts. Domain classes.
    • Structurer – Maintains relationships between other classes

    Sunday, March 15, 2009

    How to get the console output working with NBehave 0.4 and the ReSharper Testrunner

    When working with the latest build of NBehave 0.4 you may notice that there is no output written to the ReSharper Testrunner Output anymore.

    Here is how I did workaround the problem. I derived the specs from the following class and every thing was fine again:
    public class SpecBaseWithConsoleOutput: SpecBase
    {
    private EventHandler<EventArgs<MessageEventData>> addedHandler;
    private EventHandler<EventArgs<Scenario>> scenarioCreatedHandler;
    private EventHandler<EventArgs<Story>> storyCreatedHandler;
    public override void MainSetup()
    {
    base.MainSetup();
    addedHandler = (o, a) => Console.WriteLine(a.EventData.Message);
    scenarioCreatedHandler = (o, a) => Console.WriteLine(a.EventData.Title);
    storyCreatedHandler = (o, a) => Console.WriteLine(a.EventData.Title);
    Story.MessageAdded += addedHandler;
    Story.ScenarioCreated += scenarioCreatedHandler;
    Story.StoryCreated += storyCreatedHandler;
    }
    public override void MainTeardown()
    {
    Story.MessageAdded -= addedHandler;
    Story.ScenarioCreated -= scenarioCreatedHandler;
    Story.StoryCreated -= storyCreatedHandler;
    base.MainTeardown();
    }
    }

    Saturday, January 24, 2009

    Implementing and testing mapping code with AutoMapper

    I was thinking some months ago that it would be great to have a property mapper that eliminates tedious mapping code . I'm very happy that Jimmy Bogard and his team just have published a framework called AutoMapper that resolves that issue. I haven't tested it yet but the idea looks promising.

    Why would I use AutoMapper?
    • In order to implement better encapsulation and layering with less amount of coding
    • In order to unit-test mapping code using a simple 'Mapper.AssertConfigurationIsValid()'

    Sunday, January 11, 2009

    TypeMockAutoMocker on CodePlex

    I' ve just uploaded the TypeMockAutoMocker to http://www.codeplex.com/typemockautomocker

    How to use it:
    1.) Download TypeMockAutoMocker.dll
    2.) Copy it to your project and set an assembly reference to it
    2.) Set 'Copy local = true' on your TypeMock.dll
    3.) Have fun (see Link)

    StructureMap 2.5.1 and TypeMock 5.1.2 ist the only tested configuration at the moment.

    Friday, January 2, 2009

    AutoMocking Container with TypeMock Isolator

    I have implemented an AutoMocking container for the Isolator inspired by an Introduction to the AutoMocking container in StructureMap, the fact that our test setups usually are pretty messy and Jeremy's claim that TypeMock users probably don't care about dependency injection. But why do I want to use DI (Dependency Injection) in conjunctions with TypeMock? I don't want to fight a 'religious war' based on that question, but here is what I think:

    • TypeMock without DI lacks an explicit boundary that defines what the class under tests is and which classes are mocks or stubs. This is about solid design and to isolate parts of the software in a structured manner. It’s true that you can mock everything with TypeMock but this is just about mocking and not about software design.

    • DI with another mocking framework than TypeMock is like .NET without System.Reflection. I don't like to use System.Reflection but sometimes it's just the right thing. It’s the same with TypeMock. If everything (own code, legacy-code, external libraries etc.) had a solid design you wouldn't need it but sometime it makes the life so much easier.
    Example without Dependency Injection
    There is the class under test called ValidationViewPresenter and it has following dependencies:



    A a test without DI could look like:
    [Test]
    public void CanValidateCreditCardNumber()
    {
    // Arrange
    var viewMock = Isolate.Fake.Instance<ValidationView>();
    var customerServiceMock = Isolate.Fake.Instance<CustomerService>();
    var creditCardServiceMock = Isolate.Fake.Instance<CreditcardService>();
    var customer56 = new Customer {CreditCardNr = "5500 0001 0001 0001"};

    // Mock the (hidden) dependencies
    Isolate.Swap.NextInstance<ValidationView>().With(viewMock);
    Isolate.Swap.NextInstance<CustomerService>().With(customerServiceMock);
    Isolate.Swap.NextInstance<CreditcardService>().With(creditCardServiceMock);
    // Mock the calls to the dependencies
    Isolate.WhenCalled(()=>viewMock.CustomerNr).WillReturn(56);
    Isolate.WhenCalled(() => customerServiceMock.GetCustomer(56)).WillReturn(customer56);
    Isolate.WhenCalled(()=> creditCardServiceMock.ValidateCreditCard("5500 0001 0001 0001")).WillReturn(true);

    // Act
      var presenter = new ValidationViewPresenter();

    presenter.ValidateCreditCardOfCustomer();
    // Assert
    Isolate.Verify.WasCalledWithExactArguments(() => viewMock.IsValid = true);
    }

    Example with Dependency Injection
    After introducing constructor injection it looks like:
    [Test]
    public void CanValidateCreditCardNumber()
    {
    // Arrange
    var viewMock = Isolate.Fake.Instance<ValidationView>();
    var customerServiceMock = Isolate.Fake.Instance<CustomerService>();
    var creditCardServiceMock = Isolate.Fake.Instance<CreditcardService>();
    var customer56 = new Customer {CreditCardNr = "5500 0001 0001 0001"};
    // Inject dependencies manually
      var presenter = new ValidationViewPresenter(viewMock, customerServiceMock, creditCardServiceMock);

    Isolate.WhenCalled(()=> viewMock.CustomerNr).WillReturn(56);
    Isolate.WhenCalled(() => customerServiceMock.GetCustomer(56)).WillReturn(customer56);
    Isolate.WhenCalled(() => creditCardServiceMock.ValidateCreditCard("5500 0001 0001 0001")).WillReturn(true);

    // Act
    presenter.ValidateCreditCardOfCustomer();

    // Assert
    Isolate.Verify.WasCalledWithExactArguments(() => viewMock.IsValid = true);
    }

    Example with Automocking Container
    Let's eliminate the explicit constructor injection by introducing the TypeMockAutoMocker now:

    [Test]
    public void CanValidateCreditCardNumber()
    {
    // Arrange
    var customer56 = new Customer {CreditCardNr = "5500 0001 0001 0001"};
      var presenterMocker = new TypeMockAutoMocker<ValidationViewPresenter>(MockMode.AAA);

    var viewMock = presenterMocker.Get<IValidationView>();
    var customerServiceMock = presenterMocker.Get<ICustomerService>();
    var creditCardServcieMock = presenterMocker.Get<ICreditCardService>();

    Isolate.WhenCalled(() => viewMock.CustomerNr).WillReturn(56);
    Isolate.WhenCalled(() => customerServiceMock.GetCustomer(56)).WillReturn(customer56);
    Isolate.WhenCalled(() => creditCardServcieMock.ValidateCreditCard("5500 0001 0001 0001")).WillReturn(true);

    // Act
    presenterMocker.ClassUnderTest.ValidateCreditCardOfCustomer();

    // Assert
    Isolate.Verify.WasCalledWithExactArguments(() => viewMock.IsValid = true);
    }
    As you can see the AutoMocking container couldn’t eliminate a lot of complexity. This is due to the fact that the test itself is complex and there are a number of non-default preconditions.

    A better example with AutoMocking Container
    Following code tests the same method but with different preconditions again. But this time we can rely on the default behavior that was setup by the AutoMocking container. This means that all involved and not explicitly mocked interfaces or classes do have a default behavior.

    [Test]
    public void CanHandleNotExistingCustomer()
    {
    // Arrange
      var presenterMocker = new TypeMockAutoMocker<ValidationViewPresenter>(MockMode.AAA);

    var viewMock = presenterMocker.Get<IValidationView>();
    Isolate.WhenCalled(() => viewMock.CustomerNr).WillReturn(56);

    // Act
    presenterMocker.ClassUnderTest.ValidateCreditCardOfCustomer();

    // Assert
    Isolate.Verify.WasCalledWithExactArguments(() => viewMock.IsValid = false);
    }
    Conclusion
    There is a big chance that you can get lost using TypeMock and StructureMap in conjunction. The problem is that there are too many ways how they can be combined. However I hope that the TypeMockAutoMocker could help in a way that it's defining a common pattern for how to setup the tests and how to inject the mocks. Remember always:
    • Depended classes are instantiated by the AutoMocker automatically.
    • Depended interfaces and abstract classes are instantiated as mocks. These mocks do have a default behaviour where every method can be called.
    • Depended concrete classes are instantiated by calling its greediest constructor. They are not mocked.
    • To change the default behaviour you can use Inject() to register your own mock to the AutoMocker. It's how you can setup a mock manually.

    Sound’s like ‘convention over configuration’. And that makes life definitely easier.