VIPER模式介绍
                            
                            
                            一、概述 
VIPER模式的理念不屬于MV(X)系類,其理念來自于建筑設計。
建筑領域流行這樣一句話,“我們雖然在營造建筑,但建筑也會重新塑造我們”。正如所有開發者最終領悟到的,這句話同樣適用于構建軟件。
編寫代碼中至關重要的是,需要使每一部分容易被識別,賦有一個特定而明顯的目的,并與其他部分在邏輯關系中完美契合。這就是我們所說的軟件架構。好的架構不僅讓一個產品成功投入使用,還可以讓產品具有可維護性,并讓人不斷頭腦清醒的對它進行維護!
二、什么是 VIPER?
測試永遠不是構建 iOS 應用的主要部分。當我們著手改善我們的測試實踐時,我們發現給 iOS 應用寫測試代碼非常困難。因此如果想要設法改變測試的現狀,我們首先需要一個更好的方式來架構應用,我們稱之為 VIPER。 ? VIPER 是一個創建 iOS 應用簡明構架的程序。VIPER 是視圖 (View),交互器 (Interactor),展示器 (Presenter),實體 (Entity) 以及路由 (Routing) 的首字母縮寫。簡明架構將一個應用程序的邏輯結構劃分為不同的責任層。這使得它更容易隔離依賴項 (如數據庫),也更容易測試各層間的邊界處的交互:
VIPER 的不同層提供了明確的程序邏輯以及導航控制代碼來應對這個挑戰,利用VIPER ,我們的視圖控制器可以簡潔高效,意義明確地控制視圖。你也會發現視圖控制器中代碼和所有的其他類很容易理解,容易測試,理所當然也更易維護。
三、基于用例的應用設計
應用通常是一些用戶用例的集合。用例也被稱為驗收標準,或行為集,它們用來描述應用的用途。清單可以根據時間,類型以及名字排序,這就是一個用例。用例是應用程序中用來負責業務邏輯的一層,應獨立于用戶界面的實現,同時要足夠小,并且有良好的定義。決定如何將一個復雜的應用分解成較小的用例非常具有挑戰性,并且需要長期實踐,但這對于縮小你解決的問題時所要面臨的范圍及完成的每個類的所要涉及的內容來說,是很有幫助的。 ? 利用 VIPER 建立一個應用需要實施一組套件來滿足所有的用例,應用邏輯是實現用例的主要組成部分,但卻不是唯一。用例也會影響用戶界面。另一個重要的方面,是要考慮用例如何與其他應用程序的核心組件相互配合,例如網絡和數據持久化。組件就好比用例的插件,VIPER 則用來描述這些組件的作用是什么,如何進行交互。 四、VIPER 的主要部分 VIPER 的主要部分是: ? 視圖:根據展示器的要求顯示界面,并將用戶輸入反饋給展示器。 交互器:包含由用例指定的業務邏輯。 展示器:包含為顯示(從交互器接受的內容)做的準備工作的相關視圖邏輯,并對用戶輸入進行反饋(從交互器獲取新數據)。 實體:包含交互器要使用的基本模型對象。 路由:包含用來描述屏幕顯示和顯示順序的導航邏輯。 ? 這種分隔形式同樣遵循單一責任原則。交互器負責業務分析的部分,展示器代表交互設計師,而視圖相當于視覺設計師。 ? 以下則是不同組件的相關圖解,并展示了他們之間是如何關聯的:
? ? ? ? 以下是我自己的理解:
五、各部分詳解
1.交互器
交互器在應用中代表著一個獨立的用例。它具有業務邏輯以操縱模型對象(實體)執行特定的任務。交互器中的工作應當獨立與任何用戶界面,同樣的交互器可以同時運用于 iOS 應用或者 OS X 應用中。 ? 由于交互器是一個 PONSO (Plain Old NSObject,普通的 NSObject),它主要包含了邏輯,因此很容易使用 TDD(測試驅動開發) 進行開發。 不要詫異于你的實體僅僅是數據結構,任何依賴于應用的邏輯都應該放到交互器中。 2.實體
實體是被交互器操作的模型對象,并且它們只被交互器所操作。交互器永遠不會傳輸實體至表現層 (比如說展示器)。 ? 實體也應該是 PONSOs。如果你使用 Core Data,最好是將托管對象保持在你的數據層之后,交互器不應與 NSManageObjects 協同工作。 3.展示器
展示器是一個主要包含了驅動用戶界面的邏輯的 PONSO,它總是知道何時呈現用戶界面?;谄涫占瘉碜杂脩艚换サ妮斎牍δ?#xff0c;它可以在合適的時候更新用戶界面并向交互器發送請求。 展示器還會從交互器接收結果并將結果轉換成能夠在視圖中有效顯示的形式。 實體永遠不會由交互器傳輸給展示器,取而代之,那些無行為的簡單數據結構會從交互器傳輸到展示器那里。這就防止了那些“真正的工作”在展示器那里進行,展示器只能負責準備那些在視圖里顯示的數據。 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
                        
                        
                        VIPER模式的理念不屬于MV(X)系類,其理念來自于建筑設計。
