中文字幕在线观看,亚洲а∨天堂久久精品9966,亚洲成a人片在线观看你懂的,亚洲av成人片无码网站,亚洲国产精品无码久久久五月天

一個(gè)函數(shù)的自白

2018-07-20    來源:編程學(xué)習(xí)網(wǎng)

容器云強(qiáng)勢(shì)上線!快速搭建集群,上萬Linux鏡像隨意使用

我是——編程世界的函數(shù),不是數(shù)學(xué)中的冪,指,對(duì)和三角函數(shù)等等,但是和f(x)又有著千絲萬縷的關(guān)系。

我是代碼中的最小執(zhí)行組織,但不是最小執(zhí)行單元。最小的執(zhí)行單元是一條條語句,這些語句有機(jī)地組合起來完成一個(gè)或多個(gè)功能并且可以復(fù)用,這才是我——函數(shù)。

內(nèi)存與堆棧和我之間是啥關(guān)系?
有無參數(shù)的我有何異同?
我的簡(jiǎn)潔性?復(fù)雜度如何評(píng)估?
我的高階與遞歸有啥區(qū)別?
我的回調(diào)和匿名是一回事么?
對(duì)象中的方法是我么?
控制對(duì)象的行為方式有哪些呢?
為什么說類型錯(cuò)誤只是異常處理的一種方式?
面對(duì)數(shù)據(jù)密集型應(yīng)用和并發(fā)場(chǎng)景,我有何作用?
......

且聽一個(gè)函數(shù)的自白,從函數(shù)的角度看編程的方式。

我眼中的大環(huán)境——內(nèi)存

空山不見人  但聞人語響

代碼最終都要加載到內(nèi)存中執(zhí)行,組成函數(shù)的代碼同樣如此。內(nèi)存容量是受限的,需要考慮一個(gè)函數(shù)在內(nèi)存中所需要處理和生成的數(shù)據(jù)量。內(nèi)存中沒有變量名或簽名的內(nèi)存地址,只有以數(shù)字表示的內(nèi)存地址。考慮“什么將存入內(nèi)存”,“什么存入硬盤”以及“何時(shí)將內(nèi)存內(nèi)容存入硬盤”,這些考量都與性能優(yōu)化息息相關(guān)。

而現(xiàn)代編程語言強(qiáng)調(diào)透明的內(nèi)存管理,關(guān)注處理中不斷增長(zhǎng)的數(shù)據(jù)規(guī)模,這很容易失去對(duì)內(nèi)存消耗的控制,從而導(dǎo)致運(yùn)行時(shí)性能的下降。對(duì)我所采用的不同內(nèi)存使用策略,所帶來的不同結(jié)果給予適當(dāng)?shù)年P(guān)注,是件有意義的好事情。

我的運(yùn)行環(huán)境——堆棧

明月松間照 清泉石上流

由于內(nèi)存中的東西太多了,于是把我運(yùn)行環(huán)境中的內(nèi)存稱為堆棧。對(duì)于棧,所有操作都針對(duì)棧中的數(shù)據(jù),堆用于存儲(chǔ)后續(xù)操作所需的數(shù)據(jù)。堆中數(shù)據(jù)需要入棧進(jìn)行操作,最終出;氐蕉。棧溢出是內(nèi)存耗盡的情況。

通常對(duì)程序員來說,棧是不可見的,幾乎在每個(gè)現(xiàn)代的編程語言中,棧都是支持線程執(zhí)行的內(nèi)存區(qū)域。 堆是許多現(xiàn)代編程語言實(shí)現(xiàn)中的另一重要內(nèi)存區(qū)域,用于動(dòng)態(tài)內(nèi)存的分配和釋放,例如創(chuàng)建列表和對(duì)象。不要將這里的堆棧與數(shù)據(jù)結(jié)構(gòu)中的概念混淆,數(shù)據(jù)結(jié)構(gòu)中的堆是一個(gè)基于樹的數(shù)據(jù)結(jié)構(gòu)。

有一種執(zhí)行環(huán)境叫棧機(jī)器,使用了棧而不是寄存器來支持程序表達(dá)式的計(jì)算,許多現(xiàn)代虛擬機(jī)都是這樣的,例如JVM。

我源自面向過程的抽象——過程函數(shù)

大事化小  小事易了

程序員們通常會(huì)把復(fù)雜問題分解為若干個(gè)較小的容易問題,這是一種面向過程的抽象,一個(gè)過程是實(shí)現(xiàn)某一功能的我,我可能接收輸入,但未必產(chǎn)生輸出。極端一點(diǎn)的我既沒有輸入?yún)?shù),也沒有返回值,是純粹的過程函數(shù)。每個(gè)過程函數(shù)獨(dú)立做一件事,完成一項(xiàng)任務(wù),過程函數(shù)一般不返回?cái)?shù)據(jù),只操作共享數(shù)據(jù)。人們把這種編程方式叫做結(jié)構(gòu)化編程。

作為過程函數(shù)的我一般用全局變量來共享狀態(tài),我會(huì)改變或增加共享狀態(tài)。過程函數(shù)可能不是冪等的,而缺乏冪等性被很多人認(rèn)為是編程錯(cuò)誤的一個(gè)來源。

冪等性: 若一個(gè)函數(shù)或過程是冪等的,對(duì)其進(jìn)行多次調(diào)用將觀察到同樣的效果,
與一次調(diào)用的效果是相同的。

而且,采用全局變量也一直被認(rèn)為是一個(gè)餿主意,然而在系統(tǒng)層面,架構(gòu)中的組件共享其實(shí)和全局變量類似,這讓我有時(shí)候感到無語。

我和伙伴們組合起來——復(fù)合嵌套

但遠(yuǎn)山長(zhǎng) 云山亂 曉山青

當(dāng)程序員把復(fù)雜問題分解成若干小問題的時(shí)候,一般都是把我接收的輸入形成輸出,這樣就可以把所有任務(wù)都視為輸入集合到輸出集合的映射關(guān)系了。嗯,f(x)的味道來了。

這時(shí)候,函數(shù)間無狀態(tài)共享,類似于數(shù)學(xué)中的復(fù)合函數(shù)。特殊的,把函數(shù)作為輸入或者輸出的函數(shù)被稱為高階函數(shù)。多個(gè)參數(shù)的函數(shù)可以通過柯里化技術(shù)轉(zhuǎn)化為一系列的單參數(shù)高階函數(shù)。

這種串行話處理的一個(gè)知名應(yīng)用就是Unix Shell 中的管道,編譯器及其他語言處理器也很適合這種方式,且傾向于利用圖和樹等數(shù)據(jù)結(jié)構(gòu)組合過程。類似的,還有單元測(cè)試和開發(fā)部署。

構(gòu)成我的代碼簡(jiǎn)潔性

天街小雨潤(rùn)如酥 草色遙看近卻無

程序員通常把簡(jiǎn)潔作為編程技藝的標(biāo)志之一,但是當(dāng)代碼簡(jiǎn)潔成為唯一目標(biāo)的時(shí)候,每行代碼又往往會(huì)變得冗長(zhǎng)且難以理解,這是因?yàn)樾枰镁幊陶Z言的許多高級(jí)特性和庫(kù)來實(shí)現(xiàn)。無論好壞,源代碼行數(shù)(SLOC)還是可以用來估算成本和開發(fā)效率的,也可以評(píng)估可維護(hù)性和其他許多管理指標(biāo)。例如,CoCoMO就是基于SLOC的成本評(píng)估模型,至今還被采用。

基于代碼行數(shù)的簡(jiǎn)潔性往往取決于已經(jīng)構(gòu)建好的第三方庫(kù)和方法,當(dāng)然,運(yùn)用得當(dāng),簡(jiǎn)潔性也會(huì)帶來優(yōu)雅且可讀性強(qiáng)的代碼。一般地,可以信任核心庫(kù),但對(duì)第三方庫(kù)的使用需謹(jǐn)慎。

面向簡(jiǎn)潔性,融合高階函數(shù),以至于一切皆為函數(shù), 甚至形成了新的編程模式——函數(shù)式編程。純粹的函數(shù)式編程語言,以Haskell 為代表。

我的復(fù)雜性度量

吾嘗觀竅妙  渠敢譏雜駁

