Wednesday, 2 May 2012

Changing the Type of an Entity - Persistence with NHibernate

This is a follow up to my previous post which can be found here

So we have an Employee class and a Manger subclass, here are the classes:
  
    public class Employee : Entity
    {
        private string _name;
        private string _payrollNumber;
        private DateTime _joinedOn;

        public virtual string Name
        {
            get { return _name; }
            set { _name = value; }
        }

        public virtual string PayrollNumber
        {
            get { return _payrollNumber; }
            set { _payrollNumber = value; }
        }

        public virtual DateTime JoinedOn
        {
            get { return _joinedOn; }
            set { _joinedOn = value; }
        }

        public static Employee Create(string role, string name, string payrollNumber, string department)
        {
            Employee employee = null;

            if (role == "Manager")
            {
                employee = new Manager();
                Manager manager = employee as Manager;
                manager.Department = department;
                manager.BecameManagerOn = DateTime.Now;
            }
            else
            {
                employee = new Employee();
            }

            employee.Name = name;
            employee.PayrollNumber = payrollNumber;
            employee.JoinedOn = DateTime.Now;
            return employee;
        }

        public void Amend(string name, string payrollNumber, DateTime joinedOn)
        {
            _name = name;
            _payrollNumber = payrollNumber;
            _joinedOn = joinedOn;
        }

        public virtual Manager Promote(string department)
        {
            Manager manager = new Manager();
            manager.Id = _id;
            manager.Name = _name;
            manager.PayrollNumber = _payrollNumber;
            manager.JoinedOn = _joinedOn;
            manager.Department = department;
            manager.BecameManagerOn = DateTime.Now;
            return manager;
        }

    }

    public class Manager : Employee
    {
        private string _department;
        private DateTime _becameManagerOn;

        public virtual string Department
        {
            get { return _department; }
            set { _department = value; }
        }

        public DateTime BecameManagerOn
        {
            get { return _becameManagerOn; }
            set { _becameManagerOn = value; }
        }
    }

    public class Entity
    {
        protected long? _id;
        protected int? _hashCode;

        public virtual long? Id
        {
            get { return _id; }
            set { _id = value; }
        }

        public override bool Equals(object obj)
        {
            Entity other = obj as Entity;
            if (other == null) return false;
            if (!other.Id.HasValue && !_id.HasValue) return other == this;
            if (!other.Id.HasValue || !_id.HasValue) return false;
            return other.Id.Value == _id.Value;
        }

        public override int GetHashCode()
        {
            if (_hashCode.HasValue) return _hashCode.Value;

            if (!_id.HasValue)
            {
                _hashCode = base.GetHashCode();
                return _hashCode.Value;
            }

            return _id.GetHashCode();
        }
    }
And here are how they are mapped in NHibernate:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   namespace="HRSystem.Domain.Entities"
                   assembly="HRSystem.Domain">
  <class name="Employee" table="`Employee`">
    
    <id name="Id" column="Id" type="long">
      <generator class="identity"/>
    </id>
    
    <property name="Name" type="string" />
    <property name="PayrollNumber" type="string" />
    <property name="JoinedOn" type="datetime" />

    <joined-subclass name="Manager" table="`Manager`">
      <key column="`Id`"/>
      <property name="Department" type="string" />
      <property name="BecameManagerOn" type="datetime" />
    </joined-subclass>
    
  </class>
</hibernate-mapping>
A common question on Stack Overflow is about changing from one class to an inherited subclass in NHibernate. Here are some examples:

Convert type of entity to subtype with NHibernate/Hibernate
Can you change from a base class to a joined subclass type in nhibernate?
Is it ever valid to convert an object from a base class to a subclass
NHibernate - Changing sub-types

One common response is that one should use composition over inheritance. In the case of our Employee/manager example, this would mean (for example) that everyone in the company would be represented by an Employee entity. Each Employee entity would have a Role entity which would be subclassed to the respective role (BasicEmployee, Manager, etc), and any varying behaviour is deferred to the Role class. see Design Patterns by the Gang Of Four for more about favouring composition over inheritance.

This is the correct approach when it is the behaviour that varies, but in our case, Manager has some extra fields, and composition over inheritance doesn't account for this. We need somewhere to store the extra fields, and inheritance is a good solution to this.

