日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

模型描述的关系模式_你的项目该用哪种编程模式?

發(fā)布時(shí)間:2025/3/15 编程问答 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 模型描述的关系模式_你的项目该用哪种编程模式? 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

哎,一個(gè)1970年的問(wèn)題,爭(zhēng)論了快50年了,還有那么多引戰(zhàn)的。

客觀一點(diǎn)講,對(duì)于玩過(guò)不少語(yǔ)言、大體上幾種模式都上過(guò)項(xiàng)目的我來(lái)講,幾種編程模式的本質(zhì)問(wèn)題都是管理問(wèn)題。?

01

面向過(guò)程,本質(zhì)是“順序,循環(huán),分支”

拉個(gè)小學(xué)生過(guò)來(lái),十分鐘講明白,速度出項(xiàng)目,速度出東西。簡(jiǎn)單明了,大家都不亂。但這么耿直的狀況,現(xiàn)在基本上已經(jīng)不可能見(jiàn)到了。任何事物分解,用最簡(jiǎn)單的面向過(guò)程方式分解,都會(huì)讓后期復(fù)雜度提升到一個(gè)爆炸的狀態(tài)。

面向過(guò)程開(kāi)發(fā),就像是總有人問(wèn)你要后續(xù)的計(jì)劃一樣,下一步做什么,再下一步做什么。意外、事物中斷、突發(fā)事件,當(dāng)今一切事物的復(fù)雜度,都不是“順序循環(huán)分支”幾句話能說(shuō)清楚的。

來(lái)來(lái)來(lái),幾十件事兒并發(fā),多線程工作,你覺(jué)得用“順序循環(huán)分支”描述一個(gè)人、一個(gè)模塊,單線工作還好,稍微大一點(diǎn)兒,如果用這種最簡(jiǎn)單的描述方式,要么幾乎無(wú)法使用,缺失細(xì)節(jié)太多,要么事無(wú)巨細(xì),用最簡(jiǎn)單的描述,描述到量級(jí)超出人類(lèi)的掌控范圍。

這是個(gè)要么寫(xiě)個(gè)小工具,要么寫(xiě)個(gè)小玩具的代碼結(jié)構(gòu),玩玩就行了,上項(xiàng)目還是算了。有些穩(wěn)定性要求極高,掌控度要求極高的特殊環(huán)境還可能會(huì)使用。

02

面向?qū)ο?#xff0c;本質(zhì)是“繼承,封裝,多態(tài)”

可以理解為將一切事物模塊化,不要問(wèn)我你想做什么,怎么去做。而是計(jì)算手里有什么資源,有多少人,每個(gè)人會(huì)什么,每個(gè)人能做到什么。基于現(xiàn)狀,我們能完成什么。至于具體要干嘛,組合放這兒了,事物來(lái)了,就按照計(jì)劃,各自負(fù)責(zé)各自的。

上層回避下層細(xì)節(jié),讓每一層中間層接觸理解的事物控制在很小的范圍內(nèi)。很長(zhǎng)一段時(shí)間里,大量的項(xiàng)目幾乎只有面向?qū)ο筮@一種模式。人腦同時(shí)能接收的信息是有限的,同時(shí)接收的信息過(guò)多,不是忘事兒漏事兒,就是漏洞百出。

面向?qū)ο蟮拇a結(jié)構(gòu),有效做到了層層分級(jí)、層層封裝,每一層只理解需要對(duì)接的部分,其他被封裝的細(xì)節(jié)不去考慮,有效控制了小范圍內(nèi)信息量的爆炸。每個(gè)模塊,每個(gè)人做好自己的事兒就行了,自然運(yùn)轉(zhuǎn),來(lái)事兒了干事兒,沒(méi)事兒了閑置。然而當(dāng)項(xiàng)目的復(fù)雜度超過(guò)一定程度的時(shí)候,會(huì)演變成一個(gè)完全無(wú)法管理的失控狀態(tài)。一個(gè)為了簡(jiǎn)化思維出現(xiàn)的模式,嚴(yán)重增加了整個(gè)系統(tǒng)的復(fù)雜度。

第一個(gè)問(wèn)題:模塊間對(duì)接的代價(jià)遠(yuǎn)遠(yuǎn)高于實(shí)體業(yè)務(wù)干活的代價(jià)。

類(lèi)似金字塔管理模式,模塊數(shù)超出一個(gè)極限之后,最底層實(shí)現(xiàn)業(yè)務(wù)的部分寫(xiě)不了幾十行。但是該模塊的上層對(duì)接,上層的上層對(duì)接,各種框架對(duì)接代碼作為中間層遠(yuǎn)遠(yuǎn)超出業(yè)務(wù)的執(zhí)行。到了最后,所有逗逼程序猿都在研究結(jié)構(gòu)怎么設(shè)計(jì),框架怎么設(shè)計(jì),應(yīng)該使用哪種抽象,怎么抽象能簡(jiǎn)化框架,簡(jiǎn)化結(jié)構(gòu)。

