是否可以在代码库中嵌入 Cockburn 风格的文本 UML 用例内容以提高代码可读性?

发布于 2024-07-05 01:41:19 字数 2424 浏览 10 评论 0原文

在代码中试验 Cockburn 用例时,

我正在编写一些复杂的 UI 代码。 我决定使用涉及鱼类、风筝和海平面的 Cockburn 用例(Martin Fowler 在他的《UML Distilled》一书中进行了讨论)。 我将 Cockburn 用例包装在静态 C# 对象中,以便我可以针对表示 UI 工作流程中的步骤的静态常量测试逻辑条件。 我们的想法是,您可以阅读代码并知道它在做什么,因为包装的对象及其公共内容通过名称空间为您提供了英语用例。

另外,我将使用反射来提取包含所描述的用例的错误消息。 这个想法是,堆栈跟踪可以包含一些英语的 UI 用例步骤......事实证明,这是一种实现迷你、伪轻量级域语言但无需编写 DSL 编译器的有趣方法。 所以我的问题是这是否是一个好方法? 有没有人做过类似的事情?


c# 示例片段如下

假设我们有一些 aspx 页面,其中有 3 个用户控件(有很多可点击的内容)。 用户必须单击某个特定用户控件中的内容(可能进行某种选择),然后 UI 必须以视觉方式提示用户选择成功。 现在,当选择该项目时,用户必须浏览网格视图以查找其他用户控件之一中的项目,然后选择某些内容。 这听起来很容易管理,但代码可能会变得很丑陋。

就我而言,用户控制主页捕获的所有发送的事件消息。 这样,页面就像 UI 事件的中央处理器一样,可以跟踪用户单击时发生的情况。

因此,在主 aspx 页面中,我们捕获第一个用户控件的事件。

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...


     }
  }

}

因此,在 MyCompany.MyApp.Web.UseCases 命名空间中,我们可能有这样的代码:

class SeaLevel...
class FishLevel...
class KiteLevel...

嵌入类中的工作流用例可以是内部类、静态方法或枚举或任何为您提供最干净的命名空间的东西。 我不记得我最初做了什么,但你明白了。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

最好是你 2024-07-12 01:41:19

我从来没有这样做过,但我经常考虑以 UC 风格编写代码,首先是主要成功路径,然后将扩展作为捕获的异常放入下面。 还没有找到这样做的借口 - 希望看到有人尝试并编码,即使在实验之后我们得出结论它很糟糕,尝试和参考仍然很有趣。

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.

压抑⊿情绪 2024-07-12 01:41:19

我认为这是设计模式(四人帮)中中介者模式的变体——所以我想说这是一种有效的方法。 在该模式中,他们讨论了控件之间复杂的交互是使用它的原因。

编辑:链接到 维基百科上的调解器

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文