多相算法的好模式?

时间:2017-07-06 18:12:05

标签: c# algorithm coding-style refactoring

是否有改进这段代码的模式(重构)?

    int phase = 0;
    foreach (var some in arrayOfSome)
    {
        if (phase == 0)
        {
            bool result = DoSomething_0(some);
            if (result) phase = 1;
        }
        else if (phase == 1)
        {
            bool result = DoSomething_1(some);
            if (result) phase = 0;

            result = DoSomething_1_0(some);
            if (result) phase = 2;
        }
        else if (phase == 2)
        {
            bool result = DoSomething_2(some);
            if (result) break;
        }
    }

首先,我想减少条件运算符的数量并使代码更具可读性。

2 个答案:

答案 0 :(得分:0)

不要在这里看到重构的必要性。也许你可以减少一些行并像这样写:

int phase = 0;
foreach (var some in arrayOfSome)
{
    if (phase == 0)
    {
        if (DoSomething_0(some)) phase = 1;
    }
    if (phase == 1)
    {
        if (DoSomething_1(some)) phase = 0;
        if (DoSomething_1_0(some)) phase = 2;
    }
    if (phase == 2)
    {
        if (DoSomething_2(some)) break;
    }
}

如果你担心在for for中有太多if(在你的情况下它是可读的),你可以查看Flattening Arrow Code

答案 1 :(得分:0)

一种优雅的方法是完全消除if / then逻辑。您可以通过创建由状态(阶段)索引的委托数组来完成此操作。数组中的每个委托槽指向一个函数(或lambda),它执行任何操作并返回新状态(阶段)。

在这些类型的设计中,您经常会得到一个包含如下所示的单个语句的循环:

foreach (var x in data)
{
    state = handler[state](x);
}

我已经多次编码这种FSM,并且在正确完成且非常可靠时它们非常通用。错误几乎总是归结为处理程序中的小错误或为给定状态/输入组合定义的错误处理程序。

更通用,更强大的设计有这种模式:

foreach (var x in data)
{
    state = handler[state,x](x);
}

其中state和datum都用于选择处理程序委托。使用这种模式有很多好处,因为随着时间的推移,随着代码或功能的增长,在循环中添加额外的标志和条件的诱惑。

你发布的代码是正常的,但是如果 - 经过一段时间 - 最终会有十种不同的状态和无数的条件和许多处理程序,然后非常微妙的难以修复的错误将会蔓延到有时几乎无法解决的问题。