在以前的文章中,曾經提過“技術人員的價值,不在于你能寫出多么優美的代碼,也不在于你能設計出一個多么大而全的高屋建瓴的架構,而在于你實實在在的解決問題的能力,在于你使用技術手段服務于業務的能力”,
最近一段時間,因作業中遇到一些現象,讓我重又想起這句話,并且試圖思考如何來提高解決問題的能力,有沒有一種方法論的手段或者技術性的框架來實踐?
先羅列一兩個遇到的現象:
-
某同事匯報,測驗提了一個Bug,當某個用戶系結的卡資訊超過50個的時候,后臺顯示資料就會出現混亂,問能不能限制系結的卡不超過50個,我問:資料顯示出現混亂是什么意思?答:不清楚;我再問:為什么超過50個就會混亂了,少于50個有沒有可能出現混亂,造成混亂的原因是什么?答:不知道,我說你先去搞清楚什么叫“混亂”,然后再搞清楚為什么會出現“混亂”再來說解決辦法,經過與測驗人員的一番溝通后,跟我反饋說不是顯示混亂,是顯示不全,自己通過查看實作是因為在服務端做了字串拼接,超過多少就被截斷了,
-
某同事在抱怨,這個問題很難復現,我不知道怎么解決,要不要把這塊整體優化下算了,我問他你優化的目的是什么,是優化目前實作的流程、結構?還是通過優化來解決這個難以復現的問題?答:來解決這個問題,我說你問題都沒定位到,怎么通過優化來解決,不怕老問題沒解決,優化出新的問題出來了?
你有沒有也曾經說過或聽過“這個問題太復雜了, 我解決不了”,“這個功能我沒辦法實作”,“我也不知道為什么會出現這個問題”之類的話語,
以上的現象與話語,可能都是一個人解決問題的能力或方式方法還不成熟的體現,那么如何來提高解決問題的能力,我想首先需要先從思維方式或思維習慣上尋求改變,在網上看到有這么一篇文章——《How to think like a programmer — lessons in problem solving》(文章地址見文末參考部分),介紹了通過5個步驟來幫忙人們建立高效解決問題的思維框架,本文以這5個步驟為基礎,結合自身的理解與體會進行介紹,

