關(guān)于我們
書單推薦
新書推薦
|
重構(gòu)JavaScript
本書作者向你展示如何識別糟糕的代碼,然后通過多種重構(gòu)方法來改進這些糟糕的代碼。采用的技術(shù)從重命名變量到運用函數(shù)式和面向?qū)ο缶幊痰脑瓌t。如果你想在前后端寫出更好的JavaScript代碼,那么本書必不可少。利用重構(gòu)來重新組織現(xiàn)有的代碼,而不改變它的行為。了解重構(gòu)與質(zhì)量之間的關(guān)系。探索現(xiàn)今使用的不同版本的JavaScript。創(chuàng)建自動化測試以確保你的代碼可以工作,并且找到被遺漏掉的錯誤。了解如何重構(gòu)簡單的JavaScript結(jié)構(gòu)、函數(shù)以及對象。運用面向?qū)ο蠛秃瘮?shù)式編程原則來重構(gòu)你的代碼。重構(gòu)異步JavaScript的檢驗方法。
如果你的JavaScript代碼很糟糕,框架只能為你提供有限的幫助。無論使用什么框架、編譯成JS的語言或者庫,如果底層的JavaScript代碼質(zhì)量很糟糕的話,錯誤和性能問題將始終存在。通過本書,你將學(xué)到如何測試和重構(gòu)現(xiàn)有的代碼,以幫助降低復(fù)雜性、提高可讀性并提高對代碼庫的信心。
前言
歡迎閱讀本書。在本書中,我們將探討如何編寫更好的JavaScript,從經(jīng)典的重構(gòu)技術(shù)中獲取靈感,同時探索各種風(fēng)格的編程方式。為什么寫本書不管你喜歡與否,JavaScript都不會消失。無論使用什么框架、編譯成JS的語言或庫,如果底層的JavaScript代碼質(zhì)量很糟糕的話,錯誤和性能將會是始終存在的問題。重寫,包括移植到當(dāng)前熱門的框架,是非常昂貴且不可預(yù)測的。錯誤不會憑空消失,它們?nèi)詴谛碌拇a中重現(xiàn)。如果把事情變得更復(fù)雜,至少要將功能暫時丟棄掉。本書為如何最好地避免不理智地寫JavaScript提供了清晰的指導(dǎo)。糟糕的代碼不必保持這種方式。讓它變得更好并不需要讓人望而生畏,也不會太昂貴。
本書的讀者對象本書是寫給那些有寫糟糕代碼經(jīng)驗,并想要寫更好代碼的人。也是寫給那些在前端或者后端寫JavaScript的人。還是寫給那些寫JavaScript以及由于JavaScript對瀏覽器平臺的壟斷而被困住了的人。你如果是一個純粹的初學(xué)者,那么你可能首先要寫幾個月糟糕的代碼。如果你不想寫更好的代碼,你可能沒有讀完這本書的耐心。如果這兩種情況都不能描述你,那我們繼續(xù)吧。有趣的是,有許多努力使JavaScript變得更好,同時也有其他努力使它過時。寫優(yōu)秀的和糟糕的JavaScript代碼的方法在持續(xù)擴展。框架對于處理復(fù)雜性起很大作用,但是局限于框架的程序員會被限制住。如果你發(fā)現(xiàn)你(或者你的代碼庫)在一個框架之外(或者在更混亂的邊緣)很難工作,本書應(yīng)該會給你提供新的思路去處理你的工作。如果你在測試、調(diào)試或代碼置信度方面有困難,本書對你是有幫助的。我們大多數(shù)人沒有在完美的代碼庫上工作,特別是在JavaScript中,工程師可能主要使用Ruby、Python、Java等。
本書所做的是幫助你識別代碼庫中哪些部分是糟糕的,同時提供了大量的改進選擇。如何使用本書第1~5章描述了JavaScript、重構(gòu)、質(zhì)量、置信度與測試之間的相互作用。在很多書中,通常將測試放在最后。在本書中,對于我們探索的代碼類型,這是不合適的。測試對于置信度至關(guān)重要。置信度對于重構(gòu)至關(guān)重要。重構(gòu)對于質(zhì)量至關(guān)重要,這也是我們的目標(biāo):測試 置信度 重構(gòu) 質(zhì)量JavaScript(及其生態(tài)系統(tǒng))恰好提供了轉(zhuǎn)換發(fā)生的空間,所以開篇這些章節(jié)必須包括對語言本身的探索。如果你對剛才描述的轉(zhuǎn)換完全理解,你可以略讀或跳過這些章節(jié)。雖然不推薦,但這是你的書,所以你可以隨意使用它。如果你認為它最適合用作門擋,或用來取暖或做某種犧牲,那就去做吧。如果你確實發(fā)現(xiàn)了本書有非常規(guī)用途,給我發(fā)圖片或視頻:http://evanburchard.com/contact或在Twitter和GitHub上@evanburchard。我也可以把電子版燒掉或用作門擋嗎?不幸的是,不行。但是,由于本書符合知識共享許可協(xié)議,你可以自由地分享HTML版本以及任何其他在http://refactoringjs.com上的文件的鏈接。在第5章之后,內(nèi)容變得更難,尤其是如果你跳過了第1~5章。有更多的代碼需要寫和跟隨。在第6章和第7章,我們將討論重構(gòu)函數(shù)和對象,我們不會回避一些更復(fù)雜的JavaScript代碼?偟膩碚f,這些章節(jié)的目標(biāo)是為改進代碼提供選擇,而不需要從根本上改變接口。通過應(yīng)用這兩章中的技術(shù),你將能夠?qū)⒒靵y的代碼庫變成有良好質(zhì)量基準(zhǔn)的代碼。第8章將我們的架構(gòu)擴展到包含(或避免)層次結(jié)構(gòu)的視圖。第9~11章專門針對特定的主題(分別是設(shè)計模式、異步編程和函數(shù)式編程),它們可以讓你的代碼超越基準(zhǔn)代碼,這必然涉及更積極的變化。在第9章的設(shè)計模式中,我們認識到從JavaScript的面向?qū)ο蟮姆矫鏀U展和借鑒的方法,并覆蓋了重構(gòu)和面向?qū)ο缶幊蹋∣OP)之間的歷史聯(lián)系。在第10章中,我們處理了許多JavaScript代碼庫同時做很多事情的現(xiàn)實情況。在第11章中,我們將通過幾個庫來體驗函數(shù)式編程,這些庫提供了超出標(biāo)準(zhǔn)數(shù)組函數(shù)(forEach、map、reduce等)所提供的接口。從某種意義上來說,最后的三章脫離了我們最初的重構(gòu)目標(biāo):在不改變接口的情況下改變實現(xiàn)細節(jié)。另一方面,這些接口都是有用的,有時是不可避免的。我們很容易發(fā)現(xiàn)自己為了性能而寫異步代碼;蛘呶覀兛赡馨l(fā)現(xiàn)自己被困在一個代碼庫中,它在OOP 或函數(shù)式編程(FP)投入了大量好或不好的嘗試。因此,無論是通過選擇還是通過我們繼承的代碼,都是我們應(yīng)該關(guān)注并改進的 JavaScript 的部分。如果你對代碼庫采用了完全不同的范式,那么本書大部分內(nèi)容所說的不是你所做的重構(gòu)。如果我們想要嚴(yán)格控制它,這些章節(jié)仍然在它們的范式中重構(gòu)(OOP到更好的OOP,異步到更好的異步,以及FP到更好的FP),如果我們想從最廣泛的角度考慮我們的程序的執(zhí)行(例如,運行node myprogram.js 作為輸入并且being satisfiedwith how it ran作為輸出),那么即使在不同的范式間切換,我們也可以重構(gòu)。我鼓勵你先嘗試較小的增量更改,這會更容易測試并且讓你更有信心。引用William Opdyke關(guān)于重構(gòu)的原始論文:語義等價的這種定義允許在整個程序中進行更改,只要輸入到輸出值的映射保持不變。想象一下,在受重構(gòu)影響的程序周圍繪制一個圓。從圓外觀察的行為不會改變。對于一些重構(gòu),圓包圍了大部分或全部程序。例如,如果一個變量在整個程序中被引用,那么更改其名稱的重構(gòu)將影響大部分程序。對于其他重構(gòu),這個圓覆蓋的面積要小得多;例如,當(dāng)包含在一個函數(shù)中的某個函數(shù)調(diào)用被內(nèi)聯(lián)擴展時,只有一部分函數(shù)體會受到影響。在這兩種情況下,關(guān)鍵思想是從圓外部觀察,調(diào)用的操作結(jié)果(包括副作用)和圓外的引用都不會改變注1。盡管我們可以自由地繪制圓的大小,我們常?吹街貥(gòu)這個詞被隨意使用,就好像它只意味著改變代碼一樣。正如我們在第1章所討論的,它不是這樣的。這在小規(guī)模的項目中很常見,比如我們?yōu)g覽最多的頁面?紤]第8~10章,首先作為架構(gòu)的選擇,其次在這些選擇中創(chuàng)建更好的代碼(安全且增量地)的可能性。例如,如果有人說使用異步代碼來重構(gòu),這可能太寬泛了,以至于難以以安全且增量的方式執(zhí)行。但如果你想到第9章給了你這樣做的力量,我不能阻止你,F(xiàn)在這是你的書。你可以繪制你想要的圓。如果你對任何工具或概念感到困惑,你可能會發(fā)現(xiàn)附錄是有幫助的。如果你正在尋找示例代碼和其他信息,請訪問本書的網(wǎng)站。你也可以在那里找到一個HTML版本的書,如果你喜歡這樣閱讀的話。
總之,本書用來了解: 重構(gòu)。 測試。 JavaScript。 重構(gòu)與測試 JavaScript。 幾個 JavaScript 范式。 使用這些 JavaScript 范式進行重構(gòu)與測試。或者(在成人監(jiān)督下),書的紙質(zhì)版可以用來生火并用于: 取暖。 抗議。 科技圖書犧牲儀式。http://refactoringjs.com/上的電子版文件可以按照知識共享許可限制的方式傳播。如果你有任何問題、疑問、抱怨或贊美,請隨時通過我的網(wǎng)站聯(lián)系我。本書的一些術(shù)語App,應(yīng)用,程序本書中的一些詞是不精準(zhǔn)的。App、應(yīng)用、程序和網(wǎng)站大多數(shù)情況下是可以互換的。如果有任何困惑的地方,本書描述了提高JavaScript質(zhì)量的基本原則,所以這些詞不應(yīng)該完全按照字面意義解讀。也許你的代碼是一個庫或框架?
無論如何,本書中的技巧應(yīng)該都是適用的。通過詞語和圖表提高包容性本書中的一些詞可能不會對每個人都具有包容性。我試圖平衡他和她的使用,我意識到這并不是每個人理想的方式。雖然我更傾向于使用單數(shù)形式,但這不是出版商的準(zhǔn)則。此外,我(太晚)意識到我對圖表的依賴,特別是在第5章中,這可能對有視力障礙的讀者造成嚴(yán)重的傷害。如果你覺得你因為這個原因錯過了任何內(nèi)容,請隨時向我提出任何問題。用戶在本書中還有一個詞我真的很討厭,就是用戶。它并不精確,并且還在創(chuàng)建者(開發(fā)者/ 設(shè)計者)和消費者(用戶)之間拉開了一定距離。更精確和友善的詞通常特定于問題域,否則我們會被像人或使用程序/ 網(wǎng)站的人之類的術(shù)語困住。如果沒有比人或用戶(甚至包括客戶)更具體的術(shù)語,它可能暗示著商業(yè)模式純粹是將人們作為數(shù)據(jù)銷售,但這是另一個討論。關(guān)鍵是,在本書中使用術(shù)語用戶來傳達一個熟悉的概念:使用程序/網(wǎng)站的人。
此外,還沒有廣泛和準(zhǔn)確的術(shù)語來代替用戶體驗(UX)或用戶界面(UI)的相關(guān)術(shù)語。我為了節(jié)省精力,只是在這里談?wù)撍,而不是在幾個地方解釋這個問題,也沒有使用非標(biāo)準(zhǔn)或特定的術(shù)語來解釋常見的抽象概念。無論如何,我完全贊同數(shù)據(jù)達芬奇Edward Tufte的話(及其含義):只有兩個行業(yè)將其客戶稱為用戶:非法藥物和軟件公司。有一個叫做道德設(shè)計的運動,希望能在某種程度上幫助行業(yè)擺脫這一術(shù)語(以及源于它的不合理的做法)。第三方庫和社區(qū)盡管我非常努力地展示了最好的工具來說明重構(gòu)和測試JavaScript的基本原理,但有時你會發(fā)現(xiàn)某個工具并不適合你。好消息是,JavaScript具有豐富的生態(tài)系統(tǒng)以供選擇。我偏愛簡單、靈活和職責(zé)單一的工具,但你可能會有不同的想法。在本書中,大型框架尤其沒有被探究,因為它們往往有自己的其他工具的生態(tài)系統(tǒng)(通常它們本身相當(dāng)活躍和多樣)。
我絕對會在你剛開始的時候推薦一個框架,但是它們在與基礎(chǔ)語言的功能結(jié)合時才是最有用的,我相信本書在這方面會教你很多。此外,每個工具、框架和庫都伴隨著社區(qū)和歷史。正如我不相信任何一種工具能一直有效,我也不支持任何第三方代碼或項目背后的社區(qū)。很多項目有行為準(zhǔn)則,讓你知道參與其中是否會讓你愉快地利用你的時間。API、接口、實現(xiàn)、客戶端代碼這有點模糊,但我希望我能強調(diào)更多的不是對象的層次結(jié)構(gòu),而是一個設(shè)計良好的代碼庫接口的層次結(jié)構(gòu)。當(dāng)代碼是一段簡單的腳本時,我們希望它可以作為一個過程從上到下運行。隨著代碼庫的成熟(通過設(shè)計),我們期望它在三個主要的層中發(fā)展(盡管這顯然會擴展出更復(fù)雜的代碼庫)。第一層在本書中被稱為實現(xiàn),是代碼庫深處的代碼。對于重構(gòu),最重要的區(qū)別是實現(xiàn)層和下一層之間的區(qū)別。第二層可以稱為接口或API ,描述了使用代碼庫作為模塊時應(yīng)該期望與之交互的公有函數(shù)和對象。第三層一般被稱為客戶端代碼或調(diào)用代碼。它指的是與接口層交互的代碼。這是使用模塊的人寫的代碼,并且我們會寫測試代碼來測試接口層。架構(gòu)基礎(chǔ)在本書中,起初我們創(chuàng)建的程序非常沒有條理,我們的重點(不管像OOP或FP這樣的范式)在這三個層之間的劃分。這使得代碼是可測試的和可移植的。如果你主要依賴于提供自己組織的框架,那么你可能不熟悉這個過程。輸入(非局部與自由變量)貫穿全書(特別是第5章),我們區(qū)分三種類型的輸入: 顯式輸入(傳遞給函數(shù)的參數(shù))。 隱式輸入(指代包含上下文對象、函數(shù)或類的this)。 非局部輸入(函數(shù)或?qū)ο笾惺褂玫脑谄渌胤蕉x的值)。這里有兩點要注意。首先,為了圖解或其他原因,函數(shù)內(nèi)創(chuàng)建的局部變量(或常量)不被認為是輸入。其次,雖然本書使用非局部輸入作為一個精確的術(shù)語,但更常見的名稱是自由變量。然而,考慮到非局部輸入可以是常量而不是變量,這樣叫它是有點不精確。類似地,一些人使用術(shù)語綁定變量來指代我們所說的顯式輸入,在某種程度上,也指隱式輸入。本書約定本書使用下列排版約定:斜體(Italic)表示新出現(xiàn)的術(shù)語、網(wǎng)址、郵件地址、文件名與文件擴展名。此外也被用于強調(diào)重點或?qū)Ρ。等寬字體(Constant width)用于程序列表,以及在段落中引用程序中的元素,比如變量或函數(shù)名、數(shù)據(jù)庫、數(shù)據(jù)類型、環(huán)境變量、語句以及關(guān)鍵字。等寬粗體(Constant width bold)表示應(yīng)由用戶輸入的命令或者其他文本。等寬斜體(Constant width italic)表示應(yīng)由用戶提供的值或者由上下文確定的值替換的文本。表示提示或建議。表示一般性說明。表示警告或提醒。使用示例代碼補充材料(示例代碼、練習(xí)等)可以在https://refactoringjs.com下載。這本書是幫助你完成工作的。通常,如果使用本書提供示例代碼,你可以在程序和文檔中使用它。除非你需要大段大段地復(fù)制代碼,否則不需要聯(lián)系我們獲得許可。例如,使用本書中所提供的幾個代碼片段來寫一個程序不需要得到我們的許可。但銷售或發(fā)布OReilly圖書配套的CD-ROM則需要OReilly出版社的許可。引用本書的示例代碼來回答問題不需要許可。將本書中的示例代碼大量放到自己的產(chǎn)品文檔中是需要獲得許可的。如果你在使用示例代碼時注明出處,我們會很感激,但這不是必要的。注明出處的形式包括標(biāo)題、作者、出版社和ISBN。例如:Refactoring JavaScript by EvanBurchard (OReilly). Copyright 2017 OReilly Media, 978-1-491-96492-7。
如果你覺得對于示例代碼的使用超出了上面所給出的許可范圍,歡迎通過permissions@oreilly.com聯(lián)系我們。本書的代碼使用的工具可以在附錄中找到,還有更多關(guān)于覆蓋到的話題的信息。作為參考,本書使用的工具與版本是: node 6.7.0 npm 3.10.3 wish 0.1.2 mocha 3.2.0 deep-equal 1.0.1 testdouble 1.10.0 tape 4.6.3 lodash 4.17.2 assert 1.4.1 underscore 1.8.3 ramda 0.22.1 sanctuary 0.11.1以后的版本不太可能造成問題,但更早的版本可能會出現(xiàn)問題。在較低的版本中,特別是node,它不完全支持本書中的代碼。OReilly SafariSafari(以前的Safari Books Online)是為企業(yè)、政府、教育工作者和個人提供的會員制的培訓(xùn)和參考平臺。會員能夠訪問由超過250個出版商提供的數(shù)以千計的圖書、培訓(xùn)視頻、學(xué)習(xí)路線、互動教程和策劃的播放列表,包括OReilly Media、Harvard Business Review、PrenticeHall Professional、Addison-Wesley Professional、Microsoft Press、Sams、Que、Peachpit Press、Adobe、Focal Press、Cisco Press、John Wiley & Sons、Syngress、Morgan Kaufmann、IBM Redbooks、Packt、Adobe Press、FT Press、Apress、Manning、New Riders、McGraw-Hill、Jones & Bartlett和Course Technology等。欲了解更多信息,請訪問http://oreilly.com/safari。聯(lián)系我們請將關(guān)于本書的意見和問題通過以下地址提供給出版商:美國:OReilly Media, Inc.1005 Gravenstein Highway NorthSebastopol, CA 95472中國:北京市西城區(qū)西直門南大街2號成銘大廈C座807室(100035)奧萊利技術(shù)咨詢(北京)有限公司針對這本書,我們還建有一個網(wǎng)頁,列出了有關(guān)勘誤、示例和其他信息。可以通過以下地址訪問這個頁面:http://bit.ly/refactoring-js_1e。如果對這本書有什么意見,或者要詢問技術(shù)上的問題,請將電子郵件發(fā)至:bookquestions@oreilly.com。在Facebook上找到我們:http://facebook.com/oreilly。在Twitter上關(guān)注我們:http://twitter.com/oreillymedia。在YouTube上觀看我們的視頻:http://www.youtube.com/oreillymedia。致謝感謝我的家人支持我完成本書:母親、父親、Amy、Scott、Gretchen、Max 和 Jade。特別感謝幫助過我開始工作的人:Zeke Templin、Steve Souders、Mary Treseler、Simon St. Laurent和Tyler Ortman。感謝給過我技術(shù)靈感和反饋的人:Jacob Barss-Bailey、Matt Blake、Charles Baakel、Stefano De Vuono和Ryan Duchin。感謝OReilly的工作人員一直以來給予我的幫助:Annalis Clint、Nena Caviness、Michelle Gilliland、Rita Scordamalgia、Josh Garstka、Kristen Brown、Rebecca Demarest、Rachel Monaghan、Shiny Kalapurakkel,特別是我的編輯Nan Barber和Ally MacDonald。感謝我的技術(shù)審稿人:Steve Suering、Shelley Powers、Chris Deely、Darrell Heath和Jade Applegate。感謝那些所做的工作對我有幫助和啟發(fā)的人:William F. Opdyke、Martin Fowler、KentBeck、John Brant、Erich Gamma、Richard Helm、Ralph Johnson、John Vlissides、Douglas Crockford、Tony Hoare、Alexis Deveria、Addy Osmani、Robert Nystrom、BrianLonsdorf、Reginald Braithwaite、Miran Lipovaca、Kyle Simpson、Tom Stuart、MichaelFogus、David Chambers、Michael Hurley、Scott Sauyet、Yehuda Katz、Jay Fields、Shane Harvie、Russ Olsen、Joshua Kerievsky、James Halliday、TJ Holowaychuk、Justin Searls、Eric Elliot、Jake Archibald、Arnau Sanchez、Alex Chaffee、EricHodel、Sean Hussey、Brian Cardarella、Foy Savas、Katrina Owen和Bryan Liles。特別感謝Axel Rauschmayer博士出色的工作,他為我們這些人解釋了規(guī)范,他還為本書做了序。噓……嘿,讀者!我知道它看起來只是一個大名單,但是上面提到的人真的非常棒。附錄中的資源也不如這個名單重要,這里面的很多人做了這些事情。搜索他們的名字會讓你知道他們新的東西,這可能比他們的舊東西更好?烊ゲ椴檫@些人。
感謝TC39和MDN的所有人。感謝我的狗和我散步,即使是我正處于什么東西的中間。另外,也感謝每一位讀者,謝謝你支持我的工作,如果你需要什么請聯(lián)系我。序我仍然記得在1999年Martin Fowler的《重構(gòu):改善既有代碼的設(shè)計》出版時讀了這本書。這本書給了我一個啟示:我從未見過代碼被認為是可塑的。程序員傾向于從頭開始重寫代碼庫,但這本書認為可以通過小的、有原則的和比較安全的步驟來演進和清理現(xiàn)有的代碼。在這樣做的時候,測試提供了一張額外的安全網(wǎng),使你能夠自信地向前推進。我將始終遵循這本書中的一條建議,每當(dāng)你寫代碼時,始終保持兩種行為完全分開:實現(xiàn)新功能和重構(gòu)現(xiàn)有的代碼。如果這樣做,你會避免同時做太多事情,并且會產(chǎn)生更少的錯誤!吨貥(gòu)JavaScript》采用重構(gòu)的思想,將其應(yīng)用于JavaScript的世界。JavaScript的動態(tài)特性意味著與更多的靜態(tài)語言(如Java)相比,你需要使用不同的重構(gòu)技術(shù)。
在Java中,你有靜態(tài)類型。而且繼承和多態(tài)被使用得很頻繁。對于JavaScript,你通常依賴于靜態(tài)檢查工具(如ESLint和Flow),并可根據(jù)需要靈活調(diào)整對象。函數(shù)式編程技術(shù)也更受歡迎。此外,測試發(fā)揮了更重要的作用,但它們往往也更輕量級。對于所有這些問題以及更多內(nèi)容(例如,異步代碼),本書均已經(jīng)涵蓋了!閱讀愉快!Axel Rauschmayer
Evan Burchard是一位Web開發(fā)顧問,同時也是《The Web Game Developers Cookbook》的作者。在線下,他設(shè)計了一個屢獲殊榮的體感游戲,包括堆積真實的冰塊,他也定期繼續(xù)他走遍美國的計劃。
你還可能感興趣
我要評論
|