【问题标题】:Enforcing code execution sequence强制执行代码执行顺序
【发布时间】:2009-07-08 13:42:26
【问题描述】:

有时您只有一个需要按固定顺序执行的操作列表,例如在实现序列图时。强制执行代码执行顺序以防止重构通过更改顺序引入细微错误的最佳方法是什么?

让我们假设现有的单元测试不会捕获任何由于更改以下 foo() 和 bar() 的执行顺序而导致的问题。

我见过和使用过的一些方法:

  1. 评论(依赖于阅读和理解它们的人):

    // do this
    foo();
    // then this
    bar();

  2. 流利的语法(让代码读起来更像英文,不鼓励随意重构):

    obj
    .Do
    .foo()
    .Then
    .bar();

  3. 状态变量和犹豫(太复杂了):

    foo_done=false;
    if(foo()) foo_done=true;
    if(foo_done) bar(); else throw_an_exception;

  4. 将逻辑块分组为函数:

    void foo_bar()
    {
    foo();
    bar();
    }

...还有很多难以描述的东西(嵌套、事件、函数指针数组、命名函数 Begin()、Middle() 和 End()...)。

有没有更好的设计模式来做这种事情?

【问题讨论】:

  • 我认为一个更具体的例子可能会得到更好的答案。需要完成的事情的顺序有多严格?如果您总是需要以确切的顺序调用某些方法,而不这样做是错误的,那么以正确的顺序调用所有方法的 void doEverything() 有什么问题。如果您确实需要按特定顺序调用操作,有哪些限制?为什么需要按特定顺序调用它们?他们在一些共同的状态下运作吗?它们有副作用吗?你不是单元测试吗?

标签: coding-style design-patterns


【解决方案1】:

如果单元测试不能捕获它们,并且依赖关系在代码中不明确,为什么顺序很重要,我对此感到困惑;这意味着副作用是 foo() 和 bar() 操作的关键部分。 在这种情况下,最好的设计策略是明确这些副作用!

【讨论】:

  • 那么你如何明确依赖关系呢?我们唯一的方法是确保代码体外部测试通过的顺序,还是有办法使序列显式?
  • 嗯?我的意思是最字面意义上的:文件句柄 = function_a(filename);记录数 = function_b(文件句柄);数据结构=function_c(文件句柄,记录数);没有人会改变这些的顺序......
  • 并非所有序列都如此明显。 get_price() 怎么样?申请折扣(10%);加税();如果在添加税后应用折扣,则会出现问题,只有您的单元测试(以及对业务逻辑的理解)才能拯救您。也许“排序业务逻辑”是我所追求的措辞。
  • 在这种情况下,单元测试会拯救你。当单元测试无法拯救您并且必须强制执行序列时所涉及的问题。
  • 通过硬编码明确依赖关系。在您的示例中,您将有add_tax() 调用apply_discount(10%),并且apply_discount() 调用get_price()。使用惰性求值,因此如果在 apply_discount() 调用它之前调用了 get_price(),您只需返回先前计算的值。这样,您仍然可以从其他地方调用其他方法(如有必要),但您要确保在必要时以正确的顺序调用它们。
【解决方案2】:

您编写单元测试来检查调用过程后发生的情况(状态、属性更改),所以我认为您不需要检查是否调用了某个方法。

此外,如果您将测试绑定到某个方法,稍后,如果您将系统更改为使用具有与 foo() 相同效果的另一种方法,即使您的系统执行正确的操作,您的测试也会失败。

【讨论】:

    猜你喜欢
    • 2017-07-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-01
    • 2018-10-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多