Friday, April 16, 2010

Simple WCF service for Win Phone 7 / Silverlight testing

This blog post is meant to briefly illustrate a simple WCF client configuration which returns a CustomerDTO, which you can call and try out from your Win Phone 7, Silverlight, or other client.

The client calls to a simple WCF service on my website, gaddzeit.com, that returns a list of (random-name-generated) customers. The number of rows returned is based on the parameter int howMany (eg. 50 returns 50 CustomerDTO rows). There is a upper limit of 1000 rows returned before a warning exception is thrown.

Do the following:
  • Create a client app (a unit test library, console app, a repository, etc.)
  • Right-click the project and select "Add A Service Reference..."
  • enter the WCF service URL shown below
  • click the Go button
  • once the service is loaded, provide a meaningful name for the namespace (eg. FakeCustomerService)


http://www.gaddzeit.com/FakeCustomerService/


Open the config file (ServiceReferences.ClientConfig | web.config | app.config). The <system.serviceModel> element will have been generated for the WCF service:


<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <system.serviceModel>
        <bindings>
            <basicHttpBinding>
                <binding name="BasicHttpBinding_IGaddzeitServices" maxBufferSize="2147483647"
                    maxReceivedMessageSize="2147483647">
                    <security mode="None" />
                </binding>
            </basicHttpBinding>
        </bindings>
        <client>
            <endpoint address="http://www.gaddzeit.com/FakeCustomerService/FCService.svc"
                binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IGaddzeitServices"
                contract="GaddzeitServices.IGaddzeitServices" name="BasicHttpBinding_IGaddzeitServices" />
        </client>
    </system.serviceModel>
</configuration>


Next, enter a using statement for the web service namespace into:
  • the Repository or Command class (if using MVVM)
  • the code-behind (if responding directly from a control event handler in the presentation layer)

Finally, enter the following code into the above class. This code instantiates the web service, and attaches the GetRandomCustomerNamesCompleted (asynchronous) event to a callback method.
   NOTE Win Phone 7 (and Silverlight) require asynchronous web service calls.


const int howManyCustomersToReturn = 40;
GaddzeitServicesClient webService = new GaddzeitServicesClient();
webService.GetRandomCustomerNamesAsync(howManyCustomersToReturn);
webService.GetRandomCustomerNamesCompleted += new EventHandler(webService_GetRandomCustomerNamesCompleted);


Below is a rough sample of the callback method (in this sample, I am concatenating the customer names to an instance string _customerNames.)

void webService_GetRandomCustomerNamesCompleted(object sender, GetRandomCustomerNamesCompletedEventArgs e)
{
   var customers = new List<CustomerDTO>(e.Result);
    foreach (var customer in customers)
    {
        if (customer == null)
        {
            continue;
        }
        _customerNames += string.Format("{0} {1}\r\n", customer.FirstName, customer.LastName);
    }
}


NOTE You could also add code to track the time on the response by comparing DateTime.Now.Ticks for before and after the web service call.

NOTE If you want to build a complete Win Phone 7 client using TDD, mocks and MVVM, this earlier blog post provides a walk through. In this blog post, the only piece NOT included is a WCF client call (the walkthrough places a comment recommending a WCF client call inside the CustomerRepository.Save() method.)

Monday, April 12, 2010

Three types of services in Domain-Driven Design

I've been re-reading Domain-Driven Design [Evans]. My first reading was in 2006 when I'd just started using Hibernate/NHibernate. In the years since then I've done several projects using a domain, a repository, and tests to validate the domain.

In re-reading the book, I'm seeing that Evans spoke about 3 types of classes in the domain:
  • Entites
  • Value Objects
  • [Domain] Services
In the projects I had done, I used only the first of these, Entities:
  • Every class had a PK-mapped identity from the db.
  • I had not used the Value Object abstraction to group attributes using composition (eg. Person.Address).
  • My use of services had been limited to services outside the domain (application and infrastructure, defined below.) As a consequence, I had observed a design issue in my domain entities: even though though they had thorough test coverage, the entities had become large, with many methods. As a result, the tests that ran against these entities by definition had to be coarse grained, often testing logic nested several levels deep within the entity..
Last fall, I revisited the book Refactoring [Fowler], and recognized that the use of delegation (Extract Class, Strategy, and others) would help to move a lot of the logic out of my entity classes into abstractions devoted to particular parts of the business logic. Among many benefits of this, tests could now be written directly against these abstractions. However, my concern was WHERE these extracted non-entity classes should go. Would they clutter up the domain? Should I create a separate namespace specifically for these classes?

With this question in the back of my mind, Evans explanation of Domain Service classes made perfect sense. They belong inside the domain and serve the entities as useful abstractions in their own right. And they are not to be confused with either:
  • Application services (eg. the controller in MVC, or a web method); or
  • Infrastructure services (eg. adapters on calls to external infrastructure outside the application.)
The following graphic is my attempt to crystallize my understanding of the 3 distinct types of services for future reference. I've highlighted the different services in each layer.