中間層、對(duì)接層的復(fù)雜度遠(yuǎn)遠(yuǎn)高于實(shí)體業(yè)務(wù),已經(jīng)沒(méi)有任何一個(gè)人,任何一個(gè)再牛的架構(gòu)師知道整個(gè)項(xiàng)目的細(xì)節(jié),已經(jīng)沒(méi)有人能掌握,甚至因?yàn)閺?fù)雜,因?yàn)椴涣私?#xff0c;已經(jīng)幾乎無(wú)法改動(dòng)了。

這也是亞馬遜的工程師描述的:“我的工作,就是每天進(jìn)到一大片屎山里,然后進(jìn)到屎山的中心,去找到底是哪里出了問(wèn)題,為什么唯獨(dú)這一塊兒這么臭。。。”

第二個(gè)問(wèn)題:代碼膨脹讓原本寫(xiě)不了兩行的實(shí)體代碼膨脹到數(shù)十倍。

原本是有什么事兒,完成什么事兒。因?yàn)槊嫦驅(qū)ο蟾拍畹膶蛹?jí)劃分,要實(shí)現(xiàn)的業(yè)務(wù)需要封裝,封裝好跟父類(lèi)對(duì)接。多繼承是萬(wàn)惡之源,讓整個(gè)系統(tǒng)結(jié)構(gòu)變成了網(wǎng)狀、環(huán)狀,最后變成一坨亂麻。

而單繼承,原本直接找業(yè)務(wù)代碼實(shí)現(xiàn)的事情,需要層層對(duì)接,層層調(diào)度。每一層對(duì)接代碼,都是要人寫(xiě)的。雖然基本都是沒(méi)有任何技術(shù)難度的純敲,但是代碼量的提升,無(wú)論再簡(jiǎn)單的業(yè)務(wù),再簡(jiǎn)單的結(jié)構(gòu),代碼量龐大本身就已經(jīng)是一個(gè)重大的隱患性bug了。畢竟出問(wèn)題了,讀下來(lái)、找問(wèn)題也是要浪費(fèi)大量時(shí)間的。

層級(jí)劃分的代碼量提升同時(shí)也造成了第三個(gè)問(wèn)題。

第三個(gè)問(wèn)題:過(guò)多的間接過(guò)程才能訪問(wèn)到實(shí)體業(yè)務(wù),嚴(yán)重影響性能,速度極慢。

要知道,《UNIX編程藝術(shù)》,第一原則就是KISS原則,整本書(shū)都貫徹了KISS原則。(keep it simple, stupid!)

寫(xiě)項(xiàng)目、寫(xiě)代碼,目的都是為了解決問(wèn)題,寫(xiě)出解決問(wèn)題的產(chǎn)品。但是龐大的面向?qū)ο竽P?#xff0c;讓你花費(fèi)或者說(shuō)浪費(fèi)了過(guò)多的時(shí)間在考慮與要解決的問(wèn)題完全無(wú)關(guān),而且非常復(fù)雜的管理調(diào)度問(wèn)題上。但是,面向?qū)ο竽J诫m然是個(gè)最容易出屎山的模式,但是在很大程度上,無(wú)論任何一種架構(gòu)的引入,我們現(xiàn)代編程,項(xiàng)目里對(duì)接使用最多的,仍然是面向?qū)ο蟮墓ぷ髂J健?/p>

大家都很痛苦,大家都知道問(wèn)題在哪兒,大家都在罵面向?qū)ο?#xff0c;但畢竟沒(méi)有更好的解決方案,不是么?

03

函數(shù)式編程本質(zhì)是“函數(shù)映射”,通俗一點(diǎn)講叫規(guī)則制定

這個(gè)函數(shù)不是面向過(guò)程編程的函數(shù),這個(gè)函數(shù)是數(shù)學(xué)概念里的函數(shù)。定義是這樣的:兩個(gè)非空集合A與B存在著對(duì)應(yīng)關(guān)系f,而且對(duì)于A中的每一個(gè)元素x,B中總有唯一的一個(gè)元素y與它對(duì)應(yīng),就這種對(duì)應(yīng)為從A到B的映射,記作函數(shù)f(A)。。。

這個(gè)東西理解起來(lái)比較麻煩,通俗易懂一點(diǎn)講,在我們嘗試設(shè)計(jì)了無(wú)數(shù)的語(yǔ)言模型,試圖用編程模式來(lái)描述事物的運(yùn)轉(zhuǎn),描述要做的復(fù)雜業(yè)務(wù)的執(zhí)行模式,甚至描述這個(gè)世界本身的時(shí)候,從來(lái)都沒(méi)有人真正解決過(guò),最后都倒在了人腦跟不上這一點(diǎn)。事物變得越龐大復(fù)雜,對(duì)事物復(fù)雜度的描述總是會(huì)越來(lái)越失控。

