简体   繁体   English

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

[英]Best design pattern for structured sequential handling

Doing maintenance on a project I came across code, which I find unnecessary hard to read and I wish to refactor, to improve readability. 对项目进行维护我遇到了代码,我觉得这些代码难以阅读,我希望重构,以提高可读性。

The functionality is a long chain of actions that need to be performed sequentially. 功能是需要按顺序执行的长链操作。 The next action should only be handled if the previous action was successful. 只有在上一个操作成功时才​​应处理下一个操作。 If an action is not successful a corresponding message needs to be set. 如果操作不成功,则需要设置相应的消息。 And the returned type is a Boolean. 返回的类型是布尔值。 (successful true/false). (成功的真/假)。 Just like the return type of all the called actions. 就像所有被调用动作的返回类型一样。

Basically it comes down to something like this. 基本上它归结为这样的事情。

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;

My question is: What is a better structure / pattern to handle this kind of logic? 我的问题是: 处理这种逻辑的更好的结构/模式什么?

Main goals are: 主要目标是:

  • increase readability. 提高可读性。
  • increase maintainability. 提高可维护性。

Please keep in mind that it is quite a large chain of actions that is being performed sequentially. 请记住,这是一个相当大的行动链,正在顺序执行。 (Thousands lines of code) (千行代码)

Make a list of action/message pairs: 列出操作/消息对:

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 are no-argument methods returning bool . A1 .. A3是返回bool无争论方法。 If some of your actions take parameters, you can use lambda expressions for them: 如果您的某些操作采用参数,则可以使用lambda表达式:

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

Now you can go through the pairs, and stop at the first failure: 现在你可以通过对,并在第一次失败时停止:

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

@dasblinkenlight was faster... however a similar solution using yield instead of an array: @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;
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM