函數(shù)式編程與面向?qū)ο缶幊蘙5]:編程的本質(zhì)

函數(shù)式編程與面向?qū)ο缶幊蘙5]:編程的本質(zhì)


之劍 2016.5.6 01:26:31


<div id="category"></div>


編程的本質(zhì)

讀到兩篇文章,寫的不錯(cuò), 綜合摘錄一下

復(fù)合是編程的本質(zhì)

函數(shù)式程序員在洞察問題方面會遵循一個(gè)奇特的路線。他們首先會問一些似有禪機(jī)的問題。例如烘豌,在設(shè)計(jì)一個(gè)交互式程序時(shí),他們會問:什么是交互独悴?在實(shí)現(xiàn) 基于元胞自動(dòng)機(jī)的生命游戲時(shí),他們可能又去沉思生命的意義锣尉。秉持這種精神,我將要問:什么是編程决采?在最基本的層面自沧,編程就是告訴計(jì)算機(jī)去做什么,例如『從 內(nèi)存地址 x 處獲取內(nèi)容树瞭,然后將它與寄存器 EAX 中的內(nèi)容相加』拇厢。但是即使我們使用匯編語言去編程,我們向計(jì)算機(jī)提供的指令也是某種有意義的表達(dá)式晒喷。假設(shè)我們正在解一個(gè)難題(如果它不難孝偎,就沒必要用計(jì)算 機(jī)了),那么我們是如何求解問題的凉敲?我們把大問題分解為更小的問題衣盾。如果更小的問題還是還是很大,我們再繼續(xù)進(jìn)行分解爷抓,以此類推势决。最后,我們寫出求解這些 小問題的代碼蓝撇,然后就出現(xiàn)了編程的本質(zhì):我么將這些代碼片段復(fù)合起來果复,從而產(chǎn)生大問題的解。如果我們不能將代碼片段整合起來并還原回去渤昌,那么問題的分解就 毫無意義虽抄。

層次化分解與重新復(fù)合的過程

這個(gè)思維過程, 并非是受計(jì)算機(jī)的限制而產(chǎn)生走搁,它反映的是人類思維的局限性。我們的大腦一次只能處理很少的概念迈窟。生物學(xué)中被廣為引用的 一篇論文指出我們我們的大腦中只能保存 7± 2 個(gè)信息塊私植。我們對人類短期記憶的認(rèn)識可能會有變化,但是可以肯定的是它是有限的菠隆。底線就是我們不能處理一大堆亂糟糟的對象或像蘭州拉面似的代碼兵琳。我們需要 結(jié)構(gòu)化并非是因?yàn)榻Y(jié)構(gòu)化的程序看上去有多么美好,而是我們的大腦無法有效的處理非結(jié)構(gòu)化的東西骇径。我們經(jīng)常說一些代碼片段是優(yōu)雅的或美觀的躯肌,實(shí)際上那只意味 著它們更容易被人類有限的思維所處理。優(yōu)雅的代碼創(chuàng)造出尺度合理的代碼塊破衔,它正好與我們的『心智消化系統(tǒng)』能夠吸收的數(shù)量相符清女。

那么,對于程序的復(fù)合而言晰筛,正確的代碼塊是怎樣的嫡丙?它們的表面積必須要比它們的體積增長的更為緩慢。我喜歡這個(gè)比喻读第,因?yàn)閹缀螌ο蟮谋砻娣e是以尺寸 的平方的速度增長的曙博,而體積是以尺寸的立方的速度增長的,因此表面積的增長速度小于體積怜瞒。代碼塊的表面積是是我們復(fù)合代碼塊時(shí)所需要的信息父泳。代碼塊的體積 是我們?yōu)榱藢?shí)現(xiàn)它們所需要的信息。一旦代碼塊的實(shí)現(xiàn)過程結(jié)束吴汪,我們就可以忘掉它的實(shí)現(xiàn)細(xì)節(jié)惠窄,只關(guān)心它與其他代碼塊的相互影響。在面向?qū)ο缶幊讨醒龋惢蚪涌?的聲明就是表面杆融。在函數(shù)式編程中,函數(shù)的聲明就是表面霜运。我把事情簡化了一些脾歇,但是要點(diǎn)就是這些。

范疇論

在積極阻礙我們探視對象的內(nèi)部方面觉渴,范疇論具有非凡的意義介劫。范疇論中的一個(gè)對象,像一個(gè)星云案淋。對于它座韵,你所知的只是它與其他對象之間的關(guān)系,亦即它 與其他對象相連接的箭頭。這就是 Internet 搜索引擎對網(wǎng)站進(jìn)行排名時(shí)所用的策略誉碴,它只分析輸入與輸出的鏈接(除非它受欺騙)宦棺。在面向?qū)ο缶幊讨校粋€(gè)理想的對象應(yīng)該是只暴露它的抽象接口(純表面黔帕, 無體積)代咸,其方法則扮演箭頭的角色。如果為了理解一個(gè)對象如何與其他對象進(jìn)行復(fù)合成黄,當(dāng)你發(fā)現(xiàn)不得不深入挖掘?qū)ο蟮膶?shí)現(xiàn)之時(shí)呐芥,此時(shí)你所用的編程范式的原本優(yōu) 勢就蕩然無存了。

讓我們暫時(shí)撇開平臺奋岁、框架思瘟、技術(shù)、設(shè)計(jì)模式闻伶、對象思想滨攻、敏捷開發(fā)論等。 追問程序本質(zhì)蓝翰。

布爾代數(shù)的邏輯體系

布爾代數(shù)起源于數(shù)學(xué)領(lǐng)域光绕,是一個(gè)用于集合運(yùn)算和邏輯運(yùn)算的公式:〈B,∨畜份,∧诞帐,? 〉。其中B為一個(gè)非空集合爆雹,∨景埃,∧為定義在B上的兩個(gè)二元運(yùn)算,?為定義在B上的一個(gè)一元運(yùn)算顶别。

通過布爾代數(shù)進(jìn)行集合運(yùn)算可以獲取到不同集合之間的交集、并集或補(bǔ)集拒啰,進(jìn)行邏輯運(yùn)算可以對不同集合進(jìn)行與驯绎、或、非谋旦。

在布爾代數(shù)上的運(yùn)算被稱為AND(與)剩失、OR(或)和NOT(非)。代數(shù)結(jié)構(gòu)要是布爾代數(shù)册着,這些運(yùn)算的行為就必須和兩元素的布爾代數(shù)一樣(這兩個(gè)元素是TRUE(真)和FALSE(假))拴孤。亦稱邏輯代數(shù).布爾(Boole,G.)為研究思維規(guī)律(邏輯學(xué))于1847年提出的數(shù)學(xué)工具.布爾代數(shù)是指代數(shù)系統(tǒng)B=〈B甲捏,+演熟,·,′〉

它包含集合B連同在其上定義的兩個(gè)二元運(yùn)算+,·和一個(gè)一元運(yùn)算′芒粹,布爾代數(shù)具有下列性質(zhì):對B中任意元素a兄纺,b,c化漆,有:


1.a(chǎn)+b=b+a估脆, a·b=b·a.

2.a(chǎn)·(b+c)=a·b+a·c,

a+(b·c)=(a+b)·(a+c).

3.a(chǎn)+0=a座云,  a·1=a.

4.a(chǎn)+a′=1疙赠, a·a′=0.

公理化

在 1933 年,美國數(shù)學(xué)家 Edward Vermilye Huntington (1874-1952) 展示了對布爾代數(shù)的如下公理化:


交換律: x + y = y + x朦拖。

結(jié)合律: (x + y) + z = x + (y + z)圃阳。

Huntington等式: n(n(x) + y) + n(n(x) + n(y)) = x。

一元函數(shù)符號 n 可以讀做'補(bǔ)'贞谓。

Herbert Robbins 接著擺出下列問題: Huntington等式能否縮短為下述的等式限佩,并且這個(gè)新等式與結(jié)合律和交換律一起成為布爾代數(shù)的基礎(chǔ)? 通過一組叫做 Robbins 代數(shù)的公理,問題就變成了: 是否所有的 Robbins 代數(shù)都是布爾代數(shù)?

Robbins 代數(shù)的公理化:

交換律: x + y = y + x

結(jié)合律: (x + y) + z = x + (y + z)

Robbins等式: n(n(x + y') + n(x + n(y))) = x

這個(gè)問題自從 1930 年代一直是公開的裸弦,并成為 Alfred Tarski 和他的學(xué)生最喜好的問題祟同。

在 1996 年,William McCune 在 Argonne 國家實(shí)驗(yàn)室理疙,建造在 Larry Wos晕城、Steve Winker 和 Bob Veroff 的工作之上,肯定的回答了這個(gè)長期存在的問題: 所有的 Robbins 代數(shù)都是布爾代數(shù)窖贤。這項(xiàng)工作是使用 McCune 的自動(dòng)推理程序 EQP 完成的砖顷。

計(jì)算機(jī)程序的本質(zhì)

從本質(zhì)上來說, 程序就是一系列有序執(zhí)行的指令集合赃梧。 如何將指令集合組織成可靠可用可信賴的軟件(美妙的邏輯之塔)滤蝠, 這是個(gè)問題。

程序 = 邏輯 + 控制授嘀。 what to do + when to do.

從編程角度來說物咳, 開發(fā)者應(yīng)對的就是邏輯, 邏輯的表達(dá)蹄皱、組織和維護(hù)览闰。 邏輯是事物自此及彼的合乎事物發(fā)展規(guī)律的序列。指令是邏輯的具體實(shí)現(xiàn)形式巷折。

邏輯成立的先決條件是合乎事物發(fā)展規(guī)律压鉴。 程序只能處理數(shù)值, 卻傳入了字符串锻拘, 就只能報(bào)錯(cuò)而無法繼續(xù)油吭; 當(dāng)處理海量數(shù)據(jù)時(shí), 若內(nèi)存不足, 就會導(dǎo)致程序崩潰上鞠; 若程序存在內(nèi)存泄露际邻, 隨著時(shí)間的推移而耗盡內(nèi)存, 也會導(dǎo)致程序崩潰芍阎。 多個(gè)線程同時(shí)修改一個(gè)共享變量世曾, 若不加控制, 就會因?yàn)椴煌€程執(zhí)行修改變量的時(shí)序的不確定導(dǎo)致該變量最終值的不確定谴咸。 這些就是程序執(zhí)行的發(fā)展規(guī)律轮听。 要編寫程序, 必定要先通悉這些規(guī)律岭佳。

規(guī)律的表現(xiàn)形式是:如果條件 (C1, C2, ..., Cn) 是產(chǎn)生結(jié)果 (R1, R2, ... , Rn) 的充分必要條件血巍, 那么當(dāng) C1, C2, ..., Cn 任一不滿足條件時(shí), 都不可能產(chǎn)生結(jié)果 (R1, R2, ..., Rn) 珊随; 反之述寡, 若結(jié)果 (R1, R2, ..., Rn) 沒有出現(xiàn), 則必定是 C1, C2, ..., Cn 某一條件不滿足導(dǎo)致叶洞。 錯(cuò)誤和異常即是 C1, C2, ..., Cn 任一不滿足條件的表現(xiàn)鲫凶。規(guī)律的性質(zhì)是必然的, 不存在可能之說衩辟; 只存在人們探索的是否足夠精確螟炫。編程開發(fā)首先應(yīng)當(dāng)懂得程序執(zhí)行的規(guī)律, 然后才是實(shí)際的開發(fā)艺晴; 否則就會被程序的結(jié)果折騰得死去活來昼钻。

在通悉程序執(zhí)行規(guī)律之后, 程序需要解決如下問題:

  • 要表達(dá)什么邏輯
  • 如何表達(dá)該邏輯封寞;
  • 如何維護(hù)該邏輯然评。

軟件的復(fù)雜性表現(xiàn)在如何表達(dá)和維護(hù)交互復(fù)雜的大型邏輯上

暫時(shí)先回到軟件的起點(diǎn), 回顧一下這一切是如何發(fā)生的狈究。

最初沾瓦, 人們使用物理的或邏輯的二進(jìn)制機(jī)器指令來編寫程序, 嘗試著表達(dá)思想中的邏輯谦炒, 控制硬件計(jì)算和顯示, 發(fā)現(xiàn)是可行的风喇;

接著宁改, 創(chuàng)造了助記符 —— 匯編語言, 比機(jī)器指令更容易記憶魂莫;

再接著还蹲, 創(chuàng)造了編譯器、解釋器和計(jì)算機(jī)高級語言, 能夠以人類友好自然的方式去編寫程序谜喊, 在犧牲少量性能的情況下潭兽, 獲得比匯編語言更強(qiáng)且更容易使用的語句控制能力:條件、分支斗遏、循環(huán)山卦, 以及更多的語言特性: 指針、結(jié)構(gòu)體诵次、聯(lián)合體账蓉、枚舉等, 還創(chuàng)造了函數(shù)逾一, 能夠?qū)⒁幌盗兄噶罘庋b成一個(gè)獨(dú)立的邏輯塊反復(fù)使用铸本;

