成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

我的 2015 年度小結(jié)(技術(shù)方面)

Nosee / 467人閱讀

摘要:因?yàn)槁酚蓪用媸軜I(yè)務(wù)影響很大,經(jīng)常修改一些功能的行為,所以后來大部分測(cè)試都是針對(duì)層面的單元測(cè)試。在我了解的過程中,我發(fā)現(xiàn)中文網(wǎng)絡(luò)上對(duì)的討論非常分散,于是我創(chuàng)建了中文社區(qū),到年末已經(jīng)有個(gè)注冊(cè)用戶和個(gè)帖子了。

https://jysperm.me/2016/02/programming-of-2015/

從 2014 年末開始開發(fā)的一個(gè)互聯(lián)網(wǎng)金融項(xiàng)目終于在今年三月份上線了,這是一個(gè) Node.js 編寫的 Web 服務(wù),但上線僅僅是個(gè)開始,之后的半年時(shí)間我們?nèi)栽谶@個(gè)項(xiàng)目上進(jìn)行著密集地開發(fā)。

就像 2014 年度的技術(shù)小結(jié) 中提到的,2014 一整年我都在進(jìn)行有關(guān)自動(dòng)測(cè)試的實(shí)踐,經(jīng)過幾個(gè)項(xiàng)目的積累,這個(gè)項(xiàng)目從頭至尾都有著覆蓋完整的自動(dòng)測(cè)試,我所有的調(diào)試工作也都是借助自動(dòng)測(cè)試完成的,我甚至沒有在自己的電腦上運(yùn)行過這個(gè)項(xiàng)目的前端頁面。因?yàn)槁酚蓪用媸軜I(yè)務(wù)影響很大,經(jīng)常修改一些功能的行為,所以后來大部分測(cè)試都是針對(duì) Model 層面的單元測(cè)試。

這個(gè)項(xiàng)目使用了一種「以數(shù)據(jù)結(jié)構(gòu)為核心」的設(shè)計(jì),所謂數(shù)據(jù)結(jié)構(gòu)就是一個(gè) JavaScript 的 Object, 對(duì)應(yīng)著數(shù)據(jù)庫中數(shù)據(jù)表的各個(gè)字段,這些代表著業(yè)務(wù)實(shí)體的 Object 在項(xiàng)目中的各個(gè)函數(shù)之間傳遞。絕大部分函數(shù)的參數(shù)和返回值都是這種 Object, 它們?cè)谶@些 Object 上獲得或修改數(shù)據(jù),并將這些 Object 與數(shù)據(jù)庫同步,即使需要傳遞額外的數(shù)據(jù),也是將數(shù)據(jù)作為屬性附加到相關(guān)的 Object 上??梢哉f這是一種非常 JavaScript 的風(fēng)格,因?yàn)檫@些 Object 非常近似于數(shù)據(jù)庫中的一行記錄,所以在單元測(cè)試中很容易構(gòu)造,非常大地簡(jiǎn)化了單元測(cè)試中「構(gòu)造特定環(huán)境」的這個(gè)步驟 —— 函數(shù)的輸入和輸出都是特定結(jié)構(gòu)的 Object, 這對(duì)于 JavaScript 來講太簡(jiǎn)單了。

隨著功能的添加,業(yè)務(wù)邏輯變得越來越復(fù)雜,因?yàn)?Node.js 強(qiáng)制 IO 操作異步的這個(gè)特征,異步流程控制變成了一個(gè)令人頭痛的問題 —— 直到我發(fā)現(xiàn)了 Promise。Promise 是 對(duì)異步任務(wù)的一種抽象,當(dāng)我深入地理解了它的工作原理后,才認(rèn)識(shí)到我在學(xué)習(xí) Node.js 上走的最大的彎路就是很晚才開始了解和使用 Promise.

相比于編寫 Callback 風(fēng)格的異步代碼,使用 Promise 意味著一種思路上的轉(zhuǎn)變,雖然 Promise 的原理簡(jiǎn)單,但在具體的使用場(chǎng)景上還是需要自己做很多嘗試的,例如具有分支的異步邏輯、循環(huán)地處理數(shù)據(jù)、逐級(jí)傳遞異常等。

