views:

396

answers:

2

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.

+1  A: 

I think this is a variation on the Mediator Pattern from Design Patterns (Gang of Four) -- so I would say that it is a valid way to do this. In the Pattern, they discuss that the complicated interaction between controls is the reason to use it.

Edit: Link to Mediator on Wikipedia

Lou Franco
Thanks for your input. Actually, in my code, I did not create instances of the classes. I was only using static classes as a way to hold the fish, kite, and sea level use case names. Each use case was a successful step in workflow. So, I do not think it is a full mediator pattern.
fooledbyprimes
No, not as described by WikiPedia, but the idea of patterns is that they can be done lots of different ways. I would still consider this Mediator -- it solves the problem of complex interaction by centralizing it -- which is the main point of the pattern.
Lou Franco
Okay I see your point. However, I am still trying to convince myself that I was implementing a variation on that pattern. I will think about it some. Have you experience with using Cockburn style Use Cases in the code base?? I assume people have used them for documentation but what about in code?
fooledbyprimes
I haven't seen code that is trying to put Cockburn use cases in the code, but if you find it useful, then I think that's enough evidence that it is.
Lou Franco
+2  A: 

I've never done it, but I've often thought about writing code in UC style, with main success path first and extensions put in as exceptions caught down below. Have not found the excuse to do it - would love to see someone try it and code, even if after the experiment we conclude it's awful, it will still be interesting to try out and refer to. Alistair

Alistair Cockburn