我有一个进程,从文件导入数据开始,然后执行一系列过程,但在任何时候它都可以找到问题,应该停止执行其余的并运行另一组.
这是我的示例,其中每个过程设置全局gStop变量,指示停止进程.如果它被停止,我需要在最后运行一些代码.
var gStop:boolean;
procedure Run;
begin
gStop:=False;
Import; // imports data from file
If Not gStop Then
AfterImport1;
If Not gStop Then
AfterImport2;
If Not gStop Then
AfterImport3;
If Not gStop Then
AfterImport4;
If Not gStop Then
If fTypeOfData = cMSSQL Then // function returns type of imported data
begin
ProcessMSSQLData1;
If not gStop Then
ProcessMSSQLData2;
If not gStop Then
ProcessMSSQLData3;
If not gStop Then
If fObjectAFoundInData Then // function checks if ObjectA was found in imported data
ProcessObjectA;
If not gStop Then
ProcessMSSQLData4;
end;
If Not gStop Then
AfterImport5;
...
// If stopped at anytime
If gStop then
begin
LogStoppedProcess;
ClearImportedData;
...
end;
end;
Run Code Online (Sandbox Code Playgroud)
在我的情况下,它实际上超过200行代码,所以当我维护这部分代码时,我必须向上和向下滚动.
我可以用任何方式改进这个程序,使其更具可读性,更易于维护,或者是否有任何其他方法可以在没有所有IF的情况下停止该过程?
编辑1:
每个过程都可以找到错误的数据并且可以设置,gStop := True;并且该过程应该跳过所有剩余的过程,并在最后执行部分代码.gStop = True;
编辑2:
我想保持工作流程从主程序(运行)控制,这样我就可以看到主要导入后运行的所有任务.如果我将执行分解为许多较小的过程,我只会看到更多的混淆,更少的可读性和可维护性.然后我可以:
procedure Run;
begin
gStop:=False;
Import; // imports data from file
RunEverytingAferImport; // execute ALL tasks after import
// If stopped at anytime
If gStop then
begin
LogStoppedProcess;
ClearImportedData;
...
end;
end;
Run Code Online (Sandbox Code Playgroud)
此工作流程似乎没有正确设计.我想知道在导入后运行的主要任务是什么,而不是每次我需要检查它时都不进行发现之旅.所有任务都已按目的分组到程序中,它们执行的操作以及执行方式和结果.
结论:
虽然不是最好的选择,但我决定在需要停止进程时使用Raising Exception.我有点'理解这种方法带来的影响(一旦我实现它就会知道更多),但它似乎是朝着更好地实现整个过程的一个合乎逻辑的步骤.现在我不会为每个任务执行都看到所有这些IF.好!代码将更易读,更易于维护.
我阅读了提供的链接,以解释在停止工作流程执行中使用Exceptions的缺陷,但正如Dalija Prasnikar在评论中所解释的那样,这不是与任务相关的性能部分; 每个应用程序运行只执行一次进程; 任务已经完成了他们的工作; 任务已经包括多个IF语句,其中检查停止的进程等等,所以我认为异常不会成为我的问题的一个非常糟糕的解决方案.
此外,如果我将任务转换为返回结果的函数,我想我会遇到同样的问题,检查每个任务的值,并根据它停止或继续该过程.
所以,提高异常是我选择的.
您应该使用自定义异常,并在遇到打破工作和转到Stopped代码的理由时提高它.在你的Import,AfterImport1和其他的代码逻辑只需要调用Stop程序,它将执行Stopped程序.另一方面,如果一切顺利,Stopped将不会被召唤.
您可以从EAbort派生异常创建静默异常
type
EStopException = class(EAbort);
Run Code Online (Sandbox Code Playgroud)
或者从基类Exception类派生以使用常规类型异常.
type
EStopException = class(Exception);
procedure Stop(const Msg: string);
begin
raise EStopException.Create(Msg);
end;
procedure Import;
var sl: TStringList;
begin
sl := TStringList.Create;
try
// your code logic
if NeedToStop then Stop('something happened');
finally
// perform any cleanup code needed here
sl.Free;
end;
end;
procedure Stopped;
begin
end;
procedure Run;
begin
try
Import;
AfterImport1;
AfterImport2;
except
on e: EStopException do
Stopped;
end;
end;
Run Code Online (Sandbox Code Playgroud)