在這個(gè)實(shí)踐的過程中,我逐步地將自己的項(xiàng)目中的異步代碼改成基于 Promise. 在和 Express 的配合中,我發(fā)現(xiàn)因?yàn)?Express 沒有對(duì) Promise 的支持,所以 Express 的路由定義實(shí)際上變成了 Promise 的「邊界」,所有的 Promise 都要在這里進(jìn)行一次轉(zhuǎn)換,改成 Express 的錯(cuò)誤處理機(jī)制。于是我想如果有一個(gè)支持 Promise 的路由框架將會(huì)是一件很有趣的事情,于是我花了幾天的時(shí)間設(shè)計(jì)并實(shí)現(xiàn)了 Cichorium, 這是一個(gè)代碼只有一百來行,基于 Promise 來提供異步中間件和錯(cuò)誤處理的路由框架。

在使用 Promise 的過程中,也讓我對(duì)「異?!褂辛烁由钊氲恼J(rèn)識(shí),異常是現(xiàn)代語言所提供的非常強(qiáng)大的流程控制機(jī)制,讓本來唯一一條通常的、正確的執(zhí)行路徑變得可以從任何一處中斷,并進(jìn)入一個(gè)所謂的異常處理流程。異??赡馨ā割A(yù)期到的情況」和「非預(yù)期的情況」,如果在自己的代碼中拋出了異常,那么通常是屬于可以預(yù)期到的情況,例如參數(shù)錯(cuò)誤、前提條件不滿足等,拋出異常的目的是為了中斷正常流程,并通知調(diào)用者;而非預(yù)期的情況則可能是所依賴的庫拋出的異常,或因運(yùn)行時(shí)錯(cuò)誤 JavaScript 引擎拋出的異常。

異常會(huì)被調(diào)用棧上離異常被拋出處最近的處理程序捕捉到,一旦異常處理程序「解決」了這個(gè)異常,其他的異常處理程序就不會(huì)再得到通知。所以處理程序應(yīng)當(dāng)只去處理已知的、必須在此處理的異常,然后將其他的異常繼續(xù)向其他處理程序拋出,最后到達(dá)一個(gè)「邊界」,例如作為 HTTP 相應(yīng)發(fā)給客戶端,或打印一條日志。

這個(gè)項(xiàng)目在上線初期時(shí)間趕得比較緊,加上經(jīng)驗(yàn)不足,在上線后的前幾個(gè)月時(shí)間一直都在遭遇性能問題。中間出現(xiàn)過幾次因?yàn)椴l(fā)請(qǐng)求過多,多個(gè)請(qǐng)求修改同一條數(shù)據(jù)進(jìn)而出現(xiàn)的數(shù)據(jù)不一致的情況。本來是有一個(gè)通過簡(jiǎn)單的 Redis 鎖限制一個(gè)用戶同時(shí)只能有一個(gè)寫入數(shù)據(jù)的請(qǐng)求的機(jī)制的,但畢竟不是根本的解決方案。于是我開始嘗試使用 MySQL 的事務(wù),將一組相關(guān)的 SQL 查詢放入一個(gè)事務(wù)中執(zhí)行,對(duì)于有前提條件的更新操作(例如扣余額后余額不能為負(fù)數(shù)),將前提條件作為一個(gè)更新條件,如果執(zhí)行后發(fā)現(xiàn)并沒有行被更新,就說明前提條件不滿足,然后回滾這個(gè)事務(wù),向客戶端報(bào)告失敗。借助于數(shù)據(jù)庫提供的原子性和一致性,即使并發(fā)很高,或者程序崩潰,都不會(huì)出現(xiàn)數(shù)據(jù)不一致。

使用事務(wù)只是解決了在高并發(fā)情況下的數(shù)據(jù)一致性的問題,但并沒有解決性能問題。這個(gè)項(xiàng)目中的數(shù)據(jù)主要是財(cái)務(wù)記錄,用戶的每一次操作都會(huì)生成財(cái)務(wù)記錄,這些數(shù)據(jù)被用來追蹤每一筆資金的流向,會(huì)被聚合起來用于給用戶展示統(tǒng)計(jì)信息,這個(gè)過程需要對(duì)數(shù)據(jù)進(jìn)行篩選、分組、排序等復(fù)雜的計(jì)算。

顯然這些計(jì)算如果在數(shù)據(jù)庫中計(jì)算會(huì)有更好的性能,因?yàn)椴恍枰诔绦蚝蛿?shù)據(jù)庫之間傳輸大量的數(shù)據(jù),而且 MySQL 應(yīng)該會(huì)對(duì)這類計(jì)算有更好的優(yōu)化。于是我開始補(bǔ)習(xí) SQL, 將幾乎全部的篩選、分組、排序邏輯都在 MySQL 中完成。同時(shí)我開始學(xué)習(xí)如何分析 MySQL 的性能瓶頸,最簡(jiǎn)單的就是慢查詢?nèi)罩荆?jīng)一度有一些查詢需要 300 秒的執(zhí)行時(shí)間。至于解決方案,除了優(yōu)化查詢條件之外最主要的就是加索引了,我也花了一些時(shí)間來了解索引背后的原理和最佳實(shí)踐。

