Before I continue describing WF usage patterns, small personal announcement: I'm changing this blog's title from "Thoughts on Architecture" to simply "Technical Blog". This seems to be more prudent, since I am not always discussing software architecture and am not even an architect anymore (my new job title is development manager, but enough about me).
Workflow In Business Layer
When we follow the principles of layered architecture, we usually end up with two types of objects in the business layer: entities and workflows. Entities, of course, map more or less directly to domain entities - products, orders, claims, or what have you. Workflows, on the other hand, manipulate entities in order to implement specific business process. For example, business process of registering new customer may include creation of Client, Address, and CreditCard entities, validation of the last two, transmission of a welcome email, etc. Of course, there are many ways to skin the cat, but typically you would employ some sort of business workflow object.
What attracted me to implement business workflows using WF was the ability to compose workflows from custom activities. We often had a situation where the same process had to be customized for different partners. In the example above, a customer may belong to a partner which does not require credit card validation. Engineers used to create new version of business workflow by copy-pasting relevant method in the class and tweaking it. My idea was to create a set of basic WF activities that represent pieces of the process, then combine them together using WF designer rather than C#.
Contrary to the pattern I described in the previous post, this one doesn't represent a long-running process and workflow instances are never persisted to database. Another side benefit is simplified maintenace due to improved readability: it's much easier to understand the logic by looking at workflow designer than raw code. Workflows become, in a sense, a live technical documentation of the system, on the par with unit tests and Visual Studio class diagrams.
There are a couple of caveats with this approach. First of all, beware of performance penalty from using WF and be sure to stress-test your system. In my case, business workflow executed as part of a batch process, not web application, so I didn't have to worry about user experience. Second, keep in mind that WF world is very asynchronous, so you can't really treat the workflow like just another procedure call. You create workflow instance, assign input parameters and start it. If you want to get the results back from that instance, you need to do extra work with the runtime.