Is it possible to embed Cockburn style textual UML Use Case content in the code base to improve code
- by fooledbyprimes
experimenting with Cockburn use cases in code
I was writing some complicated UI code. I decided to employ Cockburn use cases with fish,kite,and sea levels (discussed by Martin Fowler in his book 'UML Distilled'). I wrapped Cockburn use cases in static C# objects so that I could test logical conditions against static constants which represented steps in a UI workflow. The idea was that you could read the code and know what it was doing because the wrapped objects and their public contants gave you ENGLISH use cases via namespaces.
Also, I was going to use reflection to pump out error messages that included the described use cases. The idea is that the stack trace could include some UI use case steps IN ENGLISH.... It turned out to be a fun way to achieve a mini,psuedo light-weight Domain Language but without having to write a DSL compiler. So my question is whether or not this is a good way to do this? Has anyone out there ever done something similar?
c# example snippets follow
Assume we have some aspx page which has 3 user controls (with lots of clickable stuff). User must click on stuff in one particular user control (possibly making some kind of selection) and then the UI must visually cue the user that the selection was successful. Now, while that item is selected, the user must browse through a gridview to find an item within one of the other user controls and then select something. This sounds like an easy thing to manage but the code can get ugly.
In my case, the user controls all sent event messages which were captured by the main page. This way, the page acted like a central processor of UI events and could keep track of what happens when the user is clicking around.
So, in the main aspx page, we capture the first user control's event.
using MyCompany.MyApp.Web.UseCases;
protected void MyFirstUserControl_SomeUIWorkflowRequestCommingIn(object sender, EventArgs e)
{
// some code here to respond and make "state" changes or whatever
//
// blah blah blah
// finally we have this (how did we know to call fish level method?? because we knew when we wrote the code to send the event in the user control)
UpdateUserInterfaceOnFishLevelUseCaseGoalSuccess(FishLevel.SomeNamedUIWorkflow.SelectedItemForPurchase)
}
protected void UpdateUserInterfaceOnFishLevelGoalSuccess(FishLevel.SomeNamedUIWorkflow goal)
{
switch (goal)
{
case FishLevel.SomeNamedUIWorkflow.NewMasterItemSelected:
//call some UI related methods here including methods for the other user controls if necessary....
break;
case FishLevel.SomeNamedUIWorkFlow.DrillDownOnDetails:
//call some UI related methods here including methods for the other user controls if necessary....
break;
case FishLevel.SomeNamedUIWorkFlow.CancelMultiSelect:
//call some UI related methods here including methods for the other user controls if necessary....
break;
// more cases...
}
}
}
//also we have
protected void UpdateUserInterfaceOnSeaLevelGoalSuccess(SeaLevel.SomeNamedUIWorkflow goal)
{
switch (goal)
{
case SeaLevel.CheckOutWorkflow.ChangedCreditCard:
// do stuff
// more cases...
}
}
}
So, in the MyCompany.MyApp.Web.UseCases namespace we might have code like this:
class SeaLevel...
class FishLevel...
class KiteLevel...
The workflow use cases embedded in the classes could be inner classes or static methods or enumerations or whatever gives you the cleanest namespace. I can't remember what I did originally but you get the picture.