貨物崇拜編程
- 2020 年 2 月 10 日
- 筆記
讀到這個標題,多數人會有疑惑,什麼是貨物崇拜編程,其實最根本的問題可能是什麼是貨物崇拜。想要了解這些就不得不說貨物崇拜(Cargo Cults,又譯貨物運動)的起源
第二次世界大戰太平洋戰爭時,美軍於塔納島建立一臨時基地。當時島上的原住民看見美軍於「大鐵船」(軍艦)內出來,皆覺得十分驚訝;他們也看到,有一些「大鐵鳥」(軍用飛機)運送穿著美軍軍服的人及許多物資。這些原住民看見這種情況均感到很驚訝,並覺得這些「大鐵船」及「大鐵鳥」十分厲害。加上美軍也提供部分物資給原住民,而這些物資對原住民來說十分有用,結果這些原住民將美軍當作神。 第二次世界大戰結束後,美軍離開塔納島,只留下一些美軍軍服及一些貨物。塔納島原住民便認為這些貨物具有神奇力量,又相信「神」(美軍)他日會回來並帶來更多貨物,使他們展開一個幸福新時代。但是美軍當然再也沒有回來塔納島,因此這些原住民便自己發展出一套敬拜儀式,崇拜美軍軍服及貨物;表現形式是原住民會穿著美軍軍服、升起美國國旗,圖騰則是木刻的飛機。
貨物崇拜編程則是上面的貨物崇拜的引申,維基百科對其定義如下
貨物崇拜編程(Cargo Cult Programming)是一種電腦程式設計中的反模式,其特徵為不明就裡地、儀式性地使用程式碼或程式架構。貨物崇拜編程通常是程式設計師既沒理解他要解決的bug、也沒理解表面上的解決方案的典型表現。
現象
- 從網路上看到一些 看似有道理卻不起作用的內容
- 為了用設計模式而用設計模式等刻意使用
- 複製Stack Overflow上的內容,只要運行OK即可
這裡以程式碼為例,列舉幾處違例
設置變數為null 釋放記憶體
可能很多人都聽過,類似手動設置變數為null,可以釋放記憶體,緩解記憶體壓力。於是就有人奉其為金科玉律,寫出了類似下面的程式碼
public class ViewHolder { private View view; private String message = "message"; public ViewHolder(View view) { this.view = view; } public void clean() { //解除引用關係,釋放記憶體 view = null; message = null; } }
上面的程式碼
- 我們在clean方法中,手動設置view和message為null以期待可以釋放記憶體
- 由於Java是自動垃圾回收,只要ViewHolder示例不被持有,view就可以釋放,
view = null
顯然是畫蛇添足 - 更複雜的情況,message對應的字元串內容回收,還需要考慮字元串常量池的存在。
message = null
無法釋放字元串內容
使用弱引用防止記憶體泄露
同樣,很多人都聽說過 弱引用(WeakReference) ,它可以避免記憶體泄露,於是寫出了下面的程式碼
private void initWebView() { try { //使用弱引用防止程式webview導致記憶體泄漏 webView = new WebView(new WeakReference<Context>(this).get()); .... } catch (Exception e) { e.printStackTrace(); } }
上面的程式碼
- 僅僅聽說了弱引用,但是不知道強引用,更不知道他們阻止GC回收的能力
- WebView構造方法接收強引用的Context,
new WeakReference<Context>(this)
試圖構造一個Context的弱引用,但是new WeakReference<Context>(this).get()
又從構建的弱引用中得出了原始的強引用 - 上面的程式碼,只會是事與願違。
處理SSLError引發安全問題
@Override public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error){ handler.proceed(); }
上面的程式碼是Webview載入遇到SSL證書問題出錯時的回調,網上很多人告訴我們,像上面的方式處理就能解決網頁載入出錯的問題,殊不知這回引發更大的風險漏洞問題。
貨物崇拜的問題
- 不熟悉內部原理,無法預期會發生什麼,這是很危險的
易出現人群
- 新手或者經驗不足的人,對很多東西和技術不熟悉
- 缺乏思考,思想懶惰的人
如何避免
如下,簡單談一些我認為能夠規避貨物崇拜編程的方式與方法
自身學習和思考,懷疑
- 這是從內部驅動的解決方法,通過學習,我們可以把對一項技術的掌握從0變為1,進而變成100。在這個過程中,我們自然能規避那些貨物崇拜的問題。
- 保持思考,切忌懶惰,對於技術和程式碼,我們在會使用的情況下,更要研究和思考並了解其內部的機制和原理。
- 保持懷疑,科學精神的精髓就是「懷疑」,在既不能證實也不能證偽的情況下那就存疑
結對編程與程式碼審核
- 這是外部驅動的解決方法
- 找一個有經驗的人來結對編程,或程式碼審核,能夠在程式碼上線之前發現潛在的問題並更正。
拒絕貨物崇拜編程,學習,思考,懷疑。