生产中的断言

后端工程师确切地知道他们的服务正在发生什么。 他们实时了解其QPS,内存占用量,错误率和CPU利用率。 如果出现严重错误,它们甚至会自动进行分页,因此他们可以快速响应。 不幸的是,iOS工程师通常只有崩溃报告以及一些产品指标。 通常,我们会在用户报告错误时或更糟地在用户发布不正确评论时了解错误。 我们可以做得更好。

断言是条件检查,可确保您的代码按预期运行。 可能,您的代码库中已经有一些。 他们检查永远不会失败的条件,如果失败,则表明代码中存在严重错误 。 但是,断言在生产中已被删除,在现实世界中没有任何影响。 在我从事的每个项目中,我都添加了一个自定义Log类型,该类型使断言报告生产中的错误。 大多数崩溃报告框架都有报告非致命错误的能力,因此实施此操作很简单。 这是使用Crashlytics的示例:

  枚举 Log { 
静态 函数断言
#if调试
Swift.assert(condition(),message(),file:file,line:line)
#其他
如果 !condition(){
域= message()
let error = NSError(domain:domain,code:domain.hashValue,userInfo: nil
Crashlytics.sharedInstance()。recordError(错误)
}
#万一
} 静态 函数 assertFailure_消息: @autoclosure ()->字符串,文件:StaticString = #file ,行:UInt = #line ){
Log.assert( false ,message,file:file,line:line)
}
}

DEBUG ,assert会像往常一样工作,并使您的应用程序崩溃。 但是在RELEASE构建中,它会创建一个错误并将其报告给Crashlytics 。 这将显示为正常崩溃,但带有non-fatal标签。 它甚至包括堆栈跟踪!

这对于快速响应错误至关重要。 一个新的非致命异常告诉我,我的代码行为异常。 通过堆栈跟踪,iOS版本和问题发生的频率,我可以开始尝试重现该问题并解决它。 现在,我要用户报告错误或发表不良评论之前对错误做出响应。

我认为断言的这种使用是属性测试的一种形式。 编写属性测试:

  1. 您定义必须为特定功能保留的某些属性。
  2. 然后,您输入函数随机输入。
  3. 如果属性成立,则测试通过。

使用断言,而不是显式地编写这些测试,而是由用户生成输入! 您的断言定义了应始终为true的“属性”。 尽管您的用户不会生成纯粹的随机输入,但是输入通常是多种多样且出乎意料的。 最好的部分是-这些测试不需要编写任何真实的测试!

如果您对属性测试感兴趣,请查看LayoutTest —一个框架,该框架使您可以轻松地为视图编写属性测试。 该库会生成随机的JSON数据,并以此扩大您的视图。 然后,您在视图上声明属性(例如,间距正确并且没有视图重叠)。

断言在大多数iOS应用和框架中使用不足。 关于函数使用方式的错误假设是导致细微错误的常见原因。 我的一般规则是:

如果没有其他声明,则应该有一个断言。

例如:

 警卫让x = x else { 
返回
}

如果x为零怎么办? 我们需要向用户显示错误吗? 某些基础设施会无声地失败吗? 通常, x永远不应为零。 在这种情况下,我将在assert语句中添加一个断言:

 警卫让x = x else { 
Log.assertFailure(“ x意外为nil”)
返回
}

这很容易添加,也有助于在代码中记录假设。 在这里,我的假设很明确: x永远不应为零。

我还为以下内容添加断言:

  • 验证功能参数正确
  • 从带有“已知键”的字典中进行读取,例如NSNotification userInfo
  • Log.assert(Thread.isMainThread, "Not on the main thread!")
  • 打开关键数据库或文件失败

我知道有些人在想:“当您遇到断言时,您的程序处于未知状态,因此崩溃比继续运行更好。” 从理论上讲,这可能是正确的,但实际上,我从未发现它是有效的。 向用户提供降级的体验通常很简单。 空屏幕胜于崩溃。 而且由于您将能够迅速对问题做出反应,因此很快就会有修复程序。 如果您正在开发安全框架或银行应用程序,则崩溃可能是可以接受的。 但是对于大多数应用程序来说,不必让用户负担您的错误。

在开发过程中,您可能不会遇到很多断言,但是您会对用户设法使您的应用程序进入哪种状态感到惊讶。 您可能不会在每种设备,每种网络条件,每种操作系统以及每个帐户上都测试您的应用程序。 我已经看到许多断言在生产中引发,这在开发中是从未见过的。


您是否使用其他系统来跟踪错误? 您还有其他改善断言的想法吗? 在评论中让我知道!

感谢Sanket Firodiya,Alice Avery,Kamilah Taylor,Melissa Huang,Joe Fabisevich和Kyle Sherman帮助审阅了这篇文章。