1.為什么不使用數據對象
問題來源:
- 修改某一領域共享對象或參數時,可能影響其他領域
- 解決某一問題,如果引入某個充滿各種不同問題領域的函數集,實質上也就引入了對不同問題領域解決方案的依賴
2.去model化的手段
a.字典流,即使用原生的數據流,通過NSDictionary方式傳遞
b.reformer(本文重點)
- 問題1:使用哪種交互模式來跟業務層做對接?
- 問題2:是否有必要將API返回的數據封裝成對象然后再交付給業務層?
- 問題3:使用集約化調用方式還是離散型調用方式去調用API?
回答1:使用哪種交互模式來跟業務層做對接
1.1 以什么方式將數據交付給業務層?
大多數App在網絡層采用的方式:Delegate、Notification、Block,建議使用Delegate,理由如下:
i.盡可能減少跨層數據交流的可能,限制耦合
ii.統一回調,便于調試和維護
iii.在跟業務層對接的部分只采用一種對接手段,限制靈活性,來交換應用的可維護性
** 什么是跨層數據交流? **
--- 就是某一層(或模塊)跟另外的與之沒有直接對接關系的層(或模塊)產生了數據交換。
** 為什么這種情況不好? **
--- 這會導致代碼混亂,破壞模塊的封裝性。
** 我們做分層架構的目的 **
--- 其中之一就在于** 下層對上層有一次抽象,讓上層可以不必關心下層細節而執行自己的業務 **。如果下層細節被跨層暴露,一方面你很容易因此失去鄰層對這個暴露細節的保護;另一方面,你又不可能不去處理這個細節,所以處理細節的相關代碼就會散落各地,最終難以維護
** Notification **
--- 使用Notification給跨層數據交流開了一道口子,相關處理的代碼不能保證都在唯一的地方。不過,在屬于它的問題領域中,這也是一種非常好的解決方案
** Block **
--- 很難追蹤,難以維護。block會延長相關對象的生命周期。block在離散型場景下不符合使用的規范。
當回調之后要做的任務在每次回調時都是一致的情況下,選擇delegate,在回調之后要做的任務在每次回調時無法保證一致,選擇block。在** 離散型調用的場景 下,每一次回調都是能夠保證任務一致的,因此適用delegate。 蘋果原生的網絡調用 采用delegate,因為蘋果是基于離散模型去設計網絡調用的。在 集約型調用的場景 下,使用block是合理的,因為每次請求的類型都不一樣,那么自然回調要做的任務也都會不一樣。 AFNetworking 就是屬于集約型調用,因此它采用了block來做回調。
在網絡請求和網絡層接受請求的地方時,使用Block沒問題。但是在獲得數據交給業務方時,最好還是通過Delegate去通知到業務方。我們實際編碼時也會意識到盡可能讓 Block的回調著陸點統一 **,所以選擇在block里面寫個一句話的方法接收參數,然后做轉發,然后就可以把這個方法放在其他地方,這實質上跟使用Delegate的手段沒有什么區別,只是繞了一下,不過還是沒有解決統一回調方法的問題,因為block里面寫的方法名字可能在不同的ViewController對象中都會不一樣,所以,建議的寫法如下:
[AFNetworkingAPI callApiWithParam:self.param successed:^(Response *response){
if ([self.delegate respondsToSelector:@selector(successWithResponse:)]) {
[self.delegate successedWithResponse:response];
}
} failed:^(Request *request, NSError *error){
if ([self.delegate respondsToSelector:@selector(failedWithResponse:)]) {
[self failedWithRequest:request error:error];
}
}];
1.1小結:以什么方式將數據交付給業務層?
盡可能通過Delegate的回調方式交付數據,這樣可以避免不必要的跨層訪問。當出現跨層訪問的需求時(比如信號類型切換),通過Notification的方式交付數據。正常情況下應該是避免使用Block的
1.2 交付什么樣的數據給業務層?
大部分的做法是:將拿到的JSON數據,轉變成對應的對象模型,這么做有如下成本:
1.數組內容轉化成本高
2.存在需要2次轉化的數據
3.只有API返回的數據高度標準化時,生成的Model的可復用性才高
4.調試時,Model的展示不如NSDictionary/NSArray直觀
5.同一個API的數據被不同的View展示,難以控制數據轉化的代碼,有可能散落在多個地方
1.2小結:交付什么樣的數據給業務層
對于業務層而言,由Controller根據View和APIManager之間的關系,選擇合適的reformer將View可以直接使用的數據(甚至reformer可以用來直接生成view)轉化好之后交付給View。對于網絡層而言,只需要保持住原始數據即可,不需要主動轉化成數據原型。然后數據采用NSDictionary加Const字符串key來表征,避免了使用對象來表征帶來的遷移困難,同時不失去可讀性