当前位置:  开发笔记 > 数据库 > 正文

如何在没有大量IF的情况下控制执行?

如何解决《如何在没有大量IF的情况下控制执行?》经验,为你挑选了1个好方法。

我有一个进程,从文件导入数据开始,然后执行一系列过程,但在任何时候它都可以找到问题,应该停止执行其余的并运行另一组.

这是我的示例,其中每个过程设置全局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语句,其中检查停止的进程等等,所以我认为异常不会成为我的问题的一个非常糟糕的解决方案.

此外,如果我将任务转换为返回结果的函数,我想我会遇到同样的问题,检查每个任务的值,并根据它停止或继续该过程.

所以,提高异常是我选择的.



1> Dalija Prasn..:

您应该使用自定义异常,并在遇到打破工作和转到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;


@Jens不!EurekaLog和例外是完全兼容的.
@MikeTorrettinni`type EStopException = class(EAbort)public class procedure Stop(const msg:string ='Import error occurred'); 结束; ...类过程EStopException.Stop; 开始提高EStopException.Create(msg); 结束;`可能提供更少的命名空间污染("停止"是太通用的名称,可以被许多libs /对象使用),你可以把它称为`EStopException.Stop;`或`EStopException.Stop(一些有意义的消息) log)` - 我更喜欢后者,我不喜欢Dalija的参数减少停止这个信息丢失
@Arioch'我修改了代码以使用`EAbort`异常类.
您不需要从EAbort派生.您只需要处理异常.
推荐阅读
Gbom2402851125
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有