This question came up in the NServiceBus mailing list, and I think it is very interesting question to try to solve. The standard disclaimers are that I haven't build a real system using this approach, although I am leaning toward it more and more.
I would like to thank Brad for agreeing to post this example here.
I would like some advice as to how to properly identify the services I need to create. I know that Udi has said that creating services for each department is a good starting point, but I keep feeling like something is missing.
So, here's some details. I work for a company that is the parent of two physician job placement companies. The parent company would like to create a single system that will support both child companies. The business processes of both companies have been analyzed and documented, and there is about a 95% overlap in the processes. Should my team create a monolithic job placement application and wrap it in a service or should I break that application into higher-level business services?
Here's an example of where I get stuck when trying to map the job placement application's functionality to a high-level business service like Sales Service. The Sales department is broken into two groups: marketers and recruiters. Marketers call hospitals to find out what positions are available and try to fill these positions. Recruiters call physicians to find out if the physician is looking for a new job and tries to find available positions. Before a physician can be placed, his or her credentials must be verified. The Credentialing department is responsible for doing this.
Ok. So I now have two service candidates (Sales and Credentialing). I have no issues with the credentialing service but the sales service feels like it should be a job placement service. What if the business decides to take on a new line of business? This new line-of-business may have the sales department selling something entirely unrelated to job placement services. Is a job placement service a better idea? But wouldn't that mean that all job placement functionality would need to be placed in that service? This feels like I'm loosing the agility that SOA gives the business because I'm no longer modeling the way the departments interact with each other.
I once built a system with very similar concepts, although with drastically different focus. What Brad has already outlined is a good start, but I would break the system even further. We have two main sections of the business that were identified, marketing and recruitment. Let us attack the problem from each side in turn, but keep in mind that we are talking about a single system here.
High level services:
- Available candidates - given a set of requirements, will attempt to find all verified candidates that match the requirements. Additional responsibilities include logging search history (important for noticing what requirements are common and desirable), and recording which requirements has no matching physicians in the system (should be passed for human inspection, to decide if head hunting should begin, or this should be ignored).
- Register open position - enter a new position into the system, with all its requirements. As part of the registration, it will query the available physicians and offer them as matches. If there are no matches, it will register the new position in the recruitment service.
- Register new candidate - enter a new candidate to the system in unverified state. Request credentials verifications from the system.
- Verify credentials - given a candidate, perform a verification of the candidate credentials, references, etc. If the verification succeeds, we move the candidate to the available candidate pool. If the verification fails, we request additional intervention.
- Problematic credentials resolver - there are several reasons for getting problematic credentials, fake credentials, honest mistakes and hostile employers are just a few that comes to mind. In most cases, you need complex logic or human intervention here, and it deserves its own section in the map.
- Candidate hunger* - which candidates are we looking for, this is used by the recruitment guys to know which candidates they should aim for.
- Candidate tracker - if we already assigned a candidate for a job, we already have a happy person, let us keep it this way by ensuring that they remember us, so when they leave, they will contact us again for their next job.
- Potential candidates - given a set of requirements, will attempt to find all candidates that match them. Potential candidates are usually candidates that were gotten from external data sources (the physician listing for the country, for instance), so you want to go through them to see if they can become real candidates.
Those are just the services that I can think of off the top of my head. Notice that each of them has very few responsibilities, and they match pretty closely a specific business scenario. The services communicate between one another, but they do so using one way, async messaging. This is especially important in this type of scenario, where some services can take long time to process a piece of work (verifying credentials requires a human to call and ask for references, for example).
My next post will deal with the actual code for one of those services, for now I think this is enough.
* It was originally a typo, but I like the implications.