這些統(tǒng)計(jì)數(shù)據(jù)和時(shí)間是強(qiáng)相關(guān)的,過去的數(shù)據(jù)通常來講就不會(huì)再修改了,所以如果能夠?qū)⑦@些數(shù)據(jù)的統(tǒng)計(jì)結(jié)果緩存起來,將會(huì)顯著地提高性能。其實(shí)本來也有一個(gè)簡(jiǎn)單的緩存機(jī)制,用戶訪問統(tǒng)計(jì)信息后會(huì)被緩存,但一旦用戶執(zhí)行任何財(cái)務(wù)操作都會(huì)使整個(gè)緩存刷新。所以很容易想到的是進(jìn)行更細(xì)粒度的緩存,即在時(shí)間的維度上應(yīng)用所謂的「套娃娃緩存」,在 Redis 中以天為單位緩存發(fā)生的財(cái)務(wù)變動(dòng)、當(dāng)日結(jié)束時(shí)各項(xiàng)統(tǒng)計(jì)指標(biāo)的值。如果某一天的財(cái)務(wù)數(shù)據(jù)發(fā)生變動(dòng),只需以前一天的數(shù)據(jù)為基礎(chǔ)去計(jì)算之后的數(shù)據(jù),大多數(shù)情況下歷史數(shù)據(jù)是不會(huì)改變的,只會(huì)刷新當(dāng)天的緩存。

這項(xiàng)修改花費(fèi)了不少時(shí)間,因?yàn)樾枰貙懰猩山y(tǒng)計(jì)數(shù)據(jù)的代碼,在前一天的計(jì)算結(jié)果的基礎(chǔ)上計(jì)算出當(dāng)天的統(tǒng)計(jì)數(shù)據(jù),并連同一些中間結(jié)果一起緩存起來,供下一天的計(jì)算使用。相當(dāng)于將原來一個(gè)簡(jiǎn)單明了的計(jì)算過程被拆分成了若干個(gè)小步驟,步驟之間還需要通過 Redis 來交換數(shù)據(jù),看似復(fù)雜,但減少了很多不必要的重復(fù)計(jì)算,上線之后將性能提高了差不多一個(gè)數(shù)量級(jí)。

這個(gè)項(xiàng)目大概是我這一年完成的最滿意的項(xiàng)目了,我參與到了絕大部分的設(shè)計(jì)工作中,也完成了差不多一半的編程工作,從頭至尾都有著完整的自動(dòng)測(cè)試覆蓋,借助 Promise 實(shí)現(xiàn)健壯的異步流程控制和異常處理,在高并發(fā)的情況下實(shí)踐了事務(wù)、緩存、索引相關(guān)的知識(shí)。

-

我從年初 開始使用 Atom 完成我的全部工作,選擇 Atom 并不是因?yàn)樗呀?jīng)有多么好用了,而是因?yàn)?Atom 有著優(yōu)良的設(shè)計(jì)和活躍的社區(qū)。最近兩年我工作都是使用 Node.js 來完成的,而 Atom 也基于 Node.js 和 Web 技術(shù)構(gòu)建起來的,甚至 Atom 也是用 CoffeeScript 實(shí)現(xiàn)的,這種相同的技術(shù)棧,令我非常有「安全感」。我也在了解和學(xué)習(xí) Atom 的實(shí)現(xiàn),它有著完全插件化的架構(gòu)和設(shè)計(jì)良好的 API, 對(duì)我后來重構(gòu) RootPanel 都非常有幫助。

在我了解 Atom 的過程中,我發(fā)現(xiàn)中文網(wǎng)絡(luò)上對(duì) Atom 的討論非常分散,于是我創(chuàng)建了 Atom 中文社區(qū),到年末已經(jīng)有 800個(gè)注冊(cè)用戶和 1000 個(gè)帖子了。說實(shí)話,中文技術(shù)社區(qū)的氛圍并不好,因?yàn)榭赡芗夹g(shù)能力較強(qiáng)或英語水平較高的人會(huì)直接選擇去參與官方的社區(qū),目前也基本上是我一個(gè)人在回答問題、翻譯官方博客和文檔、匯總一些資料,不過既然我還在用 Atom, 就會(huì)一直將這個(gè)社區(qū)維護(hù)下去。

-

