開發(fā)沒有捷徑?10倍效率10倍價(jià)值的秘密在于此
本文轉(zhuǎn)載自公眾號(hào)“讀芯術(shù)”(ID:AI_Discovery)。
即使是在軟件開發(fā)領(lǐng)域,我們也一直想象著,會(huì)否有一本“武林秘籍”能讓人很快打通任督二脈,進(jìn)入軟件開發(fā)能力和效率的全新境界。
“軟件開發(fā)沒有捷徑可走!每個(gè)人都需要練習(xí)才能變得更好!”這樣的話我們聽了很多次了,但是那些擁有10倍效率的軟件生產(chǎn)力實(shí)踐專家是怎么做到的?有沒有什么要領(lǐng)可以讓人突飛猛進(jìn)?有的!
但是,即使我把它分享給你,詳細(xì)地講給你聽,你可能也需要花費(fèi)10年的時(shí)間才能掌握它,充分體會(huì)到它的簡(jiǎn)單性。我就是這樣的。我的高中編程老師用通俗易懂的語言闡明了這一點(diǎn),然后我通過一些示例代碼,逐步了解了應(yīng)用它的流程。但直到10年后,它才真正深入我心。
這個(gè)秘密就是平均效率和10倍效率之間的關(guān)鍵區(qū)別。掌握它,你能擁有全新的效率,當(dāng)出現(xiàn)新的需求以及代碼環(huán)境發(fā)生變化時(shí),你可以編寫出重用性更高、損壞性更低的代碼。
這個(gè)秘訣就是掌握抽象化。很多開發(fā)人員討厭“抽象化”這個(gè)詞,你會(huì)聽到這樣的建議,比如“不要過早抽象化”,或是《Python之禪》中著名的“顯式比隱式好”,暗示具體化比抽象化好。
這些建議本身是沒有問題的,但一切都取決于具體內(nèi)容?,F(xiàn)代應(yīng)用程序使用了大量的代碼。如果你把現(xiàn)代十大應(yīng)用的源代碼打印出來,紙張高度能與摩天大樓一較高下,而軟件的維護(hù)成本也很高。你創(chuàng)建的代碼越多,成本就越高,而抽象化是簡(jiǎn)單代碼的關(guān)鍵。
約翰·前田在《簡(jiǎn)單法則》中寫道:“簡(jiǎn)單就是減去明顯的東西,加上有意義的東西。”正確的抽象化可以通過隱藏對(duì)當(dāng)前上下文不重要的細(xì)節(jié),減少執(zhí)行相同工作所需的代碼量(通常是幾個(gè)數(shù)量級(jí)),從而使代碼更具可讀性、適應(yīng)性和可維護(hù)性。
圖源:unsplash
抽象不是一個(gè)單向的概念。它實(shí)際上是由兩個(gè)互補(bǔ)的概念構(gòu)成的:
- 泛化--刪除重復(fù)的(顯而易見的)的部分,并將其隱藏在抽象之后。
- 特殊化--將抽象應(yīng)用于特定用例,僅添加需要不同的部分(有意義的)。
請(qǐng)看以下代碼:
- constdoubleList= list => {
- const newList = [];
- for (var i =0; i < list.length; i++) {
- newList[i] = list[i] * 2;
- }
- return newList;
- };
這段代碼本身沒有什么問題,但其中包含了很多細(xì)節(jié),對(duì)該特定的應(yīng)用而言可能并不重要:
- 包含一個(gè)顯式賦值,而不是以聲明方式描述要執(zhí)行的操作,這太冗長(zhǎng)了。
- 包括正在使用的容器/傳輸數(shù)據(jù)結(jié)構(gòu)(數(shù)組)的詳細(xì)信息,這意味著它僅適用于數(shù)組,它包含狀態(tài)形狀依賴性。
- 包括迭代邏輯,這意味著如果你需要其他操作,這些操作也需要訪問數(shù)據(jù)結(jié)構(gòu)中的每個(gè)元素,那么你也需要在該代碼中重復(fù)非常相似的迭代邏輯。它強(qiáng)制重復(fù),這違反DRY原則(請(qǐng)勿重復(fù)自己)。
這些都是沒有必要的部分,可以將其隱藏在“抽象”之后。如此一來,這種通用性很強(qiáng)的方法就能改變現(xiàn)代應(yīng)用程序的構(gòu)建方式,減少我們需要編寫的顯式for循環(huán)的數(shù)量。
使用map操作,可以將代碼簡(jiǎn)化為單行本,即通過刪除明顯的部分(我們很可能在類似代碼中重復(fù)的部分),專注于有意義的部分(只是對(duì)于我們的用例來說需要不同的東西):
- constdoubleList= list => list.map(x => x * 2);
初級(jí)開發(fā)人員認(rèn)為他們必須編寫大量代碼才能產(chǎn)生很多價(jià)值,而高級(jí)開發(fā)人員理解無需編任何寫代碼的價(jià)值。
想象一下,作為一名編碼員,你在像JavaScript這樣的編程語言中廣泛使用了map操作。Map可以把詳細(xì)信息抽象化,例如你要映射的數(shù)據(jù)類型,包含該數(shù)據(jù)的數(shù)據(jù)結(jié)構(gòu)的類型以及枚舉數(shù)據(jù)結(jié)構(gòu)中每個(gè)數(shù)據(jù)節(jié)點(diǎn)所需的迭代邏輯。正是這樣,十年來,它提高了我開發(fā)每個(gè)應(yīng)用程序的效率。
圖源:unsplash
杰里米·阿什肯納斯使此類操作在JavaScript中變得很流行,并通過開拓在CoffeeScript中的使用,為我們?cè)贘avaScript中理所當(dāng)然的許多重要語法快捷方式鋪平了道路。
他制作了Underscore和Backbone,Backscore產(chǎn)生了Lodash(JavaScript中最受歡迎的功能編程實(shí)用程序帶),Backbone則使JavaScript中的MVC架構(gòu)得以普及,并為Angular和React奠定了基礎(chǔ)。
約翰·雷西格制作了非常流行和有影響力的jQuery,它形成了可重用的、封裝的JavaScript模塊(jQuery插件)的最大集合,直到幾年后出現(xiàn)了標(biāo)準(zhǔn)的Node模塊和ES6模塊。
jQuery的選擇器API如此有影響,它構(gòu)成了當(dāng)今DOM選擇API的基礎(chǔ)。當(dāng)要對(duì)React組件進(jìn)行單元測(cè)試時(shí),我仍然能從jQuery的選擇API中受益。
給我一個(gè)足夠長(zhǎng)的杠桿和支點(diǎn),我就能翹起地球。正確的抽象就是可以極大地影響生產(chǎn)力的強(qiáng)大杠桿。抽象并不是一個(gè)令人討厭的字眼,模塊、函數(shù)、變量、類,所有這些都是抽象的形式,它們存在的全部原因是為了簡(jiǎn)化抽象和抽象的構(gòu)成。
沒有抽象就不能構(gòu)建復(fù)雜的軟件。即使是匯編語言也會(huì)使用抽象——指令名稱、內(nèi)存地址變量、子例程(如函數(shù)調(diào)用)跳轉(zhuǎn)到的代碼點(diǎn)等?,F(xiàn)代軟件是由抽象構(gòu)成的分層蛋糕,每一層都給你一個(gè)撬動(dòng)不可能的支點(diǎn)。
圖源:unsplash
我們所追求的高效率關(guān)鍵在于簡(jiǎn)單性,即如何減少正在生成的代碼數(shù)量,如何用更少的資源完成更多的工作,掌握抽象化,你就掌握了秘訣。