終于,1956年開(kāi)始出現(xiàn)質(zhì)疑,1960年lisp出現(xiàn),1970年lisp混合使用函數(shù)式模型,在當(dāng)時(shí)還只是理念。John Backus在他1977年的圖靈獎(jiǎng)?lì)C獎(jiǎng)演講中正式提出函數(shù)式編程概念。而函數(shù)式編程所做的事情很簡(jiǎn)單,就是放棄這些愚昧無(wú)知的人類(lèi)創(chuàng)造的語(yǔ)言和概念,去使用“上帝”創(chuàng)世的時(shí)候一直在使用的語(yǔ)言“數(shù)學(xué)”。這個(gè)世界的復(fù)雜度遠(yuǎn)遠(yuǎn)高于任何一個(gè)計(jì)算機(jī)軟件工程。開(kāi)始有人試圖理解并模仿世界最初的構(gòu)造,去寫(xiě)代碼,用這種方式構(gòu)建項(xiàng)目。

抽象的東西不說(shuō)那么多,說(shuō)白了,模仿的方式就是用“數(shù)學(xué)”描述“規(guī)則制定”。有人會(huì)感覺(jué),計(jì)算機(jī)編程不也是在用數(shù)學(xué)寫(xiě)嗎,跟函數(shù)式編程非要單獨(dú)提出來(lái)的“數(shù)學(xué)”區(qū)別在哪兒?函數(shù)描述和語(yǔ)句描述最直觀的界限,我這里舉一個(gè)簡(jiǎn)單而又熟悉的例子,就清楚了。

從前寫(xiě)數(shù)學(xué)題的時(shí)候最經(jīng)典的一個(gè)寫(xiě)法。設(shè)x1=3,x2=9,y=x1+x2,得出y=12。如果類(lèi)比到編程語(yǔ)言里,我們會(huì)感覺(jué)這種寫(xiě)法很冗余,會(huì)變成let x1 = 3; return x1 = x1 + 9;這事兒看習(xí)慣代碼了覺(jué)得沒(méi)毛病,還原回?cái)?shù)學(xué)模型,細(xì)思極恐。x1=3;x1 = x1 + 9???3= 3 + 9???計(jì)算機(jī)概念最初就引入了一個(gè)反數(shù)學(xué)模型的概念:變量。而變量的存在,是可以保存數(shù)據(jù)的。這個(gè)數(shù)據(jù)保存已經(jīng)不是純粹的數(shù)學(xué)描述了。

函數(shù)式模型描述的是事物是怎么運(yùn)行的,而不是事物運(yùn)行本身。所謂怎么運(yùn)行的,就像是寫(xiě)一個(gè)數(shù)學(xué)公式,傳入?yún)?shù),傳出參數(shù)。其本體是這個(gè)函數(shù),而不是傳入的什么參數(shù)。而運(yùn)行本身,最大的區(qū)別,在常規(guī)編程概念里叫“變量”,函數(shù)式編程里叫“副作用”。也就是是否將傳入的數(shù)據(jù)本身作為函數(shù)。

在常規(guī)編程模型里,變量是函數(shù)的一部分,但是在數(shù)學(xué)概念里,數(shù)學(xué)公式本身就是全部,不包含使用數(shù)學(xué)公式傳入的參數(shù)。這些是更本質(zhì)的函數(shù)式編程的描述,單看這一部分,比前面的幾個(gè)模型概念已經(jīng)復(fù)雜很多了。這些本身只是表象,后面說(shuō)具體怎么解決問(wèn)題的,舍棄變量的好處和代價(jià)又是什么呢?

計(jì)算機(jī)程序模塊因?yàn)橛凶兞窟@個(gè)概念,模塊切分之后往往并不總是正確的。某些初始化沒(méi)執(zhí)行,后面的模塊自己跑,因?yàn)閿?shù)據(jù)沒(méi)構(gòu)造、沒(méi)有數(shù)據(jù)結(jié)構(gòu)等等問(wèn)題,單獨(dú)截出來(lái)的部分直接是錯(cuò)誤的。

而數(shù)學(xué)公式,無(wú)論從任何一個(gè)位置截取出來(lái),公式的任何一個(gè)子公式都始終保持永遠(yuǎn)是正確的。子公式帶入更復(fù)雜的公式,最終得到更龐大的復(fù)雜公式。這些過(guò)程無(wú)論是組合還是截取,永遠(yuǎn)都保持著公式的正確性。

那么我們?nèi)绻怀霈F(xiàn)這種類(lèi)似,設(shè)x1 = 3;x1 = x1 + 9這種變量式代碼。保持高中寫(xiě)題的模式,設(shè)x1=3;x2=x1+9;將第一個(gè)公式帶入第二個(gè)公式,x2=3+9這種思維模式,得到x2=12。所有代碼模塊,始終保持傳入?yún)?shù),參數(shù)按照公式運(yùn)行得出結(jié)果的這唯一的lambda表達(dá)式模型。

