每個Android開發者都會犯的錯

碼個蛋(codeegg)第 935 次推文

作者: 非非白

原文: https://juejin.im/post/5d294182518825331d14cbae

本系列文章旨在概述我們搭建 Android 應用程序架構時可能會碰到的問題。我意識到,無論實現 Android app 架構的過程多麼困難,結果證明這些一定是完成每一個卓越的應用的基礎。

每種技術都有其自然的進化。或者更確切地說,它的社區經歷了進化的過程。一個新的計算機語言或框架的早期採用者是愛好者,他們只是希望掌握技術,並儘快完成一些工作。通常,新社區規模小,在開發人員之間的知識傳遞潛力有限,也就是說,每個人都從自己的錯誤中學習,因為沒有架構指南可用。

每個Android開發者都會犯的錯

前言

早期 Android 們的痛點:谷歌是否關心?

你可以說,有很多資深的傢伙在不同的技術上有很多的經驗,但誰也沒有時間提出標準。嗯,不一定。如果技術背後有一個強大的公司指望賺錢,他們的佈道師會告訴你這個新語言多麼酷,可以做很多事情,容易學習,可擴展,並且可以滿足數以百萬計的用戶。

微軟就經常用它的技術幹這樣的事情。另一方面,當谷歌收購了 Android, 我真的以為他們只是把它當作一個無關緊要的項目。如果你從 Android 誕生之時就進入 Android 的世界,你一定記得 Google 根本不在乎你的那種沮喪感。那些有額外的經驗,能力和幫助社區的意願的少數幾個人現在是 Android 的超級明星或大神 —— 譬如 Jake Wharton

“When Google bought Android, I honestly think they treated it just as some other side project.”

每個Android開發者都會犯的錯

可能你會說,你不必考慮太多架構和組織代碼的事情,因為(Android)Framework 幫你做了。Android 強迫你把界面放到 Activity 中,可重用的界面放到 Fragment 中, 後臺服務放到 Service 中,並且用 Broadcast Receiver 和其它組件通信,這樣可以使你的生活變得更美好,是這樣嗎?不是的。

首先,有一些很好的實踐和原則確實很好,與技術(平臺)無關。例如,單一職責原則,依賴倒置原則,面向接口編程,殺死全局狀態,嘗試消滅所有狀態,等等。

Framework 很少強迫你遵循原則。恰恰相反,它們以最壞的方式侵犯這些最佳實踐和原則。想想 Context 這個你到處使用的上帝對象(God object),各種單例管理者(singleton managers),擁有生命週期的 Fragment(那是怎樣的噩夢呢),常常不能正確實現的 AsyncTask,它們吸著你 app 的血。

一個缺乏指導的剛入行的開發者很容易造出一個怪物而不是一個 app。把它想象成一個意大利麵條般的怪物吧 —— 這是一個不錯的怪物,但不是一個好的 app。

譯者注:意大利麵條般的怪物寓指一團亂麻的代碼

每個Android開發者都會犯的錯

最後,技術(technology)和 Framework 隱藏了 app 的用途。好的,這是一個 Android app,但是一個什麼樣的 Android app 呢?新聞閱讀器?音樂播放器?語言學習程式?天氣應用?也許是一個計劃表。如果所有的東西都打包到由 Framework 提供的類,你就說不出(這是什麼 app)。

正如 Robert Martin,也就是 Uncle Bob 說,“你的架構應該尖聲喊出(scream)app 是做什麼”,更技術一點說,業務邏輯應該清晰地分離,獨立於 Framework。

Android 架構的四條黃金法

我希望已經說清楚了,你不應當依賴 Framework 來使你的代碼整潔有序,尤其是在編寫 Android 代碼的時候。我們很早以前就意識到這點,可是缺乏拿出牛逼解決方案的經驗。架構失敗要花很多時間才能表現出來,又不可以在項目中途改變整個架構。也不可能有時間將舊項目重構成新的、酷的、(想成為)最佳的架構。因此,我們採取漸進的方法,慢慢地從一個項目到另一個項目搭建我們的架構,從我們的錯誤中學習。我們認為我們的架構應該滿足幾個目標,它們是檢驗我們的方法的標準。好的架構應該做到:

  1. 滿足眾多利益相關者的需求

  2. 支持關注點分離

  3. 逃離現實世界(Android、DB、Internet...)

  4. 使你的組件可測試

I.滿足眾多利益相關者

利益相關者(在這篇文章中)是任何對你的 app 開發感興趣的人。除了開發,還有視覺設計師,交互設計師,項目經理,數據庫管理員,測試等等。

當然,你不可能以某種方式組織你的代碼,例如,交互設計師可以打開項目並立即瞭解所有內容,甚至可以進行一些修改。It's a unicorn.

每個Android開發者都會犯的錯

我的意思是,你可以以這樣一種方式組織你的代碼,那個和交互設計師對接的程序員只需要打理和交互相關的代碼。因此,所有交互被分離到那些負責交互的 classes / modules / components / whatever (組件)中,當處理 app 的交互部分時,只需要打理那些組件。

