當前位置:
首頁 > 最新 > 技術相對論之軟體架構

技術相對論之軟體架構

文 | 歐陽鋒

有同學問我,你是怎樣學習編程的呢?為了回答你的這個問題,今天,我們一起來做一件非常有意思的事情。我們以MVC架構為基,從服務端編程開始,依次類推iOS、Android,並最終完成登錄、註冊功能。


正文開始之前,我們先來簡單了解一下MVC架構。

MVC全稱是Model-View-Controller,是上個世紀80年底Xerox PARC為其編程語言SmallTalk發明的一直軟體設計模式。我們可以用一張圖來表示MVC架構模型:

MVC的核心思想是希望通過控制層管理視圖呈現,從將邏輯層和視圖層進行分離。

服務端編程其實就是MVC的最佳實踐,理解了MVC架構之後,我們馬上開始服務端編程。


服務端編程也叫後端編程,主要用於為前端提供數據源以及完成必要的業務邏輯處理。

這個部分我們使用Java語言開發,MVC框架使用最常用的 Spring MVC,完整配置請參考下方表格:

為了簡化資料庫的訪問,我們再增加一個輕量級的資料庫訪問框架 MyBatis。

這裡假設你已經正確安裝了MySQL資料庫和Tomcat伺服器,如果你對具體的安裝步驟有疑問,請在文章下方評論告訴我。

在開始編程之前,我們需要完成以下準備工作:

第一步:創建資料庫d_user以及用戶表t_user用於保存用戶數據

第二步:使用IntelliJ IDE創建一個Gradle依賴工程

最後一個步驟選擇工作目錄確定即可。

第三步:在build.gradle腳本文件中添加Spring MVC以及MyBatis依賴

第四步:關聯本地Tomcat伺服器

a)編輯運行設置,選擇本地Tomcat伺服器

b)選擇以war包的方式部署到Tomcat

c)在瀏覽器中輸入http://localhost:8080測試工作是否正常

如果看到下面這個界面,證明一切工作正常

第五步:配置Spring MVC

備註:參考官方文檔 Web on Servlet Stack

a)在webapp目錄下面生成WEB-INF/web.xml配置文件

選擇菜單File->Project Structure進入如下界面:

在彈出的界面中設置路徑為…/webapp/WEB-INF即可。

b)在web.xml文件中添加如下配置信息

上面這部分配置主要是使用Spring MVC的DispatcherServlet完成請求的攔截分發。配置文件中引用了另外一個配置文件app-context.xml,這個配置文件主要是完成Spring的依賴注入。

c)在app-context.xml配置文件中添加如下信息

d)添加jackson依賴用於Spring實現Json自動解析

PS:不得不承認,Java後端開發的xml文件配置實在是一件繁瑣至極的事情,儘管我們只需要配置一次。為了簡化配置,Spring官方推出了一個重磅產品 Spring Boot。不過,這不是本文討論的重點,感興趣的同學請自行了解。

雖然我們已經完成了Spring的配置,但MyBatis的配置工作才剛剛開始。

配置MyBatis

為了簡化Spring中MyBatis的配置,我們再增加一個MyBatis官方的提供的 mybatis-spring 庫。

備註:參考官方文檔 mybatis-spring

a)在spring配置文件app-context.xml配置文件中添加如下bean配置:

b)指定數據源

b1) 添加Spring JDBC與MySQL Connector依賴

注意:因為部分依賴包只存在於JCenter,需要在build.gradle腳本中添加jcenter maven源

b2)在app-context.xml文件中添加如下配置:

b3)在類路徑目錄下創建db.properties文件指定MySQL資料庫信息

至此,所有的配置工作終於完成了,接下來進入最重要的編碼階段。

由於控制層需要依賴模型層的代碼,因此,我們按照從下往上的原則進行編碼。

a)先完成資料庫的訪問部分(DAO)

結合MyBatis,這個部分的工作很簡單,甚至DAO的實現都不需要手動編碼。

為了實現DAO的依賴注入,我們在app-context.xml配置文件中添加如下配置:

b)Service層編碼(也叫Domain層)

Service部分是控制層直接調用的介面,從抽象思維來說,也應該使用面向介面的方式編碼。這裡為了簡化,Service部分我們直接使用一個類來實現了。

c)控制層編碼

想必大家應該已經注意到了,控制層部分請求類型我使用了GET,這是為了方便在瀏覽器上面測試。測試通過後,要修改為POST請求類型。

以上代碼,我已經在瀏覽器上測試通過。接下來,我們馬上進入iOS客戶端編程。


iOS部分開發工具我們使用Xcode 9.2,其實你也可以使用AppCode,這是基於IntelliJ IDE開發的一款IDE,使用習慣完全接近IntelliJ IDE。

為了防止部分同學對Swift語言不熟悉,我們使用最常見的編程語言OC。

完整配置請參考如下表格:

打開Xcode,依次選擇Create new Xcode Project->Single View App

下一步填入如下信息,語言選擇OC