我的復(fù)雜程度是由程序員決定的,可以非常簡(jiǎn)單,也可以非常復(fù)雜。一般地,可以采用一種叫圈復(fù)雜度的方式來評(píng)估我的復(fù)雜程度。圈復(fù)雜度是一個(gè)用于衡量代碼復(fù)雜度的方式,主要是通過描述控制流路徑的數(shù)量來表示復(fù)雜度。圈復(fù)雜度把程序看成一個(gè)有向圖,計(jì)算公式如下:

CC = E -N +2P  E是邊數(shù)  N 是節(jié)點(diǎn)數(shù),P是節(jié)點(diǎn)出口數(shù)。

圈復(fù)雜度可以衡量程序的復(fù)雜性,同樣適用于函數(shù)。

我調(diào)用我自己——遞歸函數(shù)

知人者智 知己者明

由于很多的問題都可以使用歸納法進(jìn)行建模,就象學(xué)生時(shí)代的數(shù)學(xué)歸納法那樣,即已知n=0的情況和n到n+1的推導(dǎo)規(guī)則,對(duì)問題進(jìn)行求解。一般地,在編程世界中,歸納法用遞歸函數(shù)表示。遞歸函數(shù)就是自己調(diào)用自己,一直在棧中操作,如果遞歸層次過深的話,會(huì)導(dǎo)致棧溢出問題的出現(xiàn)。

在許多編程語言中,尾遞歸優(yōu)化解決了遞歸調(diào)用中的棧溢出問題。 尾調(diào)用是指一個(gè)函數(shù)里的最后一個(gè)動(dòng)作是一個(gè)函數(shù)調(diào)用,即在函數(shù)尾部發(fā)生的遞歸調(diào)用。尾遞歸即在函數(shù)尾部發(fā)生的遞歸調(diào)用,尾遞歸發(fā)生時(shí),程序語言的處理器可以安全地刪除先前的棧記錄,因?yàn)樵撜{(diào)用返回時(shí)棧中不需要繼續(xù)其他操作,這就是尾遞歸優(yōu)化,尾遞歸優(yōu)化有效地將遞歸函數(shù)轉(zhuǎn)為迭代,節(jié)省了時(shí)間和內(nèi)存。

需要注意的是,python中并不對(duì)尾遞歸進(jìn)行優(yōu)化,一般要對(duì)調(diào)用深度進(jìn)行限制。

下一個(gè)是我的自動(dòng)調(diào)用——回調(diào)和匿名

忽如一夜春風(fēng)來,千樹萬樹梨花開。

一般地,函數(shù)間的調(diào)用是顯式的,即一個(gè)函數(shù)執(zhí)行完畢在執(zhí)行下一個(gè)函數(shù)。 但有這樣一種使用場(chǎng)景,一個(gè)函數(shù)有一個(gè)額外的參數(shù),通常是最后一個(gè),這一參數(shù)是另一個(gè)函數(shù),在函數(shù)執(zhí)行到末尾的時(shí)候,作為參數(shù)的函數(shù)也會(huì)被調(diào)用。

參數(shù)函數(shù)作為輸入,也作為當(dāng)前函數(shù)的輸出,函數(shù)間的這種管道式傳遞可以解決處理規(guī)模較大的問題,即管道中下一個(gè)被調(diào)用的函數(shù)會(huì)當(dāng)作當(dāng)前參數(shù)的輸出。 這種后續(xù)傳遞,通常使用匿名函數(shù)。

如果參數(shù)函數(shù)并不是在末尾被調(diào)用,而是在特定的事件或條件發(fā)生時(shí)由另外的一方調(diào)用,參數(shù)函數(shù)用于對(duì)該事件或條件進(jìn)行響應(yīng),通常使用回調(diào)函數(shù)。在C/C++中,回調(diào)函數(shù)就是一個(gè)通過函數(shù)指針調(diào)用的函數(shù),把函數(shù)的指針(地址)作為參數(shù)傳遞給另一個(gè)函數(shù),用這個(gè)指針來調(diào)用其所指向的函數(shù)。回調(diào)函數(shù)一般使用通知機(jī)制。典型的場(chǎng)景如編譯器優(yōu)化,處理程序的正常流程和異常流程,解決單線程語言的IO阻塞問題等等。

需要注意的是,大量的回調(diào)函數(shù)可能會(huì)增加復(fù)雜性,使代碼的可讀性變差,例如JavaScript 中的回調(diào)地獄。

我們長(zhǎng)在對(duì)象上就成了——方法

千人同心   則得千人之力

我們都是要處理數(shù)據(jù)的,可以把數(shù)據(jù)封裝起來形成一個(gè)可以修改的數(shù)據(jù)抽象。 將若干函數(shù)逐個(gè)綁定在數(shù)據(jù)抽象上,建立函數(shù)的調(diào)用順序,查看數(shù)據(jù)的最終結(jié)果,這是一種面向數(shù)據(jù)的過程封裝抽象,特點(diǎn)在于綁定操作將數(shù)據(jù)抽象作為參數(shù),調(diào)用指定函數(shù),并將函數(shù)返回值賦回。

如果將問題分解成某些問題領(lǐng)域的相關(guān)對(duì)象,每個(gè)對(duì)象都是一個(gè)數(shù)據(jù)封裝,處理過程暴露在外,數(shù)據(jù)只能通過這些過程訪問,不可直接訪問,每個(gè)對(duì)象可以重新定義在其他對(duì)象中已經(jīng)定義好的過程。這種長(zhǎng)在對(duì)象上的函數(shù)又叫——方法。

對(duì)象的本質(zhì)是過程分享對(duì)象內(nèi)的數(shù)據(jù),與類和繼承聯(lián)系在一起。繼承實(shí)際上定義了對(duì)象間的從屬關(guān)系,從而有了抽象類,基類,實(shí)例,覆蓋,子類,單例等等。

對(duì)象中我們的遠(yuǎn)程調(diào)用

萬里云霄送君去 不妨風(fēng)雨破吾廬

隨著網(wǎng)絡(luò)應(yīng)用的發(fā)展,網(wǎng)絡(luò)中某個(gè)節(jié)點(diǎn)的軟件希望引用其他遠(yuǎn)程節(jié)點(diǎn)的對(duì)象實(shí)例,并且把遠(yuǎn)程對(duì)象的方法當(dāng)作本地方法來使用。于是,誕生了分布式對(duì)象系統(tǒng)的平臺(tái)和框架,例如CORBA 和RMI。這些分布式對(duì)象系統(tǒng)有一個(gè)前提假設(shè),就是需要為所有的分布式組件采取通用的編程語言或基礎(chǔ)架構(gòu),但通用基礎(chǔ)架構(gòu)的假設(shè)是難以成立的。CORBA的統(tǒng)一化方式退出了舞臺(tái),它和web技術(shù)的大規(guī)模應(yīng)用相沖突,因?yàn)楹笳呋诘氖遣煌夹g(shù)的大規(guī)模系統(tǒng)設(shè)計(jì)方法。

