解決問題通用方法論

本文公衆號「AndroidTraveler」首發。java

今天跟你們講講解決問題通用的一個方法論。android

在實際開發過程當中,咱們不可避免的會遇到一些 bug。git

那麼對於 bug 或者咱們沒有遇到過的問題,怎麼處理呢?github

本篇層層遞進,一步一步跟你講解。app

各位若是有其餘方法或者補充的歡迎留言交流。oop

若是全篇看完,你發現本身平時就是這麼處理的,那麼恭喜,你有本身的一套處理問題的方法論。源碼分析

本次講解以本人 Android 開發(演示代碼之類的)爲例進行講解,可是都是通用的。學習

1. 根據奔潰棧信息

這個實際上是解決問題或者 bug 最直接的方式了。測試

尤爲是奔潰棧信息能夠直接定位到項目裏面具體文件具體報錯位置時。網站

好比下面的空指針異常:

2019-05-24 13:41:10.031 15019-15019/com.nesger.androidproject E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.nesger.androidproject, PID: 15019
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.nesger.androidproject/com.nesger.androidproject.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.lang.String.equals(java.lang.Object)' on a null object reference
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2957)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3032)
        at android.app.ActivityThread.-wrap11(Unknown Source:0)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1696)
        at android.os.Handler.dispatchMessage(Handler.java:105)
        at android.os.Looper.loop(Looper.java:164)
        at android.app.ActivityThread.main(ActivityThread.java:6944)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)
     Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.lang.String.equals(java.lang.Object)' on a null object reference
        at com.nesger.androidproject.MainActivity.onCreate(MainActivity.java:13)
        at android.app.Activity.performCreate(Activity.java:7183)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1220)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2910)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3032) 
        at android.app.ActivityThread.-wrap11(Unknown Source:0) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1696) 
        at android.os.Handler.dispatchMessage(Handler.java:105) 
        at android.os.Looper.loop(Looper.java:164) 
        at android.app.ActivityThread.main(ActivityThread.java:6944) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374) 

能夠很明顯的看到是空指針異常致使的,並且根據奔潰棧信息能夠定位到具體的文件,從下面這一行

at com.nesger.androidproject.MainActivity.onCreate(MainActivity.java:13)

能夠看出奔潰發生在 MainActivity.java 這個文件的 onCreate() 方法。具體在該文件 13 行。

具體的緣由根據奔潰棧也能夠看出是使用 null object 去調用 equals 方法。

Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.lang.String.equals(java.lang.Object)' on a null object reference

代碼裏面也確實是這樣:

除了空指針,諸如 IndexOutOfBoundsException 也是常見的,均可以經過奔潰棧信息快速解決。

2. 善用搜索引擎

假設你的問題不能經過棧信息直接獲得解決,那麼接下來就是善用搜索引擎。

通常搜索引擎一級入口就是 Google、百度等。

實際上問題的解決方法是在二級入口,好比 Stack Overflow、簡書、掘金等網站上。

因此若是你熟悉或者一級入口沒有找到,能夠直接在二級入口進行搜索。

搜索的時候注意一些小技巧,舉個例子:
在 Android 裏面一些實現能夠在 xml 配置,也能夠經過代碼動態設置。

若是你的目標是要獲取代碼動態設置的,通常在你搜索的關鍵信息以後加上 programmatically

3. 經過官方渠道

官方渠道其實指的是官網或者官方論壇。

舉些我學習 Flutter 過程當中解決問題的例子。

在原生項目嵌入 Flutter 的時候,參考的是 Flutter 在 GitHub 上面的 WIKI。

在運行出現 crash 時,解決是經過 Flutter 在 GitHub 上面的 Issues。

因此我這裏就是到 flutter 官方的 GitHub 項目上面去尋找問題的解決方法。

4. 深刻源碼分析

當上面三個方法都不能解決你的問題時,這個時候你就要結合具體業務進行具體分析,而後深刻源碼找到本質問題,進行對應處理。

好比我以前寫過的一篇文章:

zxing 如何識別反轉二維碼

遇到的問題就是業務須要識別反轉二維碼。

前面提到的三個方法論都不能解決,屬於很小衆的需求。

這種狀況下我就分析了一下需求。需求是二維碼的識別,而二維碼識別核心就是圖像獲取和解碼。那麼經過分析源碼的解碼過程,是否是就能夠解決這個問題呢?最後證實是能夠的。

又好比說咱們的業務使用了 GraphQL,而官方 GraphQL 並無提供對 Flutter 的直接支持。

這個時候我在 GitHub 上面發現了一個倉庫:https://github.com/zino-app/graphql-flutter

這個倉庫提供了 Flutter 對 GraphQL 調用的支持,可是實際測試過程當中發現有個問題,那就是錯誤沒有回調。

這個時候我經過深刻源碼,打印日誌,發現錯誤確實有被 catch,可是沒有回調回來,說明可能回調裏面的代碼有問題。

所以我經過實際例子測試並提了一個 PR,最終代碼合併解決了這個問題,固然也幫助其餘遇到這個問題提 issue 的小夥伴。

因此遇到問題你能夠提 issue 被動等待做者解決,也能夠主動出擊,分析源碼,經過實際例子證實代碼存在 bug,須要修復。

PR:https://github.com/zino-app/graphql-flutter/pull/162

5. 請教他人

這個之因此放在最後是由於,這個方法是一把雙刃劍,用的好你會成長,用很差你會給本身加上枷鎖。

咱們先說說好的一方面:
假設你按照前面 4 個方法論依然無法解決這個問題,那麼你能夠請教他人來解決這個問題。若是他人知道這個問題的解決方法,那麼你不止知足於這個問題的解決,過後你還須要進行總結。
總結爲何他人能夠解決這個問題:
是經驗問題?
仍是有一些其餘渠道你以前沒有考慮?
是否更新完善上面的解決問題方法論?
經過這樣的不斷總結,你後面須要請教他人的次數會愈來愈少。或者真的你解決不了須要請教他人的時候,可能他人也不清楚。由於他的方法論你都熟悉了,而你也是如此去完善的。

接下來講說很差的一方面:
假設你遇到問題,你就請教他人,解決問題以後就不理了。後續有問題依然如此循環往復,那麼結果你獲得的就是依賴性。假設後面有相似問題存在,而別人沒空回答你,你就不知道要怎麼辦了,由於你沒有一套本身解決問題的方法論。並且由於你以前已經善於依賴別人解決問題了,所以你如今會很迷茫,不知道如何下手。再者,你們都很忙,你請教他人,他人不必定會回答你,至於何時回答你,以及答案是否正確,都是不可預知的。

假設咱們要幫助別人,我仍是提倡授人以漁而不是授人以魚。

最後我再說一下關於請教他人這個問題:
別人沒有義務幫你解決問題,因此若是別人沒回答你的問題,這是正常的。
若是別人回答你的問題,解決你的問題你能夠表示感謝,沒有解決也不用吐槽。
最好的方式仍是本身解決問題。

總結:
1. 根據奔潰棧信息
2. 善用搜索引擎
3. 經過官方渠道
4. 深刻源碼分析
5. 請教他人

相關文章
相關標籤/搜索