整個(gè)程序就變成了無(wú)數(shù)的,絕對(duì)正確的函數(shù)(公式),以及函數(shù)之間的互相帶入。系統(tǒng)的運(yùn)轉(zhuǎn)就是傳入?yún)?shù),得到結(jié)果。不存在變量狀態(tài)、變量管理等等無(wú)數(shù)的問(wèn)題。相當(dāng)于永遠(yuǎn)設(shè)定各種各樣的規(guī)則,永遠(yuǎn)不出現(xiàn)某規(guī)則里在什么具體的情況應(yīng)該怎么怎么,而是讓該規(guī)則保持正確,剩余的一切事物只需要在該規(guī)則下自然運(yùn)轉(zhuǎn),不需要所謂的中間層管理層去做任何的程序運(yùn)轉(zhuǎn)的干涉。

采用這種代碼設(shè)計(jì)模式,第一個(gè)特點(diǎn),就是腦殼疼。最經(jīng)典的一個(gè)例子,看下面這段代碼,函數(shù)返回從x加到y(tǒng),x

function test (x, y) {

?????? let? res = 0;

?????? for(let i = x; i <= y; i++) {

????????????? res=res+i;

?????? }

?????? return? res;

}

這里已經(jīng)違反了函數(shù)式編程模型,變量res是個(gè)副作用參數(shù),i是個(gè)副作用參數(shù)。開(kāi)頭設(shè)res=0了,res=res+x這數(shù)學(xué)模型已經(jīng)被顛覆了。如果從中間截取任何一個(gè)流程,已經(jīng)是錯(cuò)的了。不引入變量,常規(guī)編程模型里,循環(huán)這個(gè)概念已經(jīng)不可能實(shí)現(xiàn)了。我們的做法是:

function test_run (x, y) {

?????? return? test2 (x, y, x);

}

function? test2 (x, y, res) {

?????? if(y ===x) {

????????????? return? x;

?????? }else {

????????????? console.log(x, y-1, res+y);

????????????? return? test2 (x, y - 1, res+y);

?????? }

}

test_run (1, 100);

這個(gè)函數(shù),除了x和y,沒(méi)有任何變量因素存在。這就是所謂“規(guī)則制定”最應(yīng)該存在的狀態(tài)。無(wú)論在什么狀態(tài)下,無(wú)論在整個(gè)系統(tǒng)運(yùn)行的哪一個(gè)步驟被截取出來(lái),這個(gè)公式都是永遠(yuǎn)正確的,所謂模仿數(shù)學(xué)模型的函數(shù)式模型。

上面這個(gè)已經(jīng)不是循環(huán)了,畢竟循環(huán)這個(gè)概念存在最根本的基石就是變量。變量作為計(jì)數(shù),才能從x加到y(tǒng)。這是個(gè)尾遞歸函數(shù)。

注意要認(rèn)清楚,尾遞歸和遞歸本質(zhì)上是兩個(gè)東西,是可以替代迭代循環(huán)的,而遞歸則不行。內(nèi)存膨脹太嚴(yán)重,雖然尾遞歸看起來(lái)很像遞歸。

采用函數(shù)式編程極大減少了系統(tǒng)的復(fù)雜度,而且減少了運(yùn)維成本。因?yàn)檎麄€(gè)系統(tǒng)里沒(méi)有所謂的運(yùn)行期,也就沒(méi)有運(yùn)行期錯(cuò)誤。中間層,對(duì)階層,管理模塊全部都可以刪除了。只要按照設(shè)定好的規(guī)則,只要不超出規(guī)則,就不需要太多管理。公式規(guī)則的設(shè)定不應(yīng)該涉及實(shí)際運(yùn)行過(guò)程中的細(xì)節(jié)變化問(wèn)題,不應(yīng)該出現(xiàn)在什么情況下要怎么樣,什么情況下怎么怎么的寫(xiě)法。有且僅只有輸入和輸出以及公式的運(yùn)轉(zhuǎn)邏輯,可以出現(xiàn)參數(shù),但不允許出現(xiàn)副作用參數(shù)。只能以類(lèi)似設(shè)x2=x1+9;x3=x1*x2這種寫(xiě)法。

僅制定合理有效正確的規(guī)范,而不糾結(jié)規(guī)則規(guī)范下的具體運(yùn)行。規(guī)則本身已經(jīng)是最好的管理了。

函數(shù)式編程的第二個(gè)特點(diǎn)是:只要確保函數(shù)正確、函數(shù)運(yùn)行正確、函數(shù)組合的復(fù)雜函數(shù)正確,你不需要關(guān)注函數(shù)在干什么,你只需要知道函數(shù)傳入什么,傳出什么,而且可以用任何多線程、多調(diào)用之類(lèi)的方式造任何模式的函數(shù)。因?yàn)楸旧聿淮嬖谧兞扛拍?#xff0c;也就不存在多線程編程里最?lèi)盒牡呐R界區(qū)問(wèn)題了。

