IoC

原文:Inversion of control - Wikipedia
以下为为摘录翻译。

简介

在软件工程领域,控制反转Inversion of control (IoC)是一种编程原理。
传统的过程式编程Procedural programming,实现业务逻辑的代码自己去调用框架去处理通用逻辑。
控制反转则把控制流反了过来,由框架自己去调用相应的业务逻辑。

Inversion of control is sometimes facetiously referred to as the “Hollywood Principle: Don’t call us, we’ll call you”.

内涵

控制反转的情况下,即使可重用代码和特定于问题的代码在应用程序中一起运行,两部分代码往往也是独立开发的。软件框架,回调,调度程序,事件循环,依赖项注入和模板方法都可视为控制反转的例子。

译者:这样的话,iOS的delegate设计模式其实也体现了控制反转的思想。

目的

  • 任务执行与实现的解耦
  • 让模块专注于它的设计任务
  • 让模块不再需要假设别的系统如何调用自己,取而代之依赖于合约contract
  • 防止替换模块时的副作用

实现技术

在面向对象编程中,有几种技术可以实现控制反转。分别是:

依赖注入是大家比较熟悉的方式,常见的几种注入又可分为:

  • 构造器(Constructor)注入
  • 参数注入
  • setter注入
  • 接口注入

Result

原文:Apple Developer Documentation
文档摘录翻译

Result 定义

1
@frozen enum Result<Success, Failure> where Failure : Error

Result 应用

编写可能失败Failable的异步API

编写可能失败的函数、方法或其他API时,可以在声明中使用throws关键字来标示此API可抛出异常。但是我们不能将throws关键字用于异步返回的API,此时可用Result枚举来保存异步调用的结果信息,并利用关联值来携带有关的值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
let queue = DispatchQueue(label: “com.example.queue”)

enum EntropyError: Error {
case entropyDepleted
}

struct AsyncRandomGenerator {
static let entropyLimit = 5
var count = 0

mutating func fetchRemoteRandomNumber(
completion: @escaping (Result<Int, EntropyError>) -> Void
) {
let result: Result<Int, EntropyError>
if count < AsyncRandomGenerator.entropyLimit {
// Produce numbers until reaching the entropy limit.
result = .success(Int.random(in: 1100))
} else {
// Supply a failure reason when the caller hits the limit.
result = .failure(.entropyDepleted)
}

count += 1

// Delay to simulate an asynchronous source of entropy.
queue.asyncAfter(deadline: .now() + 2) {
completion(result)
}
}
}

保存抛出异常函数的结果

有时,我们需要保留函数或其他抛出异常表达式的整个结果。例如,需要序列化结果,或者将其作为值传递给程序的其他部分。在这些情况下,请使用Result

转换抛出异常表达式为Result

使用Result枚举的init(catching:)进行转换:

1
let singleSample = Result { try UnreliableRandomGenerator().random() }

转换Result到抛出异常表达式

1
2
3
4
5
6
7
8
let integerResult: Result<Int, Error> = .success(5)
do {
let value = try integerResult.get()
print("The value is \(value).")
} catch error {
print("Error retrieving the value: \(error)")
}

MVC与MVVM、Rx

MVC、MVVM都是大家熟悉的常用架构。

MVVM

关于MVC不展开,下面讲讲MVVM。App 架构一书提到:

MVVM 所做的不仅仅是把代码移动到新的地方。加入一层新的 view-model 层的目的是双重的:

  • 鼓励将 modelview 之间的关系构建为一系列的变形管道。
  • 提供一套独立于 app 框架的接口,但是它在相当程度上代表了 view 应该展示的状态。

两者结合起来,对 MVC 中两个最大的被人诟病的地方进行了修正。第一项通过把 model 相关 的观察和变形从 controller 层移除出去,减少了 controller 所需要承担的责任。第二项为场景 的 view state 提供了一套干净的接口,让它可以独立于 app 框架进行测试,而不需要使用MVC 的集成测试。

但MVVM也有自己的一些要求,App 架构一书提到:
为了保持 viewview-model 的同步,MVVM 强制使用某种形式的绑定,也就是说,需要一种保证一个对象上的属性与另一个对象上的属性同步的方式。Controller负责构建这些绑定,将 view-model 所暴露的属性和场景中 view-model 所代表的 view 上的属性关联起来。

双向绑定

典型的绑定是利用响应式框架RxSwift来实现的(不是一定)。但通过学习RxSwift提供的Demo,发现RxSwift本身的知识点(如各种操作符的组合)以及响应式编程的思想的灵活运用还是有陡峭的学习曲线的。

响应式编程解决的重要的一个问题,是State的同步问题。就目前来看,该问题在我们开发的应用中并没有十分突出。而我们基于非声明式UI利用响应式编程又会导致绑定等的胶水代码过多。

结论

综上,利用MVC开始应用开发,在适当的时候引入适当的响应式编程可能才是最佳选择。

appium 入门参考

前言

游戏发行业务中,对游戏进行测试是保证游戏质量重要的一环。传统人工测试的方法费时费力、容易出错,自动化测试才是更好的解决方案。appium则是自动化测试的优秀方案,新手可以通过官网的开始文档快速入门。
本文定位为:新手阅读完开始文档的第二篇文档。重点介绍了appium方案与其他方案的优缺点对比,以及在环境配置原生控件查找图片识别方面的关键知识和常用问题解决方法。
本文适合只有单一iOS开发或者自动化测试背景的人员,阅读完开始文档,作为辅助文档阅读;不适合作为新手第一篇文档,或者已同时熟练掌握iOS开发、appium自动化测试的人员阅读。

iOS UI测试方案对比

iOS的UI测试的技术方案首先有两个大的方向:原生方向以及跨平台的方向。简单表格对比如下:

方向 框架 编程语言 原生控件查找 图片识别 更新维护 开发体验
原生 XCTest Objective-C、Swift 最优 没有 最优 最优
跨平台 appium Python、JS等 一般
跨平台 airtest Python 一般(iOS)