顺序逻辑和可读性

时间:2017-04-01 18:19:56

标签: logic

这是一个抽象的问题,没有真正的代码(也许也不是最好的伪代码),所以希望它足够有意义,不会被缓和到死。但这是一个一次又一次出现在我身上的问题,因为我正在研究的项目非常线性,取决于以前的条件,过程。所以......

鉴于一系列逻辑任务,每个都依赖于前一个任务,我尝试了两种方法来构造代码。 一个取决于proceed变量,如此

Proceed = True

If Task1 Not Successful Then
    Proceed = False
End If

If Proceed Then 
    If Task2 Not Successful Then 
        Proceed = False
    End If
End If

但是我已经在很多地方读过评论,认为这种运行的Proceed变量方法并不理想。所以,或者我可以

If Task1 Succcesful Then 
    If Task2 Successful
       Then Etc
    Else
        Error Condition
    End If
Else
    Error Condition
End If

在我看来,前者更具可读性,逻辑非常明显。并且,当序列中的任务数量变大(超过3或真的)时,嵌套的Ifs实际上变得难以处理。 所以,我的问题是,没有使用第一种方法的原因是什么? 是否有更好的方法来构建第二个示例中的逻辑以提高可读性? 或者是否有第三种方法可以解决前者的问题(无论它们是什么),以及后者的可读性问题? 或者第一种方法实际上是好的,当一个确实有一系列顺序相关的任务时?

2 个答案:

答案 0 :(得分:0)

这实际上取决于你手头的情况。如果没有任何进一步的细节,并坚持使用与原始块完全等效的代码,我将首先避免不必要的嵌套:

Proceed = False;

if Task1 successful and Task2 successful Then
    Proceed = True
end if

在大多数语言中,您只需将布尔值直接放入变量即可。

Proceed = task1 successful and task2 successful

如果你真的更愿意避免使用AND,那么也许这样:

Proceed = True;

If Task1 not successful then
    Proceed = False
Else if Task2 not successful then
    Proceed = False
Else if Task3 not successful then
    Proceed = False
End if

到目前为止,在所有情况下,您都避免嵌套。为了便于阅读,这很重要。

除此之外,您的候补人员还有两项更改。首先是“Proceed”变量完全被删除的事实。我同意这一点。原始代码的读者必须克服的是:

  

初始化x ...现在,如果x然后为y做好准备......好的,现在做y

如果您可以将其更改为:

  

如果x则执行y

这在概念上更容易。

所以我会这样做:

If Task1 successful and Task2 successful and Task3 successful then
    Do your thing
End if

或者

If Task1 not successful then
    Do something
else If Task2 not successful then
    Do some other thing
else 
    Do your main thing
end if

第二个区别是你输入了“错误状态”。特别是,你提到“错误”。如果您正在阅读的文档说您应该处理错误(例如通过停止执行和打印错误消息),那么这是正确的。虽然如果有机会,您应该在进入if / then语句之前处理它们,例如在Task1过程中。这不仅简化了if / then语句,而且对于编码器来说也是一种更好的体验,因为任何体面的IDE都会导致它们失败,并且最好在出现故障时立即处理故障,以便开发人员没有很长的路要走,看看最终的来源是什么。

答案 1 :(得分:0)

两者都很常见。第一种是在使用一些连贯的API时特别常见,它需要按顺序调用几个方法:

labels.addLabels(this); // `this` contains a reference to the MainJFrame object currently under construction

如果您不需要深度超过2-3级(​​特别是如果处理两种情况),则另一种情况很常见:

另一个未被建议的是API_THING *thing = NULL; API_RESULT result = CreateThing(&thing, ...); if (API_OK == result) result = InitializeThing(&thing, ...); if (API_OK == result) result = DoThingToThing(&thing, ...); // ... if (thing) { ReleaseThing(&thing, ...); thing = NULL; } 和/或例外:

goto

如果在上面的API_THING *thing = NULL; if (API_OK != CreateThing(&thing, ...)) goto CLEANUP; if (API_OK != InitializeThing(&thing, ...)) goto CLEANUP; if (API_OK != DoThingToThing(&thing, ...)) goto CLEANUP; //... CLEANUP: if (thing) { ReleaseThing(&thing, ...); thing = NULL; } 示例中使用了您可能喜欢的异常并抛出每一行,或者您可能将API包装在抛出的方法中:

goto

请记住:如果您正在进行正确的编程,那么您在此处做出的任何决定都不会像您从高级架构中封装这些行为那样重要。

相关问题