RootPanel 在 2015 年上半年依然在緩慢地進(jìn)行著,因?yàn)橥ㄟ^閱讀 Atom 的代碼學(xué)習(xí)到了大量有關(guān)插件化設(shè)計(jì)的方法,所以我這半年并沒有向 RootPanel 中添加新功能,而是一直在反復(fù)地重構(gòu) RootPanel 的架構(gòu)。

首先是為其中的重要概念建立抽象,例如服務(wù)組件(MySQL 數(shù)據(jù)庫、Nginx 站點(diǎn)之類)、計(jì)費(fèi)方案(計(jì)費(fèi)周期、價(jià)格、限制)、支付渠道、控制臺(tái)上的控件等。之前雖然也有針對(duì)這些概念進(jìn)行抽象,但基本上是寫到哪里、需要什么接口,就添加一個(gè)相應(yīng)的接口,缺乏一個(gè)全局性的規(guī)劃。進(jìn)而導(dǎo)致抽象出的概念不夠簡(jiǎn)潔、不夠徹底(有一些插件的邏輯仍散落在核心代碼中)。

JavaScript 本身是一個(gè)很靈活的語言,對(duì)象本身是「無模式」的,屬性和方法都可以隨意地修改,也提供了「原型鏈」來支持對(duì)象之間的繼承關(guān)系。為概念建立抽象的一種有效途徑就是「面向?qū)ο蟆癸L(fēng)格的設(shè)計(jì),Atom 就采用了這樣的設(shè)計(jì),我覺得面向?qū)ο髮?duì)于 RootPanel 可能同樣很合適。

面向?qū)ο笫紫冉y(tǒng)一了「數(shù)據(jù)」和「行為」,讓數(shù)據(jù)可以帶有行為,而在執(zhí)行這些行為的時(shí)候又不必顯式地傳遞數(shù)據(jù);對(duì)象本身也是一個(gè)抽象層級(jí),只要兩個(gè)對(duì)象有相同的屬性和方法(而不論背后的行為),就可以被當(dāng)作同一種對(duì)象操作,即所謂的「鴨子類型」,這對(duì)于插件化的系統(tǒng)而言十分便利。

于是我用了一部分面向?qū)ο蟮娘L(fēng)格來重構(gòu) RootPanel, 將其中很多概念抽象為了類,為每個(gè)模塊起一個(gè)恰當(dāng)?shù)拿?,減少不同模塊之間的依賴;為模塊劃分「級(jí)別」,建立層級(jí)一致的抽象 —— 即在任何一個(gè)層級(jí)來看,抽象都是完整的,讓同層級(jí)的類來打交道,而不是將層次不一的類混在一起。

-

在 2014 年我就一直對(duì) Mongoose 有很多不滿,一直想自己造一個(gè)輪子,在 RootPanel 的開發(fā)過程中也遇到了 Mongoose 的一些坑和一些難以實(shí)現(xiàn)的需求,于是今年終于行動(dòng)起來了,然后就有了 Mabolo —— 一個(gè)輕量級(jí)的 MongoDB ORM。

我對(duì) Mabolo 的定位是一個(gè)簡(jiǎn)單的、「沒有魔法」的 ORM, 每個(gè) Model 都是一個(gè)普通的 JavaScript 構(gòu)造函數(shù),而每個(gè)文檔則都是由這個(gè)構(gòu)造函數(shù)生成的實(shí)例 —— 除了幾個(gè)用來保存內(nèi)部狀態(tài)的不可枚舉屬性之外和普通的對(duì)象沒有任何區(qū)別。Mabolo 不去追蹤數(shù)據(jù)被改變的情況,而是鼓勵(lì)使用 MongoDB 的原子操作符進(jìn)行數(shù)據(jù)更新,Mabolo 僅在更新后幫你將最新的數(shù)據(jù)同步到這個(gè)對(duì)象上。

嵌套對(duì)象是 MongoDB 的特色之一,在實(shí)際項(xiàng)目中也經(jīng)常會(huì)用到這樣的設(shè)計(jì),于是我也為 Mabolo 添加了嵌入式對(duì)象的支持,允許將 Model 中某個(gè)字段的類型設(shè)置為另一個(gè) Model. 在儲(chǔ)存到數(shù)據(jù)庫前會(huì)運(yùn)行所有子 Model 的驗(yàn)證方法,在從數(shù)據(jù)庫取出結(jié)果后會(huì)為每個(gè)子 Model 字段構(gòu)造相應(yīng)的對(duì)象,以便在這些子 Model 上運(yùn)行更新和刪除等方法。

-

五月初的時(shí)候和 Yeechan 等人參加了 SegmentFault D-Day 上海站 的活動(dòng),主要聽了有關(guān) Docker 和 React 的主題分享。

