VIPER模式介绍

一、概述

VIPER模式的理念不属于MV(X)系类,其理念来自于建筑设计。

建筑领域流行这样一句话,“我们虽然在营造建筑,但建筑也会重新塑造我们”。正如所有开发者最终领悟到的,这句话同样适用于构建软件。

编写代码中至关重要的是,需要使每一部分容易被识别,赋有一个特定而明显的目的,并与其他部分在逻辑关系中完美契合。这就是我们所说的软件架构。好的架构不仅让一个产品成功投入使用,还可以让产品具有可维护性,并让人不断头脑清醒的对它进行维护!

二、什么是 VIPER?

测试永远不是构建 iOS 应用的主要部分。当我们着手改善我们的测试实践时,我们发现给 iOS 应用写测试代码非常困难。因此如果想要设法改变测试的现状,我们首先需要一个更好的方式来架构应用,我们称之为 VIPER。
 
VIPER 是一个创建 iOS 应用简明构架的程序。VIPER 是视图 (View),交互器 (Interactor),展示器 (Presenter),实体 (Entity) 以及路由 (Routing) 的首字母缩写。简明架构将一个应用程序的逻辑结构划分为不同的责任层。这使得它更容易隔离依赖项 (如数据库),也更容易测试各层间的边界处的交互:

VIPER 的不同层提供了明确的程序逻辑以及导航控制代码来应对这个挑战,利用VIPER ,我们的视图控制器可以简洁高效,意义明确地控制视图。你也会发现视图控制器中代码和所有的其他类很容易理解,容易测试,理所当然也更易维护。

三、基于用例的应用设计

应用通常是一些用户用例的集合。用例也被称为验收标准,或行为集,它们用来描述应用的用途。清单可以根据时间,类型以及名字排序,这就是一个用例。用例是应用程序中用来负责业务逻辑的一层,应独立于用户界面的实现,同时要足够小,并且有良好的定义。决定如何将一个复杂的应用分解成较小的用例非常具有挑战性,并且需要长期实践,但这对于缩小你解决的问题时所要面临的范围及完成的每个类的所要涉及的内容来说,是很有帮助的。
 
利用 VIPER 建立一个应用需要实施一组套件来满足所有的用例,应用逻辑是实现用例的主要组成部分,但却不是唯一。用例也会影响用户界面。另一个重要的方面,是要考虑用例如何与其他应用程序的核心组件相互配合,例如网络和数据持久化。组件就好比用例的插件,VIPER 则用来描述这些组件的作用是什么,如何进行交互。
四、VIPER 的主要部分
VIPER 的主要部分是:
 
视图:根据展示器的要求显示界面,并将用户输入反馈给展示器。
交互器:包含由用例指定的业务逻辑。
展示器:包含为显示(从交互器接受的内容)做的准备工作的相关视图逻辑,并对用户输入进行反馈(从交互器获取新数据)。
实体:包含交互器要使用的基本模型对象。
路由:包含用来描述屏幕显示和显示顺序的导航逻辑。
 
这种分隔形式同样遵循单一责任原则。交互器负责业务分析的部分,展示器代表交互设计师,而视图相当于视觉设计师。
 
以下则是不同组件的相关图解,并展示了他们之间是如何关联的:

VIPER模式 - 梁敬承 - 梁敬承技术笔记
        以下是我自己的理解:
VIPER模式介绍 - 梁敬承 - 梁敬承技术笔记

五、各部分详解

1.交互器

交互器在应用中代表着一个独立的用例。它具有业务逻辑以操纵模型对象(实体)执行特定的任务。交互器中的工作应当独立与任何用户界面,同样的交互器可以同时运用于 iOS 应用或者 OS X 应用中。
 
由于交互器是一个 PONSO (Plain Old NSObject,普通的 NSObject),它主要包含了逻辑,因此很容易使用 TDD(测试驱动开发) 进行开发。
不要诧异于你的实体仅仅是数据结构,任何依赖于应用的逻辑都应该放到交互器中。
2.实体

实体是被交互器操作的模型对象,并且它们只被交互器所操作。交互器永远不会传输实体至表现层 (比如说展示器)。
 
实体也应该是 PONSOs。如果你使用 Core Data,最好是将托管对象保持在你的数据层之后,交互器不应与 NSManageObjects 协同工作。
3.展示器

展示器是一个主要包含了驱动用户界面的逻辑的 PONSO,它总是知道何时呈现用户界面。基于其收集来自用户交互的输入功能,它可以在合适的时候更新用户界面并向交互器发送请求。
展示器还会从交互器接收结果并将结果转换成能够在视图中有效显示的形式。
实体永远不会由交互器传输给展示器,取而代之,那些无行为的简单数据结构会从交互器传输到展示器那里。这就防止了那些“真正的工作”在展示器那里进行,展示器只能负责准备那些在视图里显示的数据。
4.视图

