结构化顺序处理的最佳设计模式

时间:2017-08-01 09:20:02

标签: c# algorithm design-patterns maintainability code-readability

对项目进行维护我遇到了代码,我觉得这些代码难以阅读,我希望重构,以提高可读性。

功能是需要按顺序执行的一长串操作。只有在上一个操作成功时才​​应处理下一个操作。如果操作不成功,则需要设置相应的消息。返回的类型是布尔值。 (成功的真/假)。就像所有被调用动作的返回类型一样。

基本上归结为这样的事情。

string m = String.Empty; // This is the (error)Message.
bool x = true; // By default the result is succesful.

x = a1();
if(x) {
    x = a2();
}
else {
    m = "message of failure a1";
    return x;
}

if(x) {
    x = a3();
}
else {
    m = "message of failure a2";
    return x;
}

//etcetera..etcetera...

if(x){
    m = "Success...";
}
else{
    m = "Failure...";
}

return x;

我的问题是:处理这种逻辑的更好的结构/模式是什么?

主要目标是:

  • 提高可读性。
  • 提高可维护性。

请记住,正是按顺序执行的是一大堆动作。 (千行代码)

2 个答案:

答案 0 :(得分:5)

列出操作/消息对:

class Activity {
    public Func<bool> Action { get; set; }
    public String FailureMessage { get; set; }
}

Activity[] actionChain = new[] {
    new Activity { Action = A1, FaulureMessage = "a1 failed"}
,   new Activity { Action = A2, FaulureMessage = "a2 failed"}
,   new Activity { Action = A3, FaulureMessage = "a3 failed"}
};

A1 .. A3是返回bool的无参数方法。如果您的某些操作采用参数,则可以使用lambda表达式:

Activity[] actionChain = new[] {
    ...
,   new Activity { Action = () => An(arg1, arg2), FaulureMessage = "aN failed"}
,   ...
};

现在你可以通过对,并在第一次失败时停止:

foreach (var a in actionChain) {
    if (!a.Action()) {
        m = a.FailureMessage;
        return false;
    }
}
m = "Success";
return true;

答案 1 :(得分:4)

@dasblinkenlight更快......但是使用yield而不是数组的类似解决方案:

public string Evaluate()
{
    foreach (var customAction in EnumerateActions())
    {
        if (!customAction.Execute())
            return customAction.Error;
    }
    return "Success...";
}

public IEnumerable<CustomAction> EnumerateActions()
{
    yield return new CustomAction(a1, "Error for A1");
    yield return new CustomAction(a2, "Error for A2");
    ...
}

public class CustomAction
{
    public Func<bool> Execute { get; }
    public string Error { get; }
    public CustomAction(Func<bool> action, string error)
    {
        Execute = action;
        Error = error;
    }
}