建筑領域流行這樣一句話,“我們雖然在營造建筑,但建筑也會重新塑造我們”。正如所有開發者最終領悟到的,這句話同樣適用于構建軟件。
編寫代碼中至關重要的是,需要使每一部分容易被識別,賦有一個特定而明顯的目的,并與其他部分在邏輯關系中完美契合。這就是我們所說的軟件架構。好的架構不僅讓一個產品成功投入使用,還可以讓產品具有可維護性,并讓人不斷頭腦清醒的對它進行維護!
二、什么是 VIPER?
測試永遠不是構建 iOS 應用的主要部分。當我們著手改善我們的測試實踐時,我們發現給 iOS 應用寫測試代碼非常困難。因此如果想要設法改變測試的現狀,我們首先需要一個更好的方式來架構應用,我們稱之為 VIPER。 ? VIPER 是一個創建 iOS 應用簡明構架的程序。VIPER 是視圖 (View),交互器 (Interactor),展示器 (Presenter),實體 (Entity) 以及路由 (Routing) 的首字母縮寫。簡明架構將一個應用程序的邏輯結構劃分為不同的責任層。這使得它更容易隔離依賴項 (如數據庫),也更容易測試各層間的邊界處的交互:
VIPER 的不同層提供了明確的程序邏輯以及導航控制代碼來應對這個挑戰,利用VIPER ,我們的視圖控制器可以簡潔高效,意義明確地控制視圖。你也會發現視圖控制器中代碼和所有的其他類很容易理解,容易測試,理所當然也更易維護。
三、基于用例的應用設計
應用通常是一些用戶用例的集合。用例也被稱為驗收標準,或行為集,它們用來描述應用的用途。清單可以根據時間,類型以及名字排序,這就是一個用例。用例是應用程序中用來負責業務邏輯的一層,應獨立于用戶界面的實現,同時要足夠小,并且有良好的定義。決定如何將一個復雜的應用分解成較小的用例非常具有挑戰性,并且需要長期實踐,但這對于縮小你解決的問題時所要面臨的范圍及完成的每個類的所要涉及的內容來說,是很有幫助的。 ? 利用 VIPER 建立一個應用需要實施一組套件來滿足所有的用例,應用邏輯是實現用例的主要組成部分,但卻不是唯一。用例也會影響用戶界面。另一個重要的方面,是要考慮用例如何與其他應用程序的核心組件相互配合,例如網絡和數據持久化。組件就好比用例的插件,VIPER 則用來描述這些組件的作用是什么,如何進行交互。 四、VIPER 的主要部分 VIPER 的主要部分是: ? 視圖:根據展示器的要求顯示界面,并將用戶輸入反饋給展示器。 交互器:包含由用例指定的業務邏輯。 展示器:包含為顯示(從交互器接受的內容)做的準備工作的相關視圖邏輯,并對用戶輸入進行反饋(從交互器獲取新數據)。 實體:包含交互器要使用的基本模型對象。 路由:包含用來描述屏幕顯示和顯示順序的導航邏輯。 ? 這種分隔形式同樣遵循單一責任原則。交互器負責業務分析的部分,展示器代表交互設計師,而視圖相當于視覺設計師。 ? 以下則是不同組件的相關圖解,并展示了他們之間是如何關聯的:
? ? ? ? 以下是我自己的理解:
五、各部分詳解
1.交互器
交互器在應用中代表著一個獨立的用例。它具有業務邏輯以操縱模型對象(實體)執行特定的任務。交互器中的工作應當獨立與任何用戶界面,同樣的交互器可以同時運用于 iOS 應用或者 OS X 應用中。 ? 由于交互器是一個 PONSO (Plain Old NSObject,普通的 NSObject),它主要包含了邏輯,因此很容易使用 TDD(測試驅動開發) 進行開發。 不要詫異于你的實體僅僅是數據結構,任何依賴于應用的邏輯都應該放到交互器中。 2.實體
實體是被交互器操作的模型對象,并且它們只被交互器所操作。交互器永遠不會傳輸實體至表現層 (比如說展示器)。 ? 實體也應該是 PONSOs。如果你使用 Core Data,最好是將托管對象保持在你的數據層之后,交互器不應與 NSManageObjects 協同工作。 3.展示器
展示器是一個主要包含了驅動用戶界面的邏輯的 PONSO,它總是知道何時呈現用戶界面?;谄涫占瘉碜杂脩艚换サ妮斎牍δ?#xff0c;它可以在合適的時候更新用戶界面并向交互器發送請求。 展示器還會從交互器接收結果并將結果轉換成能夠在視圖中有效顯示的形式。 實體永遠不會由交互器傳輸給展示器,取而代之,那些無行為的簡單數據結構會從交互器傳輸到展示器那里。這就防止了那些“真正的工作”在展示器那里進行,展示器只能負責準備那些在視圖里顯示的數據。 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
總結
 
                            
                        - 上一篇: iOS应用图片命名规则
- 下一篇: 计算机硬件在线修复,计算机硬件维修