但是對(duì)象方法的遠(yuǎn)程調(diào)用還是有使用場(chǎng)景的,如果每個(gè)對(duì)象是僅公開一個(gè)過程的數(shù)據(jù)封裝,即能夠接收和發(fā)送消息。消息分發(fā)機(jī)制能將消息發(fā)送至另一個(gè)封裝。 對(duì)象向外界公開一個(gè)函數(shù)————接收消息的函數(shù)而并非一系列函數(shù),其他的數(shù)據(jù)和函數(shù)被隱藏在內(nèi)部, 接口函數(shù)處理能夠被對(duì)象解釋的消息;一些無法被對(duì)象解釋的消息,則被忽略或生成某種形式的錯(cuò)誤;另一些消息可能并不由該對(duì)象直接處理,而是由其他與接收對(duì)象相關(guān)的對(duì)象處理。

對(duì)于消息分發(fā)機(jī)制,帶來的是某個(gè)對(duì)象使用其他對(duì)象的方法執(zhí)行過程的能力。消息分發(fā)是接收消息、解釋消息并確定執(zhí)行步驟的過程。該過程可能是方法執(zhí)行、錯(cuò)誤返回或者向其他對(duì)象轉(zhuǎn)發(fā)消息。

對(duì)象的域——我們與對(duì)象中數(shù)據(jù)的關(guān)系

悠然一曲泉明調(diào) 淺立閑愁輕閉門

對(duì)象的域一般是指鍵與簡(jiǎn)單值的映射,對(duì)象中的一些方法成為了鍵與值之間的函數(shù)映射,構(gòu)造函數(shù)是最先被調(diào)用的方法。閉域是指每個(gè)對(duì)象是一個(gè)鍵值映射,其中某些值是我們這些函數(shù)。對(duì)象的方法引用對(duì)象自身的鍵,使得映射是封閉域的。

閉域解釋了對(duì)象編程中的一個(gè)特色——原型。原型常見于無類面向?qū)ο笳Z言中的對(duì)象。原型帶有自己的數(shù)據(jù)和函數(shù),可以自由地改變而不影響其他對(duì)象,新原型可以通過復(fù)制已存在的原型獲得。

閉域風(fēng)格的缺點(diǎn)在于沒有訪問控制,只能由程序員來約束,通過鍵來檢索字典等同于向字典發(fā)消息。

對(duì)象的抽象——抽象對(duì)象

草枯鷹眼疾 雪盡馬蹄輕

抽象對(duì)象是將大問題分解為問題域相關(guān)的對(duì)象抽象。抽象對(duì)象定義了對(duì)象的抽象行為,具體對(duì)象以某種方式與抽象對(duì)象綁定,綁定機(jī)制可以不定,應(yīng)用程序的其他部分并不依賴對(duì)象的內(nèi)容,而依賴對(duì)象的行為。

在設(shè)計(jì)模式中,適配器模式的目的與抽象對(duì)象是一致的,隔離了應(yīng)用程序與具體的功能實(shí)現(xiàn)。抽象對(duì)象在大型系統(tǒng)設(shè)計(jì)中舉足輕重,抽象對(duì)象的實(shí)現(xiàn)根據(jù)涉及的具體編程語言而定。Java中的抽象對(duì)象是接口,可以在類型上參數(shù)化;Haskell是一種強(qiáng)類型的純函數(shù)語言,抽象對(duì)象表現(xiàn)為類型類;C++擁有抽象類,連同模版一起完備地提供了參數(shù)化抽象對(duì)象的概念。

控制對(duì)象中我們的另一方式——控制反轉(zhuǎn)

春潮帶雨晚來急  野渡無人舟自橫

還有另一種對(duì)象行為的控制方式,利用對(duì)象和模塊等不同形式的抽象,將大問題分解成若干個(gè)實(shí)體,這些實(shí)體不能被直接調(diào)用,而是為其他實(shí)體提供接口,使其他實(shí)體能夠注冊(cè)回調(diào)函數(shù),這些實(shí)體中的函數(shù)調(diào)用是通過其他實(shí)體注冊(cè)過的回調(diào)函數(shù)來完成的。

這種行為控制方式不會(huì)在程序中顯式地調(diào)用函數(shù),而是通過反轉(zhuǎn)關(guān)系,使調(diào)用者可以同時(shí)觸發(fā)多個(gè)行為,是一種能夠在框架中觸發(fā)任意應(yīng)用代碼的機(jī)制,這就是控制反轉(zhuǎn)。

控制反轉(zhuǎn)是分布式系統(tǒng)設(shè)計(jì)的一個(gè)重要概念,源于異步硬件中斷,回調(diào)函數(shù)可以同步執(zhí)行也可以異步執(zhí)行。在事件發(fā)生時(shí),不同網(wǎng)絡(luò)節(jié)點(diǎn)間的回調(diào)函數(shù)不用長(zhǎng)輪詢,從而,事件驅(qū)動(dòng)框架應(yīng)運(yùn)而生。

類似的,可以使用一個(gè)用于發(fā)布和訂閱事件的基礎(chǔ)結(jié)構(gòu),對(duì)象實(shí)體中的我們負(fù)責(zé)訂閱和發(fā)布事件,基礎(chǔ)結(jié)構(gòu)負(fù)責(zé)事件的管理和分發(fā)。 這樣的基礎(chǔ)結(jié)構(gòu)常與異步組件共同使用,也可能包含更復(fù)雜的事件結(jié)構(gòu),支持更精確的事件過濾,相當(dāng)于控制反轉(zhuǎn)的輕量級(jí)形式。

審視自身,進(jìn)而改變我自己

見賢思齊焉 見不賢而內(nèi)自省也

