6

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.

skaffman
  • 398,947
  • 96
  • 818
  • 769
fooledbyprimes
  • 999
  • 1
  • 11
  • 29
  • I would love to see a simple code example, if possible – Lou Franco Sep 22 '08 at 20:35
  • I will have to spend a few minutes writing some examples because I do not have access to the code I originally wrote. I will try to post a sample soon. – fooledbyprimes Sep 23 '08 at 03:50
  • Can you put some paragraph spacing in too? – Matt Mitchell Sep 23 '08 at 04:02
  • very difficult to add sample code with 300 char limits on comments. will try to send you a message. thanks. – fooledbyprimes Sep 23 '08 at 04:43
  • I was using c# for a web app. Following will be some snippets to give you an idea. – fooledbyprimes Sep 23 '08 at 04:45
  • using MyCompany.MyApp.Web.UseCases; protected void MyFirstUserControl_SomeUIWorkflowRequestCommingIn(object sender, EventArgs e) { ... UdateUserInterfaceOnFishLevelUseCaseGoalSuccess(FishLevel.SomeNamedUIWorkflow.SelectedItemForPurchase) } – fooledbyprimes Sep 23 '08 at 04:46
  • UpdateUserInterfaceOnFishLevelGoalSuccess(FishLevel.SomeNamedUIWorkflow goal) { switch (goal) { case FishLevel.SomeNamedUIWorkflow.NewMasterItemSelected: ... ... ... etc. – fooledbyprimes Sep 23 '08 at 04:49
  • //also we have protected void UpdateUserInterfaceOnSeaLevelGoalSuccess(SeaLevel.SomeNamedUIWorkflow goal) { switch (goal) { case SeaLevel.CheckOutWorkflow.ChangedCreditCard: // do stuff – fooledbyprimes Sep 23 '08 at 04:50
  • okay I realized I should have put the code samples in the Question. So look there instead of in these comments. Thanks (ps: I'm a newbie!) – fooledbyprimes Sep 23 '08 at 04:55
  • You have posted the same question twice, see http://stackoverflow.com/questions/119268/ and http://stackoverflow.com/questions/117401/ . Please delete one of them! – SCdF Sep 23 '08 at 07:16
  • I did not do that on purpose. I was editing on just one post and the web app did something crazy. Anyway, I tried to figure out how to delete the second one but it is taking time. First day Newbies can't figure out where the delete button is... :) I'll look again. Thanks for the notice. – fooledbyprimes Sep 23 '08 at 16:43
  • hmm... I am having a difficult time trying to find a way to delete the accidentally duplicated post. Can someone give me a hand? Thanks. – fooledbyprimes Sep 23 '08 at 16:46
  • Okay...! I found the delete button!!! It was hard to see because I am stupid! :) – fooledbyprimes Sep 23 '08 at 16:48

2 Answers2

2

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.

j0k
  • 22,600
  • 28
  • 79
  • 90
1

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
  • 87,846
  • 14
  • 132
  • 192
  • 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 Sep 23 '08 at 16:51
  • 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 Sep 23 '08 at 16:56
  • 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 Sep 23 '08 at 17:02
  • 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 Sep 23 '08 at 17:51