Tag: Collin Flynn

通过创造混乱来进行单元测试竞赛条件(快速)

多线程竞争条件不会始终如一地发生,这使得它们很难重现。 另一方面,最佳软件实践要求我们编写自动化测试以验证我们的更改。 我将分享我的技术来创建足够的混乱,以使那些罕见的崩溃变得足够可靠以进行测试。 什么是比赛条件? 如果您有多个线程试图同时变异和访问数据,可能会发生不好的事情。 一个线程可能会更改一个值,而另一个线程正在使用它! 避免这种情况的最好方法是以不可能的方式构造代码。 Swift的结构是一个很好的起点,因为它们是在写操作时复制的(额外的功劳:从功能上考虑!)。 但是我们不能总是做理想的事情。 我们在现实世界中发展,但我们的控制范围之外。 也许我们陷入了遗留代码库。 也许我们没有时间或金钱来重构所有东西。 有时,我们所能做的就是实施最佳实践。 最佳实践之一是: 修复错误时,编写一个可重现该错误的单元测试以防止退化。 通常这是直截了当的,但是这些竞争条件崩溃可能很棘手。 它们很少出现在崩溃报告器中,并且您从未在设备上看到过这种情况。 让我们崩溃 首先,设置一个包含一些不安全代码的简单方法: 不料? 更像预期的那样。 现在,您可以修复它,并且可以放心,将来的更改不会使它恢复正常。 肖恩每天在 Livefront对抗 混乱 。

如果您的类型名称平庸,则您的代码将构成责任

我创建代码的过程如下所示: 研究目标的细节(学习) 提出实施计划(创建) 代码(单击并键入) 当我意识到我有一个错误的假设时,请返回步骤1(遗憾) 在进行编码工作之前,正确命名类型是计划中的最后一个障碍。 就像,嗯,我知道计算机不在乎我给我命名的类型。 机器解释指令时,所有这些都将被剥夺。 我的功能不会受到影响。 为什么我花了很多时间来确定角色以及事情如何融合在一起? 因为代码不仅仅适用于机器。 适用于必须充分理解它才能正确操作它的开发人员。 该类别中包括“未来”。 要做到这一点,就需要弄清问题集,并有足够的同理心,以使听众可以预期您选择的名字的所有含义。 真名 有一个古老的想法,即如果您知道某事的“真实名称”,那么您将拥有权力。 这是幻想中的常见现象,也是宗教故事的一部分。 以伊西斯和拉的故事为例。 伊希斯(Isis)是一位出色的治疗师,但只有知道她的真实姓名时才能帮助Ra。 他试图用“小写”的名字满足她的要求,但这仅使Ra未能解决核心问题。 一旦他放弃了他的真实姓名,她就可以治愈他。 这听起来像调试我。 如果您不知道所处理事物的真正含义,就无法解决该问题。 懒惰的标签将欺骗人。 您在阅读代码时让人们做的心理锻炼越多,使用它的认知就越消耗精力。 “是的,被称为 Provider 但实际上只是转换数据。” “该 modelId 不适用于该模型,适用于其他通用模型。” 但是,如果您真正知道什么是东西,则可以轻松地对其进行操作。 这很重要,因为将来必须更改代码。 我的理想是功能与代表功能的标签之间的绝对统一。 既然是理想的,我永远都不会到达那里。 想起名字时会出现回报递减的情况,但是值得花一些时间。 在清晰度和可读性之间取得平衡 某物的最精确名称可能是…… 绝对清晰。 把它收拾好。 该名称公然忽略了所有可用的上下文。 显然,这个例子很荒谬,但是添加不必要的限定词可能很诱人。 即使您觉得这个名字不是最好的,也最好在项目内部保持一致,而不要在两个约定之间来回穿梭。 一旦人们适应了您项目的标准,他们就会知道您在说什么。 一致的信息比冲突的信息要好,即使最终效果不佳。 同样,在引入新元素时也不要害怕重命名旧元素,以澄清它们之间的差异。 我们不是用石碑编码。 有些人梦想着将来验证自己的代码并期待未来的变化。 我宁愿使代码清晰地代表当前的情况,并在反映未来的将来进行更改。 这使我省去了很多我无法控制的事情。 我们控制双方 也许您没有花时间准确地命名某件事,因为它正在做很多事情…… 再塞另一种方法 有时正确的答案可能是重构基础实现以启用更好的名称。 我们都可以控制。 […]

在Swift中进行功能性思考

如上图所示,从服务器解析JSON响应需要进行两次转换: 从原始HTTP响应转换为数据的JSON表示形式。 从JSON表示形式到模型。 在第一步和第二步之间,我们将使用数据的JSON表示形式。 这种JSON表示形式使我们能够对服务器响应进行增量转换。 通过在模型之前解析为中间JSON表示,我们的代码变得更加可组合。 JSON的表示方式对于理解本文中的功能编程概念并不是必不可少的。 但是,为了完整起见,让我们现在对其进行定义。 如果阅读JSONSerialization的文档,您会注意到有效JSON的规则之一是: 所有对象都是NSString , NSNumber , NSArray , NSDictionary或NSNull 。 由于案例数量有限,因此使用枚举似乎是一个好情况。 定义了JSONObject类型后,我们现在知道第一次转换之前,第一次与第二次转换之间以及第二次转换之后的数据类型。 它们是Data -> JSONObject > Model (我们稍后会定义模型。) 功能方法 有一个核心概念将通过此练习来推动我们的思考过程。 我们将过程中的每个步骤都视为独立于函数外部变量的转换 。 让我们看一下如何将这种思考过程应用于上面概述的两个转换。 转换1:将数据转换为JSON对象 我们将从定义一个新类型Deserialize开始,该类型将Data转换为JSONObject 。 在函数式编程中,类型由其方法签名定义。 要使用此类型,我们编写了一个函数,该函数返回新的Deserialize类型。 我想强调关于JSON()函数的几件事。 该函数返回一个闭包。 以面向对象的思维方式看待这个问题可能看起来很奇怪,但这是标准的函数式编程。 请注意,从JSON()返回的闭包完全独立于该函数外部可能存在的任何状态。 这与我们非常依赖状态的面向对象编程形成了鲜明的对比。 转换2:将JSON对象转换为模型 正如我们在第一个转换中所做的那样,让我们​​定义一个新类型,该类型接受一个JSONObject作为参数并返回类型T的模型: typealias Decode =(JSONObject?)->(T?) 注意:我们使 Decode 函数通用,因此我们可以解码各种模型。 由于我们尚未定义任何模型,因此这是我们开始从JSON创建模型所需的所有样板代码! 下一步是定义我们的模型以及可以解析JSON的函数。 全部放在一起 让我们导出一个简单的示例,以显示与该代码交互的外观。 对于此示例,我们将期望服务器向我们发送有关用户的信息。 我们将定义User模型,并编写一个函数decodeUser() ,以执行从JSONObject到User的转换。 […]

斯威夫特预期为零,不是

我的单元测试失败。 它想要nil但得到了 。 我最初的反应是指责我的计算机愚蠢。 您是否期望我提供其他类型的nil ? 只有一个nil ,名字叫nil 。 但是请稍等。 电脑还不足以欺骗我们。 我做错了什么? 字典问题 这一切都很好,而且是预期的。 我遇到了问题,因为我将值类型设置为“ Any? 而不是Any 。 Swift让我的价值翻倍! 将键设置为nil 在“字典”中将键设置为nil ,它将为您删除该键/值对。 这就是上面第8行的行为符合预期的原因。 如果要在具有可选值类型的Dictionary中将值显式设置为nil ,则必须先将其包装。 当我第一次使用var dict: [String: Any?] = [“first”, nil]创建字典时,Swift会自动执行此额外步骤var dict: [String: Any?] = [“first”, nil] —它在后台为我包装了nil。 不要这样! 最后,我重构了Dictionary,使其值不使用可选参数。 必须记住的规则越少越好。 如果我对自己的代码感到困惑,那么另一个开发人员加入该怎么办? 如果您想进一步思考这个想法,请查看Tyler Johnson关于代码设计的文章。 代码应该像政治卡通一样呈现自己-充满了直率的隐喻,带有有用的标签,没有任何微妙之处。 肖恩判断 Livefront的 代码是什么样的 。

如何在iOS上调试后台获取事件

注册您的应用以进行后台抓取,使您可以为用户做各种事情……例如更新图标的徽章计数! 但是您应该如何测试呢? 取回操作取决于操作系统…… 我将向您展示如何调试后台获取解决方案以及遇到的陷阱。 首先,在performFetchWithCompletionHandler设置一个断点,以便我们可以验证测试。 接下来,从Xcode的Debug菜单触发获取: 这应该可以正常工作,但这不是最有用的方案。 如果您想像这样进行调试,则可以直接直接调用performFetchWithCompletionHandler方法。 棘手的部分是重新创建完全不加载您的应用程序的情况,iOS将其唤醒以在后台执行。 这是我们遇到的#xcode问题。 编辑应用程序目标的方案,您将看到一个选项,用于模拟从后台提取事件启动。 在模拟器中尝试。 您将永远等待而不会出错。 显然,这曾经在模拟器中起作用。 但是不再。 精细。 让我们尝试使用该设备。 您可能会认为此错误是有意义的。 也许您需要进入手机上的“设备管理”设置,以验证您是否信任开发者证书。 我一般建议这样做,但是这里无济于事。 据我所知,这是一个通用的“超时”错误。 是什么赋予了? 好吧,这是一个错误。 在iOS 11.0.3之后,此功能就中断了。 如果您使设备保持最新状态(在撰写本文时为11.2.6),则将无法测试设备上的后台抓取。 那么现在怎么办? (编辑:自iOS 11.3和Xcode 9.3起,此功能现在可以使用!感谢Marco Mussini) 希望在Apple解决此问题之前,您可以使用较旧的测试设备。 如果您位于双子城,则可以在Livefront停留并使用运行11.0.3的iPhone 7 Plus(在FinalPass上注册-第一小时免费!)。 以此为警告-始终准备有备用测试设备,以及较旧版本的iOS! Sean在 Livefront 与Xcode有着严格的专业关系 。 ps如果您没有设备,但想验证启动顺序,我已经更新了AppLaunchSequence文档以包括后台获取。