在程序設(shè)計(jì)的過程中可以將程序自身也一起考慮。有一種抽象的方式是可以獲取自身以及其他的抽象信息,但不能改變這些信息。程序獲取自身信息的能力叫做自省,支持自省的語言有java,python,javascript,以及PHP等,而C/C++不支持自省。其中,python 有強(qiáng)大的自省能力,如callable,inspect等。 然而,使用自省使得程序變得不直觀,甚至難以理解,有利有弊吧。

反射使用了自省,程序在運(yùn)行時(shí)可以通過增加抽象、變量等方式進(jìn)行自我修改。反射的目的是要求程序能自我修改,ruby支持完備反射,python 和javascript在限制條件下支持反射,而java只支持小部分的反射。在設(shè)計(jì)過程中,當(dāng)無法預(yù)期代碼被修改方式的時(shí)候,會(huì)使用反射。

如果將問題的切面增加到主程序中,但不改變這種抽象方式的源碼和使用該抽象的代碼段,再通過一個(gè)外部綁定機(jī)制將這種抽象形式和切面綁定在一起,這就是AOP。AOP是一種受限制的反射,目的是在已有程序的指定代碼前后插入任意代碼。 切面主要關(guān)注可能被分散到應(yīng)用程序中的代碼,這些代碼通常會(huì)影響許多組件,典型的切面如 profiling 和 tracing。

把我們有組織的固定下來充分復(fù)用——插件

但要前塵減   無妨外相同

如果把我們有組織的固定下來,所有或部分被預(yù)編譯后通常會(huì)自成一體,主程序和每個(gè)包單獨(dú)編譯,主程序在開始時(shí)動(dòng)態(tài)地加載這些包,使用動(dòng)態(tài)加載包中的函數(shù)和對(duì)象,無需知道具體事項(xiàng),這就是插件。

插件又叫plugin或者addon,不需重新編譯,就可以將一系列功能加入到正在執(zhí)行的應(yīng)用程序中。通過一個(gè)外部定義來說明哪些包需要被加載,通常是配置文件,路徑約定,用戶輸入或其他運(yùn)行時(shí)加載外部代碼的機(jī)制,F(xiàn)代操作系統(tǒng)的動(dòng)態(tài)鏈接庫(kù)dll/so 就是插件風(fēng)格,需要注意的是存在配置深淵。

對(duì)于分布式體系結(jié)構(gòu)和支持第三方擴(kuò)展的獨(dú)立應(yīng)用程序,帶有反射能力的編程語言使得在運(yùn)行時(shí)鏈接組件變得可行并且非常簡(jiǎn)單。Java Spring框架就支持由反射機(jī)制帶來的插件化開發(fā),稱為“依賴注入”和“插件”,插件一般使用描述性配置語言如INI和XML。

據(jù)說,插件是軟件進(jìn)化和定制的核心。

我錯(cuò)了?!——異常處理

此情可待成追憶  只是當(dāng)時(shí)已惘然

異常是在程序運(yùn)行中超出正常預(yù)期的情況。我和每一個(gè)伙伴都會(huì)檢查自身參數(shù)的合理性,當(dāng)參數(shù)不合理時(shí),返回合理的結(jié)果或者給參數(shù)指定合理的值。所有的代碼塊都會(huì)檢測(cè)可能存在的錯(cuò)誤,當(dāng)錯(cuò)誤發(fā)生時(shí),跳過代碼塊,設(shè)置合理的狀態(tài)并繼續(xù)執(zhí)行函數(shù)的其他部分。

通常防御式編程能為用戶帶來較好的體驗(yàn),每個(gè)過程和函數(shù)都檢測(cè)自身參數(shù)的合理性,若參數(shù)不合理,程序停止運(yùn)行。另外,當(dāng)錯(cuò)誤發(fā)生時(shí),最好將上下文相關(guān)的信息寫入日志,同時(shí)將錯(cuò)誤傳遞回函數(shù)調(diào)用鏈。如果對(duì)異常采取消極態(tài)度,至少也應(yīng)該通知各方正確的使用方式,以及停止運(yùn)行的原因。

全局捕獲是我們另一種處理異常的方法,在調(diào)用其他函數(shù)時(shí),程序僅檢測(cè)能夠提供有意義反饋的錯(cuò)誤。這種異常處理在函數(shù)調(diào)用鏈中位于較上層,僅在程序最外層進(jìn)行異常處理,無視異常時(shí)間發(fā)生的位置。