逐漸地,產(chǎn)生了面向過程的編程方法遵堵;

后來箱玷, 人們發(fā)現(xiàn)將數(shù)據(jù)和邏輯封裝成對象, 更接近于現(xiàn)實(shí)世界陌宿, 且更容易維護(hù)大型軟件锡足, 又出現(xiàn)了面向?qū)ο蟮木幊陶Z言和編程方法學(xué), 增加了新的語言特性: 繼承限番、 多態(tài)舱污、 模板、 異常錯(cuò)誤弥虐。

為了不必重復(fù)開發(fā)常見工具和任務(wù)扩灯, 人們創(chuàng)造和封裝了容器及算法、SDK霜瘪, 垃圾回收器珠插, 甚至是并發(fā)庫;

為了讓計(jì)算機(jī)語言更有力更有效率地表達(dá)各種現(xiàn)實(shí)邏輯颖对, 消解軟件開發(fā)中遇到的沖突捻撑, 還在語言中支持了元編程、 高階函數(shù)缤底, 閉包 等有用特性顾患。

為了更高效率地開發(fā)可靠的軟件和應(yīng)用程序, 人們逐漸構(gòu)建了代碼編輯器个唧、 IDE江解、 代碼版本管理工具、公共庫徙歼、應(yīng)用框架犁河、 可復(fù)用組件鳖枕、系統(tǒng)規(guī)范、網(wǎng)絡(luò)協(xié)議桨螺、 語言標(biāo)準(zhǔn)等宾符, 針對遇到的問題提出了許多不同的思路和解決方案, 并總結(jié)提煉成特定的技術(shù)和設(shè)計(jì)模式灭翔, 還探討和形成了不少軟件開發(fā)過程魏烫, 用來保證最終發(fā)布的軟件質(zhì)量。 盡管編寫的這些軟件和工具還存在不少 BUG 缠局,但是它們都“奇跡般地存活”则奥, 并共同構(gòu)建了今天蔚為壯觀的軟件世界。

此外狭园, 軟件還經(jīng)歷了“單機(jī)程序 => 多機(jī)程序 => 分布式程序” 的過程 读处, 多機(jī)聯(lián)網(wǎng)程序因?yàn)槎鄠€(gè)子系統(tǒng)的交互變得更加復(fù)雜。 這里不再贅述唱矛。

但請注意罚舱, 無論軟件發(fā)展到多么復(fù)雜的程度, 總有一群人绎谦, 在試圖從程序的本質(zhì)中探究軟件開發(fā)的基本問題管闷, 他們試圖論證和確保程序的正確性、提煉軟件的基本屬性并進(jìn)行衡量窃肠; 程序的正確性本質(zhì)是邏輯學(xué)來保證的包个。 沒有邏輯學(xué), 程序根本就無法立足冤留, 更不可能有今天的大規(guī)模應(yīng)用碧囊。

軟件開發(fā)工具讓我們更有效率地創(chuàng)造邏輯、 遠(yuǎn)離語法錯(cuò)誤的困擾纤怒;

公共庫將常用的通用邏輯塊封裝成可反復(fù)使用的組件糯而, 避免不必要的重復(fù)勞動(dòng);

設(shè)計(jì)模式體現(xiàn)的是如何可擴(kuò)展地解決常見的邏輯交互問題泊窘;

應(yīng)用框架解決的是應(yīng)用的通用邏輯流的控制的問題熄驼,讓開發(fā)者更多地聚焦具體業(yè)務(wù)邏輯上;

開發(fā)技術(shù)是在具體的應(yīng)用情境下按照既定總體思路去探究具體問題解決的方法烘豹。

表達(dá)和維護(hù)大型邏輯

我們要解決的是更通用的問題: 如何以更不易出錯(cuò)的方式去表達(dá)和維護(hù)大型邏輯 瓜贾?

表達(dá)和維護(hù)大型邏輯的終極訣竅就是: 將大型邏輯切分為容易消化的一小塊一小塊, “不急不忙地吃掉”携悯。

在該方法的實(shí)踐中阐虚, 可以充分利用現(xiàn)有的開發(fā)工具、公共庫蚌卤、設(shè)計(jì)模式实束、應(yīng)用框架、開發(fā)技術(shù)逊彭。

獨(dú)立無交互的大型邏輯或接口實(shí)現(xiàn)

