结构化顺序处理的最佳设计模式
Best design pattern for structured sequential handling
我在维护一个项目时遇到了一些代码,我发现这些代码不必要地难以阅读,我希望重构它以提高可读性。
该功能是一长串需要按顺序执行的操作。仅当上一个操作成功时才应处理下一个操作。如果操作不成功,则需要设置相应的消息。 returned 类型是布尔值。 (成功true/false)。就像所有调用的动作的 return 类型一样。
基本上就是这样。
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;
我的问题是:处理这种逻辑的更好结构/模式是什么?
主要目标是:
- 增加可读性。
- 提高可维护性。
请记住,这是一连串按顺序执行的操作。 (数千行代码)
列出 action/message 对:
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;
@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;
}
}
我在维护一个项目时遇到了一些代码,我发现这些代码不必要地难以阅读,我希望重构它以提高可读性。
该功能是一长串需要按顺序执行的操作。仅当上一个操作成功时才应处理下一个操作。如果操作不成功,则需要设置相应的消息。 returned 类型是布尔值。 (成功true/false)。就像所有调用的动作的 return 类型一样。
基本上就是这样。
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;
我的问题是:处理这种逻辑的更好结构/模式是什么?
主要目标是:
- 增加可读性。
- 提高可维护性。
请记住,这是一连串按顺序执行的操作。 (数千行代码)
列出 action/message 对:
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;
@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;
}
}