Some people suggest that the employee object should have a ManagerFields objects, where fields specific to a manager role ('_department', '_becameManagerOn') would be stored if the employee is a manager, and would be null if not. Or even, just have nullable fields '_department' and '_becameManagerOn' on Employee that are only used if the Employee is a manager. You have to ask yourself if you would do this if you were not using NHibernate?

Some people suggest that if you are using inheritance, then to promote an Employee to Manager, you should use native SQL to insert a record into the manager table, so when you next get the Employee it will cast to manager. This doesn't even warrant discussion.

The answer, that some people touch on on in the StackOverflow questions, is that you need to to delete the old entity, and replace it with the new entity. This seems quite straightforward, but there is one aggrevating factor: often we would want it to keep the same ID, as this may be a foreign key in other entities. (This is not a problem if the entity being changed is a child in an aggregate, as the aggregate root would have all the references, and would be doing all the updating so could update these references.) But what if it is an aggregate root? What if other entities in the domain, or even other domains/systems reference it? We need a way to preserve the ID.

Replacing Entities While Maintaining the Identity - GUIDs


One answer is to use GUIDs instead of auto incrementing IDs, this way assigned identites can be used. In this situation, it is not too much of a problem to delete the old Employee entity and save the new Manager entity which has the same ID. This way, when any entity is loaded that references the Employee, it will load the Manager entity. The code for the base entity would now look like this:
    public class Entity
    {
        protected Guid? _id;    //Changed from long?
        protected int? _hashCode;

        public virtual Guid? Id    //Changed from long?
        {
            get { return _id; }
            set { _id = value; }
        }

        //Implementation of Equals() and GetHaskCode() etc...
    }
The mapping files now look like this:
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   namespace="HRSystem.Domain.Entities"
                   assembly="HRSystem.Domain">
  <class name="Employee" table="`Employee`">
    
    <id name="Id" column="Id" type="guid">
      <generator class="assigned"/>
    </id>
    
    <property name="Name" type="string" />
    <property name="PayrollNumber" type="string" />
    <property name="JoinedOn" type="datetime" />

    <joined-subclass name="Manager" table="`Manager`">
      <key column="`Id`"/>
      <property name="Department" type="string" />
      <property name="BecameManagerOn" type="datetime" />
    </joined-subclass>
    
  </class>
</hibernate-mapping>
Remember what the Promote code lookes like?
        public virtual Manager Promote(string department)
        {
            Manager manager = new Manager();
            manager.Id = _id;       //Especially pay attention to this line!!!
            manager.Name = _name;
            manager.PayrollNumber = _payrollNumber;
            manager.JoinedOn = _joinedOn;
            manager.Department = department;
            manager.BecameManagerOn = DateTime.Now;
            return manager;
        }
Now the code for a service to promote an Employee to a Manager looks like this:
using System;
using NHibernate;
using NHibernate.Cfg;
using HRSystem.Domain.Entities;

namespace HRSystem.Application.Implementations
{
    public class EmployeeService
    {
        public void Promote(Guid employeeId, string department)
        {
            Configuration configuration = new Configuration();
            configuration.Configure();
            configuration.AddAssembly("HRSystem.Data");
            ISessionFactory sessionFactory = configuration.BuildSessionFactory();
            ISession session = sessionFactory.OpenSession();
            Employee employee = session.Get<Employee>(employeeId);
            Manager manager = employee.Promote(department);

            using (ITransaction transaction = session.BeginTransaction())
            {
                session.Delete(employee);
                session.Save(manager);
                transaction.Commit();
            }
        }
    }
}
This is all quite straigntforward. This application service loads the Employee, gets a Manager version of it, deletes the Employee and then Saves the Manager in its place, with the same Id. Now when you go to load an Employee with the same Id, it will return an entity of type Manager. No need to update any other entities that have references to the entity because they will load the new Manager entity, because the ID has not changed.

Replacing Entities While Maintaining the Identity - Auto Incrementing IDs


The problem comes when you are trying to do this in system that uses auto-incrementing ints or bigints as IDs. This is when things start to get a bit messy. You need to do two things: first you need to dynamically manipulate the NHibernate configuration so the Id of the Employee class can be assigned. Secondly, we need to allow the identity to be inserted in the database, and the only way to do this (that I know of) is to use native SQL. Assume the Entity class and mapping file have reverted back to using auto-increment IDs, the way they were at the beginning of this post. The resulting code for the application service now looks like this:
using System;
using NHibernate;
using NHibernate.Cfg;
using HRSystem.Domain.Entities;

namespace HRSystem.Application.Implementations
{
    public class EmployeeService
    {
        public void Promote(Guid employeeId, string department)
        {
            Configuration configuration = new Configuration();
            configuration.Configure();
            configuration.AddAssembly("HRSystem.Data");

            //Get the class mapping for the Employee entity.
            var employeeClassMapping = (from classMapping 
                     in configuration.ClassMappings 
                     where classMapping.MappedClass == typeof(Employee)
                     select classMapping).FirstOrDefault();

            //Change the identifier strategy to assigned dynamically.
            (employeeClassMapping.Identifier as SimpleValue).IdentifierGeneratorStrategy = "assigned";

            ISessionFactory sessionFactory = configuration.BuildSessionFactory();
            ISession session = sessionFactory.OpenSession();
            Employee employee = session.Get<Employee>(employeeId);
            Manager manager = employee.Promote(department);

            using (ITransaction transaction = session.BeginTransaction())
            {
                //First delete the Employee entity.
                session.Delete(employee);

                //Native SQL to allow identity insert.
                session.CreateSQLQuery("SET IDENTITY_INSERT Employee ON").ExecuteUpdate(); 

                //Then save the Manager entity.
                session.Save(manager);

                //This is needed to ensure manager is saved while identity insert is on.
                session.Flush(); 

                //Native SQL to disallow identity insert.
                session.CreateSQLQuery("SET IDENTITY_INSERT Employee OFF").ExecuteUpdate(); 

                transaction.Commit();
            }
        }
    }
}
I never said it would be pretty but it works.

Changing the Type of an Entity - Domain

Occasionally, there are times where it makes sense to transform an entity from one type to another. Take the example of a Manager entity which inherits from an Employee entity. At some point an Employee may be promoted to a manager. Here is the code for the Employee entity, including a factory class for creation and a class to amend the entity:
  
using System;
using HRSystem.Domain.Common;

namespace HRSystem.Domain.Entities
{
    public class Employee : Entity
    {
        private string _name;
        private string _payrollNumber;
        private DateTime _joinedOn;

        public virtual string Name
        {
            get { return _name; }
            set { _name = value; }
        }

        public virtual string PayrollNumber
        {
            get { return _payrollNumber; }
            set { _payrollNumber = value; }
        }

        public virtual DateTime JoinedOn
        {
            get { return _joinedOn; }
            set { _joinedOn = value; }
        }

        public static Employee Create(string role, string name, string payrollNumber, string department)
        {
            Employee employee = null;

            if (role == "Manager")
            {
                employee = new Manager();
                Manager manager = employee as Manager;
                manager.Department = department;
                manager.BecameManagerOn = DateTime.Now;
            }
            else
            {
                employee = new Employee();
            }

            employee.Name = name;
            employee.PayrollNumber = payrollNumber;
            employee.JoinedOn = DateTime.Now;
            return employee;
        }

        public void Amend(string name, string payrollNumber, DateTime joinedOn)
        {
            _name = name;
            _payrollNumber = payrollNumber;
            _joinedOn = joinedOn;
        }
    }
}
And here is the code for the Manager entity:
  
using System;

namespace HRSystem.Domain.Entities
{
    public class Manager : Employee
    {
        private string _department;
        private DateTime _becameManagerOn;

        public virtual string Department
        {
            get { return _department; }
            set { _department = value; }
        }

        public DateTime BecameManagerOn
        {
            get { return _becameManagerOn; }
            set { _becameManagerOn = value; }
        }
    }
}
Please note that these both ultimately inherit from the Entity class, which should be familliar to any regular users of NHibernate:
  
using System;
using HRSystem.Domain.Entities;

namespace HRSystem.Domain.Common
{
    public class Entity
    {
        protected long? _id;
        protected int? _hashCode;

        public virtual long? Id
        {
            get { return _id; }
            set { _id = value; }
        }