视图一般是被动的,它通常等待展示器下发需要显示的内容,而不会向其索取数据。视图(例如登录界面的登录视图控件)所定义的方法应该允许展示器在高度抽象的层次与之交流。展示器通过内容进行表达,而不关心那些内容所显示的样子。展示器不知道 UILabel,UIButton 等的存在,它只知道其中包含的内容以及何时需要显示。内容如何被显示是由视图来进行控制的。
 
视图是一个抽象的接口 (Interface),在 Objective-C 中使用协议被定义。一个 UIViewController 或者它的一个子类会实现视图协议。

视图和视图控制器同样会操纵用户界面和相关输入。因为通常来说视图控制器是最容易处理这些输入和执行某些操作的地方,所以也就不难理解为什么视图控制器总是这么大了。为了使视图控制器保持苗条,我们需要使它们在用户进行相关操作的时候可以有途径来通知相关部分。视图控制器不应当根据这些行为进行相关决定,但是它应当将发生的事件传递到能够做决定的部分。

视图和展示器之间边界处是一个使用 ReactiveCocoa 的好地方。在这个示例中,视图控制器可以返回一个代表按钮操作的信号。这将允许展示器在不打破职责分离的前提下轻松地对那些信号进行响应。
5.路由

屏幕间的路径会在交互设计师创建的线框 (wireframes) 里进行定义。在 VIPER 中,路由是由两个部分来负责的:展示器和线框。一个线框对象包括 UIWindow,UINavigationController,UIViewController 等部分,它负责创建视图/视图控制器并将其装配到窗口中。
 
由于展示器包含了响应用户输入的逻辑,因此它就拥有知晓何时导航至另一个屏幕以及具体是哪一个屏幕的能力。而同时,线框知道如何进行导航。在两者结合起来的情况下,展示器可以使用线框来进行实现导航功能,它们两者一起描述了从一个屏幕至另一个屏幕的路由过程。
六、利用 VIPER 组织应用组件

iOS 应用的构架需要考虑到 UIKit 和 Cocoa Touch 是建立应用的主要工具。架构需要和应用的所有组件都能够和平相处,但又需要为如何使用框架的某些部分以及它们应该在什么位置提供一些指导和建议。
 
iOS 应用程序的主力是 UIViewController,我们不难想象找一个竞争者来取代 MVC 就可以避免大量使用视图控制器。但是视图控制器现在是这个平台的核心:它们处理设备方向的变化,回应用户的输入,和类似导航控制器之类的系统系统组件集成得很好,而现在在 iOS 7 中又能实现自定义屏幕之间的转换,功能实在是太强大了。
 
有了 VIPER,视图控制器便就能真正的做它本来应该做的事情了,那就是控制视图。 

应用在接入网络以后会变得更有用处,但是究竟该在什么时候联网呢?又由谁来负责启动网络连接呢?典型的情况下,由交互器来启动网络连接操作的项目,但是它不会直接处理网络代码。它会寻找一个像是 network manager 或者 API client 这样的依赖项。交互器可能聚合来自多个源的数据来提供所需的信息,从而完成一个用例。最终,就由展示器来采集交互器反馈的数据,然后组织并进行展示。
 
数据存储模块负责提供实体给交互器。因为交互器要完成业务逻辑,因此它需要从数据存储中获取实体并操纵它们,然后将更新后的实体再放回数据存储中。数据存储管理实体的持久化,而实体应该对数据库全然不知,正因如此,实体并不知道如何对自己进行持久化。
 
交互器同样不需要知道如何将实体持久化,有时交互器更希望使用一个 data manager 来使其与数据存储的交互变得容易。Data manager 可以处理更多的针对存储的操作,比如创建获取请求,构建查询等等。这就使交互器能够将更多的注意力放在应用逻辑上,而不必再了解实体是如何被聚集或持久化的。
当使用 TDD 来开发一个交互器时,是可以用一个测试用的模拟存储来代替生产环境的数据存储的。避免与远程服务器通讯(网络服务)以及避免读取磁盘(数据库)可以加快你测试的速度并加强其可重复性。
 
将数据存储保持为一个界限清晰的特定层的原因之一是,这可以让你延迟选择一个特定的持久化技术。如果你的数据存储是一个独立的类,那你就可以使用一个基础的持久化策略来开始你的应用,然后等到有意义的时候升级至 SQLite 或者 Core Data。而因为数据存储层的存在,你的应用代码库中就不需要改变任何东西。
 