無論在哪里捕獲異常,調(diào)用棧都是異常信息的一部分,除非局部存在有意義的處理方式,更好的做法是將異常返回到函數(shù)調(diào)用鏈的上游。

我眼中的類型錯(cuò)誤

堪嗟歲月蹉跎久   卻悔塵寰錯(cuò)誤多

對(duì)于輸入?yún)?shù)而言,一般地,我會(huì)聲明所期待的參數(shù)類型。如果調(diào)用方?jīng)]有傳送預(yù)期類型的參數(shù),則會(huì)產(chǎn)生類型錯(cuò)誤,這時(shí)將不再執(zhí)行。類型不匹配是指我得到的值類型與所期待的值類型不符;或者一個(gè)伙伴返回了一個(gè)特定類型的值,但該值稍后被調(diào)用者當(dāng)作其他類型的值使用。不同類型的值通常被分配不同大小的內(nèi)存空間,這意味著當(dāng)發(fā)生類型不匹配時(shí),內(nèi)存可能被重寫而變得不一致,這就是這類異常的問題所在。

所有現(xiàn)代高級(jí)編程語言都有一個(gè)類型系統(tǒng),在開發(fā)和執(zhí)行過程中的不同節(jié)點(diǎn)檢測(cè)數(shù)據(jù)類型。靜態(tài)類型的語言如Java 和 Haskell,動(dòng)態(tài)類型如JS,python等等。參數(shù)類型分為顯示類型和隱式類型,相關(guān)的邏輯操作包括強(qiáng)制類型裝換,類型推理和類型安全。

我可以專注于數(shù)據(jù)計(jì)算

無邊落木蕭蕭下  不盡長(zhǎng)江滾滾來

如果我專注于數(shù)據(jù)計(jì)算的話,會(huì)有一些特殊的約束。首先是隔離,核心函數(shù)不要有任何副作用,所有IO行為都最好和純粹的函數(shù)明確區(qū)分開來,所有包含IO的函數(shù)最好從主程序中調(diào)用。這樣做的主要目的是避免或最小化IO操作,盡量隔離IO操作,因?yàn)镮O操作在大型系統(tǒng)中是個(gè)大問題。

典型的數(shù)據(jù)密集型應(yīng)用是數(shù)據(jù)庫(kù),數(shù)據(jù)獨(dú)立于程序執(zhí)行,能夠被多個(gè)程序使用,存儲(chǔ)易于快速檢索,通過對(duì)數(shù)據(jù)查詢來解決問題。對(duì)某些數(shù)據(jù)的規(guī)范處理可能包含數(shù)據(jù)列及公式,某些數(shù)據(jù)可能由其他數(shù)據(jù)通過公式?jīng)Q定。當(dāng)數(shù)據(jù)改變時(shí),相關(guān)聯(lián)數(shù)據(jù)將自動(dòng)改變,例如數(shù)據(jù)庫(kù)中的視圖,觸發(fā)器和存儲(chǔ)過程等。

如果數(shù)據(jù)的可用形式是流,我就是數(shù)據(jù)流的過濾器/變換器,根據(jù)下游的需求,對(duì)上游的數(shù)據(jù)進(jìn)行處理。流式處理適用于支持生成器的語言,對(duì)于Java 這些不支持生成器的語言,可以通過迭代器實(shí)現(xiàn)。

我也可以適應(yīng)并發(fā)處理場(chǎng)景

水深草茂群蛙怒   日出風(fēng)和宿麥秋

面向高并發(fā)的場(chǎng)景,每個(gè)對(duì)象都存在一個(gè)隊(duì)列,用于放置向其他對(duì)象發(fā)送的消息。每個(gè)對(duì)象都是一個(gè)數(shù)據(jù)封裝,僅公開其接收消息的接口,用于前述隊(duì)列,每個(gè)對(duì)象運(yùn)行于獨(dú)立的線程中。每個(gè)對(duì)象主動(dòng)輪詢各自的消息隊(duì)列,一次處理一條消息,當(dāng)隊(duì)列為空時(shí),阻塞當(dāng)前線程。這大概就是Actor模型了。