        public override bool Equals(object obj)
        {
            Entity other = obj as Entity;
            if (other == null) return false;
            if (!other.Id.HasValue && !_id.HasValue) return other == this;
            if (!other.Id.HasValue || !_id.HasValue) return false;
            return other.Id.Value == _id.Value;
        }

        public override int GetHashCode()
        {
            if (_hashCode.HasValue) return _hashCode.Value;

            if (!_id.HasValue)
            {
                _hashCode = base.GetHashCode();
                return _hashCode.Value;
            }

            return _id.GetHashCode();
        }
    }
}
So how do we model the promotion of an Employee to a Manager? Perhaps a method on the Employee called Promote, like the following code. Note that in order to change the Employee to a Manager, the extra parameters that a Manager has need to be supplied:

  
        public void Promote(string department)
        {
            //Make the class I'm in a Manager, not an Employee...
        }
The problem with this is that method would somehow have to change the type of the class it belongs to. This is not possible, not in C#, not in Java, not in any OO language.

In Domain Driven Design, Eric Evans makes the case for factory methods. The arguments is that on a car, the methods represent things like the accelerator or brake, which change the state of the car. However, the car does not carry around the ability to build itself - that is done in a factory. But what if we really wanted to change the state of the car? I'm talking tuned engine, new alloys, new paint job, new ICE etc. Unfortunately my car doesn't have a button for that - I have to take it to the garage. When it comes back, it's hardly the same car. The car entity could have a myRide.Pimp() method, and what comes back from that is a whole new car.

For the Employee, the method would look something like this:
  
        public virtual Manager Promote(string department)
        {
            Manager manager = new Manager();
            manager.Id = _id;
            manager.Name = _name;
            manager.PayrollNumber = _payrollNumber;
            manager.JoinedOn = _joinedOn;
            manager.Department = department;
            manager.BecameManagerOn = DateTime.Now;
            return manager;
        }
The code to promote an employee to the manager of ICT would look like this:
  
            Manager manager = employee.Promote("ICT");
I'm not completely sure that Promote(string department) is the quite the right name for this, it should possibly be something like 'GetPromotedVersion(string department)', but I feel it is acceptable in this instance.

The next stage is how to load the Employee and then persist it as a Manager, which I will cover in the next post.

Wednesday, 4 April 2012

Domain Modelling Training Session 2

Last Friday saw the practical part of my Domain Modelling Training Session. This time the 'add to cart' functionality was in place, and it was the purpose of the rask to add the 'place order functionality', following the rules and guidelines set down in the last session. The specifications for this were:
  • Place an Order with an OrderLine for each book.
  • OrderLine must record price of book.
  • Order must record total book price in Cart.
  • Order must also record shipping cost of £2 + 50p per book.
  • Order must record grand total.
Another part of the test was for the developers to begin with the Domain unit tests, then move on to develop the Domain, then the Application Layer, then the UI.
Here are some examples of what was produced:
 

Domain Unit Test Code


public static Order Place(Cart cart)
{
    Order order = new Order();
           
    foreach (Book book in cart.Books)
    {
        order._orderLines.Add(new OrderLine { Book = book, PricePaid = book.Price });
        order._booksTotal += book.Price;
    }
    order._shippingCost = 2f + (cart.Books.Count * .5f);
    order._grandTotal = order._booksTotal + order._shippingCost;     
    return order;
}

Domain Code


[TestClass]
public class OrderTest
{
    [TestMethod]
    public void CanPlaceOrder()
    {
        Cart cart = new Cart();
        Book book = new Book()
        {
            Id = 1,
            AuthorName = "Robert C. Martin",
            Title = "Agile Principles, Patterns and Practices in C#",
            Price = 35.00f
        };
        cart.AddBook(book);
        Order myOrder = Order.Place(cart);
        Assert.AreEqual(myOrder.OrderLines.Count, 1);
        Assert.AreEqual(myOrder.OrderLines[0].Book.Id, 1);
        Assert.AreEqual(myOrder.OrderLines[0].PricePaid, 35.00F);
        Assert.AreEqual(myOrder.BooksTotal, 35.00F);
        Assert.AreEqual(myOrder.GrandTotal, 37.50F);
        Assert.AreEqual(myOrder.ShippingCost, 2.5F);
    }
}

Application Layer Code