第一步:完成UI部分

這一部分參考蘋果官方文檔,按照蘋果官方推薦,我們使用Storyboard進行布局。由於我們只是完成一個簡單的Demo,所有的頁面將在同一個Storyboard中完成。實際開發過程中,要根據功能劃分Storyboard,方便進行小組開發。

使用約束布局我們很快完成了UI的構建,接下來進入最重要的編碼階段。約束布局的意思就是為一個控制項添加N個約束,使其固定在某個位置。這個部分只要稍加嘗試,就能掌握。具體的使用方法,請參考官方文檔。

第二步:創建控制器,並關聯UI

從伺服器編程類推,iOS編程模型中應該也有一個叫Controller的東西。果不其然,在iOS新創建的工程中就有一個叫做ViewController的類,其父類是UIViewController。沒錯,這就是傳說中的控制器。

完成登錄、註冊功能,我們至少需要三個控制器:LoginViewController、RegisterViewController、MainViewController,分別代表登錄、註冊、首頁三個頁面。

接下來,將控制器與UI進行關聯。

UI關聯控制器部分,如果你不知道,請先參考蘋果官方文檔。

事實上,Xcode的Interface Builder非常好用。按照下圖操作即可:

最後,關聯按鈕點擊事件以及輸入框。

選中控制項並按住滑鼠右鍵拖拽到控制器源碼中,鬆開,並選擇相應類型即可:

以登錄控制器為例,拖拽完成後的源碼如下:

接下來進入網路部分編程。

為了簡化網路部分編程,我們引入AFNetworking框架。還記得服務端編程是怎麼引入依賴的嗎?沒錯,是Gradle。iOS端也有類似的依賴管理工具Cocoapods,這個部分如果不會依然請你參考官方文檔。

使用如下步驟安裝依賴(這裡假設你已經正確安裝了Cocoapod):

a)在根目錄下面創建Podfile文件,並添加如下內容:

b)安裝依賴

PS:可能有人會問,為什麼服務端編程沒有安裝依賴的步驟。其實,很簡單,intelliJ IDE非常智能,它自動檢測了build.gradle文件的修改。一旦發現修改,自動安裝依賴。因此,看起來就像沒有依賴安裝這個步驟一樣。事實上,Cocoapod並非蘋果官方的產品,如果產品來自蘋果官方,恐怕Xcode也會支持自動安裝依賴。

依賴安裝完成後,為了更好地服務我們的業務。我們對網路請求做一點簡單封裝,增加HttpClient類,僅提供一個POST請求介面即可。

為了簡化JSON解析,我們增加一個最常見的Json解析庫 jsonmodel 庫。等待對話框也使用最常見的第三方庫 SVProgressHUD。

安裝依賴使用同樣的命令pod install即可。

接下來,我們添加登錄註冊邏輯,完成最後部分編碼:

通過上面的步驟,我們已經完成了iOS客戶端的開發。蘋果官方默認支持的就是經典的MVC模式。因此,我們完全參考服務端開發模式完成了iOS客戶端的開發。你唯一需要克服的是對新語言的恐懼,以及適應UI開發的節奏。事實上,大部分服務端程序員都害怕UI編程。

最後,我們進入Android客戶端編程。


Android部分開發工具,我們使用Android Studio,網路框架使用Retrofit,完整配置參考下方表格:

打開Android Studio,選擇Start a new Android Studio Project,在打開的頁面中填入以下信息:

剩下步驟全部選擇默認。

按照iOS編碼部分類推,Android端應該也有一個類似UIViewController的控制器。果不其然,在模板工程中就有一個MainActivity,其父類是AppCompatActivity,這就是Android的控制器。

PS:事實上Android早期版本的控制器就叫Activity,由於系統設計不斷變更,最終誕生了兼容性子類AppCompatActivity。這都是早期設計不夠嚴謹,導致的問題。相對而言,iOS端的設計就靠譜了許多。

同樣地,在開始編碼之前,我們加入所需的第三方依賴。那麼,問題來了。Android端如何添加依賴呢?

碰巧,Android端主要的開發語言就是Java。因此,我們依然可以使用Gradle進行依賴管理。碰巧,Android Studio默認支持的就是使用Gradle進行依賴管理。

首先,在app模塊目錄的build.gradle添加 Retrofit 依賴:

添加完成後,點擊文件右上方Sync now下載依賴:

相對於AFNetworking,Retrofit設計的更加精妙。參考Retrofit官方文檔,我們開始加入登錄註冊邏輯:

Retrofit設計的其中一個巧妙之處在於:你只需要定義好介面,具體的實現交給Retrofit。你可以看到,上面的代碼中我們僅僅定義了請求的類型,以及請求所需要的參數就已經完成了網路部分的所有工作。

不過,操作這個介面實現,需要使用Retrofit實例。接下來,我們參考官方文檔生成一個我們需要的Retrofit實例。

在生成Retrofit實例之前,還需要注意一個事情。還記得iOS端我們是怎麼完成JSON解析的嗎?是的,我們使用了第三方庫jsonmodel。