函數(shù)式編程的第三個(gè)特點(diǎn)是:快。沒(méi)有中間商賺差價(jià),沒(méi)有中間層瞎折騰,資源可以完全利用在該利用的地方,運(yùn)行快。

函數(shù)式編程的第四個(gè)特點(diǎn)是:快。這個(gè)快,是寫(xiě)代碼快。我們寫(xiě)項(xiàng)目,其實(shí)根本就不是在寫(xiě)業(yè)務(wù)。業(yè)務(wù)代碼兩三天敲完了,然后結(jié)構(gòu)設(shè)計(jì),框架設(shè)計(jì),對(duì)接設(shè)計(jì),數(shù)據(jù)管理,內(nèi)存管理,調(diào)度管理,資源管理。這些都還好說(shuō),運(yùn)行起來(lái)出bug,10%時(shí)間寫(xiě)bug,90%時(shí)間調(diào)bug。(你是我們公司雇來(lái)專(zhuān)職寫(xiě)bug的么?)

而函數(shù)式編程任何一個(gè)無(wú)副作用參數(shù)的模塊取出來(lái),都是與數(shù)據(jù)本身無(wú)關(guān)的公式。只要你寫(xiě)的最小的那個(gè)模塊沒(méi)錯(cuò),只要你沒(méi)寫(xiě)錯(cuò)邏輯,就不會(huì)出錯(cuò)。

經(jīng)常有說(shuō)法,一個(gè)項(xiàng)目開(kāi)發(fā),C++和java要寫(xiě)一年,C語(yǔ)言要寫(xiě)5年,而lisp可能只需要三個(gè)月。這個(gè)對(duì)比有點(diǎn)夸大的成分,但單從代碼量上講,這個(gè)量級(jí)也差不多。

說(shuō)著說(shuō)著是不是感覺(jué)函數(shù)式編程就是未來(lái),就是以后的趨勢(shì)了?是趨勢(shì)沒(méi)錯(cuò),肯定該學(xué)的都還是要學(xué)的。我要開(kāi)始打臉了。

如果真的函數(shù)式編程這么好用,效果也這么好,真要是沒(méi)點(diǎn)兒致命的缺點(diǎn),為什么50多年了,都還沒(méi)有那么普及,現(xiàn)在普及的還是面向?qū)ο竽亍?/p>

缺點(diǎn)一:門(mén)檻太高,也就意味著你招不到人。

面向?qū)ο竽J街v究的是群體開(kāi)發(fā),每個(gè)人只需要關(guān)注你所在位置,你的眼前需要關(guān)注的問(wèn)題,用封裝屏蔽底層運(yùn)行細(xì)節(jié)的方式,簡(jiǎn)化一次性接收的信息量。在寫(xiě)好架構(gòu)的情況下,分發(fā)架構(gòu)文檔,多人同時(shí)開(kāi)發(fā)。你優(yōu)秀,把你水準(zhǔn)拉低,封裝到代碼層內(nèi)。你水平低,過(guò)不了TDD測(cè)試,只要能過(guò),也出不了什么大問(wèn)題,這是一種可以量產(chǎn),可以找大量廉價(jià)勞動(dòng)力堆出來(lái)一個(gè)能用的屎山的工作模式。同時(shí)不需要能力過(guò)高的人,不需要會(huì)很多,覆蓋面很廣的人。

有面向?qū)ο蠹軜?gòu)師一個(gè)人把握全局就可以了,其他人只用看著文檔、無(wú)腦堆代碼、過(guò)測(cè)試就行了。重復(fù)工作量幾百倍幾千倍的堆,跑不起來(lái),浪費(fèi)資源,那就拿錢(qián)砸。

要知道,拿錢(qián)砸硬件,是看得見(jiàn)的,而且是誠(chéng)實(shí)的。一倍的錢(qián),砸一倍的性能,不需要寫(xiě)的太好。而人存在著無(wú)數(shù)不確定性,用錢(qián)很難直觀體現(xiàn)出來(lái)能力大小,增加算法復(fù)雜度,讓水平低的看不懂,導(dǎo)致各種問(wèn)題,還不如用錢(qián)砸硬件。

水平拉低的另一個(gè)好處,招人好招,都可以互相替代,難度都不大。找個(gè)能加班的,比找個(gè)能力強(qiáng)的有用。

面向?qū)ο箝_(kāi)發(fā)模式是非常適合商業(yè)運(yùn)作的開(kāi)發(fā)模式。而函數(shù)式編程的門(mén)檻,我就兩個(gè)字,“數(shù)學(xué)?”,呵呵。。。

function test_run (x, y) {

?????? return? test2 (x, y, x);

}

function? test2 (x, y, res) {

?????? if(y === x) {

?????? ?????? return? x;

?????? }else {

????????????? console.log(x, y-1, res+y);

????????????? return? test2 (x, y - 1, res+y);

?????? }

}

test_run (1, 100);