public long Place()
{
    ICartRepository cartRepository = new CartRepository();
    IOrderRepository orderRepository = new OrderRepository();
    Cart cart = cartRepository.GetByUserName(Thread.CurrentPrincipal.Identity.Name)
    Order placedOrder = Order.Place(cart);

    using (ITransactionProvider transactionProvider = new TransactionProvider())
    {
        transactionProvider.BeginTransaction();
        orderRepository.Save(placedOrder);
        transactionProvider.CommitTransaction();
    }

    return placedOrder.Id.Value;
}

UI code is simply one line calling this method.

Monday, 26 March 2012

Domain Modelling Training Session 1

On Friday I hosted a training session about Domain Modelling. The session was preceeded with some 'homework', a small task I set my collegues. I created a classic e-commerce website which had a list of books, and a button to add a book to the cart. The system was built as the usual UI sitting on top of an Application Layer, which sat on and the Domain, and a Data Layer (which uses NHibernate). However, the code in the 'AddToCart' event was missing:

protected void gvBooks_RowCommand(object sender, GridViewCommandEventArgs e)
{
    if (e.CommandName == "AddToCart")
    {
        long bookId = Convert.ToInt64(e.CommandArgument);
        //ADD YOUR CODE HERE!!!
        PopulateCartGrid();
    }
}

One requirement was that the total for the cart had to be calculated, and persisted in the database.

There was also a second stage of the homework which required a discount to be added of £5 for each different book that was added, so only 1 book gets no discount, 2 of the same book gets no discount, 2 different books gets £5 discount, 3 different books get £10 discount etc.

Here are some of the proposed solutions, starting with the code in the UI and working down:

User Interface Code


Here are some examples of the submissions for code in the UI, showing how the UI interacts with the Application Layer:

Example 1


ICartService cartService = new CartService();
Cart cart = cartService.GetCurrentUsersCart(); 
IBookService bookService = new BookService();
Book book = bookService.GetById(bookId);
cart.AddBook(book);
cartService.Save(cart);

This code has three calls to the application layer to add the book to the cart, including a Save() service that takes an entity as a parameter (something that should be avoided). Also, here we have UI code calling a method on an entity, something which should also be avoided, and would be impossible if using DTOs or WCF.

Example 2


ICartService cartService = new CartService();
IBookService bookService = new BookService();
var book = bookService.GetById(bookId);
Cart cart = cartService.GetCurrentUsersCart();
cartService.AddItemtoCart(cart,book);

This is an improvement. There are still three calls to the UI, but no methods being called on the Cart entity, and there is no Save service which takes an entity as a parameter. The AddItemToCart service performs the logic associated with adding the item to the cart and then persists it, all in one shot. But the consumer of the service has to get the Cart and Book entities before calling AddItemToCart. This could be encapsulated further by passing the IDs only.

Example 3


ICartService cartService = new CartService();
cartService.AddBook(bookId);

This is all that is required. It is not even required to pass in the user name, because the Application Layer is running in the same process, and because the UI uses Windows authentication, the Application Layer can get the user from the principal identity. All that is needed is the bookId. The service can then load the book by the ID, the cart by the username, perform any business logic and then save the result.

Summary


All commands should be done in one service call. A command can be defined as anything that changes the state of the business, or anything where a user presses a 'Submit' button. The reason for this is that this may not be the only consumer of this service, there may be a mobile App that consumes it, or possibly another service. This example is trivial, but if the system starts accessing the file system, or interacting with other services, the code can become very comlpex. Any systems consuming the service would have to replicate all required code.

Application Layer Code


Example 1


public void AddBook(Cart cart, long bookId)
{
    BookService bookService = new BookService();
    Book selectedBook = bookService.GetById(bookId);
    cart.Books.Add(selectedBook);
    cart.Total = (from b in cart.Books select b.Price).Sum();
}

This submission is from before the addition of the extra requirement for discounts. This shows an example of a service call in which the Cart has to have been loaded externally, and which which the Cart has to be saved externally. Another problem here is that the business logic of calculating the total is contained in the Application Layer, not the Domain.

Example 2


public void AddItemtoCart(Cart cart, Book book)
{
    ICartRepository cartRepository = new CartRepository();
    cart.AddItem(book);
    using (ITransactionProvider transactionProvider = new TransactionProvider())
    {
        transactionProvider.BeginTransaction();
        cartRepository.SaveOrUpdate(cart);
        transactionProvider.CommitTransaction();
    }
}

