如何避免 Objective C 中每一层的大量错误处理代码

Posted

技术标签:

【中文标题】如何避免 Objective C 中每一层的大量错误处理代码【英文标题】:How to avoid extensive error handling code on every layer in Objective C 【发布时间】:2014-12-12 12:56:39 【问题描述】:

在 Objective C 中,如何避免在我的方法中进行所有这些广泛的错误处理?我读过 Apple 建议仅在预期出现错误时才应使用 NSError 引用,但这种方法会导致代码完全被错误处理代码弄得一团糟。

Apples guide to Exceptions

这份文件中有一句话特别吸引我的眼球;

解析库可能会在内部使用异常来指示问题并允许快速退出可能深度递归的解析状态;但是,您应该注意在库的顶层捕获此类异常并将它们转换为适当的返回代码或状态

这是一个(不完整且未优化的)sn-p 代码演示了我的意思。我在我的方法中进行的每一次调用都需要对每一步进行错误检查,使代码与 if 语句混淆,使其难以阅读。

- (NSNumber) countFriendsForUserName:(NSString*) userName error:(NSError **)error 
    NSError *internalError = nil;
    Session *session = [_sessionMgr openSessionWithError:&internalError];
    if (!error) 
        User *user = [session findUserByName:userName error:&internalError];
       if (!error) 
           NSArray * bestFriends = [session getFriendsByUserId:user.id error:&internalError];
       
    
    [_sessionMgr closeSession];        
    if (internalError) 
        *error=internalError;
        return 0;
     
    return [bestFriends count];

如果我改用异常,代码看起来像这样(同样,这段代码只是一个不完整的例子),我现在没有 XCode。

- (NSNumber) countFriendsForUserName:(NSString*) userName error:(NSError **)error 
    @try
        Session *session = [_sessionMgr openSession];
        User *user = [session findUserByName:userName];
        NSArray * bestFriends = [session getFriendsByUserId:user.id];
        [_sessionMgr closeSession];  
        return [bestFriends count];            
     
    @catch (NSException *e) 
        [_sessionMgr closeSession];        
        *error=[ExceptionParser createNSErrorFromException:e];
        return 0;
     

如果我正确解释 Apple 异常指南,如果我的代码表现得像“解析库”(Apple 示例),那么在内部使用异常可能完全没问题,只需在返回调用函数之前翻译它们,然后反过来可能会对我的 NSError 代码采取适当的措施。还是我误解了 Apples 的指导方针?

【问题讨论】:

【参考方案1】:

您应该测试方法的返回值,而不是NSError 对象的存在。您还可以链接NSError 对象以将低级错误返回给调用者:

- (NSInteger)countFriendsForUserName:(NSString*)userName
                               error:(NSError **)error

    NSArray *bestFriends = nil;
    Session *session = [_sessionMgr openSessionWithError:error];
    if (session) 
        User *user = [session findUserByName:userName error:error];
        if (user) 
           bestFriends = [session getFriendsByUserId:user.id error:error];
        
    
    [_sessionMgr closeSession];
    return [bestFriends count];

注意:

bestFriends 移至方法顶部。 已更改返回类型。

【讨论】:

你打字比我快;) 这些都是非常有效的观点。但我仍然很好奇为什么 Exceptions 不会更好呢?该代码根本不需要任何 if 语句,并且在最后一步,在将结果返回给应用程序(和用户)之前,异常将被转换为应用程序用户 UI 可以解释的 NSError。 您应该对异常情况使用异常。如果一个方法返回一个值,并且该返回值是NOnil 或其他任何值,那么这不一定是错误。它仅仅意味着正在寻找的东西不存在,如果你想看看你是否需要添加那个东西,这不是一个错误。在细粒度级别上处理异常也很昂贵且麻烦。 还要注意 ARC 不是异常安全的。如果您抛出异常,您将在 ObjC 中泄漏内存。这通常没问题,因为预计您会在抛出异常后很快崩溃。异常处理指南中的指南早于 ARC。如果您编译为 ObjC++(或者如果您将某些标志传递给编译器),您将获得内存安全异常,但这会影响性能(内存和时间),不鼓励这样做。

以上是关于如何避免 Objective C 中每一层的大量错误处理代码的主要内容,如果未能解决你的问题,请参考以下文章

如何在每一层和每个时期获得权重然后保存在文件中

如何获得每一层的权重形状?

如何获得每一层的重量

如何在 Pytorch 中获取神经网络每一层的输出维度?

CNN输出每一层的卷积核,即每一层的权重矩阵和偏移量矩阵

1004. Counting Leaves