譯者注:如果暫時不能理解利益相關者,沒關係的,看完本系列第三部分你就明白了

II.支持關注點分離

我剛剛所說的就是一個關注點分離的例子。我們支持這種特定的方法,因為它能很好地表達團隊組織和項目階段的配合,一般來說,你的架構也應該支持關注點分離。關注點分離或者單一職責原則是指,每一個組件應該只有一個變化的原因。

III.逃離真實世界(Android、DB、Internet...)

逃離真實世界這條規則,先前已經提及。我們曾說我們想要尖聲喊出 app 真正是做什麼的,就是那樣。我們想要強調業務邏輯並且隱藏 Framework 的細節。這條規則應該更嚴格:不僅要隱藏 Framework 的細節,而且要隱藏所有與外部世界相關的細節。

每個Android開發者都會犯的錯

所有的骯髒的 Android 的東西,如傳感器、通知機制、屏幕細節、數據庫訪問、互聯網訪問等。

IV.使你的組件可測試

你應該儘可能地對你的 app 進行單元測試,並且你的架構應該允許你這樣做。如果你不能測試所有東西,你至少應該覆蓋你的業務邏輯。與真實世界分離可以很方便地做到這點。如果你的業務邏輯清晰地和 app 其餘部分隔離,是很容易測試的。

每個Android開發者都會犯的錯

第一次迭代 —— 上帝 Activity

<code>

public

final

class

UsersActivity

extends

ListActivity

{


void

onCreate

(Bundle savedInstanceState)

{

super

.onCreate(savedInstanceState);
















/<code>

你可能在 “上古時代” 看到過這樣的代碼。如果沒有,說明你很年輕。但是這一段代碼哪裡有問題呢?答案是哪裡都有問題。

每個Android開發者都會犯的錯

我們有一個 Activity 操作數據庫,訪問網絡,解析數據,切換線程以及渲染數據。所有的利益相關者都在看這一個類,沒有關注點是分離的,它是不可測試的,業務邏輯和 Android 的東西混雜在一起。

每個Android開發者都會犯的錯

譯者注:留意上圖左邊紅色的標籤。每個標籤分別對應一條黃金法則,紅色表示不滿足。SRP 是指單一職責原則,即分離關注點。

第二次迭代 —— MVP

第一種方法顯然是不能工作的。我們嘗試過的第一件事情是 MVP,或者說 model-view-presenter。每個人都熟悉 MVP。它是最受歡迎的架構模式之一。看起來像這樣:

每個Android開發者都會犯的錯

這裡,我們分離了實際上是 Android Fragment 的 View,我們擁有代表我們業務的(領域)模型,最後我們有協調一切的 Presenter。這肯定是更好的。關注點有了一些分離,利益相關者不再那麼困惑,你也可以寫一些單元測試了。儘管如此,由於 Presenter 直接操作數據庫和所有一切,我們仍然和真實世界混雜在一起。Presenter 成了上帝對象。它處理模型,將數據發送到視圖,它擁有業務邏輯(業務邏輯是那些齒輪 :)),它訪問數據庫和網絡,獲取傳感器數據,等等。所以,是好了些,但可以更好。

每個Android開發者都會犯的錯

譯者注:黃色的標籤表示好了些

第三次迭代 —— MVP + managers

當政府不知道做什麼的時候它會做什麼?它成立一個代理機構。當開發不知道做什麼的時候他們會做什麼?他們引入一些 Manager。你不一定把它命名為 “*Manager” 。這些類有很多名字:uitls、helpers、fooBarBuzz-ator、等等。因此我們引入 Manager。

每個Android開發者都會犯的錯

說實話,這甚至有點湊效。業務邏輯包含在 Manager 中。利益相關者知道往哪看,關注點一定程度是分離的但可以做得更好,你可以編寫更多的測試,但你依然直接觸摸 Android ,所以你必須編寫 Android 測試用例,並預先填寫數據庫來測試業務邏輯,一個字:不爽。

是的,Manager 有變成巨獸的傾向,很快就變得難以維護。你可能爭論說它不會變得更復雜,你可以通過更簡單的架構來更快地提供代碼,但通過這種方法依然會有很多 BUG,可維護性也會遭到破壞。

每個Android開發者都會犯的錯

譯者注:留意 Manager this 和 Manager that 之間的標籤

總結

在本系列的第一部分,我們經歷了搭建實際可用的 Android 架構的挑戰。良好的 Android 架構應該滿足眾多利益相關者的需求,支持關注點分離,強調業務邏輯,隱藏 Framework 的細節,並使你所有的組件都可以測試。在系列的第二部分,我們將向你展示我們如何管理對我們有用的功能。在此之前,你是否有如何創建合適的 Android 工作流的建議?或者你遇到了什麼問題?

原文(http://five.agency/android-architecture-part-1-every-new-beginning-is-hard)

  • 助攻面試:圖解Android Binder機制

  • Android多線程技術選型最全指南(1)

  • 趣圖:如何假裝自己是一個IT人?

大家項目現在採用什麼架構?提升開發效率了嗎?


分享到:


相關文章: