自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

如何以失敗驅(qū)動(dòng)開(kāi)發(fā)?

原創(chuàng) 精選
開(kāi)發(fā)
每一次失敗都是一次提升自己的機(jī)會(huì)。正是對(duì)失敗過(guò)程的不斷迭代解決,多年以后,讓我成為一個(gè)更好的開(kāi)發(fā)者。

作者  | 馬大偉

多年以后,面對(duì)這篇文章,我會(huì)想起那兩天失敗的令人崩潰的開(kāi)發(fā)過(guò)程。當(dāng)時(shí),只是一個(gè)簡(jiǎn)單的編碼需求,我信心滿滿的計(jì)劃一下午搞定,但是最終的過(guò)程卻是令人如此沮喪,讓我不得不懷疑我還適不適合繼續(xù)當(dāng)程序員。

思緒飄到那天的場(chǎng)景,我在開(kāi)發(fā)過(guò)程中遇到一個(gè)很簡(jiǎn)單的需求:將 JSON 格式的文件轉(zhuǎn)換成 JavaScript 的常量文件(json到j(luò)s的轉(zhuǎn)換不只是格式的轉(zhuǎn)換,還要在js文件生成json的全路徑)。如下圖:

我的想法是先把 JSON 轉(zhuǎn)成一棵抽象語(yǔ)法樹(shù)(AST),然后遍歷這棵樹(shù),在特定的節(jié)點(diǎn)打印出所需的字符就可以了。JSON 轉(zhuǎn) AST 直接用 Clojure 的神器 instaparse 庫(kù)。我對(duì) Clojure 不熟悉,剛好可以通過(guò)這個(gè)過(guò)程提升下,也能試試這個(gè)神器到底神不神。通過(guò)這種特殊需求能一舉多得,讓無(wú)聊的開(kāi)發(fā)過(guò)程變得有期待。

第一步是將 JSON 轉(zhuǎn) AST。對(duì)于 instaparse 庫(kù)來(lái)說(shuō)這是個(gè)很簡(jiǎn)單的任務(wù),網(wǎng)上隨便搜索下就找到了解析 JSON 的代碼。耗時(shí)不過(guò)幾分鐘。

第二步是需要遍歷這棵樹(shù)。遍歷樹(shù)是我在大學(xué)算法課程上就學(xué)過(guò)的,雖然年代久遠(yuǎn)算法的細(xì)節(jié)都已經(jīng)忘記,但是我還記得有深度遍歷和廣度遍歷兩種方式。我的這個(gè)需求特殊之處在于需要在遍歷的時(shí)候打印相關(guān)的字符,比如需要在遍歷某個(gè)節(jié)點(diǎn)開(kāi)始和結(jié)束的時(shí)候都得打印 [] 或 {} 。Clojure 應(yīng)該有具體的庫(kù)做這個(gè)事,簡(jiǎn)單搜索下很快就找到了 walk 和 tree-seq 這兩個(gè)函數(shù)。這兩個(gè)函數(shù)看起來(lái)比較復(fù)雜,找了一些例子大概了解到: walk 函數(shù)可以在遍歷是提供入和出兩個(gè)鉤子來(lái)執(zhí)行對(duì)集合元素的轉(zhuǎn)換,而 tree-seq 會(huì)以深度遍歷樹(shù)的方式輸出一個(gè)節(jié)點(diǎn)序列。理解后就開(kāi)始嘗試,花了半天后發(fā)現(xiàn)事情比我想象中的復(fù)雜,這兩個(gè)函數(shù)看起來(lái)強(qiáng)大,但是無(wú)法在遍歷節(jié)點(diǎn)時(shí)保存狀態(tài),而我卻需要這個(gè)狀態(tài)來(lái)記錄我遍歷的路徑??雌饋?lái)需要自己寫(xiě)個(gè)遍歷算法來(lái)實(shí)現(xiàn)了,這時(shí)候半天已經(jīng)過(guò)去了,但我目前的進(jìn)度只解決了一半的問(wèn)題。

自己寫(xiě)遍歷樹(shù)的算法是一件不難的事情,我用 Java 也實(shí)現(xiàn)過(guò),現(xiàn)在用 Clojure 實(shí)現(xiàn)看起來(lái)也不難。但是 Clojure 和 Java 的差異很大:它是函數(shù)式的,數(shù)據(jù)類(lèi)型都不可變,很多操作都是通過(guò)遞歸來(lái)完成。用遞歸來(lái)實(shí)現(xiàn)深度遍歷也不是難事,但是當(dāng)你用不熟悉的語(yǔ)言去實(shí)現(xiàn)問(wèn)題可能就會(huì)變得不可控。

在嘗試了一天多并寫(xiě)了三個(gè)失敗的版本后我陷入了絕望的狀態(tài),因?yàn)橐粋€(gè)非常簡(jiǎn)單的問(wèn)題我卻搞不定。在第二個(gè)版本的時(shí)候我以為我解決了這個(gè)問(wèn)題,最終把實(shí)際的數(shù)據(jù)輸入?yún)s發(fā)現(xiàn)結(jié)果不符合預(yù)期。因?yàn)槲矣昧撕?jiǎn)單的測(cè)試數(shù)據(jù),實(shí)際的數(shù)據(jù)比測(cè)試數(shù)據(jù)全面,我寫(xiě)的版本只是解決了測(cè)試數(shù)據(jù)的問(wèn)題。在第三個(gè)版本的時(shí)候因?yàn)榭紤]的情況更多寫(xiě)的也更復(fù)雜了,導(dǎo)致程序始終跑不起來(lái)。因?yàn)槲也皇煜?Clojure 的語(yǔ)法,始終難以寫(xiě)出滿足條件的遞歸代碼。

由于長(zhǎng)時(shí)間在這個(gè)問(wèn)題上耗著又沒(méi)有任何思路,我在周末連續(xù)搞了十幾小時(shí)后眼睛和腰終于受不了了。第二天整個(gè)人身心俱疲,在床上躺了半天后琢磨如何尋求幫助。腦海中第一個(gè)念頭就是在 Clojure 的社區(qū)里直接提問(wèn)。為了能讓大家有意愿回答我的問(wèn)題,我首先把自己的問(wèn)題梳理了下,畫(huà)了一個(gè)簡(jiǎn)單的草圖:

然后在 StackOverflow 提了這個(gè)問(wèn)題,并在 Clojure 的 Discord 群組、Telegram 國(guó)內(nèi)社群和微信群里發(fā)了這個(gè)問(wèn)題。大概不到半小時(shí),微信群里有兩個(gè)人發(fā)了自己的代碼。這兩種代碼體現(xiàn)了不同的解決思路,并且附帶優(yōu)雅的實(shí)現(xiàn),具體的實(shí)現(xiàn)方案我整理到了這個(gè) livebook 中。

第一種方案直接通過(guò)遞歸將 AST 語(yǔ)法樹(shù)轉(zhuǎn)換成了目標(biāo) Map 的數(shù)據(jù)結(jié)構(gòu),然后使用 Json 庫(kù)打印成 Json 格式。第二種方案沒(méi)有使用 AST 語(yǔ)法樹(shù),直接通過(guò) Json 庫(kù)拿到 Json 數(shù)據(jù)結(jié)構(gòu)然后遞歸遍歷輸出最終目標(biāo)數(shù)據(jù)結(jié)構(gòu)。

在群里與這兩個(gè)人溝通的過(guò)程中,我發(fā)覺(jué)我在不知不覺(jué)中犯了幾個(gè)錯(cuò)誤:

  • 不熟悉 Clojure 代碼,導(dǎo)致沒(méi)法使用最佳的函數(shù)和思路去解決問(wèn)題;
  • 通過(guò) Json 庫(kù)去輸出最終數(shù)據(jù)結(jié)構(gòu),而我卻是采用打印的方式將問(wèn)題復(fù)雜化;
  • 沒(méi)必要通過(guò)抽象語(yǔ)法樹(shù)去解決,通過(guò) Json 庫(kù)遞歸遍歷 Json 是更簡(jiǎn)單的方案;
  • 沒(méi)使用更好的工具。我一開(kāi)始用命令行自帶的 Repl,后來(lái)覺(jué)得編輯長(zhǎng)函數(shù)不方便,所以在網(wǎng)上找了一個(gè)在線 Repl。不過(guò)后來(lái)看到群友提供的在線 livebook, 這種能更方便的開(kāi)發(fā)并記錄這類(lèi)代碼。

回顧這個(gè)問(wèn)題的解決過(guò)程,我總結(jié)此次開(kāi)發(fā)失敗的原因有以下:

  • 理解需求錯(cuò)誤。我在遇到這個(gè)問(wèn)題后并未做深入的分析思考,導(dǎo)致一開(kāi)始就沖著問(wèn)題的表象去解決。想著用打印的方式去解決問(wèn)題,實(shí)際上可以用庫(kù)來(lái)輸出目標(biāo)格式。
  • 不熟悉相關(guān)技術(shù)。我對(duì) Clojure 的熟悉程度還不足以解決這類(lèi)并不簡(jiǎn)單的問(wèn)題。
  • 解決問(wèn)題不全面。問(wèn)題總有很多解,拿著錘子很容易看啥都是釘子。我從一開(kāi)始就想通過(guò) AST 去解決這個(gè)問(wèn)題,導(dǎo)致思維局限到一條線上了。
  • 害怕失敗。因?yàn)橐婚_(kāi)始覺(jué)得問(wèn)題很簡(jiǎn)單,害怕自己沒(méi)法在很短的時(shí)間解決,心態(tài)處于失衡的狀態(tài)。后期耗著的時(shí)間越長(zhǎng),思考能力越不在狀態(tài),反而越來(lái)越迷糊。

失敗驅(qū)動(dòng)開(kāi)發(fā)

不了解程序員的人眼中的程序員可能是這樣的:

但開(kāi)發(fā)程序或維護(hù)程序,失敗是很常見(jiàn)的:

  • 編譯失敗;
  • 運(yùn)行失??;
  • 網(wǎng)絡(luò)失??;
  • 內(nèi)存失敗;
  • 并發(fā)失敗;
  • I/O 失??;
  • 認(rèn)證失敗;
  • 權(quán)限失??;
  • 依賴(lài)失??;
  • 資源失敗;
  • 上線失??;
  • 升級(jí)失?。?/li>
  • 環(huán)境設(shè)置失?。?/li>
  • 理解需求失?。?/li>
  • 項(xiàng)目管理失??;
  • 架構(gòu)設(shè)計(jì)失?。?/li>

程序員的日常就是要在無(wú)數(shù)失敗中找尋讓程序正常運(yùn)行的那一種組合,成功運(yùn)行更像是運(yùn)氣與實(shí)力的雙重作用,這也就有了失敗驅(qū)動(dòng)開(kāi)發(fā)(Failure Driven Development)。

失敗既然是不可避免的,要做好一個(gè)程序員,與失敗平和相處是必須要解決的問(wèn)題,不然情緒會(huì)長(zhǎng)期處于失衡狀態(tài)。

如何以失敗驅(qū)動(dòng)開(kāi)發(fā)?我會(huì)從以下清單出發(fā)找尋處理失敗的方法:

是否全面理解問(wèn)題?

很多時(shí)候不是問(wèn)題復(fù)雜,而是我錯(cuò)誤的理解了問(wèn)題,在錯(cuò)誤的路上越走越遠(yuǎn)。每當(dāng)失敗時(shí)我會(huì)重新全面的思考問(wèn)題,看是否能發(fā)現(xiàn)新的解決問(wèn)題的思路。

是否涉及知識(shí)盲區(qū)?

盲區(qū)是你不知道自己不知道。用有限的知識(shí)去解決未知的問(wèn)題很容易陷入盲區(qū)而不自知。我的方法是如果一個(gè)失敗的原因我沒(méi)法在幾天內(nèi)解決,那很可能就是遇到知識(shí)盲區(qū)了。要跳脫盲區(qū)必須全面的搜索關(guān)聯(lián)的知識(shí),通過(guò)知識(shí)的交叉理解或?qū)ふ腋私膺@個(gè)領(lǐng)域的人幫忙是有效的解決方法。

對(duì)技術(shù)的掌握是否滿足要求?

用不熟悉的技術(shù)去解決不懂的問(wèn)題很容易失敗。如果對(duì)技術(shù)不熟悉并且難以解決問(wèn)題的話,我會(huì)從短期和長(zhǎng)期兩個(gè)方面出發(fā)制定不同的方案。短期可能會(huì)尋求外部幫助讓更了解的人來(lái)幫我解決,長(zhǎng)期我會(huì)投入更多時(shí)間提升這方面的技術(shù)。

所用技術(shù)或工具是否合適?

用不合適的技術(shù)和工具去解決問(wèn)題也很容易導(dǎo)致失敗,并且這種失敗是難以察覺(jué)的。有時(shí)候不合適的技術(shù)或工具并不會(huì)讓問(wèn)題無(wú)法得到解決,而是會(huì)浪費(fèi)你大量的時(shí)間去解決技術(shù)或工具本身的問(wèn)題。要解決這類(lèi)失敗需要擴(kuò)大知識(shí)廣度,在搜索資料時(shí)不局限某一種技術(shù),如果你對(duì)多種技術(shù)有一定的理解,就很容易發(fā)覺(jué)技術(shù)之間的差異。用合適的技術(shù)或工具能達(dá)到事半功倍的效果。

是否存在解決方案?

很多問(wèn)題早已經(jīng)被前人解決。所以當(dāng)遇到感覺(jué)復(fù)雜的問(wèn)題,我會(huì)先搜索一番已經(jīng)存在的解決方法,對(duì)問(wèn)題現(xiàn)存的解決方法有個(gè)大概的認(rèn)知,然后修改這些解決方法讓其能更好的解決我的問(wèn)題。

是否需要記錄問(wèn)題?

各類(lèi)很難搞的問(wèn)題是提高能力的好機(jī)會(huì),學(xué)習(xí)現(xiàn)存的解決方法能消滅知識(shí)盲區(qū)。所以不斷的記錄總結(jié)這種問(wèn)題是提高我能力的好方法。如果一個(gè)人一輩子遇不到難題,他也只能停留在現(xiàn)有的能力圈無(wú)法破圈。

是否需要尋求幫助?

花了很多時(shí)間問(wèn)題卻解決不了是很令人沮喪,有些問(wèn)題還很緊迫。在嘗試一定時(shí)間還毫無(wú)頭緒時(shí)我就會(huì)想辦法找人幫忙。讓人愿意幫忙也需要一些技巧,如果你提出一個(gè)很大的問(wèn)題,沒(méi)人會(huì)愿意免費(fèi)幫忙。所以我會(huì)把問(wèn)題相關(guān)的上下文都寫(xiě)下來(lái)或畫(huà)下來(lái),然后將我錯(cuò)誤的解決方法放上去,標(biāo)記清楚失敗的點(diǎn)在哪里,然后把問(wèn)題發(fā)給我覺(jué)得有這方面技術(shù)的朋友、同事及相關(guān)的社區(qū)。

