我通常在Objective-C中使用要声明值的声明。在调试版本中,我声明为停止程序执行并检查我的假设是否不正确。但是,在生产版本中,我找到了一种安全失效的方法,可以将对用户的影响降至最低。我通过创建一个将NSAssert封装在if语句中的宏来实现此目的,该语句还执行我想在生产环境中作为故障保护运行的代码。例如:
我将使用的断言宏:
#define AssertTrueOrExecute(condition, action) \
if (!condition) { \
NSAssert(testCondition, @"Condition failed"); \
action; \
}
在我的应用程序中的某个地方,我会遇到这样的事情:
- (void)someMethod
{
BOOL testCondition = ...
// Ensure the testCondition is true before proceeding any further
AssertTrueOrExecute(testCondition, return);
// Potentially unsafe code that never gets executed if testCondition is false
}
- (void)someReturningMethod
{
BOOL testCondition = ...
// Ensure the testCondition is true before proceeding any further
AssertTrueOrExecute(testCondition, return @"safe string");
// Potentially unsafe code that never gets executed if testCondition is false
}
由于我无法像Swift中提到的那样定义宏,是否有一种方法可以实现相同的行为?那就是我要如何为我的AssertTrueOrExecute
宏使用Swift等效项?
更新:
为了进一步解释这个问题,如果我使用的是Swift,我目前将编写如下内容:
func someMethod () {
let testCondition : Bool = ...
// Ensure the testCondition is true before proceeding any further
if (!testCondition) {
assert(testCondition);
return;
}
// Potentially unsafe code that never gets executed if testCondition is false
}
因此,问题更多地在于如何用类似的方式包装带有断言的if语句,使我拥有Objective-C宏,以便例如可以断言或早返回?
更新2:
另一个示例将在函数中返回一些内容,例如:
func someReturningMethod () -> String {
let testCondition : Bool = ...
// Ensure the testCondition is true before proceeding any further
if (!testCondition) {
assert(testCondition);
return "safe string";
}
// Potentially unsafe code that never gets executed if testCondition is false
return "some other string"
}
Swift中没有宏,但是Swift中可能还有其他手段可以实现与Objective-C相同的功能。
但是,这里真正的问题是,您尝试以一种您实际上不应该采用的方式来解决问题:
不要混用程序员错误和运行时错误!
相反,要清楚地区分什么是程序员错误以及什么是运行时错误。使用断言处理程序员错误,并NSError
在Swift中分别使用try
&catch
和来处理运行时错误throw
。
请注意,程序员错误的“范围”不限于程序由于断言失败而失败的时间:这种错误很可能会带来不良的副作用,使程序处于无效状态,并且此断言通常会检测到错误。断言可能在很长时间之前就发生了。因此,当断言失败时,您的程序很可能已经处于无效状态。
一条经验法则是,断言失败不应在生产代码中发生(请务必阅读)。好吧,这些是程序员的错误,应该解决,不是吗?您可以在单元测试中使用断言来验证您的假设。如果您仍然担心,您的假设可能会中断生产,并且还确保这不是运行时错误(应始终妥善处理),则应停止程序-无论如何,所有赌注都无效。在Swift中,您可以使用fatalError
它。
有时,对特定假设的违反是程序员错误还是运行时错误的区分并不总是那么明显,并且可能取决于上下文。但是,作为程序员,您始终可以定义它是什么。以一个字符串参数为例:如果您是直接从想要创建帐户并要求输入用户名的用户输入的文本字段中获取的,则应该验证该字符串并在不适合的情况下返回/抛出错误您的期望-例如,如果它为空,太短等。也就是说,在Swift中,您可能会throw
出错并在调用站点(可能是在View Controller中)优雅地处理该错误。另一方面,您定义初始化一个User
对象,该对象的name
将为空。也就是说,在初始化例程中,您定义了一个前提条件,即有效的用户名一定不能为空,然后使用assert
或进行检查fatalError
。在这种情况下,如果没有用于初始化名称为空的用户的代码路径,则您的程序是正确的。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句