獨(dú)立無交互的邏輯通常體現(xiàn)為公共庫咸灿, 可以解決常用或公共的日常任務(wù), 對其他邏輯無任何依賴和交互侮叮, 即自足邏輯避矢。

應(yīng)對獨(dú)立無交互的大型邏輯的首要方法是分解為若干的容易實(shí)現(xiàn)、測試和復(fù)用的小塊邏輯囊榜, 編寫和嚴(yán)格測試审胸。

其次是運(yùn)用成熟的編程模式去表達(dá)邏輯, 盡可能復(fù)用經(jīng)過嚴(yán)格測試的可靠的庫卸勺。

獨(dú)立無交互的大型邏輯通過合理的邏輯塊切分砂沛、嚴(yán)格的單元測試可以獲得充分的測試和可靠度。

獨(dú)立無交互的耗時(shí)長的邏輯或接口實(shí)現(xiàn)

快速響應(yīng)的問題: “用戶要求等待時(shí)間短” 與 “請求處理耗時(shí)長” 之間的矛盾導(dǎo)致的曙求。

解決獨(dú)立無交互的耗時(shí)長的邏輯依然可以采用切分邏輯塊碍庵、嚴(yán)格的單元測試的做法使之更容易處理;

此外悟狱, 有兩種設(shè)計(jì)思路可以考慮: 并發(fā) 與 異步静浴。

  • 并發(fā)思路是將切分的相互獨(dú)立的邏輯塊分配給不同的控制線程中執(zhí)行, 從而降低請求處理時(shí)長挤渐; 并發(fā)方案獲得的性能提升取決于串行操作在總操作中的時(shí)間占比苹享。

  • 異步思路是“先響應(yīng), 后處理浴麻, 終通知” 的"先奏后斬"方案得问。

將一步分離成了三步, 為了讓用戶首先獲得初步的承諾白胀, 再去履行承諾椭赋。 這樣做能讓用戶暫時(shí)地放心, 卻增加了新的問題: 消息中間件組件的開發(fā)與部署或杠、異步消息發(fā)送與接收哪怔、編程模型的變化和適應(yīng)。如果整個(gè)過程運(yùn)作良好向抢, 將會達(dá)到很好的體驗(yàn)认境,容易為用戶接受。如果其中一步發(fā)生差錯(cuò)挟鸠, 就會導(dǎo)致各種問題叉信, 比如數(shù)據(jù)不一致, 消息堆積艘希、 請求無法被處理硼身。最終用戶等待時(shí)間并沒有降低硅急, 反而使體驗(yàn)更加糟糕。 當(dāng)然佳遂, 如果成功率為 95%营袜, 也是“可以接受”的, 這樣用戶可能會怪自己“運(yùn)氣不太好”丑罪, 而不會過多怪責(zé)系統(tǒng)的不完善荚板。畢竟沒有任何事情能夠做到完美的地步。

并發(fā)與異步方案的調(diào)試難度和排查問題都比同步方案增加不少吩屹。 每一種新的設(shè)計(jì)方案都會有其優(yōu)點(diǎn)跪另, 同時(shí)也會有其缺點(diǎn)。 權(quán)衡優(yōu)缺點(diǎn)煤搜, 擇善而從之 免绿。值得注意的是, 并發(fā)方案是針對服務(wù)端實(shí)際處理請求邏輯而言宅楞, 而異步方案是針對請求處理之前是否立即回復(fù)的方式针姿。 并發(fā)與順序、 異步與同步兩兩組合厌衙, 可得到四種方式:

順序同步: 最初的編程模型

  • 優(yōu)點(diǎn)是簡單距淫、安全、 容易維護(hù)和調(diào)試婶希;
  • 缺點(diǎn)是性能較低榕暇, 響應(yīng)時(shí)間和吞吐量都不高; 若請求處理時(shí)長非常短喻杈, 采用順序同步的方案佳彤枢;

并發(fā)同步: 改進(jìn)的編程模型

  • 優(yōu)點(diǎn)是通過并發(fā)提高服務(wù)端的處理速度和吞吐量, 但若請求處理耗時(shí)較長筒饰, 響應(yīng)時(shí)間仍然不高缴啡, 影響客戶端體驗(yàn);
  • 若通過并發(fā)方案處理請求的時(shí)長非常短瓷们, 或客戶端體驗(yàn)要求不高业栅, 可以采用并發(fā)同步的方案;