當(dāng)一個(gè)或多個(gè)并發(fā)單元,同時(shí)配備了一個(gè)或多個(gè)數(shù)據(jù)空間,數(shù)據(jù)空間用于并發(fā)單元的數(shù)據(jù)存儲(chǔ)和檢索,并發(fā)單元之間只能通過數(shù)據(jù)空間進(jìn)行數(shù)據(jù)交換。 尤其是當(dāng)任務(wù)需要橫向開展的時(shí)時(shí)候,這種基于數(shù)據(jù)空間交換的方式,也是適合于數(shù)據(jù)密集型并行處理的。

對(duì)于流式數(shù)據(jù)而言,輸入的數(shù)據(jù)流被分成若干塊,map函數(shù)對(duì)每個(gè)數(shù)據(jù)塊運(yùn)用worker,通常過程是并行的。而 reduce 函數(shù)得到各個(gè)worker函數(shù)的結(jié)果,并重組成相關(guān)輸出。 這種基于MapReduce的函數(shù)處理方式,極其適用于可以單獨(dú)拆分和處理數(shù)據(jù)的數(shù)據(jù)密集型操作,其局部結(jié)果在最后被重組。如果將worker 函數(shù)的結(jié)果重組,第二次map以重組后的數(shù)據(jù)作為reduce函數(shù)的參數(shù)的話,就是雙重MapReduce方式了。

一般的,map可以并行,而reduce不行,hadoop將map的結(jié)果列表重組并打亂,使后續(xù)reduce函數(shù)的調(diào)用可以對(duì)數(shù)據(jù)重組進(jìn)行修改,從而reduce也成了可以并行化的。

至于restful,不過是將我們函數(shù)的思想用于子系統(tǒng),更關(guān)注擴(kuò)展性,去中心化和獨(dú)立組件開發(fā)而已。

結(jié)尾的告白

誰人在處望風(fēng)煙  蕓蕓眾生吾自潛

函數(shù)是程序中最小的有序時(shí)空,運(yùn)轉(zhuǎn)于內(nèi)存堆棧。

關(guān)于參數(shù),沒有輸入?yún)?shù)和返回值就是純過程函數(shù), 而同時(shí)有參數(shù)和返回值才可能實(shí)現(xiàn)冪等性。多參數(shù)的我可以柯里化為單參數(shù)高階函數(shù),而參數(shù)中是函數(shù)的話可以形成處理管道,或者回調(diào)函數(shù)。我自己調(diào)用自己,就是遞歸函數(shù)。

關(guān)于對(duì)象,我長(zhǎng)在對(duì)象上變成了方法,進(jìn)一步可以提升為抽象對(duì)象。對(duì)象間的遠(yuǎn)程調(diào)用一般用消息機(jī)制,對(duì)象間的行為操控可以說是控制反轉(zhuǎn),而通過對(duì)本身的自省可以形成反射,AOP 可以看作有條件的反射。對(duì)于插件,幾乎是函數(shù)組裝之集大成者。

關(guān)于錯(cuò)誤,一般采用防御式編程,也可以采用消極的方式,無論是否采用全局捕獲,調(diào)用棧都是異常信息的重要部分。

關(guān)于特定場(chǎng)景,不論是密集數(shù)據(jù)計(jì)算還是高并發(fā)情況,都最終落實(shí)到函數(shù)的層面。

 

來自:http://mp.weixin.qq.com/s/1VtITPEufTMcI42WFEhoEw

 

標(biāo)簽: O2O 安全 代碼 數(shù)據(jù)庫(kù) 網(wǎng)絡(luò)

版權(quán)申明:本站文章部分自網(wǎng)絡(luò),如有侵權(quán),請(qǐng)聯(lián)系:west999com@outlook.com
特別注意:本站所有轉(zhuǎn)載文章言論不代表本站觀點(diǎn)!
本站所提供的圖片等素材,版權(quán)歸原作者所有,如需使用,請(qǐng)與原作者聯(lián)系。

上一篇:由FTWRL導(dǎo)致的MySQL從庫(kù)死鎖分析及參數(shù)深究

下一篇:2018 年初值得關(guān)注的 25 個(gè)新 Android 庫(kù)和項(xiàng)目