因?yàn)槲议_發(fā) RootPanel 的經(jīng)驗(yàn),對(duì) Docker 這種性能損耗極低的虛擬化技術(shù)自然十分感興趣,在參加這次活動(dòng)之前就去簡(jiǎn)單地了解過 Docker, 當(dāng)時(shí)我對(duì) Docker 的不解主要在于 Image 只能單繼承,這樣就不太容易像「搭積木」一樣去組合自己想要的環(huán)境,這可能是因?yàn)槲臋n上面那個(gè)搭積木的示意圖對(duì)我的誤導(dǎo)比較大。

經(jīng)過這次的主題分享,我才比較全面地了解到基于 Docker 去部署應(yīng)用的思路,即既然創(chuàng)建容器的成本是極低的,那么可以為系統(tǒng)中的每個(gè)部分去創(chuàng)建多帶帶的 Image, 運(yùn)行多帶帶的容器,然后通過 Docker Compose 這類工具去組合容器。Dockerfile 描述了應(yīng)用的運(yùn)行環(huán)境和依賴項(xiàng),而 docker-compose.yml 描述了如何將一個(gè)系統(tǒng)中所需要的各個(gè)部分組合起來,完成了關(guān)于一個(gè)系統(tǒng)的完整描述。在實(shí)際運(yùn)行時(shí),因?yàn)槿萜髦g的聯(lián)系非常少,通常只暴露幾個(gè)網(wǎng)絡(luò)端口,所以給整個(gè)系統(tǒng)帶來了非常好的橫向拓展的能力,系統(tǒng)的每個(gè)部分都可能會(huì)運(yùn)行多個(gè)容器,甚至這些容器可能會(huì)分布在不同的物理服務(wù)器上,同時(shí)提供一致的服務(wù)。

因?yàn)?Docker 是內(nèi)核級(jí)別的虛擬化,對(duì)系統(tǒng)調(diào)用的抽象代價(jià)很低,而因?yàn)槭褂昧?AUFS 對(duì)文件系統(tǒng)進(jìn)行抽象、需要建立虛擬網(wǎng)卡進(jìn)行端口轉(zhuǎn)發(fā),所以磁盤和網(wǎng)絡(luò) IO 的抽象開銷相對(duì)較大。所以 Docker 更適合計(jì)算密集型、依賴復(fù)雜(這樣才能發(fā)揮 Docker Image 的優(yōu)勢(shì))的程序,就是通常 Web 項(xiàng)目中負(fù)責(zé)處理請(qǐng)求的「應(yīng)用」這部分,而將數(shù)據(jù)庫等 IO 密集、部署簡(jiǎn)單、不頻繁升級(jí)的程序直接部署在物理機(jī)上。

現(xiàn)在 Web 后端程序面臨的主要挑戰(zhàn)就是高并發(fā),保證單個(gè)程序的穩(wěn)定性,倒不如采用分布式的架構(gòu),將一個(gè)處理能力強(qiáng)的實(shí)例拆分為若干個(gè)處理能力較弱的實(shí)例,轉(zhuǎn)而保證一旦有實(shí)例失效,可以立刻重新創(chuàng)建一個(gè)實(shí)例接替它繼續(xù)工作。但如果在實(shí)例中儲(chǔ)存了一些全局的狀態(tài)(例如鎖)就無法通過啟動(dòng)多個(gè)實(shí)例的方式來橫向拓展。所以比較理想的實(shí)踐就是將應(yīng)用實(shí)現(xiàn)為「無狀態(tài)」的,即容器中的應(yīng)用只根據(jù)來自網(wǎng)絡(luò)的請(qǐng)求進(jìn)行計(jì)算,對(duì)數(shù)據(jù)庫、緩存和文件系統(tǒng)的調(diào)用同樣通過網(wǎng)絡(luò)去請(qǐng)求容器外部的服務(wù)。這樣才可以進(jìn)一步利用 Docker 的優(yōu)勢(shì) —— 容器可以根據(jù)規(guī)模需要隨時(shí)去在不同的物理機(jī)上創(chuàng)建和銷毀而不需要同步數(shù)據(jù)。

隨著對(duì) Docker 了解的深入,我開始意識(shí)到 Docker 對(duì) RootPanel 這類 PaaS 平臺(tái)是一個(gè)「殺手級(jí)」的應(yīng)用,像 RootPanel 那樣笨拙地使用一系列 Linux 的機(jī)制和工具去隔離用戶和直接使用 Docker 相比毫無優(yōu)勢(shì),讓我很有將 RootPanel 改為基于 Docker 的架構(gòu)的沖動(dòng)。但想來想去還是放棄了這個(gè)想法,因?yàn)橐环矫孢@個(gè)改動(dòng)可能會(huì)非常大,另一方面其實(shí)已經(jīng)有了很多非常優(yōu)秀的基于 Docker 的開源 PaaS 程序了。