在 iOS 的项目中使用 Core Data 经常比构架本身还容易引起更多争议。然而,利用 VIPER 来使用 Core Data 将给你带来使用 Core Data 的前所未有的良好体验。在持久化数据的工具层面上,Core Data 可以保持快速存取和低内存占用方面,简直是个神器。但是有个很恼人的地方,它会像触须一样把 NSManagedObjectContext 延伸至你所有的应用实现文件中,特别是那些它们不该待的地方。VIPER 可以使 Core Data 待在正确的地方:数据存储层。
七、利用 VIPER 实现测试驱动的开发模式

VIPER 的出现激发了一个关注点的分离,这使得采用 TDD 变得更加简便。交互器包含独立与任何 UI 的纯粹逻辑,这使测试驱动开发更加简单。同时展示器包含用来为显示准备数据的逻辑,并且它也独立于任何一个 UIKit 部件。对于这个逻辑的开发也很容易用测试来驱动。
 
我们更倾向于先从交互器下手。用户界面里所有部分都服务于用例,而通过采用 TDD 来测试驱动交互器的 API 可以让你对用户界面和用例之间的关系有一个更好的了解。
既然我们已经知道了交互器的 API 长什么样,接下来就是开发展示器。一旦展示器接收到了交互器传来的数据,我们就需要测试看看我们是否适当的将数据进行格式化,以便接下来在用户界面中正确的显示它。
接下来我们可以开发视图功能了。
首先建立交互器是一种符合 TDD 的自然规律。如果你首先开发交互器,紧接着是展示器,你就可以首先建立一个位于这些层的套件测试,并且为实现这是实例奠定基础。由于你不需要为了测试它们而去与用户界面进行交互,所以这些类可以进行快速迭代。在你需要开发视图的时候,你会有一个可以工作并测试过的逻辑和表现层来与其进行连接。在快要完成对视图的开发时,你会发现第一次运行程序时所有部件都运行良好,因为你所有已通过的测试已经告诉你它可以工作。

转自:http://www.cocoachina.com/ios/20140703/9016.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/499951.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

强制消除Xcode警告的方法

比如我已经知道某行会报警告了,但是代码有这么写的道理,实在不想看到警告,可以用下面这个宏把这几行代码包住,就可以消除警告了。#pragma clang diagnostic push#pragma clang diagnostic ignored "-Wunused-variable"/…

springMVC 源码级别总结原理,DispatcherServlet核心方法

前言 springMVC自我总结 本次maven: <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc --><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>4.3.…

SQLite3中的数据类型

一、概述 大多数的数据库引擎&#xff08;到现在据我们所知的除了sqlite的每个sql数据库引擎&#xff09;都使用静态的、刚性的类型&#xff0c;使用静态类型&#xff0c;数据的类型就由它的容器决定&#xff0c;这个容器是这个指被存放的特定列。 Sqlite使用一个更一般的动态类…

关于iOS7里的JavaScriptCore framework

在iOS7沸沸扬扬的扁平化论战之外&#xff0c;WWDC 2013还是公布了很多让开发者小兴奋的点&#xff0c;其中包括多任务加强支持background fetch和transfer&#xff0c;近场通信的AirDrop和p2p&#xff0c;以及游戏控制器和游戏中心的加强&#xff1b;当然还包括了让web开发同学…

深入浅出Fetch API

多年来&#xff0c;XMLHttpRequest一直是web开发者的亲密助手。无论是直接的&#xff0c;还是间接的&#xff0c; 当我们谈及Ajax技术的时候&#xff0c;通常意思就是基于XMLHttpRequest的Ajax&#xff0c;它是一种能够有效改进页面通信的技术。 Ajax的兴起是由于Google的Gmail…

[设计模式] ------ 简单工厂模式

简单工厂模式 不同类型下创建对应的不同的对象&#xff0c;得到不同的结果&#xff0c;就叫简单生产模式 比如 定义一个接口&#xff0c;叫A&#xff0c;里面有方法a&#xff0c;返回int类型 类B1实现A接口&#xff0c;也实现a方法&#xff0c;里面做的是加法运算 类B2实现…

第19章总结

一.Java绘图类 1.Graphics类 Graphics类是所有图形上下文的抽象基类&#xff0c;它允许应用程序在组件以及闭屏图像上进行绘制。Graphics类封装了Java支持的基本绘图操作所需的状态信息&#xff0c;主要包括颜色、字体、画笔、文本、图像等。 2.Graphics2D类 Graphics2…

RSA公钥文件(PEM)解析

公钥语法为&#xff1a; RSAPublicKey :: SEQUENCE { modulus INTEGER, //RSA合数模n publicExponent INTEGER //RSA公开幂e } 说明&#xff1a; 1.此语法中的modulus和publicExponent&#xff0c;提取自对应私钥中的同名域值。 2.PKCS1和PKCS8的公钥文件是一样的&#xff…

