本文涉及点,项目实践地址(含项目演示动画)JiandanIOS
本文涉及三个层面
程序员的思维模式
- 面向过程——>面向对象(此文略去不说)
- 指令式编程—>函数响应式编程
软件架构
- MVC——>MVVM
- 测试
- 传统测试框架(XCTest等)——>行为驱动开发(BDD)
一、关于指令式编程和响应式编程
举这么两个例子
(1)a=1;b=2; c=a+b; 此时c=3,又a=2
- 指令时编程:那么依然c=3;
- 响应式编程:现在c=4,体现了数据变化的实时性,自动性;
(2)去报社获取报纸
- 指令时编程:你想看报纸,必须每次去报社购买
- 响应式编程: 你订阅了报纸,定时配送到家(是不是更方便)
为什么要采用响应式编程
- 响应式编程可以加深你代码抽象的程度,让你可以更专注于定义与事件相互依赖的业务逻辑,而不是把大量精力放在实现细节上,同时,使用响应式编程还能让你的代码变得更加简洁。
- 在MV*软件架构中,响应式编程允许将相关模型的变化自动反映到视图上,反之亦然(取自百度百科)。
- UI事件的自动性,实时性,高级版的观察者模式。
- 当今的Apps都含有丰富的实时事件来保证一个高效的用户体验,我们就需要采用一个合适的工具来处理,那么响应式编程就正好是我们想要的答案。
二、关于指令式编程和函数式编程
两者的差异
- 指令时编程:设计一个复杂的执行过程,强调执行过程
- 函数式编程: 利用若干简单的执行单元让计算结果不断渐进,逐层推导复杂的运算,强调执行的结果
为什么要采用函数式编程
结合响应式编程,你会拥有一些令人惊艳的函数去结合、创建和过滤任何一组数据流。 这就是”函数式编程”的魔力所在。一个数据流可以作为另一个数据流的输入,甚至多个数据流也可以作为另一个数据流的输入。你可以合并两个数据流,也可以过滤一个数据流得到另一个只包含你感兴趣的事件的数据流,还可以映射一个数据流的值到一个新的数据流里。
三、关于MVC和MVVM
App开发为什么要抛弃MVC软件架构
- Controller 很变得比较庞大和复杂(几乎所有的复杂的代码都在Controller中)。
- 由于 Controller 承担了 Model 和 View 之间的桥梁作用,所以 Controller 常常与对应的 View 和 Model 的耦合度非常高。
- controller的高耦合度,导致了单元测试非常不容易
- 相同的逻辑代码的重用性,也变得很低
为什么要采用MVVM软件架构
- 将controller中的视图代码和逻辑代码分离,引用ViewModel层负责逻辑部分
- controller变得更加简单,只有视图代码
- ViewModel层只含有逻辑代码,没有相关视图。使得单元测试在ViewModel层进行,逻辑重用性也更高(参考唐巧技术博客)
四、关于测试代码的形式
为什么抛弃传统测试框架
XCTAssertEqual(topNumber, 4.6, @"Top value of VVStack should be the last num pushed into it");
XCTest的问题:在书写性和可读性上都不太好。在测试用例太多的时候,由于各个测试方法是割裂的,想在某个很长的测试文件中找到特定的某个测试并搞明白这个测试是在做什么并不是很容易的事情。所有的测试都是由断言完成的,而很多时候断言的意义并不是特别的明确,对于项目交付或者新的开发人员加入时,往往要花上很大成本来进行理解或者转换。另外,每一个测试的描述都被写在断言之后,夹杂在代码之中,难以寻找。使用XCTest测试另外一个问题是难以进行mock或者stub,而这在测试中是非常重要的一部分
行为驱动开发的优势
describe(@"Team", ^{
context(@"when newly created", ^{
it(@"should have a name", ^{
id team = [Team team];
[[team.name should] equal:@"Black Hawks"];
});
it(@"should have 11 players", ^{
id team = [Team team];
[[[team should] have:11] players];
});
});
});
我们很容易根据上下文将其提取为Given..When..Then的三段式自然语言
Given a team, when newly created, it should have a name, and should have 11 players
行为驱动开发(BDD)正是为了解决上述问题而生的,作为第二代敏捷方法,BDD提倡的是通过将测试语句转换为类似自然语言的描述,开发人员可以使用更符合大众语言的习惯来书写测试,这样不论在项目交接/交付,或者之后自己修改时,都可以顺利很多。如果说作为开发者的我们日常工作是写代码,那么BDD其实就是在讲故事。一个典型的BDD的测试用例包活完整的三段式上下文,测试大多可以翻译为Given..When..Then的格式,读起来轻松惬意。(此部分,摘自Onevcat博客)
五、iOS项目总结和实践(Android类似)
总结
ReactiveCocoa+MVVM+kiwi
iOS项目实践遇到问题
- 要实现MVVM模式,需要把Controller里的逻辑代码剥离到ViewMoldel层,其中的交互的部分的处理成为难点
- 先要达成这样的目标: 把ViewModel层作为黑箱处理,controller提供条件,然后从ViewModel层,直接获得结果(这也是函数式编程重结果,不注重过程的体现)
解决方案:RAC 的信号机制很容易将某一个 Model 变量的变化与界面关联,所以非常容易应用 Model-View-ViewModel 框架。通过引入 ViewModel 层,然后用 RAC 将 ViewModel 与 View 关联,View 层的变化可以直接响应 ViewModel 层的变化,这使得 Controller 变得更加简单,由于 View 不再与 Model 绑定,也增加了 View 的可重用性。
- MVVM软件架构得已方便的实现,现在逻辑层被剥离,我们就可以对ViewModel层进行充分的单元测试了
- 整个项目开发流程也就打通了
本文涉及点,项目实践地址(含项目演示动画)JiandanIOS