1.制定安全機(jī)制
一個(gè)App,最核心的就是數(shù)據(jù),而數(shù)據(jù)的主要來(lái)源就是API。
①保證API的調(diào)用者是經(jīng)過(guò)自己授權(quán)的App
設(shè)計(jì)簽名:對(duì)每個(gè)客戶端,Android、iOS、WeChat,分 別分配一個(gè)AppKey和AppSecret。需要調(diào)?用API時(shí),將AppKey加?請(qǐng)求參數(shù)列表,并將AppSecret 和所有參數(shù)一起,根據(jù)某種簽名算法生成一個(gè)簽名字符串,然后調(diào)用API時(shí)把該簽名字符串也一起帶上。服務(wù)端接收到這個(gè)請(qǐng)求時(shí)驗(yàn)證AppKey和AppSecret和簽名字符串是否一致, 若一致則請(qǐng)求是安全的.每個(gè)端都有一個(gè)Key,也?便不同端的標(biāo)識(shí)和統(tǒng)計(jì)。為了防止AppSecret被別人獲取,這個(gè)AppSecret一般寫(xiě)死在代碼?面。另外,簽名算法也需要有一定的復(fù)雜度,不能輕易被別人破解,最好是采?自己規(guī)定的一套簽名算法,?而不是采用外部公開(kāi)的簽名算法。另外,在參數(shù)列列表中再加?一個(gè)時(shí)間戳,還可以防止部分重放攻擊 。
②保證數(shù)據(jù)傳輸?shù)陌踩?/h4>
采用HTTPS, HTTPS因?yàn)樘砑恿薙SL安全協(xié)議,自動(dòng)對(duì)請(qǐng)求數(shù)據(jù)進(jìn)行了壓縮加密,在一定程度上可以防止監(jiān)聽(tīng)、劫持、防止重發(fā),主要就是防止中間人攻擊。
為了安全考慮,建議對(duì)SSL證書(shū)進(jìn)行校驗(yàn),包括簽名CA是否合法,域名是否匹配、是不是自簽名證書(shū)、證書(shū)是否過(guò)期等。
2.接口協(xié)議標(biāo)準(zhǔn)化
每個(gè)技術(shù)團(tuán)隊(duì)一般都會(huì)有一份接口協(xié)議文檔,包括對(duì)對(duì)每個(gè)接口的描述、入?yún)?、輸出結(jié)果等。但一般并不嚴(yán)謹(jǐn),很多地方?jīng)]有同意標(biāo)準(zhǔn),從而容易出現(xiàn)很多坑。有一份標(biāo)準(zhǔn)且嚴(yán)格執(zhí)行的接口協(xié)議非常重要。協(xié)議的內(nèi)容除了規(guī)定每個(gè)接口中每個(gè)數(shù)據(jù)具體的數(shù)據(jù)類(lèi)型,還需要規(guī)定一套共用的數(shù)據(jù)字典,以及其他需要統(tǒng)一定義的信息,比如簽名算法等。
3.接口版本控制
接口變動(dòng)會(huì)導(dǎo)致舊版本App出錯(cuò),而且變動(dòng)不一定是修改了接口本身,有可能是增加了一種新的數(shù)據(jù)結(jié)構(gòu),客戶端舊版本解析不了,從而就導(dǎo)致出錯(cuò)。
為了解決接口的兼容性問(wèn)題,需要做好接口版本控制。實(shí)現(xiàn):
1.每個(gè)接口有各自的版本,一般為接口添加個(gè)version參數(shù)
2.整個(gè)接口系統(tǒng)有統(tǒng)一的版本,一般在URL中添加版本號(hào),比如http://api.domain.com/v2
平時(shí)小版本更新,就采用第一種方式, 根據(jù)不同版本號(hào)做不同分支的處理;大版本采用第二種。(跟舊版本相對(duì)獨(dú)立)
太舊的版本提醒用戶強(qiáng)制升級(jí)或者普通升級(jí)。
4.架構(gòu)分層(高內(nèi)聚、低耦合)
數(shù)據(jù)管理、數(shù)據(jù)加工、數(shù)據(jù)展示,三層架構(gòu):數(shù)據(jù)層、業(yè)務(wù)層、展示層
- 數(shù)據(jù)層是最底層,往下,接入API ;往上,向業(yè)務(wù)層交付數(shù)據(jù);
- 業(yè)務(wù)層處于中間層,數(shù)據(jù)的加工,將數(shù)據(jù)層提供上來(lái)的數(shù)據(jù)加工成展示層需要展示的數(shù)據(jù)。
- 展示層處于最上層,主要將業(yè)務(wù)層取得的數(shù)據(jù)展示到界面上。
數(shù)據(jù)層:(數(shù)據(jù)管理者,封裝API,并將數(shù)據(jù)交付給上層,中間會(huì)再加個(gè)數(shù)據(jù)緩存)
1>業(yè)務(wù)層向數(shù)據(jù)層請(qǐng)求數(shù)據(jù);
2>數(shù)據(jù)層檢查緩存中有沒(méi)有請(qǐng)求需要的數(shù)據(jù);
3>如果有緩存直接返回緩存數(shù)據(jù);
4>如果沒(méi)有緩存,則從網(wǎng)絡(luò)API獲取數(shù)據(jù),并將數(shù)據(jù)加入緩存,然后返回?cái)?shù)據(jù)。
調(diào)用API 時(shí),還要判斷網(wǎng)絡(luò)狀態(tài),根據(jù)不同狀態(tài)做不同處理。如果網(wǎng)絡(luò)不可用,就無(wú)需發(fā)起請(qǐng)求。無(wú)網(wǎng)絡(luò)可用時(shí),也要區(qū)分是WIFI還是移動(dòng)網(wǎng)絡(luò)。連接移動(dòng)網(wǎng)絡(luò)時(shí),一般要限制比較耗流量的請(qǐng)求。
獲取分頁(yè)數(shù)據(jù)時(shí), 可以將下一頁(yè)的數(shù)據(jù)預(yù)先請(qǐng)求、
緩存策略:對(duì)于獲取數(shù)據(jù)的接口設(shè)置緩存。
數(shù)據(jù)層與外部交互:提供對(duì)外開(kāi)放的數(shù)據(jù)接口。參數(shù)分為兩類(lèi):系統(tǒng)參數(shù)和業(yè)務(wù)參數(shù),像appKey、version、sign、time這些屬于系統(tǒng)參數(shù),而currentPage,或usderName的類(lèi)則屬于業(yè)務(wù)參數(shù)。
數(shù)據(jù)層開(kāi)發(fā)的接口參數(shù)只需要包含業(yè)務(wù)參數(shù)就可以了,業(yè)務(wù)層并不需要關(guān)心系統(tǒng)參數(shù)是什么,系統(tǒng)參數(shù)在內(nèi)部封裝API時(shí)就已經(jīng)指定了。
業(yè)務(wù)層:(數(shù)據(jù)加工者)
從數(shù)據(jù)層獲取數(shù)據(jù),然后經(jīng)過(guò)業(yè)務(wù)邏輯處理后轉(zhuǎn)化成展示層需要的數(shù)據(jù)。(參數(shù)的有效性檢查,注冊(cè)成功后自動(dòng)登錄)
業(yè)務(wù)層交付給展示層的數(shù)據(jù)也是通過(guò)接口的方式,不同于數(shù)據(jù)層交付給業(yè)務(wù)層的是,給展示層的數(shù)據(jù)應(yīng)該是通過(guò)異步回調(diào)返回的。因?yàn)楂@取數(shù)據(jù)是一個(gè)比較耗時(shí)的任務(wù),通過(guò)異步回調(diào)才不會(huì)阻塞UI主線程。
展示層:(數(shù)據(jù)展示者)
關(guān)心數(shù)據(jù)如何展示:
界面布局、屏幕適配、圖片資源、文本資源、顏色資源等等、
保持高質(zhì)量代碼:
1>保持規(guī)范性:定義好開(kāi)發(fā)規(guī)范,包括書(shū)寫(xiě)規(guī)范、命名規(guī)范、注釋規(guī)范等,并按照規(guī)范嚴(yán)格執(zhí)行;
2>保持單一性:布局就只做布局,內(nèi)容就是只做內(nèi)容,各自分離好,每個(gè)方法、每個(gè)類(lèi),也只做一件事情;(保持單一性是減低耦合度的關(guān)鍵標(biāo)準(zhǔn),界面的單一就是要保持界面上每個(gè)維度做好分離,從界面布局到數(shù)據(jù)獲取,數(shù)據(jù)檢查,數(shù)據(jù)展示)。
3>保持簡(jiǎn)潔性:保持代碼和結(jié)構(gòu)的簡(jiǎn)潔,每個(gè)方法,每個(gè)類(lèi),每個(gè)包,每個(gè)文件,都不要塞太多代碼或資源,感覺(jué)多了就應(yīng)該拆分。
代碼混亂的問(wèn)題必須嚴(yán)格執(zhí)行開(kāi)發(fā)規(guī)范。
-
環(huán)境分離:不同環(huán)境有不同的App。iOS可以通過(guò)創(chuàng)建多個(gè)環(huán)境的Target來(lái)實(shí)現(xiàn)環(huán)境分離,不同target可以設(shè)置不同的Bundle Identify , Bundle display name , 更換圖標(biāo)。每個(gè)Target也各自有自己的一份Plist文件,環(huán)境變量和第三方設(shè)置之類(lèi)的,都可以設(shè)置在相應(yīng)的plist文件里。
模塊之間不要存在相互調(diào)用的關(guān)系,以framework的形式存在。高內(nèi)聚,高復(fù)用。
MVC
MVC 架構(gòu)問(wèn)題:
繁重的UI ,啰嗦業(yè)務(wù)邏輯,難受的用戶代理,很長(zhǎng)的網(wǎng)絡(luò)層,內(nèi)部方法,
- VC代碼過(guò)于繁重
- 代碼耦合性過(guò)高 (View和控制器耦合性強(qiáng))
解決辦法:
- 代碼繁重(代碼封裝、抽取:誰(shuí)的事情,誰(shuí)干)
- 耦合性高(解耦 eg:cell,setModel)
- VC的任務(wù)是要建立依賴(lài)關(guān)系(依賴(lài)綁定)
MVP
面向協(xié)議,View和Model完全解耦,Controller層不顯示網(wǎng)絡(luò)請(qǐng)求數(shù)據(jù)的過(guò)程,只要遵循協(xié)議就能拿到數(shù)據(jù)
V層UI改變,通知P層,P層更新數(shù)據(jù)通知M層,M層拿到新數(shù)據(jù)通知P層,P層通知V層UI改變。
MVP 優(yōu)缺點(diǎn):
①模型與視圖完全分離,我們可以修改視圖而不影響模型
②可以更高效的使用模型,因?yàn)樗械慕换ザ及l(fā)生在一個(gè)地方,Presenter內(nèi)部
③我們可以將一個(gè)Presenter用于多個(gè)視圖,而不需要改變Presenter的邏輯。這個(gè)特性非常的有用,因?yàn)橐晥D的變化總是比模型的變化頻繁。
④如果我們把邏輯放在Presenter中,那么我們就可以脫離用戶接口來(lái)測(cè)試這些邏輯(單元測(cè)試)
MVVM
KVO雙向綁定
ViewModel作為樞紐,溝通View和Model之間的關(guān)系。
- (void)setWithViewModel:(MVVMViewModel *)vm {
self.vm = vm;
//KVO
[self.vm addObserver:self forKeyPath:@"nameStr" options:NSKeyValueObservingOptionOld|NSKeyValueObservingOptionNew context:nil];
self.label.text = vm.nameStr;
}
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change: (NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{
if ([keyPath isEqualToString:@"nameStr"]&&[change objectForKey:NSKeyValueChangeNewKey]) {
NSNumber *new = [change objectForKey:NSKeyValueChangeNewKey];
self.label.text = [NSString stringWithFormat:@"%@",new];
}
}
-(void)mvvmClickChangModel{
[self.vm clickChangeName];
}
//MVVMModel
#import "MVVMViewModel.h"
@implementation MVVMViewModel
-(void)setWithModel:(MVVMModel *)model{
self.model = model;
self.nameStr = model.name;
}
-(void)clickChangeName{
self.model.name = [NSString stringWithFormat:@"name%d",arc4random()%10];
self.nameStr = self.model.name;
NSLog(@"%@",self.nameStr);
}
@end
架構(gòu)模式選擇
- 面向需求編程,以需求驅(qū)動(dòng)編程
補(bǔ)充
1.MVC跟MVP的區(qū)別以及使用的優(yōu)缺點(diǎn)?
MVC:View和控制器耦合性強(qiáng)
MVP:面向協(xié)議,View和Model完全解耦,Controller層不顯示網(wǎng)絡(luò)請(qǐng)求數(shù)據(jù)的過(guò)程,只要遵循協(xié)議就能拿到數(shù)據(jù)
MVVM: KVO雙向綁定
2.MVVM
M層-就是View和Model層的粘合劑,是一個(gè)放置用戶輸入驗(yàn)證邏輯,視圖顯示邏輯,發(fā)起網(wǎng)絡(luò)請(qǐng)求和其他各式各樣的代碼的極好的地方.其實(shí),就是把VC層的業(yè)務(wù)邏輯和頁(yè)面邏輯剝離出來(lái)放到ViewModel層,View層,就是VC層,他的任務(wù)就是從ViewModel層獲取數(shù)據(jù),然后顯示