就上面這個(gè)東西,一個(gè)簡(jiǎn)單的從1加到100,能看出來(lái)這是個(gè)循環(huán)的,估計(jì)都已經(jīng)不好招了。

缺點(diǎn)二:慢。。。

上面說(shuō)快,這邊開(kāi)始打臉。我說(shuō)的慢,真的就是運(yùn)行起來(lái),運(yùn)行資源占用導(dǎo)致的慢。舉個(gè)例子,現(xiàn)在神經(jīng)網(wǎng)絡(luò)算法非常火,有幾個(gè)真的知道神經(jīng)網(wǎng)絡(luò)算法是什么的?這個(gè)名詞其實(shí)根本沒(méi)那么玄幻,簡(jiǎn)單一點(diǎn)說(shuō),神經(jīng)網(wǎng)絡(luò)算法的本質(zhì)就是多項(xiàng)式分解。

最常見(jiàn)的多項(xiàng)式分解,f(x)=an·x^n+an-1·x^(n-1)+…+a2·x^2+a1·x+a0,這個(gè)東西還有三角多項(xiàng)式分解什么的,都學(xué)過(guò)沒(méi)什么好介紹的。

多項(xiàng)式分解就是使用n次冪的多項(xiàng)式,可以描述任何一個(gè)函數(shù),可以將任何一個(gè)函數(shù)分解為無(wú)限次冪的多項(xiàng)式函數(shù)。神經(jīng)網(wǎng)絡(luò)就是能用神經(jīng)網(wǎng)絡(luò)加權(quán)算法描述任何一個(gè)函數(shù),可以將任何一個(gè)函數(shù)分解為無(wú)限級(jí)神經(jīng)網(wǎng)絡(luò)加權(quán)的多項(xiàng)式函數(shù)。但是為什么不用初中還是高中就學(xué)過(guò)的多項(xiàng)式分解,一定要引入一個(gè)這么復(fù)雜的神經(jīng)網(wǎng)絡(luò),還這么火呢?

說(shuō)白了,計(jì)算機(jī)說(shuō)起來(lái)很強(qiáng)大,我們好像都覺(jué)得CPU很強(qiáng)大。學(xué)計(jì)算機(jī)的都知道,計(jì)算機(jī)CPU這個(gè)寄存器設(shè)計(jì)能做的事情很有限,根本就不強(qiáng)大。多項(xiàng)式分解這種東西,你教一個(gè)初中生算,現(xiàn)在大體上都會(huì),貌似是不是小學(xué)都開(kāi)始教這個(gè)了?但是你讓計(jì)算機(jī)算多項(xiàng)式分解,用了無(wú)數(shù)的套路才抽象出一個(gè)近似的多級(jí)的冪運(yùn)算,或者多級(jí)的sin,cos運(yùn)算。

神經(jīng)網(wǎng)絡(luò)算法,每一個(gè)神經(jīng)元節(jié)點(diǎn)的加權(quán)運(yùn)算,看起來(lái)輸入輸出權(quán)值運(yùn)算比多項(xiàng)式分解復(fù)雜多了,但實(shí)際上每個(gè)神經(jīng)元的權(quán)值運(yùn)算,計(jì)算機(jī)是算的動(dòng)的,而冪運(yùn)算,計(jì)算機(jī)代價(jià)無(wú)法估量了。完全以數(shù)學(xué)思維寫(xiě)代碼,帶入的某些數(shù)學(xué)概念,在計(jì)算機(jī)上運(yùn)行時(shí),因?yàn)椴簧瞄L(zhǎng),會(huì)多出來(lái)大量額外的工作,而且可能是近似,永遠(yuǎn)都算不對(duì)。

畢竟某種意義上來(lái)說(shuō),計(jì)算機(jī)概念使用的“浮點(diǎn)數(shù)”這個(gè)概念,已經(jīng)是算個(gè)近似,注定永遠(yuǎn)都不可能像數(shù)學(xué)一樣準(zhǔn)確運(yùn)算了。而如果用其他代碼回避浮點(diǎn)數(shù)概念,增加其他機(jī)制,復(fù)雜度和資源占用又要開(kāi)始爆表了。再說(shuō)2^32,2^64這幾個(gè)寄存器限制,大數(shù)運(yùn)算,僅僅是加減法,可能都已經(jīng)是一個(gè)很復(fù)雜的運(yùn)算了。這些問(wèn)題如果放在真正的數(shù)學(xué)運(yùn)算里原本是不需要考慮的。

再舉個(gè)簡(jiǎn)單的例子,計(jì)算機(jī)根本就不會(huì)算除法。

我們當(dāng)今世界的網(wǎng)絡(luò)安全基礎(chǔ),就是RSA算法,誰(shuí)都解不開(kāi)。肯定不是真的解不開(kāi),只是因?yàn)橛?jì)算機(jī)不會(huì)算除法,兩個(gè)大質(zhì)數(shù)相乘的乘積,除開(kāi)這件事情,是一個(gè)世界難題。有些事情其實(shí)是細(xì)思極恐,你會(huì)算除法么?除法是什么?你會(huì)的除法運(yùn)算是不是只是背了個(gè)乘法表,然后反過(guò)來(lái)背著乘法表,撞除法運(yùn)算。