This example is an improvement, because the business logic is encapsulated in the Cart entity. This business logic is called from the service, and then the entity is saved, all in a single serive call. However, the Cart and Book entitys must be loaded and apssed to the service before it can be used, so it is not completely encapsulated.

Example 3


public void AddBook(long bookId)
{
    ICartRepository cartRepository = new CartRepository();
    IBookRepository bookRepository = new BookRepository();   
    Cart cart = cartRepository.GetByUserName(Thread.CurrentPrincipal.Identity.Name);
    Book book = bookRepository.GetById(bookId);
    cart.AddBook(book);
    using (ITransactionProvider transactionProvider = new TransactionProvider())
    {
        transactionProvider.BeginTransaction();
        cartRepository.Save(cart);
        transactionProvider.CommitTransaction();
    }
}

In this example, the Book is loaded from the ID passed in, the Cart is loaded from the current security principle identiy name, the business logic is called on the Cart (passing in the Book) and then the Cart is saved. This is all encapsulated into one call.

Domain


Example 1


public virtual void AddItem(Book book)
{
    if (Books == null)
    {
        Books = new List<Book>();
    }

    Books.Add(book);
    Total = _books.Sum(b=>b.Price);
}

In the examples where the Cart entity had an 'AddBook' or similar method which took a Book entity as a parameter, the logic was encapsulated in the Domain (this example was from before the discount requirement). However, one problem here is that the entity is accessing its own public 'set' properties.

Example 2


public virtual void AddBook(Book book)
{
    _books.Add(book);
    float discount = ((from curBook in _books select curBook).Distinct().Count() - 1) * 5f;
    _total = (from curBook in _books select curBook.Price).Sum() - discount;
}

In this example (which includes the discount requirement), the entity is accessing its private member variables. We can create a rule that the 'set' properties should not be used at all (I will keep them in for NHibernate, although I believe it is possible for NHibernate to use the private members - I will review this). The private member variables should only be ammended through methods that reflect use cases. This was the entities will adhere to OO principles and will reflect the business more acurately.

Unit Tests


[TestMethod]
public void AddingTwoDifferentBooksGivesDiscount()
{
    Cart cart = new Cart();

    Book book1 = new Book()
    {
        Id = 1,
        AuthorName = "Robert C. Martin",
        Title = "Agile Principles, Patterns and Practices in C#",
        Price = 35.00f
    };

    Book book2 = new Book()
    {
        Id = 2,
        AuthorName = "Martin Fowler",
        Title = "Patterns of Enterprise Application Architecture",
        Price = 30.00f
    };


    cart.AddBook(book1);
    cart.AddBook(book2);
    Assert.AreEqual(60.00f, cart.Total);
}

One way of ensuring that the Domain has been developed correctly is to check that tests for business logic can be written against the Domain which touch only the Domain and nothing else, as in this example (of course, if you are following TDD, the tests should be written first).

Summary


The lessons learnt from this training session can be summarised in this following list of rules and guidances:

  • All commands which change the state of the business (equivalent to pressing ‘Submit’ button) should be encapsulated in one service call.
  • Never have a ‘Save’ service operation which takes an entity (or DTO of an entity) as a parameter.
  • Never call methods of entities in the UI.
  • Services usually just load entities, call business logic in domain, and save. *
  • Command services should have names that reflect use cases, and call methods on entities with a similar name. *
  • Business logic should be contained in the entities.
  • You should be able to write tests for the business logic that touch the Domain and nothing else.
  • Do not use ‘set’ properties of entities – entity state can only be changed through methods that have names that reflect use cases.

* These are guidances rather than hard rules.

Thursday, 19 January 2012

Enterprise Application Integration: Part 3

Click here to download the code from Codeplex. Please make sure you click on 'Code for Part 3'. This example cannot be run using SQL Server Express, it must be run on SQL Server. Please run the script in the SQL Scripts solution folder to create the required databases (even if you have done this for the last part).

General Refactoring


Database Scripts

The databases scripts were creating the database files to a specified directory. This has been rectified.

Response Objects