在Json解析的設計上,Retrofit也相當巧妙。Retrofit提供了一個轉換適配器用於實現Json數據的自動轉換。使用它,你可以自定義自己的Json轉換適配器;也可以使用官方已經實現好的適配器。一旦添加了這個適配器,所有的Json解析工作Retrofit就會自動幫忙完成。不再需要像AFNetworking一樣在回調裡面反覆進行Json解析操作。

因此,我們增加一個官方版本的Json轉換適配器依賴 converter-json:

加入Json適配器之後,我們使用一個新的Retrofit管理類RetrofitManager用於生成項目所需要的Retrofit實例。完整代碼如下:

接下來,我們嘗試在MainActivity中測試登錄介面,確定是否編寫正確。我們在MainActivity的onCreate方法中加入如下代碼:

打開模擬器,運行,你將看到以下錯誤:

提示我們許可權被拒絕,這是和iOS平台不一樣的地方。如果你的應用需要使用網路,你需要在清單文件中手動指定使用網路許可權。為此,我們在AndroidManifest.xml文件中添加如下配置:

再次運行,一切正常。

注意:這裡的service部分和服務端的service不一樣,它只是Retrofit用於將網路介面分模塊處理的一種手段,不要混淆。

上面說到,Android裡面的AppCompatActivity就是MVC中的控制器,接下來我們就完成最重要的控制器以及UI部分編碼。

a)創建LoginActivity以及布局文件activity_login.xml,在其onCreate方法中使用setContentView介面進行關聯。

b)UI編程

你相信嗎?一旦你學會了一門新的技術,你的技能就會Double。

iOS UI部分我們使用了約束布局的方式完成了整體布局,Android是否也可以使用約束布局呢?答案是:當然可以。

事實上,Android官方也推薦使用這種布局方式進行頁面布局。

切換到可視化布局模式,我們依然使用拖拽UI的方式完成整個布局,完整代碼請參考文章最後的附錄部分:

PS:目前,Android端的約束布局相對iOS遜色不少,希望後面官方能夠提供更多功能支持。

按照同樣的方式完成註冊頁面和首頁布局,UI部分開發完成後,嘗試跳轉到指定控制器。你會發現,出錯了。這也是和iOS不一樣的地方,Android端四大組件必須在清單文件中註冊。具體是什麼原因,請自行思考,這不是本文研究的重點。

因此,我們首先在清單文件中對所有控制器進行註冊:

然後,以登錄為例,我們在控制器中完善登錄邏輯:

至此,按照iOS的開發模式,我們完成了Android客戶端的開發。與iOS不同的地方是,Android端控制器必須在清單文件中註冊。程序員不能主動創建Activity,只能間接使用intent進行通信。而對於布局,兩者都可以使用約束管理的方式完成。從這個角度來說,Android端和iOS端開發切換的難度還是比較低的。


至此,我們已經完成了文章開頭定下的目標。以MVC架構為基礎,完成了服務端、iOS客戶端、Android客戶端編碼。

然而,很多同學希望成為一個全棧工程師。按照現在的主流開發分支來說,成為一個全棧工程師,你還需要掌握Web前端開發。那麼,問題來了,Web前端開發是否也是使用MVC架構呢?

事實上,如果你使用 Angular,你應該早就習慣了MVC。而如果你偏愛React,你恐怕會搭配Redux,使用這種響應式的數據流框架編碼。如果你使用Vue,你恐怕也會選擇MVC或者MVVM架構。

如果你選擇使用MVC,你依然可以按照類推的方式來學習。由於文章篇幅的原因,這部分就不予展示了。


這篇文章我們以MVC為架構,從服務端編程開始,使用類推的方式依次完成了iOS客戶端、Android客戶端的開發。

有人可能會說,文章中的例子太簡單,沒有實際意義。事實上,在學習一門新技術的時候,就要從最基礎的部分出發,建立對這門技術的最初印象。很多同學容易一開始就陷入細節當中無法自拔,產生的最直觀的結果就是對新技術產生恐懼。因此,你常常可以看到一個程序員面對新東西罵娘,無怪乎。

其實,如果你慢慢進入到細節編程中,你會發現技術之間越來越多的相似性。這個時候你的積極性就會越來越高,編碼也會更加得心應手。

我在學習一門新技術的時候,都是先從相似性開始。然後,再去攻克不同的部分。從不同的部分中去提煉相同的思想,這樣在面對不同問題的時候,我始終可以使用同樣的思想去解決。

當然,我想,你應該會說。雖然克服了框架問題,可是不同的編程語言千差萬別。我們無法從一門語言快速過渡到另外一門語言,這在學習新技術的時候才是最大的攔路虎。

你說的很對,這恰好是下一個我想和你分享的問題。


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 愛做飯的小鱷魚 的精彩文章:

看懂動態代理,其實你只需要10分鐘

TAG:愛做飯的小鱷魚 |