编码模式c#

编码模式c#,c#,refactoring,C#,Refactoring,前几天,我在一次代码审查中遇到了一些类似的代码 public void DoSomeTasks() { if (CheckSomeState()==true) return; DoTaskOne(); if (CheckSomeState()==true) return; DoTaskTwo(); if (CheckSomeState()==true) return; DoTaskThree(); if (CheckSomeState()==true) r

前几天,我在一次代码审查中遇到了一些类似的代码

public void DoSomeTasks()
{
  if (CheckSomeState()==true) return;
    DoTaskOne();
  if (CheckSomeState()==true) return;
    DoTaskTwo();
  if (CheckSomeState()==true) return;
    DoTaskThree();
  if (CheckSomeState()==true) return;
    DoTaskFour(); 
}
随着任务数量的增加,代码的圈复杂度越来越高,我觉得这也不对

我提出的解决方案是

private void DoTasksWhile(Func<bool> condition, Action[] tasks)
{
   foreach (var task in tasks)
   {
      if (condition.Invoke()==false) break;
        task.Invoke();
   }
}

有人对如何提高代码的可读性提出了建议吗?

如果您的编排代码非常复杂,请考虑使用WF(workflow foundation)等框架

否则,您的代码很好,但我不会更改初始代码,因为它更具可读性。它也更加灵活,因为将来您可能会修改这些IFs,即条件可能不会保持相同


我看不出圈复杂度是如何降低的,或者可以如何降低。

我对您的实现进行了一些重构

private void DoTasksWhile(Func<bool> predicate, IEnumerable<Action> tasks)
{
    foreach (var task in tasks)
    {
        if (!predicate())
            return;
        task();
    }
}
用法将非常简单:

tasks.DoWhile(() => CheckSomeState());

您的解决方案就目前而言是完全足够的(尽管在仅四个步骤的情况下可能会有过大的杀伤力),但在这种情况下,它是否是最佳方法取决于CheckSomeState在您的程序上下文中的实际用途:

  • 在每个任务之间只调用一次CheckSomeState是否重要
  • 有时也需要在任务的中途调用它吗
例如,如果CheckSomeState实际上正在检查取消标志,那么在长时间运行的任务中可能需要额外的检查

您可以使用的另一个选项是引发异常(例如OperationCancelledException)。这使得圈复杂度非常低,您现在只需执行以下操作:

CheckForCancel();
DoTaskOne();
CheckForCancel();
DoTaskTwo();

(下边是一些人会认为这是使用异常控制流,这通常是皱眉)。< / P>


我还应该补充一点,目标不应该是减少圈复杂度,而是要有易于理解和维护的代码。圈复杂度是一个有用的指标,但有时它会不必要地惩罚非常简单的代码。

解决什么问题?你似乎已经准备好了干溶液。可读性问题到底是什么?您经常需要将布尔值与
true/false
进行比较。只需在
if
语句条件中使用布尔值。哇,缩进模式非常混乱……这是打开的。@Oded,谢谢,当我发布时,我意识到原来的代码不是干的这一事实是困扰我的。我在想也许有一种方法可以更流畅地实现这一点。e、 g.While(someCondition).Do(firstTask()).ThenDo(secondTask).ThenDo(thirdTask).Go(0);谢谢,==true更易于描述,它清楚地表明代码返回的是布尔值,但是if语句也暗示了这一点。删除调用()使代码更整洁。@安得烈考虑重命名<代码> CuthSoMalds<代码>方法,以显示它返回布尔值,例如“代码> ISSOMOSWANDS >代码> @安得烈:只有对布尔值进行求值的表达式才能出现在<代码>内,如果语句,则不必明确说明。至于意外分配而不是比较。。。不太可能。编译器将警告您条件表达式中的赋值。
tasks.DoWhile(() => CheckSomeState());
CheckForCancel();
DoTaskOne();
CheckForCancel();
DoTaskTwo();