I now no longer favour the generic Response objects returned by the Application Layer. The need to cast this to the actual type adds complexity for the consumer. The point was to return other types in various circumstances (ie. validation failures or if an entity is not found). Instead, Fault Exceptions will handle these circumstances (although I do wonder whether a failed validation is really exceptional?). I still favour Data Transfer Objects.

On some projects, I always have a request object, even if it only has one property. The advantage of this is that if a new version of the service is released, it will be backwardly compatible with existing consumers of the service.

WCF Layer

The Remote Façade Layer has been renamed the WCF layer, because this is more meaningful, and it is not truly an implementation of the Remote Façade pattern. I am wondering if this layer is truly needed - the Application layer is already polluted with WCF related stuff.

Logging and Infrastructure Layer

I have added in some logging. This is in a new layer - the Infrastructure layer. This is not yet perfected - if the Domain needed to log events, it would need a dependency on the Infrastructure layer, violating a principle of the Domain Model Pattern. Each service operation logs the content of the request, and errors are also logged. The logging still relies on SQL - I may change this in future to harness NHibernate, to keep it consistent with the rest of the project.

Note that depending on which binding you are using, you can't always use Application_Error in Global.asax, so instead a Behaviour Attribute is added to each service to log errors. Hopefully, I will figure out a way to log service calls with attributes, removing the need to add _log.Add() at the start of each service, forming a type of AOP. Also note that setting up behaviour extensions in web.config is affected by a bug that has existed since the dawn of WCF and has not yet been fixed.

Also, Application_EndRequest does not work for some bindings, so I have moved this to the end of each service call. Hopefully I will be able to fix this with a Behaviour Attribute.

Integration Refactoring


One thing I haven't been happy with when using XML or WCF Web Services in the past is the point-to-point connections between applications, which makes the applications tightly coupled. This leads to many design problems, including entities being duplicated between systems - like the Site entity in the account system.

I have been reading up on SOA, and while I don't claim to be building an SOA here, I am borrowing some concepts. One borrowed concept is the composite service. In this system, some composite services consume the services from the Client Data System and the Accounts System, and any integration is performed in the composite services. This removes the reference from the Accounts System to the Client Data System, removes the need for Service Gateways, removes the need for any Client Data System entities or properties from the Accounts System, removes the need for the consequent mapping files, and removes the need for the views in the database. The two systems have become completely decoupled.


The only connection that remains are foreign keys in the Accounts System to the Client data System (for example - Site ID in the Account entity). I read somewhere even this is frowned upon, but I'm not at all sure how this would work? I'll leave this for now.

There is some business logic in the composite services> I'm not sure this is the best place for it, and may review it later. Some validation is occurring in the composite services too, and again I will review this. For example, the Account composite service checks if the client is established before calling the Account Service to create it - an alternative would be to pass the Client entity regardless to the Account Service and let it decide whether to create the account?

The validation is all a bit spread out - maybe this could go in the UI.

Another bonus is that I have avoided replicating the FullName business logic.

The Contact entity may appear to be replicated in the Accounts System, but in fact this only holds information about a contact that is specific to the Accounts System, and does not replicate any properties from the Client data System (except the ID to tie them together).

Wednesday, 4 January 2012

Enterprise Application Integration: Part 2

Warning! This post and related code is something I began a while ago but did not get round to completing. Since starting this I have read up on EAI techniques and also on SOA. I now understand that while the examples here may be suitable for integrating two or three small applications, they would not scale for anything other than a very small business. However, as one of the primary functions of this blog is to record my learning process, I have decided to include it.

Click here to download the code from Codeplex. Please make sure you click on 'Code for Part 2'. This example cannot be run using SQL Server Express, it must be run on SQL Server. Please run the script in the SQL Scripts solution folder to create the required databases (even if you have done this for the last part).

Firstly, I have removed the integration layer and incorporated it into the Application layer to reduce complexity.

Extending Properties of an Entity


A new business requirement has been specified: contacts must have a payment authorisation level (low, medium and high) and this must be displayed in the drop down list in the create payment page.

Clearly, the Contact entity needs a new field: PaymentAuthorizationLevel, but should this go in the Client Data System? This information is specific to the Accounts System, and if every system stored its own information relating to a contact in the Client Data System, the Client Data System would become soon bloated, and the constant change would be hard to manage. This solution is unscalable.