后來我加入 LeanCloud 負(fù)責(zé)云引擎的開發(fā)工作,云引擎實(shí)際上就是一個(gè)基于 Docker 的 PaaS 平臺(tái),各方面都和 RootPanel 非常相似。既然日常的工作已經(jīng)是這樣一個(gè)項(xiàng)目了,所以進(jìn)一步促使我中止了 RootPanel 的開發(fā)。但說實(shí)話我對(duì) PaaS 還依然有興趣,也許有一天我會(huì)根據(jù)我在 RootPanel 和 LeanCloud 的經(jīng)驗(yàn),重新設(shè)計(jì)一個(gè)最簡(jiǎn)架構(gòu)的 PaaS 來紀(jì)念 RootPanel.

隨著在工作中深入地了解 Docker, 在年末的時(shí)候我將我的服務(wù)器上應(yīng)用全部換成了基于 Docker 來運(yùn)行,這樣的好處就是每個(gè)應(yīng)用都可以有自己的環(huán)境,而且每個(gè)服務(wù)的環(huán)境和服務(wù)之間的依賴關(guān)系都被描述在了 Dockerfile 和 compose.yml 中,徹底解決了以前服務(wù)器上各種應(yīng)用「亂七八糟」的現(xiàn)象,以后若要遷移服務(wù)器或重新部署將會(huì)變得非常容易。

-

過去一年我花了不少時(shí)間斷斷續(xù)續(xù)地將「JavaScript 權(quán)威指南」和「計(jì)算機(jī)程序的構(gòu)造和解釋」看完了,對(duì) JavaScript 的了解也進(jìn)了一步,其實(shí) JavaScript 對(duì)函數(shù)式風(fēng)格的代碼還是有很不錯(cuò)的支持的。按我在 JavaScript 中對(duì)函數(shù)式編程的實(shí)踐,最有價(jià)值的的兩點(diǎn)就是「無狀態(tài)」和「無副作用」。

隨著前端應(yīng)用越來越復(fù)雜,所展現(xiàn)的數(shù)據(jù)之間的邏輯關(guān)系也越來越復(fù)雜,也出現(xiàn)了很多框架來解決前端 UI 和數(shù)據(jù)(即狀態(tài))之間的同步問題,其中之一的 React 從一個(gè)非常有趣的角度來入手 —— UI 可以是應(yīng)用狀態(tài)的一個(gè)函數(shù),給定一組狀態(tài)就有一個(gè)確定的 UI. 如果每次狀態(tài)發(fā)生變化都重新渲染整個(gè) UI, 便可以極大地降低管理 UI 和 狀態(tài)的復(fù)雜度。

React 還在瀏覽器提供的 DOM 上建立了一層抽象,在每次重新渲染 UI 時(shí),React 操作的都是 Virtual DOM, 而后再去與真正的 DOM 進(jìn)行對(duì)比,更新必要的部分。我覺得這種抽象還是非常有價(jià)值的,Virtual DOM 限制了很多操作,但它提供了優(yōu)化性能的空間,也為將 React 程序遷移到非 Web 平臺(tái)提供了可能性,例如后來我就嘗試過在服務(wù)器端使用 React 來渲染 HTML.

后來我在 RootPanel 和其他一些項(xiàng)目上實(shí)驗(yàn)性地使用了 React, 我也使用了官方推薦的 JSX 來編寫代碼,React 這種將 JavaScript 作為應(yīng)用主體的做法很不同于一些將 HTML 作為應(yīng)用主體的框架。有一些人批評(píng) JSX 將這些年好不容易才分開的 HTML 和業(yè)務(wù)邏輯(JavaScript 代碼)又重新混在了一起。而我則認(rèn)為「模板語言」的出現(xiàn)一方面是因?yàn)椴糠终Z言表現(xiàn)能力較弱,需要模板語言將 HTML 和瑣碎的語法細(xì)節(jié)分離;另一方面則是試圖在數(shù)據(jù)和冗長的 HTML 表現(xiàn)之間建立一層抽象。JavaScript 本來已有很不錯(cuò)的表現(xiàn)能力,JSX 又添加了一些與 HTML 相融合的語法;React 通過引入「組件」的概念來拓展 HTML 的標(biāo)簽,讓用戶可以自己創(chuàng)建包含內(nèi)部邏輯和狀態(tài)的標(biāo)簽,進(jìn)而讓 HTML 表現(xiàn)不再冗長,所以分離就變得不必要了。

