views:

96

answers:

2

Hi!

Say, I am building a business process management application. It has the following entities: issues and tasks, related to each other as 1 issue to many tasks. Both, task and issue, have their own states and the state of one may influence the state of another.

For example, both of them have "Cancelled" and "Completed" states. When I change the state of the issue to "Cancelled", all of its tasks should become "Cancelled". When I change the state of all tasks to "Completed", the issue should automatically become "Completed".

Supposing that there are quite a few states for both entities and the logic of transitions from one state to another and the dependency of states may change, are there any design patterns and/or best practices to handle that situation?

+1  A: 

The design pattern that leaps to mind is a "rule" ;-)

Or, if you prefer, a Command Pattern

In other words, for situations like this I would create a database table listing the states and acceptable transitions, and associate an action with each transition (using reflection)

I have found this to be useful to handle cases where the transition action is more complex than just updating the statuses to match.

For example, in one system we had a workflow where a request document had to pass through several committee review stations, each of which could reject or pass on the document to the next stage, plus custom side-effect procesing. The committee organization, processing structures, and processing actions changed significantly three times during development, and five more times in the first year of deployment.

Steven A. Lowe
That's what we use now - a service that performs an action upon an issue. This is a great pattern to manage workflows, but it doesn't really help to synchronise two state machines in a clean transparent and maintainable way.
artemb
would an action equivalent to "make statuses the same" not do the trick?
Steven A. Lowe
I can't really imagine such an action. Let's say, I have a CancelIssueAction that updates the state of an issue to "Cancelled". If I want to make all the tasks for that issue cancelled too, I need to code it into CancelIssueAction, which is not very transparent.
artemb
i was thinking something more generic, like PropagateIssueState, to set all Actions of the given Issue to the same status as the Issue. In practice, however, I would most likely use the more specific CancelIssueAction behavior in anticipation of side-effects (such as notifying whoever is working on in-progress Actions that the action was cancelled!)
Steven A. Lowe
+1  A: 

I prefer the observer pattern for this sort of thing: http://en.wikipedia.org/wiki/Observer_pattern In the example you gave, I'd have tasks observe their issue and issues observe their tasks. When an issue is marked canceled, the tasks see and mark themselves canceled. When a task is marked completed, the issue sees it and checks to see if the other tasks are completed, etc.

Dave