2017-04-01 69 views
2

这是一个抽象的问题,没有真正的代码(也可能不是最好的伪代码),所以希望它足够有意义,不会被主持人死亡。但是这个问题一直在我面前反复提出,因为我正在开展的项目是非常线性的,取决于以前的条件和流程。所以...顺序逻辑和可读性

给定了一系列逻辑任务,每个逻辑任务都依赖于前一个,我尝试了两种方法来构造代码。 一个取决于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 

但我已经在许多地方意见的效果看,这种运行继续变量的方法是不理想的。所以,或者我可以有

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

在我看来,前者更可读,逻辑非常明显。而且,当顺序中的任务数量变大(超过3个或者真的)时,嵌套的Ifs真的变得笨拙。 所以,我的问题是,不使用这种第一种方法的原因是什么? 有没有更好的方法来构建第二个例子中的逻辑来提高可读性? 还是有第三种方式解决前者的问题(不管他们是什么)以及后者的可读性问题? 还是第一种方法实际上很好,当一个确实有顺序依赖任务序列?

回答

0

这真的取决于你的情况。如果没有进一步的细节,并与代码是完全等同于原来的块坚持,我会避免不必要的嵌套开始:

Proceed = False; 

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

在大多数语言中,你可以把布尔直入变量。

Proceed = task1 successful and task2 successful 

如果你真的喜欢避免和的话,或许是这样的:

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 

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

除此之外,您的替代品有两个变化。首先是“继续”变量完全丢失的事实。我同意这一点。什么你原来的代码读者必须克服的是:

初始化X ...现在,如果x然后准备Y ...好了,现在做ÿ

如果你可以改变这:

如果x然后做ÿ

这是概念上更容易。

所以我会做:

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都会导致他们失败,最好是一出现就处理失败,这样开发商没有很长的路要跟踪,看看最终的来源。

0

两者都很常见。第一次使用需要几种方法的顺序调用一些连贯的API的工作时尤为常见:

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; 
} 

另一种是常见的,如果你不需要巢超过2-3层深(特别是如果这两种情况的处理):

尚未提出另外一个是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; 
} 

如果使用异常你可能不喜欢在goto上面的例子,扔在每一行,或者你mig HT包装你的API中抛出方法:

void DoCreateThing(API_THING **thing, ...) 
{ 
    if (API_OK != CreateThing(thing, ...)) 
     throw new ApiException("CreateThing Failed!"); 
} 

//... 

API_THING *thing = NULL; 
try 
{ 
    DoCreateThing(&thing, ...); 
} 
catch (ApiException e) 
{ 
    // ... 
} 
// ... 
finally 
{ 
    if (thing) 
    { 
     ReleaseThing(&thing, ...); 
     thing = NULL; 
    } 
} 

采取心脏:如果你是做节目吧,你做任何决定,这里将不那么重要,你怎么从你的高层架构封装的行为该位。