如果問(wèn)題比較復(fù)雜,我會(huì)提出付費(fèi)咨詢(xún)的請(qǐng)求。在別人幫忙解決后,及時(shí)表達(dá)感謝之情,如有必要也可以發(fā)個(gè)紅包。當(dāng)你通過(guò)這種方法認(rèn)識(shí)不同領(lǐng)域的人,逐漸地你解決問(wèn)題的效率也會(huì)得到提高。一些人會(huì)擔(dān)心,將自己的愚蠢公開(kāi)暴露出來(lái),尤其是一些低級(jí)錯(cuò)誤出現(xiàn)的時(shí)候,是一件很掉面子的事情。其實(shí)一開(kāi)始我也擔(dān)心,但是在網(wǎng)上你可以有很多虛擬身份,能緩解這種不適。

更重要的是,暴露自己的愚蠢能有效的解決自己的知識(shí)盲區(qū),你覺(jué)得很復(fù)雜的問(wèn)題在有經(jīng)驗(yàn)的人看來(lái)是很簡(jiǎn)單的事情。這其實(shí)是一種極其有效的學(xué)習(xí)成長(zhǎng)方式,在這個(gè)過(guò)程中我不僅可以解決我的難題,還能學(xué)習(xí)有經(jīng)驗(yàn)的人在這領(lǐng)域里的方法論和效率工具。

身體狀態(tài)是否合適?

長(zhǎng)時(shí)間耗在一個(gè)問(wèn)題上,身體和大腦都會(huì)疲憊。當(dāng)心態(tài)失衡時(shí),解決問(wèn)題的能力也會(huì)直線下降。我經(jīng)常會(huì)陷入一種急迫解決問(wèn)題的困境,直到身體完全扛不住才放棄。這其實(shí)是一種低效的方式,情緒會(huì)在這個(gè)過(guò)程中逐漸壓制理智,讓人很難全面的思考問(wèn)題。

與自己平和相處,接納自己的不足,休息好重新出發(fā)才能走的更長(zhǎng)遠(yuǎn)。所以當(dāng)遇到自己很難解決的問(wèn)題時(shí),試著先確保身體狀態(tài)是正常的,如果身體很疲憊,先休息而不是直接攻克難題。

每一次失敗都是一次提升自己的機(jī)會(huì)。正是對(duì)失敗過(guò)程的不斷迭代解決,多年以后,讓我成為一個(gè)更好的開(kāi)發(fā)者。

責(zé)任編輯:趙寧寧 來(lái)源: Thoughtworks洞見(jiàn)
相關(guān)推薦

2020-07-15 07:33:18

物聯(lián)網(wǎng)大數(shù)據(jù)IOT

2014-04-29 10:44:50

驅(qū)動(dòng)開(kāi)發(fā)開(kāi)發(fā)

2011-08-22 13:52:20

iPhone開(kāi)發(fā)View

2020-12-16 15:53:59

開(kāi)發(fā)編程語(yǔ)言技術(shù)

2013-10-28 19:23:21

OA信息化

2018-06-22 13:25:14

2017-08-31 16:39:57

2022-04-27 08:22:41

非代碼形式開(kāi)源開(kāi)發(fā)者

2023-03-06 08:53:02

2013-03-28 10:52:41

企業(yè)級(jí)移動(dòng)應(yīng)用開(kāi)發(fā)移動(dòng)信息化

2023-02-23 19:28:09

ODD測(cè)試

2021-11-25 22:49:58

Windows 10Windows微軟

2023-04-26 09:37:25

智駕開(kāi)發(fā)

2023-09-19 09:35:31

CIO技能趨勢(shì)

2011-08-01 09:20:12

簡(jiǎn)化數(shù)據(jù)庫(kù)

2011-07-25 16:50:24

Windows安全模式

2023-03-02 13:32:23

2011-12-20 09:24:15

2021-03-11 12:23:13

Linux驅(qū)動(dòng)開(kāi)發(fā)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)