如果真的拿數(shù)學(xué)理念上,讓計(jì)算機(jī)這種低級(jí)CPU的一個(gè)字節(jié)8位去算,來(lái)上幾次方,幾個(gè)大數(shù),幾十行代碼,能給你把超級(jí)服務(wù)器算崩潰。但凡你覺(jué)得很簡(jiǎn)單的概念上到計(jì)算機(jī)上,算法的膨脹,資源的消耗很可能在你沒(méi)注意的,莫名其妙的梗上卡死。

缺點(diǎn)三:慢。。。?

這個(gè)慢,對(duì)應(yīng)上面的開(kāi)發(fā)效率慢、寫(xiě)代碼慢。

說(shuō)白了,本質(zhì)上還是門(mén)檻太高。你招一批水平一般的面向?qū)ο蟪绦騿T,設(shè)計(jì)好結(jié)構(gòu),呼呼啦啦都開(kāi)始敲,敲了幾千上萬(wàn)行代碼,事兒搞定了。從代碼量上說(shuō)很龐大,解決一個(gè)很小的事兒,效率很低。實(shí)際上呢?你找了個(gè)函數(shù)式開(kāi)發(fā)的高手,蹲在哪兒開(kāi)始思考,寫(xiě)寫(xiě)刪刪,測(cè)測(cè)改改。幾十行,百十來(lái)行寫(xiě)完項(xiàng)目。這個(gè)開(kāi)發(fā)效率高?而且相對(duì)還很有意思,動(dòng)腦程度很高?

如果他沒(méi)考慮清楚呢?如果這哥們兒家里有事兒呢?如果這哥們兒生病了呢?如果這哥們兒技術(shù)其實(shí)沒(méi)那么屌,腦子都快想炸了,憋不出來(lái)呢?

如果團(tuán)隊(duì)里水平都很高,都有很深厚的底子。項(xiàng)目開(kāi)發(fā)效率會(huì)高,但真實(shí)情況是,這種條件你根本找不來(lái)。而哪怕你找來(lái)了,也沒(méi)什么用,這就是第四個(gè)缺點(diǎn)了。

缺點(diǎn)四:lisp詛咒(The Lisp Curse)?

關(guān)于這個(gè)名詞,有很多文章都有講,也是幾十年來(lái)無(wú)數(shù)引戰(zhàn)帖討論過(guò)的問(wèn)題。這個(gè)又是個(gè)描述起來(lái)比較麻煩的概念,同時(shí)也是我確信,哪怕以后程序員水準(zhǔn)普遍提高,函數(shù)式編程再優(yōu)秀,都永遠(yuǎn)都是小眾,而且不建議鋪開(kāi)了上項(xiàng)目使用的最重要的原因。

對(duì)于lisp詛咒最準(zhǔn)確的描述,也是大眾最容易理解的描述,是這樣的。Lisp是如此強(qiáng)大,以至于在其他編程語(yǔ)言中的技術(shù)問(wèn)題,到了Lisp中變成了社會(huì)問(wèn)題。

是的,你沒(méi)有看錯(cuò),不是技術(shù)問(wèn)題,是社會(huì)問(wèn)題。社會(huì)問(wèn)題跟技術(shù)問(wèn)題最大的區(qū)分點(diǎn),是“人”。技術(shù)沒(méi)問(wèn)題,技術(shù)很強(qiáng)大,但是強(qiáng)大的技術(shù)模式,必然會(huì)導(dǎo)致人的分裂,社區(qū)的分裂,以至于函數(shù)式開(kāi)發(fā)模型最后一定會(huì)死在技術(shù)無(wú)關(guān)的“管理問(wèn)題”上。其中l(wèi)isp詛咒導(dǎo)致的最嚴(yán)重的問(wèn)題就是,“孤狼式開(kāi)發(fā)”。

我舉個(gè)例子:面向?qū)ο笾皇且环N設(shè)計(jì)思路,是一種概念,并沒(méi)有說(shuō)什么C++是面向?qū)ο蟮恼Z(yǔ)言,java是面向?qū)ο蟮恼Z(yǔ)言。

C語(yǔ)言一樣可以是面向?qū)ο蟮恼Z(yǔ)言,Linux內(nèi)核就是面向?qū)ο蟮脑鶪NU C89編寫(xiě)的,但是為了支持面向?qū)ο蟮拈_(kāi)發(fā)模式,Linux內(nèi)核編寫(xiě)了大量概念維護(hù)modules,維護(hù)struct的函數(shù)指針,內(nèi)核驅(qū)動(dòng)裝載等等機(jī)制。而C++和java為了增加面向?qū)ο蟮膶?xiě)法,直接給編譯器加了一堆語(yǔ)法糖。