順序異步: 改善客戶端體驗(yàn)的編程模型

  • 優(yōu)點(diǎn)是提高了響應(yīng)時(shí)間和客戶端體驗(yàn)谬晕, 由于其邏輯處理仍然采用順序方式碘裕, 請求處理時(shí)長并未有改善, 因此吞吐量并沒有改善攒钳。 是一種較好的折衷方案帮孔;
  • 若請求處理耗時(shí)較長, 影響客戶端體驗(yàn)不撑, 且請求處理邏輯復(fù)雜文兢, 采用并發(fā)方案容易出錯(cuò)或難以并發(fā)晤斩, 可采用順序異步方案;

并發(fā)異步: 同時(shí)改善客戶端體驗(yàn)和服務(wù)端處理速度

  • 優(yōu)點(diǎn)是提高了響應(yīng)時(shí)間姆坚、客戶端體驗(yàn)和處理速度尸昧、吞吐量。
  • 缺點(diǎn)是容易出錯(cuò)旷偿, 且不易調(diào)試;
  • 若客戶端對響應(yīng)體驗(yàn)要求較高爆侣, 請求處理邏輯簡單(比如簡單的數(shù)據(jù)拉取和匯總)萍程, 采用并發(fā)方式可有效提升處理速度, 可以采用并發(fā)異步方案兔仰;

邏輯塊之間的交互耦合與可擴(kuò)展性

軟件的復(fù)雜性真正體現(xiàn)在邏輯塊的持續(xù)長久的交互耦合和可擴(kuò)展上茫负。這是軟件開發(fā)與維護(hù)中極具挑戰(zhàn)性的部分。

邏輯塊之間的交互耦合通常體現(xiàn)在三種情境:

a. 操作順序的依賴乎赴。 比如資源更新操作必須在指定資源已經(jīng)創(chuàng)建的情況下進(jìn)行忍法。
b. 對共享有限資源的并發(fā)申請。 比如打印機(jī)只有兩臺榕吼, 卻有多個(gè)應(yīng)用程序連接上去請求打印文檔饿序;
c. 對共享可變狀態(tài)的并發(fā)訪問。 比如兩個(gè)操作同時(shí)要更新數(shù)據(jù)庫中的同一條記錄羹蚣;

三種情境的復(fù)雜性均是由并發(fā)引起的原探。 假設(shè)所有操作都是串行進(jìn)行的, 邏輯塊的交互無非是“你方唱罷我登場”的次序控制顽素, 而資源對單個(gè)請求通常是足夠的咽弦; 一旦采用了并發(fā)方案, 就難以控制邏輯塊的執(zhí)行次序和資源分配的具體情況了胁出, 容易導(dǎo)致某資源對單個(gè)請求不足的情況型型, 從而阻塞多個(gè)請求的處理甚至死鎖。并發(fā)提升了應(yīng)用的性能全蝶, 卻增加了出錯(cuò)的風(fēng)險(xiǎn)和幾率闹蒜。并發(fā)控制是大型邏輯交互的本質(zhì)性難點(diǎn)。并發(fā)控制的難點(diǎn)在于時(shí)序的合理控制和有效資源的合理分配裸诽。

對于 a 情境嫂用, 通常采用添加前置條件來求解, 在操作之前校驗(yàn)相關(guān)資源是否滿足丈冬、實(shí)體狀態(tài)是否合理嘱函, 實(shí)體之間的關(guān)聯(lián)是否正確; 若前置條件不滿足埂蕊, 則直接返回錯(cuò)誤提示往弓, 或者暫時(shí)掛起以備后續(xù)繼續(xù)執(zhí)行疏唾;

對于 b 情境, 需要?jiǎng)?chuàng)建一個(gè)可靠適用的資源分配算法 和資源分配模塊 函似, 應(yīng)用程序不再“自行”去拉取資源槐脏, 而是向資源分配模塊申請資源, 由資源分配模塊根據(jù)實(shí)際申請的整體情況及申請條件來決定如何分配資源撇寞;

對于 c 情境顿天, 需要進(jìn)行安全的互斥訪問, 謹(jǐn)慎地控制蔑担。

邏輯塊之間的交互耦合應(yīng)該交給交互解耦模塊去完成牌废, 而不是在自己的接口里實(shí)現(xiàn)。

