Tuesday 22 January 2013

Enterprise Example Part 4

The code for this is available on Github, commit 8a00a5f248.

In this commit, I have added the ability to book visits in advance in the Sales system (and assign them to a consultant), and to book holidays in advance in the Human Resources system.

I have also included a Calendar system. This includes core data about appointments (visits/holidays). Those visits and holidays have a foreign key to their appointment. Holidays and visits could have used the same ID as their corresponding appointment, but I have seen confusion arise from this sort of design before.

Both the Sales and Human Resources systems validate a booking against the Calendar system, to ensure a booking does not clash with any other appointment. The UI does this using request/response over WCF because it is effectively a query and therefore not suitable for NServiceBus.

The Human Resources also validates locally against some holiday specific logic (whether the employee has enough holiday left). This is a useful demonstration of validating against 2 sources. Now I no longer have an application layer, I wasn't quite sure where to put the validation code, as it does not really belong in the UI. I decided to place it in its own assembly.

Future plans include retunring details of clashing appointments and the ability to move appointments.

Monday 7 January 2013

Enterprise Example Part 3

The code for this post is available on <a href="https://github.com/lucidcoding/EnterpriseExample">Github</a>. This post relates to commit 4225b569c2.

Another issue I had with the original design was that the value of the Deal was being stored in Client Services, for no reason other than that it could be passed on to Finance when the Agreement is activated. I have decided this is another candidate for a saga.

This is more of a saga in the traditional sense - a long running process. Here is how it happens:

  1. When the user completes the form to register a deal, and the RegisterDeal command is sent, when this is processed, a DealRegistered event is raised.
  2. This is subscribed to by the Finance service, and it starts of an OpenAccountSaga in Finance.
  3. When a user of the Client Services system actives an Agreement, this raises an AgreementActivated event.
  4. This is also handled by the OpenAccountSaga.
  5. When the saga has received both these events, it will have all the information it needs to open the Account.
I found it was not possible to use a specific correlation ID here, and I'm still not sure this is the correct way to go. Instead I have used the Deal ID. The Agreement ID is now different from the Deal ID and the Deal ID is just a property of the Agreement .

I have now been able to remove Value from Agreement.

Thursday 3 January 2013

Enterprise Example Part 2

The code for this post is available on Github. This post relates to commit 217cdad9f5. One thing I was not happy about in the last post was the way when a client had been initialised, it then had to use WCF from th UI to query the Sales service for information about the client. The new design uses a Saga.

Sagas are designed for long running processes, but they can also be used for orchestrating services. Here is what now happens:

  1. When the user completes the form to register a deal in the Sales system, this sends a RegisterDeal command to the Sales message handlers containing the information about the Deal.
  2. This also sends an InitializeClient command to Client Services, which contains information about the Agreement (This command is possibly named incorrectly).
  3. When the RegisterDeal command is handled in Sales, it raises a LeadSignedUp event, containing all information about the lead.
  4. Bot the InitializeClient command and LeadSignedUp event are handled by the InitializeClient saga. Once the saga has received both of these messages, it has all the information to properly initialize the client.
I had at first used the client/lead ID as the correlation Id for the saga, but decided against this, as two users could register a deal for the same client at the same time. Instead I have used a specific CorrelationId. I'm not sure if this is common practice in NServiceBus?

Now I have been able to remove the service references to Sales from the CLient Services UI.