“這個國家的每個人都應該學計算機編程,因為它會教你如何思考”
像程式員一樣思考
像程式員一樣思考,到底意味著什么,需要如何來做?
像程式員一樣思考本質上來說,是一種更為有效的解決問題的方法,
解決問題的能力是一項元技能
什么叫元技能?
類比于元資料——描述資料的資料叫元資料,我理解元技能就是提升技能的技能,就是說當你掌握了解決問題的能力,你就可以通過這種能力去提升其它各項專業技能,
解決問題的能力也是最重要的能力,比精通編程語言,除錯能力,以及系統設計能力都更為重要,
提高解決問題能力的方法
我們平時解決問題的方式可能是:
- 嘗試一種解決方案,
- 如果這種解決方案無效,再嘗試另一種方案,
- 如果還是沒有用,重復第二步直到你碰巧把問題解決了,
這種方法被作者 Richard Reis 定義為解決問題最糟糕的方式,因為它不但浪費時間,而且能不能達到目的還得看運氣,
經過對優秀程式員在編程時的思維框架的分析,作者總結出提高解決問題能力的最好方法包括:
- 有一個處理問題的框架
- 按照這個框架反復練習
那么,當你遇到一個新的問題時,該如何來解決?
第一步:理解
遇到問題時,我們應該先要弄明白問題本身,大部分情況下,問題之所以難解決只是因為你沒真正理解它們(很多時候是出于溝通的不充分),理解問題是解決問題的第一步,
如何確定自己是否真正理解一個問題?
最有效的方法是,嘗試用自己的語言來說出它,看有沒有邏輯漏洞,當你能講清楚一個問題時,說明你理解了它,優秀的程式員編程時,一般都會寫下自己遇到的問題,畫出流程或序列草圖,或同產品經理、其它開發人員、測驗人員等一起討論確認,這個程序,就是在確定自己對問題的理解有沒有偏差,
“如果你不能用簡單的語言來解釋一個事情,那意味著你根本就沒有理解它” —— Richard Feynman
面對一個新需求時,你應該了解這個需求產生的場景——什么人,在什么時候通過執行什么操作,來達到什么目的?這個場景及其中的行為邏輯是否合理,設計是否存在漏洞,然后帶著問題來與需求提出方討論確認,而不是斷章取義或不經任何思考直接編碼開干,不做代碼的搬運工,要做有思想的程式員,
同樣,面對一個 Bug 時,你應該首先了解這個 Bug 產生的場景——什么人,在什么場景,通過什么操作會產生這個問題?要追本溯源,定位問題的本源在哪里,
我認為定位問題的本源比解決問題更重要!因為你只有正確地找到了問題的癥結,才有可能去解決它,而解決辦法卻可能有多種,且從花費的時間來說,定位問題往往會占整個解決問題時間的一半以上,
如果沒有找到問題的本源,只是頭痛醫頭腳痛醫腳,那么可能不僅對解決問題無事無補,甚至還可能引進新的問題,常見的頭痛醫頭腳痛醫腳的處理方式包括,CPU占用高了,記憶體溢位了——升級服務器配置(可能過兩天又得升級了!);介面超時了——增大超時時間(可能導致用戶投訴或其它依賴的服務級聯超時),等等,
那么日常作業中,如何來定位問題的根源?對于一般問題來說,可能通過查看日志大致就能找到問題所在,對于比較棘手的問題,針對問題的性質一般可通過如下方法進行定位:
- 對于易復現的問題: 常用的就是 Debug,通過 IDE 斷點來跟蹤資料的流轉與變更,一個個環節檢查資料輸入輸出是否正確來進行排查,可借助條件斷點、例外斷點等技巧來提高 Debug 效率,
- 對于不易復現的問題:可通過對比法——對比其它地方的類似功能或實作,尋找兩者之間的差異,差異之處往往就是問題所在;分析法——走讀整體流程代碼,捋清各個環節的邏輯,分析定位問題;日志法——在各個關鍵環節添加日志,將場景鏡像下來,當下次復現的時候,通過分析日志定位問題,
第二步:計劃
理解了問題,接下來就是解決問題的方案,沒有明確的方案計劃時,不要輕易去著手解決問題,不要寄希望于碰運氣蒙混過關,許多開發人員習慣于快速掃一眼需求,就打開 IDE 開始壘代碼,壘完發現要么與需求不符,要么漏洞百出,