總體上來講我對(duì) React 很有好感,因?yàn)槲矣X得 React 很好地實(shí)現(xiàn)了一些函數(shù)式編程的風(fēng)格,來簡(jiǎn)化 UI 編程中對(duì)狀態(tài)的管理,React 鼓勵(lì)將組件設(shè)計(jì)為無狀態(tài)的,同時(shí)將渲染過程設(shè)計(jì)為無副作用的,這樣無論何時(shí),只要狀態(tài)發(fā)生改變就重新渲染整個(gè) UI 即可。

在我后來編寫 LeanEngine Snipper 的時(shí)候,需要在前端進(jìn)行大量數(shù)據(jù)處理以便根據(jù)用戶的篩選來展示圖表。一開始沒有考慮太多,部分函數(shù)是會(huì)修改其參數(shù)(往往是一個(gè)包含大量對(duì)象的數(shù)組)的,在后來支持用戶修改篩選條件時(shí)就遇到了問題 —— 原始數(shù)據(jù)在繪圖的各個(gè)環(huán)節(jié)中都有可能被修改,不得不在開始繪圖之前對(duì)原始數(shù)據(jù)進(jìn)行一次 clone, 在后來的性能分析中發(fā)現(xiàn) 98% 的時(shí)間都花費(fèi)在了 clone 上面。

于是我不得不重構(gòu)代碼,讓大部分函數(shù)不修改參數(shù),而是在參數(shù)的基礎(chǔ)上返回一個(gè)新的對(duì)象,將需要 clone 的數(shù)據(jù)減少到了最小,經(jīng)過這次的優(yōu)化,篩選的性能提高了 40 倍以上。從直觀感受上來看,每個(gè)函數(shù)返回新的對(duì)象會(huì)消耗更多的資源,但在 JavaScript 中,返回新對(duì)象實(shí)際上只是在拷貝它的屬性的引用,并不會(huì)花費(fèi)多少時(shí)間,反倒是在 clone 對(duì)象時(shí)需要遍歷所有的屬性,才需要花費(fèi)大量的 CPU 時(shí)間。

-

因?yàn)樽罱鼉赡甓荚谑褂?Node.js, 我希望也使用 Node.js 來驅(qū)動(dòng)我的博客,我最后選擇了插件化架構(gòu)的 Hexo —— 一個(gè)靜態(tài)博客生成器,我自己編寫了 主題,并將博客的數(shù)據(jù)也托管在 GitHub 上。后來我將 RP 主機(jī)博客、粉絲團(tuán)主頁 也都遷移到了 Hexo, 后來新建的 皮蛋豆腐的博客 也使用了 Hexo.

-

今年我作為 HackPlan 的成員,參與了幾次招聘,后來我也作為求職者參加了幾次面試。

國外的一些職業(yè),包括醫(yī)生、律師,也包括工程師,都普遍地去打造自己的個(gè)人品牌,目的是為了找到更好的工作。確實(shí)在過去兩年中這種個(gè)人品牌對(duì)我的工作是很有幫助的,在我面試的過程中,我去的幾乎所有公司的面試官都表示曾經(jīng)聽說過我。雖說技術(shù)崗位以能力為先,但至少如果混個(gè)臉熟,雙方會(huì)有一個(gè)基本的信任。

我當(dāng)時(shí)說在找到工作之后會(huì)和大家分享一下參加面試的經(jīng)驗(yàn),但后來想了一下,寫出來的話應(yīng)該都是關(guān)于我沒有選擇的那些公司的負(fù)面評(píng)價(jià),大家都是同行,這樣不是很好,所以后來只寫了 加入 LeanCloud 的過程。

-

說實(shí)話,現(xiàn)在使用 Node.js 的公司依然是少數(shù),因此在求職時(shí)我也將 PHP 納入了考慮。在我離開 PHP 之后,社區(qū)發(fā)生了許多變化,出現(xiàn)了像 Laravel 這樣設(shè)計(jì)優(yōu)良的一站式框架,composer 這個(gè)包管理器也被越來越多的人接受。為了重新?lián)炱?PHP 這個(gè)技能,我花了一些時(shí)間用 Laravel 做了一個(gè)最簡(jiǎn)單的論壇系統(tǒng)的輪子 —— labbs-laravel.

