背景:基礎側期望能統一視頻的合成流程,換個說法,就是合成用他們的代碼。
思考1: 我首先思考的是這個需求該不該做
在手q上,兩端的業務邏輯差別很大,比如基礎側支持圖片上傳,日跡要求特效封面跟視頻分離(清晰度原因),各自支持的拍攝(日跡有分段拍攝)和編輯模式(基礎側有專門針對圖片的編輯模式)也不盡相同,最重要的是有各自的拍攝入口,所以有兩套合成代碼算合理。但在qim上,拍攝和編輯都是統一的,差異落在了封面分離和編輯圖片上,而清晰度問題自從提高了分辨率后,也不算是大問題了。其次,基礎側一直在增加拍攝和編輯的功能,兩套代碼后面會非常難維護,所以,流程統一是趨勢,重構勢在必行。
思考2:除了滿足產品需求,我還能做什么
現有代碼有什么問題,能否借著重構的機會解決現有代碼的問題?我匯總了當前發表流程的一些問題:
1 代碼耦合嚴重,可讀性差
視頻合成,數據存儲,通知發送都在一個類里,回調級級嵌套,if..else代碼太多
2 拓展性差
整塊代碼對外層是個黑盒子,參數都是固定的,沒有任何可拓展性
3 同步代碼困難
4 數據上報準確率有問題
5 取消任務的代碼散落在各處,切賬號引起的bug很難修改
6 不支持并發,通過信號量間接實現單任務,任務卡死就會卡死整個任務隊列
重構時,能一并解決上面問題再好不過。
思考3:如何落地
一般技術需求,尤其是大一點的技術需求,都會面臨工期問題,比如,你的排期超過了當前迭代版本的deadline,排完產品需求你還有人力富余嗎,同期有沒有產品需求也在修改這塊的功能,如果他們在源代碼基礎上做需求,會不會互相影響 ?
排期問題,要跟pm仔細確認灰度時間和發布時間,預留后足夠的測試時間。
需求問題,要跟leader和產品確認好人力情況,保證有人員能排。確認同期是否有對應的該模塊需求,方便協調。
方案問題,要考慮好幾套落地方案,比如,完整方案,折中方案,臨時方法等,在討論時大家有選擇的余地。
考慮了上面的幾個問題,我才放心進行方案設計。
思考4:如何設計
以前一直說,希望我們有一套數據層的框架,可以很容易的拓展和復用。但是這套框架該解決什么問題,其抽象粒度如何,一直沒有定論,而且數據層一直是其他同事負責的,我也沒有太關注。
現在問題交到我手里,我又重新開始思考這個問題。
誠然,我們現在有一套基于wns封裝的網絡請求api,有面向對象的數據庫,有約定好的通知機制,如果完全理解這里面的規則,使用起來做業務需求完全沒問題。但是,注意,我這里用了“api”這個字眼,從整個app的角度來看,不管你提供了多少個調用接口,能處理多少的功能,其只能算是針對業務邏輯提供的一些數據請求接口以及數據回調,是非常靜態的。
如何合理的調用這些api,把數據請求,數據存儲,UI刷新全部串起來的機制是沒有的,即“動態”框架是沒有的。
我們可以回想以前接觸過的能真正稱之為框架的東西,比如MFC,不僅提供了View/Doc的設計規范(靜態),而且提供了大批的宏來控制和分發消息windows消息(動態)。又比如BeeFramework,不僅提供beeModel、BeeView等mvc各個層級的基礎模塊類,而且提供了編輯器,路由代碼等等有效組織模塊運行的框架。
一套框架之所以能成為框架,我的看法是,不僅要有靜態的模塊,也要有動態的模塊。想當年我們用mfc的時候,是可以一行代碼不寫就運行app的,beeframework雖然要寫啟動的VC,但這也是遵循蘋果的機制。
廢話這么多,其實只是想提出我的看法,我們現在的數據層框架,不能算是個框架,只能算一組“api”。
思考5:任務隊列可以實現app的動態框架嗎
答案是不能。任務隊列本身有其特定的使用場景,一般不涉及到UI操作的代碼適合放到任務隊列里。(當然你也可以認為runloop也是個任務隊列,這里不爭論這個問題), 我這里說的任務隊列應該是異步,支持并發,以及UI無關的。雖然不能解決UI問題,但是針對數據層,卻完全可以實現動態框架,因為數據層天生符合異步,支持并發,以及UI無關等要求。
思考6:技術選型
在IOS里,系統提供了一套隊列框架。NSOperation以及NSOperationQueue。
NSOperation
NSOperationQueue
NSOperation提供了三種狀態的流轉execute -> cancel -> finish,以及標識該操作能否并發運行,任務依賴等等執行相關的屬性,NSOperationQueue提供了添加操作,取消所有操作,設置最大并發數等管理任務的接口,正式我們想要的東西。
但是為什么很少看到有人使用他們呢?
一般一套看起來很好的東西卻沒什么人用的原因無外乎以下幾個原因:
1 看起來很美,用起來其實很復雜,很麻煩。
2 性能有問題,不可控。
3 一開始設計的時候沒用,現在沒法子用了。
4 有很好的替代方案,系統逐漸淘汰它了。(ios經常發生這種情況)
5 大家都不用,我也不用。(萬一出問題咋辦)
6 見識短,其實大家都在用,你不知道而已。
后面一個是開玩笑,帶著以上擔憂,我google了一下。google過程省略,整理的結論如下:
1 使用確實有門檻,首先NSOperation的各個屬性基本都是只讀的(比如,isExecute, isCancel,isFinished等),只能通過重載的方式來實現狀態的流轉,而且系統要求你實現相關屬性的KVO。
你也可以使用系統提供的派生類,NSBlockOperation或者NSInvocationOperation,從字面你可以看出一個是對oc函數的封裝,一個是對c函數調用的封裝。
2 性能有一點小問題,就是內存開銷比GCD要大,GCD底層是基于C的,其效率更高,開銷更小。NSOperation早于GCD出現,早期版本他們的實現是完全不同的,在iOS 4 與 MacOS X 10.6以后,Operation Queue的底層實現都是用GCD來實現的。(網上說法,沒驗證) 。
3 這個不討論。
4 暫時沒有這種跡象。
5 Operation VS GCD
貼篇stackover的爭論https://stackoverflow.com/questions/7651551/why-should-i-choose-gcd-over-nsoperation-and-blocks-for-high-level-applications,年代可能有點久遠,最近的文章好像都沒看到比較激烈的討論了。
類似xxx VS xxx的文章,跟php是世界上最好的語言一樣,只要不是某一方具有壓倒性的優勢,一般的結論就是沒有結論。存在即合理,只要我們的場景適合,那他就是組好的語言。