制定計劃,就是制定解決問題的戰略步驟,
不論面對需求還是 Bug,都應該好好計劃你的解決方案,設計好解決方案中的各個環節,如業務需求的資料表設計、介面設計、流程邏輯,Bug 修復的具體實施步驟,并給自己一點時間思考與預演,該解決方案可能存在的漏洞與影響有哪些,除了這樣處理,還有沒有另外更好的解決方案,
在沒有想清楚解決方案時,不要直接上來就擼代碼,暫停一下,給你的大腦一些分析問題和處理資訊的時間,
第三步:分解
這是思維框架中最重要的一步,
分解,就是化繁為簡,就是我們常說的分治思想,拆分法——將大問題拆分為若干個小問題,然后逐個擊破各個小問題,再合并總結,微服務架構,MapReduce 演算法,都是這一思維(或思想)的體現,
不要嘗試一次解決一個復雜的大問題,而應把復雜的大問題分解成若干個簡單的小問題(或子問題),從最簡單的子問題開始(最簡單意味著你知道怎么解決它或它更容易被解決,也或者這個子問題的解決不需要依賴于其它子問題),一個一個逐步解決,一旦你解決了所有的子問題,把它們串聯起來,一般就意味著你解決了之前的那個復雜的大問題,
分解問題的能力是解決問題的基石,這也是優秀的程式員在編程中最常用到的技能,對于他們來說,分解問題的能力,要比編程語言的熟練度、系統設計等技術更為重要,
第四步:卡殼了怎么辦?
當你理解了問題,做出了解決方案的計劃,將復雜問題分解為子問題后,在處理子問題時依然卡殼了怎么辦?
首先,淡定!然后告訴自己,這很正常,每個人都會遇到,
優秀程式員或解決問題的高手,與普通人之間的差別就在于,他們對問題更有求知欲,更有耐心,他們的注意力更多地是在如何解決問題上,而不是為此畝訓或甩鍋發牢騷,
當遇到卡殼的情況時,可以試試這幾種方法:
-
Debug:與前面定位問題一樣,一步一步除錯,直到找出究竟哪里出錯了,
“Debug 的藝術關鍵在于你究竟讓軟體干了些啥,而不是你以為你讓軟體干了些啥,”—— Andrew Singer -
重新評估問題:退回去,從另一個角度重新審視問題,別讓自己迷失在細節里,有時候我們容易迷失在具體的細節中而忽略了更一般的原則,重新評估問題的另一種途徑是推倒重來,可以洗掉(回滾)所有已做的事,重新開始,有時這是非常行之有效的方式,
-
搜索解決方案:利用搜索引擎找到類似問題的解決辦法,向他們學習,使用搜索引擎需要學會提煉關鍵字,關鍵字越有代表性,越容易找到答案,對搜索結果應該抱著參考的態度,而不是照搬,要明白為什么如此這般處理就能解決問題,并在解決問題后能依次延伸了解其上下游或相關知識,比如SQL查詢慢,發現是索引未生效,則可以延伸了解都有哪些場景會導致索引失效;比如并發問題,則可以依此了解如何保證執行緒安全,同步機制,鎖機制等相關知識,事實上,即使問題已經解決,你也可以經常這么做,因為這樣你可以從其他人的解決方案中及上下游知識中學到更多,
-
尋求支援:當通過以上方法都無法獲得解決辦法時,向你的同事、上級或朋友求援,如果是開源專案,到開源社區、技術群,或 github 的 issue 串列中發帖求援,
-
記錄問題與解決方案:將你本次遇到的問題與最終的解決方案用(電子)筆記本記錄下來,便于后面回顧或參考,
第五步:練習
羅馬不是一天建成的,你也不可能期盼通過解決一兩個問題就能成為解決問題的高手,但是,如果你能以學習的態度來尋求問題的解決辦法,通過以上四個步驟來建立一套解決問題的思維框架,每一個問題的處理都是提高你能力的機會,那么距離成為一個解決問題的高手,就只差一步了,那就是:練習,練習,再練習,在問題中練習,訓練你的思維方式與習慣,

“我不害怕一次練習1000個踢打動作的人,但我害怕將一個踢打動作練習1000次的人”
總結
其實,解決問題的能力,不論在IT技術領域,還是在其它各個領域,都是一種最基本的技能,當你在說出“這個問題我解決不了”,“這個問題我沒辦法定位”前,試試本文介紹的理解、計劃、分解、卡殼時怎么處理的建議方法,多一些耐心,一步步實踐,說不定慢慢就看到曙光了,按照這個處理模式或習慣,在榷訓月累的問題處理中,你可能已在不知不覺成為了解決問題的高手,
參考:
- https://www.freecodecamp.org/news/how-to-think-like-a-programmer-lessons-in-problem-solving-d1d8bf1de7d2/
原文地址:http://blog.jboost.cn/think-like-a-programmer.html
[轉載請注明出處]
作者:雨歌,可以關注作者公眾號:半路雨歌

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/225490.html
標籤:其他
上一篇:距離順序排列矩陣單元格
下一篇:我的第二故鄉 – 成都 I