在之前,無論是 PHP 還是 Node.js 中,我都沒有使用過像 Laravel 這種重量級(jí)的框架。Laravel 不同于國內(nèi)一些粗制濫造的重量級(jí)框架,雖然它提供了很多功能,但卻并不顯得臃腫。首先 Laravel 并沒有選擇造輪子而是構(gòu)建在 搜索結(jié)果 Packagist 中已有的包之上,它有著一個(gè)非常精簡(jiǎn)的核心架構(gòu),除了經(jīng)典的 MVC 支持外,其他的各類功能(認(rèn)證、緩存、隊(duì)列)都被抽象成了「服務(wù)」,這些服務(wù)可以獨(dú)立為多帶帶的包發(fā)布在 Packagist 上,且同類的服務(wù)是可以互相替換的。

Laravel 對(duì)我來講最大的亮點(diǎn)是 ORM 部分(Eloquent),我之前用過的 ORM 比較少,在實(shí)現(xiàn) Mabolo 的過程中一直在糾結(jié)如何實(shí)現(xiàn)對(duì)象之間的引用關(guān)系。Eloquent ORM 將關(guān)系本身也抽象為了一個(gè)類,當(dāng)你訪問一個(gè)對(duì)象的關(guān)系字段時(shí),得到的是一個(gè)「關(guān)系對(duì)象」,你可以在這個(gè)對(duì)象上進(jìn)行篩選和查詢等操作。其實(shí)這樣的設(shè)計(jì)還是非常直觀的,但因?yàn)槲抑伴]門造車,一直沒能「獨(dú)立發(fā)現(xiàn)」,在新的一年中我會(huì)用這樣的思路去給 Mabolo 添加關(guān)系支持。

-

最后如果做個(gè)總結(jié)的話,我這一年依然主要在編寫 Node.js 代碼,也寫過少量的前端代碼,對(duì) JavaScript 的了解越來越深入。這一年的我在關(guān)注基于 Promise 的異步流程控制和錯(cuò)誤處理、深入了解關(guān)系型數(shù)據(jù)庫和 SQL、探索函數(shù)式風(fēng)格的 JavaScript、探索和學(xué)習(xí)插件化架構(gòu)的設(shè)計(jì)、借助 Docker 來管理應(yīng)用的部署和拓展。

https://jysperm.me/2016/02/programming-of-2015/

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/26532.html

相關(guān)文章

  • 我的 2015 年度小結(jié)技術(shù)方面

    摘要:因?yàn)槁酚蓪用媸軜I(yè)務(wù)影響很大,經(jīng)常修改一些功能的行為,所以后來大部分測(cè)試都是針對(duì)層面的單元測(cè)試。在我了解的過程中,我發(fā)現(xiàn)中文網(wǎng)絡(luò)上對(duì)的討論非常分散,于是我創(chuàng)建了中文社區(qū),到年末已經(jīng)有個(gè)注冊(cè)用戶和個(gè)帖子了。 https://jysperm.me/2016/02/programming-of-2015/ 從 2014 年末開始開發(fā)的一個(gè)互聯(lián)網(wǎng)金融項(xiàng)目終于在今年三月份上線了,這是一個(gè) Node...

    宋華 評(píng)論0 收藏0
  • 2016年總結(jié) - 收藏集 - 掘金

    摘要:然而這次的文章,就像賀師俊所說的這篇文章是從程序員這個(gè)老年度總結(jié)前端掘金年對(duì)我來說,是重要的一年。博客導(dǎo)讀總結(jié)個(gè)人感悟掘金此文著筆之時(shí),已經(jīng)在眼前了。今天,我就來整理一篇,我個(gè)人認(rèn)為的年對(duì)開發(fā)有年終總結(jié)掘金又到 2016 Top 10 Android Library - 掘金 過去的 2016 年,開源社區(qū)異常活躍,很多個(gè)人與公司爭(zhēng)相開源自己的項(xiàng)目,讓人眼花繚亂,然而有些項(xiàng)目只是曇花一...

    DataPipeline 評(píng)論0 收藏0
  • 2016年度 JavaScript 展望(下)

    摘要:與是年最早公開發(fā)布的兩個(gè)框架,后來者還包括與。此外,另一重心是與團(tuán)隊(duì)的合作,預(yù)計(jì)將貫穿年。年展望對(duì)平臺(tái)而言,年的重點(diǎn)是提升穩(wěn)定性與采納率。最早由開發(fā),于年公開發(fā)布。時(shí)間會(huì)告訴我們,的極速增長能否在年持續(xù)下去。 【編者按】本文作者為資深 Web 開發(fā)者 TJ VanToll, TJ 專注于移動(dòng)端 Web 應(yīng)用及其性能,是《jQuery UI 實(shí)踐》 一書的作者。 本文系 OneAPM 工...

    XGBCCC 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<