So the solution to this I have implemented in this version is have an entity in the Accounts System also called 'Contact' which holds all the fields from the Client Data System and also the new PaymentAuthorizationLevel field. There is a table in the database for the Accounts System called 'Contact', which contains only an Id and the PaymentAuthorizationLevel field. The Id is not auto-incrementing: it is the primary key but it is also a foreign key to the Id in the Client Data System's Contact table.

There are now two mappings for Contact in the Data Layer: one with an entity name of 'ReadContact': This maps to a view which is a join of both Contact tables, and therefore populates all fields in the Accounts System. This mapping is read-only:


The other mapping is 'WriteContact', and is for writing. This saves the Contact object to the Accounts System database, but only the Id and PaymentAuthorizationLevel fields. In order to save a new Contact, the ContactService of the Account System must call the CreateContact method of the ContactService in the ClientDataSystem, return the Id, build a Contact entity in the Accounts System with the returned ID and PaymentAuthorizationLevel and then save that:


Edit: I've later noticed that the Contact Mapping (Read) in the above diagram should say Contact Mapping (Write)!

As mentioned in my disclaimer, this is not a perfect solution (The CreateContact method of the AccountService is very bloated), and I have already learnt new methods, but I thought I would document this as part of my learning process, and it may be useful for some smaller integration problems.

Monday, 19 December 2011

Enterprise Application Integration: Part 1

Warning! This post and and related code is something I began a while ago but did not get round to completing. Since starting this I have read up on EAI techniques and also on SOA. I now understand that while the examples here may be suitable for integrating two or three small applications, they would not scale for anything other than a very small business. However, as one of the primary functions of this blog is to record my learning process, I have decided to include it.

Click here to download the code from Codeplex. Please make sure you click on 'Code for Part 1. This example cannot be run using SQL Server Express, it must be run on SQL Server. Please run the script in the SQL Scripts solution folder to create the required databases.

The solution contains the Client Data System from previous posts, and also the new Accounts System, which integrates with it. Both systems have an added layer: the Remote Facade layer, which provides a WCF wrapper around the Application Services. The UI then calls these WCF services.

This example demonstrates integration at three levels: at the UI level, the Domain level, and the Data level. Each of these forms of integration has its own motivations and features.

Integration at the UI Level



The Accounts System UI layer has references to both the Accounts WCF services Client Data System WCF services. The Client/Index page displays a list of clients, and to populate this, the Client controller has uses the Client Data System's WCF services to return the list of clients. There is no contact with the Account System's WCF services or domain at all.

Integration at the Data Level



From the client index screen, the user can click the 'Accounts' link for a particular client and this will display a list of accounts associated with that client. There is a business requirement that each account must be associated with a particular site, and the list of accounts lists the relevant site along side each account. The account record only has the ID of the site, but the list has to display the first line of the address. One way to do this would be to get the list of accounts from the Accounts System, and then for each record, call the Client Data System to get the site. However, this would result in n+1 database calls, and would therefore perform very badly. Another option would be for the UI to get the list of accounts, and then when it has all the site ID's, it could get all the sites in one go, and then join them in the UI controller. However, this would push too much code into the controller. (This could however be done by a service composition or possibly a task service. I will cover these in later posts.)

The method that has been adopted in this code is at the data level. A copy of the site entity exists in the domain (only with get/set properties - no logic), and also a mapping file that points to the Client Data System's database. The site entity in the Accounts System is read only - any edits to sites should be done though the Client Data System's services. This way, a query to return a collection of accounts can join to the sites.

Integration at the Domain Level



There is a business requirement that only established client can have accounts. Currently, an established client is on that has been a client for at least three months, but this is a possible area of change, so the logic must remain in the client entity in the Client Data System. When the validation logic in Accounts System needs to check if the client is established, it needs to use the services of the Client Data System so it can access the business logic in the domain to verify that the client is established. However, the domain cannot directly consume the Client Data System's as this would break the rule that the domain cannot have any dependencies. Instead, it consumes it though an interface. Another layer, the 'Integration Layer' contains the implementation of this gateway to make the service call, and this is injected in by the Application Layer. This is an example of the Gateway Pattern.

Another possibility would be for a service composition to use the Client Data Service to check the client's established status, and if it is established, it will then call the Accounts Service. This will be covered in a later post.