而lisp、Haskell,在純粹的函數(shù)式編程模型下,寫(xiě)出來(lái)一整套支持面向?qū)ο蟮母拍詈涂蚣?#xff0c;需要多少代碼呢?幾百行。。。

這種開(kāi)發(fā)優(yōu)勢(shì)最終導(dǎo)致了社區(qū)里有無(wú)數(shù)套隨手寫(xiě)的、低質(zhì)量的、無(wú)人維護(hù)的、bug無(wú)數(shù)的垃圾面向?qū)ο罂蚣堋R舱驗(yàn)槿绱?#xff0c;你只能自己寫(xiě)一套面向?qū)ο蟮目蚣?#xff0c;只要你理論知識(shí)扎實(shí),估計(jì)寫(xiě)不了幾百行,也就是一天兩天的事兒。

每個(gè)人都在使用自己寫(xiě)的面向?qū)ο?#xff0c;每一個(gè)人都在使用自己寫(xiě)的庫(kù),而且上下是斷層的。層次高的,寫(xiě)幾套自己項(xiàng)目用的依賴(lài)沒(méi)什么難度,卻沒(méi)有別人用。時(shí)間久了,很容易消失。項(xiàng)目交接的時(shí)候,大量無(wú)人維護(hù)的,個(gè)人開(kāi)發(fā)的依賴(lài),代碼量很小,功能很強(qiáng)大,但是難度太大。項(xiàng)目交接幾乎無(wú)法進(jìn)行,除非來(lái)一個(gè)大牛接手,但同樣的,如果不是這種方式,一旦技術(shù)斷層,項(xiàng)目再也沒(méi)人能看得懂了,最好的辦法不是撞大運(yùn)的招人,而是把看不懂,又不得不改的部分刪了重寫(xiě)。

最終導(dǎo)致,邏輯過(guò)于復(fù)雜的函數(shù)式編程,總是會(huì)出現(xiàn)技術(shù)人員斷層,畢竟能力參差不齊,一次性技術(shù)門(mén)檻提的過(guò)高了。還能維護(hù)的項(xiàng)目,幾乎都是一個(gè)人寫(xiě)出來(lái)維護(hù)的項(xiàng)目,哪怕第二個(gè)人的存在,可能都只是暫時(shí)的。“孤狼式開(kāi)發(fā)”,這個(gè)名字起的是非常到位的。

最后,總結(jié)一下,也是軟件項(xiàng)目管理經(jīng)典教材《人月神話》上講的,“沒(méi)有銀彈”。

在什么情況使用什么樣的模式。不要太自信,不要太相信自己習(xí)慣使用的開(kāi)發(fā)模式和框架。你只會(huì)一種模式,怎么對(duì)比?你只會(huì)一種語(yǔ)言,怎么對(duì)比?

別爭(zhēng)論了,讓他們最后各歸各位

在驅(qū)動(dòng)開(kāi)發(fā)、嵌入式底層開(kāi)發(fā)這些地方,面向過(guò)程開(kāi)發(fā)模式,干凈,利索,直觀,資源掌控度高。在這些環(huán)境,面向過(guò)程開(kāi)發(fā)幾乎是無(wú)可替代的。

在工作量大,難度較低、細(xì)節(jié)過(guò)多、用簡(jiǎn)單的規(guī)范規(guī)則無(wú)法面面俱到的環(huán)境下,用面向?qū)ο箝_(kāi)發(fā)模式,用低質(zhì)量人力砸出來(lái)產(chǎn)業(yè)化項(xiàng)目。

在復(fù)雜度過(guò)高、層級(jí)過(guò)高的架構(gòu)頂層、面向?qū)ο竽J皆黾拥膶?duì)接復(fù)雜度已經(jīng)開(kāi)始接近失控的環(huán)境下,把上層的中間層代碼都刪了,讓少數(shù)精英使用制定規(guī)范的函數(shù)式模型,函數(shù)式編程的引入則能大大簡(jiǎn)化項(xiàng)目復(fù)雜度和開(kāi)發(fā)成本。

要學(xué)的東西還很多,學(xué)無(wú)止境吧~

1.這才是大學(xué)教育該有的樣子!

2.“玄鐵”之后是“無(wú)劍”:阿里平頭哥發(fā)布AIoT芯片平臺(tái),欲引領(lǐng)芯片開(kāi)發(fā)新模式

3.傳統(tǒng)的嵌入式C語(yǔ)言程序員快要滅絕了?

4.華為釋放信號(hào):若ARM受限,考慮用RISC-V架構(gòu)

5.一位嵌入式工程師的硬核單片機(jī)編程思想!

6.讓嵌入式開(kāi)發(fā)事半功倍,這些工具你備齊了嗎?

總結(jié)

以上是生活随笔為你收集整理的模型描述的关系模式_你的项目该用哪种编程模式?的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。