《程序猿的呐喊》读书笔记(下)
接著《程序猿的吶喊》讀書筆記(上)。繼續(xù)分享下篇。這次干貨比較多哦。有靜動態(tài)類型的優(yōu)缺點、強弱類型系統(tǒng)的對抗、設(shè)計模式、程序猿的數(shù)學(xué)、編譯器的重要性以及保守派自由派的較量,一時消化不了的建議保存以便read it later。
靜態(tài)類型和動態(tài)類型的優(yōu)缺點
靜態(tài)類型的長處
以下列出了靜態(tài)類型的主要長處:
(1)靜態(tài)類型能夠在程序執(zhí)行之前。依賴其與生俱來的限制來及早發(fā)現(xiàn)一些類型錯誤。(或是在插入/更新記錄,解析XML文檔等情況下進行檢測。)
(2)靜態(tài)類型有很多其它機會(或者說更easy)優(yōu)化性能。比如僅僅要數(shù)據(jù)模型完整豐富,那么實現(xiàn)智能化的數(shù)據(jù)庫索引就會更easy一些。編譯器在擁有更精確的變量和表達式類型信息的情況下能夠做出更優(yōu)的決策。
(3)在C++和Java這樣擁有復(fù)雜類型系統(tǒng)的語言里,你能夠直接通過查看代碼來確定變量、表達式、操作符和函數(shù)的靜態(tài)類型。
這種優(yōu)勢也許在ML和Haskell這種類型推導(dǎo)語言里并不明顯,他們顯然認(rèn)為到哪里都要帶著類型標(biāo)簽是缺點。
只是你還是能夠在有助閱讀理解的情況下標(biāo)明類型一而這些在絕大多數(shù)動態(tài)語言里是根本做不到的。
(4)靜態(tài)類型標(biāo)注能夠簡化特定類型的代碼自己主動化處理。比方說自己主動化文檔生成、語法高亮和對齊、依賴分析、風(fēng)格檢查等各種“讓代碼去解讀代碼”的工作。換句話說,靜態(tài)類型標(biāo)簽讓那些相似編譯器的工具更easy施展拳腳:詞法工具會有很多其它明白的語法元素,語義分析時也比較少要用猜的。
(5)僅僅要看到API或是數(shù)據(jù)庫結(jié)構(gòu)(而不用去看代碼實現(xiàn)或數(shù)據(jù)庫表)就能大致把握到它的結(jié)構(gòu)和使用方法。
還有其它要補充的嗎?
靜態(tài)類型的缺點例如以下:
(1)它們?nèi)藶榈叵拗屏四愕谋磉_能力。
比方,Java的類型系統(tǒng)里沒有操作符重載、多重繼承、mix-in、引用參數(shù)、函數(shù)也不是一等公民。原本利用這些技術(shù)能夠做出非常自然的設(shè)計,如今卻不得不去遷就java的類型系統(tǒng)。不管是Ada還是C++,或是OCaml等不論什么一種靜態(tài)類型系統(tǒng)都有這種問題。差點兒相同半數(shù)的設(shè)計模式(不光是Gof的那些)都是扭曲原本自然直觀的設(shè)計,好將它們?nèi)M某種靜態(tài)類型系統(tǒng):這根本就是方枘圓鑿嘛。
(2)它們會拖慢開發(fā)進度。
事先要創(chuàng)建非常多靜態(tài)模型(自頂向下的設(shè)計)。然后還要依據(jù)需求變化不斷改動。這些類型標(biāo)注還會讓源碼規(guī)模膨脹導(dǎo)致代碼難以理解,維護成本上升。(這個問題僅僅在Java里比較嚴(yán)重,由于它不支持給類型取別名。)還有就是我上面已經(jīng)提到過的,你得花很多其它的時間來調(diào)整設(shè)計。以適應(yīng)靜態(tài)類型系統(tǒng)。
(3)學(xué)習(xí)曲線比較陡。
動態(tài)類型語言比較好學(xué)。
靜態(tài)類型系統(tǒng)則相對挑剔,你必須花非常多時間去學(xué)它們建模的方式。外加靜態(tài)類型的語法規(guī)則。
另外。靜態(tài)類型錯誤(也能夠叫編譯器錯誤)對于剛開始學(xué)習(xí)的人來說非常難懂,由于那時程序根本還沒跑起來呢。
你連用printf來調(diào)試的機會都沒有,僅僅能撞大運似的調(diào)整代碼,祈求能讓編譯器愜意。
因此學(xué)習(xí)C++比C和Smalltalk難,OCaml比Lisp難,Nice語言比Java難。
而Perl所具備的一系列靜態(tài)復(fù)雜性—各種詭異的規(guī)則,怎么用,什么時候用等—讓它的難度比Ruby和Python都要高。我從來沒見過有哪門靜態(tài)類型語是非常好學(xué)的。
(4)它們會帶來虛幻的安全感。
靜態(tài)類型系統(tǒng)確實能降低執(zhí)行時的錯誤,提升數(shù)據(jù)的完整性。所以非常easy誤導(dǎo)人們認(rèn)為僅僅要能通過編譯讓程序跑起來,那它基本上就沒什么bug了。人們在用強靜態(tài)類型系統(tǒng)的語言敲代碼時似乎非常少依賴單元測試,當(dāng)然這也可能僅僅是我的想像罷了。
(5)它們會導(dǎo)致文檔質(zhì)量下滑。
非常多人認(rèn)為自己主動生成的javadoc就足夠了,哪怕不凝視代碼也沒關(guān)系。 Sourceforge 上充斥著這種項目,甚至連Sun JDK也經(jīng)常有這個問題。
(比方,Sun非常多時候都沒有給static final常量加入javadoc凝視。
)
(6)非常難用它們寫出兼具高度動態(tài)和反射特點的系統(tǒng)。
絕大多數(shù)靜態(tài)類型語言(大概)都出于追求性能的目的,在執(zhí)行時丟棄了差點兒全部編譯器生成的元數(shù)據(jù)。可是這樣一來這些系統(tǒng)通常也就非常難在執(zhí)行時作出改動(甚至連內(nèi)省都做不到)比方,若要想給模塊加一個新函數(shù),或是在類里加個方法,除了又一次編譯,關(guān)閉程序然后重新啟動之外別無他法。
受此影響的不單是開發(fā)流程整個設(shè)計理念也難逃波及。你可能須要搭建個復(fù)雜的架構(gòu)來支持動態(tài)功能而這些東西會無可避免地和你的業(yè)務(wù)代碼混在一起。
動態(tài)類型的優(yōu)缺點:
僅僅要把上面的列表對調(diào)一下,你基本上就能夠列出動態(tài)類型語言的優(yōu)缺點了。
動態(tài)語言的表達能力更強。設(shè)計靈活度也更大;易學(xué)易用,開發(fā)速度快;通常執(zhí)行時的靈活性也更高。
相對地,動態(tài)語言無法及時給出類型錯誤(至少編譯器做不到)。性能調(diào)優(yōu)的難度也比較高,非常難做自己主動化靜態(tài)分析,另外。變量和表達式的類型在代碼里非常不直觀。沒辦法一眼看出來。
靜態(tài)語言終于會向用戶屈服開始加入一些動態(tài)特性,而動態(tài)語言經(jīng)常也會嘗試引入一下可選的靜態(tài)類型系統(tǒng)(或是靜態(tài)分析工具)。此外它們還會設(shè)法改善性能添加錯誤檢測,以便及早發(fā)現(xiàn)問題。非常遺憾。除非一開始設(shè)計語言的時候就考慮到可選的靜態(tài)類型,否則強扭的瓜怎么也不會甜的。
強類型與弱類型系統(tǒng)的較量
以下我會以略微有點戲謔的方式解釋這兩種理念(指的是強類型和弱類型)的工作流程,盡可能將它們本質(zhì)差別展現(xiàn)出來。
強類型陣營基本是這樣工作的:首先是依照當(dāng)前的需求進行設(shè)計。制定出文檔哪怕僅僅是初稿也沒關(guān)系;然后定義接口和數(shù)據(jù)模型。如果系統(tǒng)要承受巨大流量,因此每一個地方都要考慮性能。避免採用垃圾收集和正則表達式這類抽象。(注意:即便是Java程序猿,通常也會努力避免觸發(fā)垃圾收集,他們總是在開始敲代碼之討論對象池的問題。
)
他們僅僅有在無計可施的情況下才會考慮動態(tài)類型。比如,一支採用Corba的團隊僅僅有在極端情況下才會在每一個接口調(diào)用上加入一個XML字符串參數(shù),這樣他們就能繞開當(dāng)初選擇的死板的類型系統(tǒng)了。
第二個陣營基本是這樣工作的:先搭建原型。僅僅要你寫代碼的速度比寫同等具體程度的文檔快。你就能夠更早地從用戶那里獲得反饋。依照當(dāng)下的需求定義合理的接口和數(shù)據(jù)模型,可是別在上面浪費太多時間。
一切以能跑起來為準(zhǔn)。怎么方便怎么來。如果自己肯定要面對大量的需求變化,所以每一個地方首先考慮的是盡快讓系統(tǒng)執(zhí)行起來。能用抽象的地方就盡量用(比方如每次都去收集數(shù)據(jù)而先不考慮緩沖,能用正則的地方就先不用字符串比較)就算明明知是牛刀也沒關(guān)系,由于你換回的是更大的靈活性。
代碼量比較少,通常bug的數(shù)量也會更少。
他們僅僅有在被逼無奈的情況下才會進行性能調(diào)優(yōu)以及禁止改動接口和數(shù)據(jù)定義。
比如。一支Perl團隊可能會將一些關(guān)鍵的核心模塊用C重寫。然后創(chuàng)建XS綁定。
時間—長。這些抽象就漸漸變成了既定標(biāo)準(zhǔn),它們被包裹在數(shù)據(jù)定義和仔細(xì)的OO接口里,再也無法改動。(就算是Perl程序猿也經(jīng)常會忍不住祭出銀彈,為經(jīng)常使用的抽象編寫OO接口)
那你認(rèn)為終于採用這些策略的結(jié)果會怎么樣?
設(shè)計模式
工廠不是特性,托付、代理、橋接也都不是。它們僅僅是提供了美麗的盒子,以松散的方式來裝載特性。
可是別忘了。盒子、袋子和隔板自己也是要占用空間的。
設(shè)計模式也不例外(至少在“四人幫”的書里所介紹的大多數(shù)模式都是這樣)。更悲劇的是“四人幫”模式里唯一能精簡代碼的解釋器(Interpreter)模式卻被那些恨不得把設(shè)計模式紋在身上的程序猿忽略了。
依賴注入是還有一個新型的Java設(shè)計模式。Ruby、Python、Perl還有Javascript,程序猿大概聽都沒聽過吧。就算他們聽過,他們也能正確地得出他們根本不須要這種玩意兒的結(jié)論。
依賴注入是一種驚人的描寫敘述式架構(gòu)。讓Java能在某些方面和更高級的語言一樣,變得更動態(tài)一點。你猜得沒錯,依賴注入會讓Java代碼變得更大。
變大是Java中無法回避的東西。成長是生活的一部分。Java就像是俄羅斯方塊,只是積木和積木之間的空隙都填不滿,結(jié)果僅僅能越堆越高。
me:如今Java程序猿相信都知道依賴注入了,由于它太重要了,用在各大框架里,比方spring。依賴注入使得能夠在文件中配置類及其各種關(guān)系。當(dāng)然使得Java更靈活更強大了。
程序猿須要了解的是哪些數(shù)學(xué)分支?
me:程序猿所要解決的數(shù)學(xué)問題一般都是離散數(shù)學(xué)。當(dāng)中最實用的課程應(yīng)該就是組合數(shù)學(xué)和概率論統(tǒng)計。
(1) 統(tǒng)計。我的離散數(shù)學(xué)書里講到了一點。可是統(tǒng)計是一門完整的學(xué)科,并且是非常重要的學(xué)科,重要到根本不須要額外介紹。
(2)代數(shù)和線性代數(shù)(比方矩陣)。線性代數(shù)應(yīng)該緊跟在代數(shù)后面教。它不是非常難,并且在非常多領(lǐng)域都非常非常實用,比方機器學(xué)習(xí)。
(3)數(shù)理邏輯。
(4)信息論和柯氏復(fù)雜度。信息論(粗略地講)主要是關(guān)于數(shù)據(jù)壓縮的。而柯氏復(fù)雜度(相同粗略地講)則是關(guān)于算法的復(fù)雜度(比方最小空間是多少,須要多長時間,程序或者數(shù)據(jù)結(jié)構(gòu)有多優(yōu)雅等)的。它們都是好玩,有趣,實用的學(xué)科。
當(dāng)然還有其它的分支。并且有些學(xué)科互有重疊。
但重點在于:對你實用的數(shù)學(xué)和學(xué)校認(rèn)為實用的數(shù)學(xué)是非常不同的。
非常實用。記憶和非常多煩瑣的步驟程序猿通常不須要這些東西。
知道大致概可是須要大量的概念和技巧就能夠了,細(xì)節(jié)方面等到須要的時候再查也來得及。
編譯器,你懂嗎?
me:作者強烈要求程序猿學(xué)編譯器原理。你還記得嗎?
它能夠是每一行像素所組成的流。
每一個像素就是一個數(shù)字。每一個數(shù)字就是一個符號。編譯器當(dāng)然能夠轉(zhuǎn)換圖片。
英語能夠被當(dāng)做符號流叫嗎?當(dāng)然能夠。規(guī)則也許會非常復(fù)雜,可是自然語言處理的確能夠被看成是某種非常炫的編譯。
第二個大階段是類型檢查。
這是一群狂熱的學(xué)術(shù)分子(包括他們的組織以及或者手下的研究生)他們自信能夠?qū)懗龇浅B斆鞯某绦?#xff0c;能分析出你的程序想干什么。并且在你出錯的時候幫你指出。只是奇怪的是,他們并不認(rèn)為自己是在研究人工智能畢竟人工智能界已經(jīng)(明智地)放棄確定性的方法了。
第三個陣營是代碼生成。他們通常都被邊緣化了。僅僅要你對遞歸有足夠的了解,知道自己的祖先不是亞當(dāng)和夏娃。那么代碼生成還是挺直觀的。這里要講的事實上是優(yōu)化就是那種生成足夠正確的代碼,讓絕大多數(shù)用戶都意識不到有問題的藝術(shù)。
等等不好意思。這是亞馬遜化。
優(yōu)化是指依據(jù)你那些昂貴的菜鳥程序猿寫出來的垃圾代碼生成“正確”代碼的藝術(shù)。
保守派和自由派,你屬于哪派?
畢竟“保守的”這個形容詞基本上和慎重、厭惡風(fēng)險就是同義詞。金融上的保守主義經(jīng)常(也是顯而易見的)和年齡以及財富聯(lián)系在一起。公司會隨著時間逐漸變得保守起來。由于它們熬過過了各種法律訴訟、技術(shù)失敗、公共危機、金融風(fēng)暴等危機。連螞蟻和蚱蜢的寓言故事都告訴我們寒冬將至。要儲存食物。
本質(zhì)上,保守主義就是風(fēng)險管理。
相同自由派的觀點經(jīng)常和年輕、理想主義、天真無邪聯(lián)系在一起。在企業(yè)里。創(chuàng)業(yè)公司往往是典型的自由派,一部分原因是他們本來就是為了(在一定程度上)改變世界而存在的(而自由主義原本就意味著變化),還有一部分則是他們必須全力以赴完畢投資人設(shè)定的目標(biāo),所以放棄一點軟件安全也就變得合理(不得已)了。
me:保守派,盡量修復(fù)全部bug,回避錯誤。學(xué)不會新語法,通過編譯器安全檢查。數(shù)據(jù)必須遵循事先定義好的格式,公共接口必須嚴(yán)格建模。生產(chǎn)系統(tǒng)里絕不同意存在危急過有風(fēng)險的后門,安全性有疑慮就不能上線。快比慢好,注重性能。
自由派則相反。
各大語言的分派:(作者自己使用語言的經(jīng)驗。僅供參考)
難以言喻的自由:匯編語言
極端自由:Perl、Ruby、PHP、腳本
非常自由:Javascript、VB、Lua
自由:Python、Common Lisp、Smalltalk/Sqeak
溫柔自由:C、Object-C、Schema
溫柔保守:C++、Java、C#、D、Go
保守:Clojure、Erlang、Pascal
非常保守:Scala、Ada、Ocaml、Eiffel
極端保守:Haskell、SML
(1)Facebook是極端自由的。
他們主要用的是C++和PHP,他們的數(shù)據(jù)都放在memcached里:僅僅有鍵值對,沒有數(shù)據(jù)庫結(jié)構(gòu)。他們把數(shù)據(jù)導(dǎo)出來放到一個后臺Hⅳe數(shù)據(jù)倉庫里,然后用Hadoop來進行離線數(shù)據(jù)分析。每兩個星期左右他們?nèi)匀粫e辦通宵黑客馬拉松,反正他們的程序猿大多都是單身男青年(至少我上次去參觀的時候還是如此),股票的估值也還非常高(我上次查價格的時候好像已經(jīng)沒那么好了)。作為一家公司,Facebook是非常緊密的。具有非常強的執(zhí)行力,十分注重程序猿在站點上公布新功能的單兵能力。沒有什么官僚主義。這對一家規(guī)模這么大、用戶那么多多的公司來講是難能可貴的。保守派毫無疑問會厭惡蔑視他們。可是Facebook證明了不管具有什么世界觀的程序猿,僅僅要聯(lián)合起來。就能解決非常多問題。
(2)Amazon是自由的。
(3)Google是保守的。開始是有點自由的 ,然后就變得越來越保守了。
僅僅有在剛剛開始的時候才是軟件自由的。那時候的搜索引擎是用Python寫的。
隨著公司不斷壯大,他們非常快就轉(zhuǎn)向了軟件保守主義,而這全然是由project師自己主導(dǎo)的。他們寫了非常多宣言警告太多語言所帶來的危急,而僅有的幾門語言里。也里,也有嚴(yán)格的風(fēng)格指南,限制使用那些端保守。險”或者“難以閱讀”的語言特性。
(4)微軟是難以言喻的保守。
轉(zhuǎn)載于:https://www.cnblogs.com/blfbuaa/p/6946025.html
總結(jié)
以上是生活随笔為你收集整理的《程序猿的呐喊》读书笔记(下)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 动态密码卡TOTP算法
- 下一篇: js数组去重的三种常用方法