也就是說啤握, 只有交互解耦模塊知道所有接口之間的交互鸟缕, 而接口只做自己知道的事情就可以了。否則排抬, 接口 A 與接口 B 必須知道彼此究竟做了什么懂从, 才能正確地做自己的事情。 假設(shè) 接口 A 和接口 B 都修改某個(gè)資源的狀態(tài)蹲蒲。 接口 A 在做某項(xiàng)操作執(zhí)行必須執(zhí)行 IF (ConditionX) do something 番甩; DoMyOwnThing ; 接 口 B 也要根據(jù) A 的邏輯相應(yīng)地執(zhí)行 if (ConditionY) do anotherThing悠鞍;DoMyOwnThing. 而程序員在維護(hù)和修改接口 A 的邏輯時(shí)对室, 不一定知道接口 B 的邏輯與之相關(guān), 于是修改不可避免地破壞了接口 B 的邏輯咖祭。 耦合的接口數(shù)量越多掩宜, 或者耦合接口之間的耦合資源越多, 對后期維護(hù)和擴(kuò)展將是一個(gè)難以應(yīng)對的噩夢么翰。

對于邏輯塊之間的交互解耦牺汤, 或者通俗地說, 模塊解耦.

實(shí)現(xiàn)邏輯時(shí)的容錯(cuò)考慮

程序中的邏輯主要是三類:

  • 獲取值: 從數(shù)據(jù)庫浩嫌、網(wǎng)絡(luò)或?qū)ο笾蝎@取值檐迟。 如果數(shù)據(jù)庫或網(wǎng)絡(luò)訪問足夠穩(wěn)定的話, 可以看成是簡單的獲取值码耐, 數(shù)據(jù)庫訪問和網(wǎng)絡(luò)訪問對獲取值是透明的追迟;

  • 檢測值: 檢測值是否合法, 通常是前置條件校驗(yàn)骚腥、 中間狀態(tài)校驗(yàn)和后置結(jié)果校驗(yàn)敦间, 根據(jù)檢測結(jié)果執(zhí)行“獲取值”或“設(shè)置值”的邏輯;

  • 設(shè)置(拷貝)值: 設(shè)置數(shù)據(jù)庫、對象中的值廓块; 或者發(fā)送數(shù)據(jù)和指令給網(wǎng)絡(luò)厢绝。如果數(shù)據(jù)庫或網(wǎng)絡(luò)訪問足夠穩(wěn)定的話, 可以看成是簡單的設(shè)置值带猴, 數(shù)據(jù)庫訪問和網(wǎng)絡(luò)訪問對設(shè)置值是透明的昔汉;

這三類邏輯可以稱為邏輯元。 具體業(yè)務(wù)邏輯就是基于物理的或邏輯的資源限制拴清, 將邏輯元的組合封裝成邏輯塊靶病, 有效控制邏輯塊的時(shí)序交互和資源分配。 時(shí)序控制不合理和資源缺乏導(dǎo)致錯(cuò)誤和異常口予。兩個(gè)程序同時(shí)更新一個(gè)共享變量嫡秕, 如果時(shí)序不控制, 就會導(dǎo)致錯(cuò)誤的結(jié)果苹威; 網(wǎng)絡(luò)通信錯(cuò)誤, 是因?yàn)榫W(wǎng)絡(luò)帶寬資源是有限的驾凶。

如何應(yīng)對錯(cuò)誤和異常 牙甫?

防御性編程

預(yù)防錯(cuò)誤的方法就是進(jìn)行防御性編程, 進(jìn)行容錯(cuò)考慮调违。 多思考: 如果這一步發(fā)生錯(cuò)誤窟哺, 會導(dǎo)致什么問題? 該如何做才能預(yù)防這個(gè)錯(cuò)誤技肩? 如果難以預(yù)防且轨, 該如何描述, 才能在出現(xiàn)錯(cuò)誤時(shí)更好地定位出這樣的錯(cuò)誤虚婿? 在出現(xiàn)錯(cuò)誤時(shí)旋奢, 如何才能恢復(fù)到正常合法的狀態(tài) ? 如果無法程序自動(dòng)恢復(fù)然痊, 怎樣做才能讓手工處理更加簡單 至朗?

要健壯地表達(dá)和維護(hù)大型邏輯, 首先系統(tǒng)整體架構(gòu)必須足夠穩(wěn)固可靠剧浸, 在開發(fā)和維護(hù)過程中持續(xù)加固彼硫。 假設(shè)一棟建筑整體設(shè)計(jì)有問題劣领, 那么, 無論里面的房間裝飾得多么漂亮優(yōu)雅, 都會隨著建筑的坍塌而消亡高氮。 這需要深入去探究所使用的應(yīng)用框架, 挖出可能的不可靠風(fēng)險(xiǎn)荚醒, 并加以預(yù)防和控制滓技。