RSA私钥文件(PEM-PKCS#1)解析

在PKCS#1 RSA算法标准中定义RSA私钥语法 RSAPrivateKey :: SEQUENCE { version Version, //版本 modulus INTEGER, // RSA合数模 n publicExponent INTEGER, //RSA公开幂 e privateExponent INTEGER, //RSA私有幂 d prime1 INTEGER, //n的素数因子p prime2 INTEGER, //n的…

[分布式] ------ 全局唯一id生成之雪花算法(Twitter_Snowflake)

雪花算法&#xff08;Twitter_Snowflake&#xff09; 我们知道&#xff0c;分布式全局唯一id的生成&#xff0c;一般是以下几种&#xff1a; 基于雪花算法生成基于数据库基于redis基于zookeeper 本文说下雪花算法&#xff0c;后面附源码以及测试代码。 如下图&#xff1a; …

非对称加解密交互故事

1.鲍勃有两把钥匙&#xff0c;一把是公钥&#xff0c;另一把是私钥。 2.鲍勃把公钥送给他的朋友们—-帕蒂、道格、苏珊—-每人一把。 3.苏珊要给鲍勃写一封保密的信。她写完后用鲍勃的公钥加密&#xff0c;就可以达到保密的效果 4.鲍勃收信后&#xff0c;用私钥解密&#xff0…

Sqlite3中replace语句用法详解

在本例中使用如下数据库表&#xff1a; &#xff08;图 1&#xff09; 该表的表名为student&#xff0c; 存储学生信息。 所有字段的数据类型都是TEXT 。 其中id和name作为复合主键。 email字段加上了唯一约束。建表语句如下&#xff1a; CREATE TABLE IF NOT EXISTS student …

[分布式一致性协议] ------ raft协议的解释与理解

前言 在分布式系统中&#xff0c;为了保证容错性&#xff0c;一般会维护多个副本集群&#xff0c;提高系统的高可用&#xff0c;但与之带来的问题就是多个副本的一致性&#xff08;consensus&#xff09;问题。 我们认为&#xff0c;对于一个具有一致性的的集群中&#xff0c;…

利用.dSYM和.app文件准确定位Crash位置

当发布到iPhone上的应用程序Crash之后&#xff0c;iPhone会自动生成一个Crash Log&#xff08;*.crash&#xff09;&#xff0c;这个文件包含了一些有用的调试信息&#xff0c;但对于堆栈&#xff0c;它只记录的函数地址&#xff0c;而无法显示函数名。函数名保存在一个叫dSYM的…

MVPVM模式介绍

一、概述MVPVM即&#xff1a;Model-View-Presenter-ViewModel。此模式是MVVM和MVP模式的结合体。但是交互模式发生了比较大的变化。MVVM参考本博客文章&#xff1a;iOS-MVVM-模式介绍MVP参考本博客文章&#xff1a;MVP模式介绍 二、原理&#xff1a;Presenter同时持有View、Mod…

分组密码的工作模式

一、理论基础1.概述密码学中&#xff0c;块密码的工作模式允许使用同一个块密码密钥对多于一块的数据进行加密&#xff0c;并保证其安全性。块密码自身只能加密长度等于密码块长度的单块数据&#xff0c;若要加密变长数据&#xff0c;则数据必须先被划分为一些单独的密码块。通…

PBOC3.0中使用的国密SM2算法

一、知识准备 PBOC3.0规范就是《中国金融集成电路&#xff08;IC&#xff09;卡规范》3.0版本。SM2是国密局推出的一种他们自己说具有自主知识产权的非对称商用密码算法。本身是基于ECC椭圆曲线算法的&#xff0c;所以要讲SM2, 先要弄懂ECC。 完全理解ECC算法需要一定的数学功底…

Markdown入门

Markdown 是一种轻量级的「标记语言」&#xff0c;它的优点很多&#xff0c;目前也被越来越多的写作爱好者&#xff0c;撰稿者广泛使用。看到这里请不要被「标记」、「语言」所迷惑&#xff0c;Markdown 的语法十分简单。常用的标记符号也不超过十个&#xff0c;这种相对于更为…

mysql数据库支持emoji表情的详解

mysql存储emoji表情的时候&#xff0c;就会报错&#xff0c;如下&#xff1a; Error updating database. Cause: java.sql.SQLException: Incorrect string value: ‘\xF0\x9F\x98\x8A\xF0\x9F…’ for column ‘这是我表中的字段’ at row 1 初步定位是我的数据库是utf8编码…

编程规范:长函数的思考

在工作&#xff0c;我们应该都不想看到非常的长函数。对于一个运行5年左右的项目&#xff0c;极有可能出现这种情况。由于长函数的长、if/else嵌套&#xff0c;导致代码的可读性非常差&#xff0c;这对于项目的维护和开发带来了极大的困难。所以我们应该避免写长函数&#xff0…