我有一个进程,从文件导入数据开始,然后执行一系列过程,但在任何时候它都可以找到问题,应该停止执行其余的并运行另一组.
这是我的示例,其中每个过程设置全局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;
在我的情况下,它实际上超过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;
此工作流程似乎没有正确设计.我想知道在导入后运行的主要任务是什么,而不是每次我需要检查它时都不进行发现之旅.所有任务都已按目的分组到程序中,它们执行的操作以及执行方式和结果.
结论:
虽然不是最好的选择,但我决定在需要停止进程时使用Raising Exception.我有点'理解这种方法带来的影响(一旦我实现它就会知道更多),但它似乎是朝着更好地实现整个过程的一个合乎逻辑的步骤.现在我不会为每个任务执行都看到所有这些IF.好!代码将更易读,更易于维护.
我阅读了提供的链接,以解释在停止工作流程执行中使用Exceptions的缺陷,但正如Dalija Prasnikar在评论中所解释的那样,这不是与任务相关的性能部分; 每个应用程序运行只执行一次进程; 任务已经完成了他们的工作; 任务已经包括多个IF语句,其中检查停止的进程等等,所以我认为异常不会成为我的问题的一个非常糟糕的解决方案.
此外,如果我将任务转换为返回结果的函数,我想我会遇到同样的问题,检查每个任务的值,并根据它停止或继续该过程.
所以,提高异常是我选择的.
您应该使用自定义异常,并在遇到打破工作和转到Stopped
代码的理由时提高它.在你的Import
,AfterImport1
和其他的代码逻辑只需要调用Stop
程序,它将执行Stopped
程序.另一方面,如果一切顺利,Stopped
将不会被召唤.
您可以从EAbort派生异常创建静默异常
type EStopException = class(EAbort);
或者从基类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;