在已確定的設(shè)計(jì)方案和業(yè)務(wù)邏輯的情況下, 如何編寫B(tài)UG更少的代碼:

簡明扼要的注釋 + 契約式/防御式編程 + 更短小的邏輯塊 + 復(fù)用公共庫 + 嚴(yán)格測試

編寫更少BUG程序的六條準(zhǔn)則:

      1.   在方法前面編寫簡明扼要的注釋: 方法用途, 接收參數(shù)碑宴,  返回值软啼, 注意事項(xiàng), 作者延柠, 時(shí)間祸挪。

      2.   契約式編程: 在方法入口處編寫前置條件校驗(yàn),在方法出口處編寫后置結(jié)果校驗(yàn) 贞间;

      3.   防御式編程: 編程時(shí)嚴(yán)格校驗(yàn)參數(shù)和前置條件贿条; 仔細(xì)考慮各種錯(cuò)誤與異常的定位和處理;

      4.   編寫和保持短小邏輯塊增热, 易于為人的腦容量一次性處理整以, 容易測試; 

      5.   復(fù)用經(jīng)過嚴(yán)格測試的可靠的公共庫峻仇; 如果庫沒有經(jīng)過很好的測試公黑,但有很好的用處, 幫助其添加測試摄咆;

      6.   對所編寫的代碼凡蚜, 如果不是邏輯元, 都要進(jìn)行嚴(yán)格測試吭从。

關(guān)于作者: 陳光劍朝蜘,江蘇東海人, 號行走江湖一劍客,字之劍涩金。程序員谱醇,詩人, 作家

http://universsky.github.io/?


<link rel="stylesheet" >

<script src="http://code.jquery.com/jquery-1.7.2.min.js"></script>
<script src="http://yandex.st/highlightjs/6.2/highlight.min.js"></script>

<script>hljs.initHighlightingOnLoad();</script>
<script type="text/javascript">
$(document).ready(function(){
$("h2,h3,h4,h5,h6").each(function(i,item){
var tag = $(item).get(0).localName;
$(item).attr("id","wow"+i);
$("#category").append('<a class="new'+tag+'" href="#wow'+i+'">'+$(this).text()+'</a></br>');
$(".newh2").css("margin-left",0);
$(".newh3").css("margin-left",20);
$(".newh4").css("margin-left",40);
$(".newh5").css("margin-left",60);
$(".newh6").css("margin-left",80);
});
});
</script>

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市步做,隨后出現(xiàn)的幾起案子副渴,更是在濱河造成了極大的恐慌,老刑警劉巖全度,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件佳晶,死亡現(xiàn)場離奇詭異,居然都是意外死亡讼载,警方通過查閱死者的電腦和手機(jī)轿秧,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來咨堤,“玉大人菇篡,你說我怎么就攤上這事∫淮” “怎么了驱还?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵嗜暴,是天一觀的道長。 經(jīng)常有香客問我议蟆,道長闷沥,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任咐容,我火速辦了婚禮舆逃,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘戳粒。我一直安慰自己路狮,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布蔚约。 她就那樣靜靜地躺著奄妨,像睡著了一般。 火紅的嫁衣襯著肌膚如雪苹祟。 梳的紋絲不亂的頭發(fā)上砸抛,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天,我揣著相機(jī)與錄音树枫,去河邊找鬼锰悼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛团赏,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播耐薯,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼舔清,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了曲初?” 一聲冷哼從身側(cè)響起体谒,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎臼婆,沒想到半個(gè)月后抒痒,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡颁褂,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年故响,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片颁独。...
    茶點(diǎn)故事閱讀 38,117評論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡彩届,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出誓酒,到底是詐尸還是另有隱情樟蠕,我是刑警寧澤,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站寨辩,受9級特大地震影響吓懈,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜靡狞,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一耻警、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧耍攘,春花似錦榕栏、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至式曲,卻和暖如春妨托,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背吝羞。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工兰伤, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人钧排。 一個(gè)月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓敦腔,卻偏偏與公主長得像,于是被迫代替她去往敵國和親恨溜。 傳聞我的和親對象是個(gè)殘疾皇子符衔,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,877評論 2 345

推薦閱讀更多精彩內(nèi)容