廣義的編程思維

引言

PC互聯(lián)網(wǎng)應(yīng)用與移動(dòng)互聯(lián)網(wǎng)應(yīng)用發(fā)展至今楔脯,有很多的軟件開發(fā)技術(shù)問題得到了很好的解決纠脾,但有很多中小規(guī)模企業(yè)的軟件孩哑,沒有得到很好的指引和撐握到很好的方法栓霜。

中國(guó)目前有著大概99%的軟件公司使用SQL進(jìn)行著日常的數(shù)據(jù)存取、使用請(qǐng)求返回進(jìn)行著日常的數(shù)據(jù)展示横蜒、使用類進(jìn)行著日常的數(shù)據(jù)抽象處理胳蛮。

在這些開發(fā)者們習(xí)以為常的重復(fù)事情中,是否會(huì)存在些問題丛晌?如何發(fā)現(xiàn)問題和改善仅炊?

軟件工程是一門很好的軟件理論指導(dǎo)的知識(shí),有著很早的歷史和有著深厚技術(shù)的先輩專家遺留的實(shí)踐知識(shí)理論澎蛛,由于知識(shí)中有很多很早期的概念用詞與現(xiàn)在發(fā)展的新概念用詞不同抚垄,以及有些深入的理論講解不夠簡(jiǎn)單具體,使得網(wǎng)上總結(jié)分析的文章較少和文章中對(duì)理論的舉例理解的質(zhì)量較低或有誤谋逻,大部分中小規(guī)模軟件企業(yè)的軟件仍沒有與軟件工程理論相結(jié)合得很好呆馁,筆者一直專注研究軟件開發(fā)技術(shù),對(duì)軟件工程理論也只是剛參透一部分毁兆,未來還需要仔細(xì)研究分享浙滤。

軟件開發(fā)有其復(fù)雜的地方,需要對(duì)每一個(gè)相關(guān)的重要概念理解其含義气堕,可以逐步的理解和發(fā)現(xiàn)軟件開發(fā)存在的問題纺腊。未來的軟件領(lǐng)域的企業(yè)發(fā)展,只靠一個(gè)CTO懂得軟件重要問題還不夠茎芭,全體開發(fā)工程師都理解和撐握軟件的重要問題是有必要的揖膜,這樣的組織方式會(huì)更好的保證軟件質(zhì)量和持續(xù)深化學(xué)習(xí)討論梅桩。

廣義

從狹義上我們都是人類壹粟,從廣義上我們都是動(dòng)物,因此我們常常會(huì)拿白老鼠做實(shí)驗(yàn)研究宿百,再把研究成果應(yīng)用到人類上煮寡。

廣義編程,就是從廣義的角度研究軟件開發(fā)的方法理論犀呼。

HTML從廣義上是xml標(biāo)簽,狹義上是html標(biāo)簽薇组、head標(biāo)簽外臂、body標(biāo)簽等,并且head標(biāo)簽和body標(biāo)簽必需在HTML里面律胀。同樣把這種廣義的思想應(yīng)用到軟件開發(fā)的各個(gè)方面宋光。

廣義編程包括三個(gè)層面的內(nèi)容:

  1. 從廣義層面理解狹義貌矿,尋找更廣闊的意義。
  2. 從廣義層面保障狹義罪佳。狹義認(rèn)為靠人力能解決問題逛漫,廣義則認(rèn)為僅靠人力不能完全有效的解決問題總會(huì)有些意外出現(xiàn),并提出宏觀上管理的辦法解決赘艳。狹義認(rèn)為現(xiàn)有很多技術(shù)已經(jīng)問題不多酌毡,廣義認(rèn)為現(xiàn)在有很多技術(shù)還存在不確定因素,并提出些辦法來保障蕾管。
  3. 學(xué)習(xí)各個(gè)層面的知識(shí)枷踏,開闊視野,對(duì)編程有一個(gè)全面的理解掰曾。

事物

事物指客觀存在的一切事情(現(xiàn)象)和物體旭蠕,我們?nèi)祟惱斫膺@個(gè)世界一切元素歸為萬事與萬物。

人類

軟件開發(fā)如同是在創(chuàng)造生靈的過程旷坦,程序如同創(chuàng)造大腦的智慧掏熬,輸入設(shè)備如同為大腦提供信息,控制輸出設(shè)備如同皮肉骨骼與大腦協(xié)調(diào)秒梅,為軟件考慮外在病毒功擊的安全威脅旗芬,每一個(gè)程序里的方法屬性如同為生靈創(chuàng)造溝通的語言,每一個(gè)程序里的類結(jié)構(gòu)如同為生靈創(chuàng)造認(rèn)知番电,每一個(gè)程序員如同是一位創(chuàng)造智慧的圣賢岗屏。

軟件開發(fā)的過程中,軟件是為了人類需求而開發(fā)的漱办,軟件的開發(fā)與生靈產(chǎn)生有著許多相似之處这刷,回顧人類作為高智慧生靈被創(chuàng)造與文明發(fā)展的過程,對(duì)軟件開發(fā)有著一些相似與區(qū)別的啟發(fā)作用娩井。

安全需要
安全是人類的根本需求暇屋,人類的本質(zhì)是動(dòng)物細(xì)胞進(jìn)化而來,生命是細(xì)胞本質(zhì)的需要洞辣,沒食物進(jìn)食就會(huì)餓死咐刨,沒地耕作就沒食物來源,人類是一種單獨(dú)個(gè)體的存在扬霜,必然需要與不可知的外界相處定鸟,外界是兇險(xiǎn)還是友好需要獨(dú)自判斷,安全成了人類作為單獨(dú)個(gè)體的根本需求著瓶。

安全是人類重要事物發(fā)展的根源联予,因?yàn)樯踩祟愋枰獙ふ沂澄锷妫驗(yàn)樯姘踩祟愋枰嘧陨韮r(jià)值與自尊,因?yàn)槊篮蒙畹陌踩祟愑辛烁鞣N的心理需求沸久。

信息需要
人類通過感官收集周圍環(huán)境的信息季眷,眼睛收集圖像信息、耳收集聲音信息卷胯、鼻收集氣體信息子刮、舌收集固體與液體信息、身體收集溫度窑睁、壓感信息挺峡,動(dòng)物在進(jìn)化過程中更多依靠物理?xiàng)l件的變化,適應(yīng)環(huán)境生存下去的其中重要進(jìn)化是收集更多周圍環(huán)境信息卵慰。

計(jì)算需要
人類收集到的信息需要計(jì)算處理沙郭,也就是大腦對(duì)信息的感受思考,看見一只猛獸然后思考如何避開危險(xiǎn)裳朋,聽到風(fēng)吹草動(dòng)思考聲源方向與聲源事物病线,人類開始有資產(chǎn)信息后就需要計(jì)算資產(chǎn)。

存儲(chǔ)需要
人類對(duì)收集到的信息需要存儲(chǔ)處理鲤嫡,也就是大腦對(duì)信息的記錄送挑,人類寶寶一出生本能只知道饑餓,對(duì)周圍環(huán)境信息一無所知暖眼,看見老虎需要把老虎的特征信息記錄下來惕耕,下次再看到老虎就知道老虎的習(xí)性了,人類之間相遇需要記錄五官特征信息與行為特征信息诫肠,下次遇到就知道是朋友還是敵人了司澎。

人類對(duì)更復(fù)雜的計(jì)算需要存儲(chǔ)處理,也就是大腦對(duì)信息的復(fù)雜推理過程栋豫,需要將推理過程的中間結(jié)果臨時(shí)存儲(chǔ)挤安。

人類對(duì)存儲(chǔ)的信息需要更持久的存儲(chǔ)需要,人類大腦對(duì)于信息的記憶并不穩(wěn)定丧鸯,有的信息可以記很久蛤铜,有的信息很容易忘記,需要把大腦中存儲(chǔ)的信息轉(zhuǎn)變成符號(hào)文字放置在更穩(wěn)定的存儲(chǔ)介質(zhì)上丛肢,比如:石板围肥、龜殼、竹簡(jiǎn)蜂怎、紙張等穆刻。

互聯(lián)需要
人類之間需要互聯(lián)信息,人類本質(zhì)是一種群體繁衍的物種杠步,注定需要互動(dòng)并且相互傳達(dá)信息氢伟,信息的傳達(dá)不能通過心靈直接感應(yīng)到撰洗,需要物理上的表達(dá)并經(jīng)過空間傳到人的感官上,人類可以通過發(fā)聲腐芍、支體動(dòng)作、表情直接傳遞信息试躏,逐漸人類對(duì)互聯(lián)本質(zhì)的需要猪勇,發(fā)展出運(yùn)用文字、信颠蕴、書泣刹、電話、收音機(jī)犀被、電視椅您、短信、互聯(lián)網(wǎng)寡键、論壇掀泳、博客、聊天工具等西轩。

模塊需要
人類對(duì)信息需要模塊化的認(rèn)知员舵,就是對(duì)所有事物的分類有利于理解和處理,對(duì)物品的分類擺放藕畔、對(duì)文字的創(chuàng)造马僻、對(duì)事物認(rèn)知的學(xué)說書籍,都是在事物信息認(rèn)知過程中進(jìn)行歸納總結(jié)的結(jié)果注服,人類幾千年文明至今仍在認(rèn)知事物與歸納事物韭邓,用于更好的理解和處理復(fù)雜事物。

自動(dòng)需要
人類對(duì)事物需求需要自動(dòng)化溶弟,要實(shí)現(xiàn)自動(dòng)化的前提條件是能量和機(jī)械的配合女淑,從奴隸社會(huì)、封建社會(huì)的階層化開始可很,人類首先把自動(dòng)化的目標(biāo)投向人體勞動(dòng)力诗力,以人體作為自動(dòng)化的智能計(jì)算機(jī)械和能量,其次古人運(yùn)用最多的自動(dòng)化是水力機(jī)械我抠,接著就是工業(yè)革命的蒸汽時(shí)代與電氣時(shí)代苇本,時(shí)至今日人類仍然還需要更多自動(dòng)化,人民群眾日益增長(zhǎng)的物質(zhì)文化生活需要與落后的生產(chǎn)力之間的矛盾菜拓、人民群眾日益增長(zhǎng)的美好生活需要和不平衡不充分的發(fā)展之間的矛盾瓣窄,這兩個(gè)矛盾正是反映了人類對(duì)自動(dòng)的需要。

信息

信息意思指有一定可信度的沒有物理形態(tài)的纳鼎,“信”指真實(shí)的俺夕、客觀的裳凸、可靠的,“息”在商周時(shí)期是指事字劝贸,甲骨文字形上部像鼻子(寫作“自”)姨谷,下部用幾筆短畫表示呼出氣的樣子,意為沒有物理形體映九。

信息存于自然世界的事物中梦湘,人認(rèn)知信息后存于人的記憶中,可以以數(shù)據(jù)的形式記錄在介質(zhì)中件甥,如:書畫捌议、硬盤數(shù)據(jù)朋蔫、內(nèi)存數(shù)據(jù)棚饵。

數(shù)據(jù)

數(shù)解藻,數(shù)值拗秘,符號(hào)谈息,有物理表達(dá)形式
據(jù)簇捍,依據(jù)禽炬,邏輯碎节,有其存在的意義

性質(zhì):
(1)符號(hào)导帝,有物理表達(dá)形式
(2)邏輯守谓,有其存在的意義
(3)位數(shù),數(shù)據(jù)占用存儲(chǔ)器空間的位數(shù)您单,由0和1表示
(4)賦值斋荞,可將數(shù)據(jù)傳遞給變量
(5)多態(tài),同一個(gè)數(shù)據(jù)可以有多種表達(dá)方式虐秦,如9平酿、九、1001

數(shù)據(jù)定義
不同的數(shù)據(jù)類型會(huì)有不同的定義方式悦陋,同一種數(shù)據(jù)類型也有可能會(huì)有多種數(shù)據(jù)定義方式蜈彼,一般用阿拉伯?dāng)?shù)字直接表示數(shù)字定義,用true或false表示布爾值定義俺驶,雙引號(hào)表示字符串定義等幸逆。

對(duì)象是數(shù)據(jù)嗎?
對(duì)象是由一組數(shù)據(jù)集合構(gòu)成的非基本數(shù)據(jù)暮现,對(duì)象有其自身屬性(數(shù)據(jù))和行為(方法)还绘,否則不能稱之為對(duì)象,定義一個(gè)無屬性栖袋、無行為的對(duì)象是沒有意義的對(duì)象拍顷,僅有行為的對(duì)象稱之為工具類而非對(duì)象。

位置類型 外置類型 內(nèi)置類型

內(nèi)置
顧名思義塘幅,指內(nèi)部設(shè)置昔案,如內(nèi)置類型尿贫、內(nèi)置api、內(nèi)置類踏揣、內(nèi)置方法……等

內(nèi)置數(shù)據(jù)類型
顧名思義庆亡,指內(nèi)部設(shè)置的數(shù)據(jù)類型,就是某種語言內(nèi)部自己定義的一些東西的類型捞稿,如:基本數(shù)據(jù)類型身冀、引用類型、變量類型……等

性質(zhì):
(1)內(nèi)部設(shè)置括享,內(nèi)部定義
(2)類型,分類

外置數(shù)據(jù)類型
指外部設(shè)置的數(shù)據(jù)類型珍促,與內(nèi)置類型相反的是外置類型铃辖,就是非語言官方設(shè)置的類型,如:第三方類庫(kù)……等

基本數(shù)據(jù)類型

基本
指根本的猪叙,所有事物的前提根源娇斩。

數(shù)據(jù)
數(shù),數(shù)值穴翩,符號(hào)犬第,有物理表達(dá)形式
據(jù),依據(jù)芒帕,邏輯歉嗓,有其存在的意義

基本數(shù)據(jù)
指根本的數(shù)據(jù),很常用的數(shù)據(jù)背蟆,是其它非基本數(shù)據(jù)的構(gòu)成數(shù)據(jù)鉴分。

基本數(shù)據(jù)類型
顧名思義,指最基本數(shù)據(jù)的類型带膀,可簡(jiǎn)稱為基本類型志珍,如int、char垛叨、boolean伦糯、byte……等

性質(zhì):
(1)基本,根本嗽元,是其它非基本數(shù)據(jù)的構(gòu)成數(shù)據(jù)
(2)數(shù)據(jù)敛纲,具有符號(hào)與意義
(3)位數(shù),數(shù)據(jù)占用存儲(chǔ)器空間的位數(shù)还棱,由0和1表示
(4)取值范圍载慈,有些數(shù)據(jù)類型的取值范圍數(shù)量等于其數(shù)據(jù)位數(shù)的值范圍
(5)默認(rèn)值,有些編程語言的基本數(shù)據(jù)類型具有默認(rèn)值珍手,有些編程語言的基本數(shù)據(jù)類型默認(rèn)值為null
(6)賦值办铡,可將數(shù)據(jù)傳遞給變量
(7)獨(dú)享辞做,具備值類型的性質(zhì),賦值時(shí)是對(duì)值進(jìn)行復(fù)制給到變量寡具,每個(gè)變量獨(dú)享自己的數(shù)據(jù)的物理存儲(chǔ)空間秤茅,對(duì)數(shù)據(jù)的變動(dòng)是相互獨(dú)立的,互不影響童叠。
(8)類型框喳,分類

引用數(shù)據(jù)類型

引用
在漢語詞典中引用有兩個(gè)動(dòng)詞意思:
(1)引出事例,用他人的事例或言詞作為根據(jù)厦坛,如:引用詩(shī)句五垮、格言、成語等,以表達(dá)自己思想感情的修辭方法杜秸。
(2)引薦任用放仗,如:引用天下名士

在計(jì)算機(jī)編程中,引用則是名詞作修飾撬碟,表示數(shù)據(jù)的兵符诞挨,有了兵符才具備對(duì)數(shù)據(jù)傳達(dá)命令的權(quán)力。

數(shù)據(jù)
數(shù)呢蛤,數(shù)值惶傻,符號(hào),有物理表達(dá)形式
據(jù)其障,依據(jù)银室,邏輯,有其存在的意義

引用數(shù)據(jù)
表示那些需要通過兵符傳達(dá)命令的數(shù)據(jù)励翼,有了兵符才具備對(duì)數(shù)據(jù)傳達(dá)命令的權(quán)力粮揉。

引用數(shù)據(jù)類型
表示那些需要通過兵符傳達(dá)命令的數(shù)據(jù)的類型,如對(duì)象抚笔、實(shí)例
引用(兵符)可直接調(diào)用扶认,如 new MyData().sayHello()
引用(兵符)可賦于變量中,通過對(duì)變量的調(diào)用(傳達(dá)命令)殊橙,就是對(duì)數(shù)據(jù)的調(diào)用辐宾。

性質(zhì):
(1)引用(兵符),通過引用(兵符)對(duì)數(shù)據(jù)傳達(dá)命令
(2)數(shù)據(jù)膨蛮,具有符號(hào)與意義
(3)位數(shù)叠纹,數(shù)據(jù)占用存儲(chǔ)器空間的位數(shù),由0和1表示
(4)賦值敞葛,可將引用(兵符)傳遞給變量誉察,通過對(duì)變量的調(diào)用(傳達(dá)命令),就是對(duì)數(shù)據(jù)的調(diào)用惹谐。
(5)共享性持偏,可將引用(兵符)傳遞給多個(gè)變量驼卖,多個(gè)變量共享同一個(gè)數(shù)據(jù)的調(diào)用權(quán),對(duì)數(shù)據(jù)的變動(dòng)會(huì)影響多個(gè)變量的數(shù)據(jù)鸿秆。
(6)類型酌畜,分類
(7)引用計(jì)數(shù),即引用(兵符)發(fā)放了多少給變量或其它擁有者卿叽。

瀏覽器的數(shù)據(jù)

表現(xiàn)層

瀏覽器內(nèi)存數(shù)據(jù)類型

瀏覽器內(nèi)存的基本數(shù)據(jù)類型是String桥胞、Number、Boolean考婴、Object贩虾、Array、Null沥阱、對(duì)象指針整胃、Function、函數(shù)指針喳钟、變量、變量指針在岂、Undefined奔则。HTML數(shù)據(jù)模型是界面結(jié)構(gòu)的數(shù)據(jù)類型,由基本數(shù)據(jù)類型構(gòu)成蔽午。CSS數(shù)據(jù)模型是界面樣式的數(shù)據(jù)類型易茬,由基本數(shù)據(jù)類型構(gòu)成。

數(shù)據(jù)類型 數(shù)據(jù)結(jié)構(gòu)
String 雙引號(hào)"任意字符"或單引號(hào)'任意字符'及老,有長(zhǎng)度限制
Number 0123456789.的組合抽莱,有最大值最小值限制
Boolean true、false
Array 內(nèi)容組骄恶,引用計(jì)數(shù)
Null 空值
變量 變量?jī)?nèi)容食铐,引用計(jì)數(shù)
Object 鍵值組,引用計(jì)數(shù)
對(duì)象指針 內(nèi)存位置
Function 變量組僧鲁、函數(shù)名虐呻、參數(shù)組、函數(shù)邏輯內(nèi)容
函數(shù)指針 內(nèi)存位置
Undefined 未定義值
HTML數(shù)據(jù)模型 標(biāo)記名寞秃、標(biāo)記屬性組斟叼、標(biāo)記內(nèi)容組
CSS數(shù)據(jù)模型 樣式名稱組、樣式內(nèi)容組

瀏覽器內(nèi)存數(shù)據(jù)定義

數(shù)據(jù)類型 數(shù)據(jù)定義
String 雙引號(hào)"hello"或單引號(hào)'world'
Number 0123456789
Boolean true春寿、false
Array [ ]
Null null
變量 var
Object { }
對(duì)象指針 賦值對(duì)象時(shí)
Function function 函數(shù)名(參數(shù)){ }
函數(shù)指針 賦值函數(shù)時(shí)
Undefined undefined
HTML數(shù)據(jù)模型 <div id="myDiv"></div> 或 document.createElement("div")
CSS數(shù)據(jù)模型 #myDiv{ color:red } 或 style="color:red"

計(jì)算

計(jì)算指根據(jù)已知數(shù)通過數(shù)學(xué)方法求得未知數(shù)朗涩,即計(jì)算是對(duì)已知的信息處理得出結(jié)果信息的過程。

信息處理

從軟件技術(shù)發(fā)展至今绑改,會(huì)發(fā)現(xiàn)每一種信息數(shù)據(jù)類型谢床,都會(huì)有對(duì)應(yīng)的信息處理工具:

信息處理工具 信息數(shù)據(jù)類型 代碼混合
javascript 基本數(shù)據(jù)類型
html dom api HTML數(shù)據(jù)模型
css api CSS數(shù)據(jù)模型
服務(wù)器動(dòng)態(tài)頁(yè)面
(ASP兄一、JSP、PHP)
后端數(shù)據(jù)類型萤悴、HTML數(shù)據(jù)模型瘾腰、CSS數(shù)據(jù)模型、前端邏輯代碼
JQuery HTML數(shù)據(jù)模型
JSX HTML數(shù)據(jù)模型
MV模板引擎 HTML數(shù)據(jù)模型
MVVM模板引擎 HTML數(shù)據(jù)模型
less覆履、scss CSS數(shù)據(jù)模型

其中服務(wù)器動(dòng)態(tài)頁(yè)面技術(shù),已經(jīng)不是主流的前端信息處理工具硝全,因?yàn)闃I(yè)務(wù)邏輯容易跑到表現(xiàn)層中栖雾,甚至業(yè)務(wù)邏輯代碼與前端代碼聚集在一起,不利于可讀和模塊化的理解伟众。

JQuery使用函數(shù)式編程處理HTML數(shù)據(jù)模型的集合析藕,簡(jiǎn)單理解就是代碼量更少的處理相同的功能,代碼量更少代碼就越容易觀察可讀凳厢,更容易理解账胧。JQuery相對(duì)于“html dom api”處理信息的性能要慢比較多。

JSX是一種可以在javascript上寫html標(biāo)簽來創(chuàng)建HTML數(shù)據(jù)模型先紫,也就是在js中的嵌入式模塊治泥,簡(jiǎn)單理解就是代碼量更少的創(chuàng)建HTML數(shù)據(jù)模型,代碼量更少代碼就越容易觀察可讀遮精,更容易理解居夹,同時(shí)保證了HTML數(shù)據(jù)模型創(chuàng)建的性能,但HTML信息的處理依然使用javascript本冲。

MV模板引擎使HTML信息處理與javascript分離准脂,使HTML信息更聚集在一塊,更容易觀察可讀檬洞,更容易理解狸膏。

MVVM模板引擎是在MV模板引擎的基礎(chǔ)上改進(jìn),具備MV模板引擎的特點(diǎn)的同時(shí)添怔,使HTML數(shù)據(jù)模型的修改性能更快环戈,因?yàn)閿?shù)據(jù)的修改不需要HTML數(shù)據(jù)模型重建。

“l(fā)ess澎灸、scss”用于處理CSS信息數(shù)據(jù)院塞,使得避免使用服務(wù)器動(dòng)態(tài)頁(yè)面技術(shù)來處理CSS信息數(shù)據(jù),避免業(yè)務(wù)邏輯代碼混入其中性昭。并且“l(fā)ess拦止、scss”是預(yù)處理,服務(wù)器動(dòng)態(tài)頁(yè)面技術(shù)屬于動(dòng)態(tài)處理,預(yù)先處理的每次請(qǐng)求CSS文件無需計(jì)算汹族,動(dòng)態(tài)處理的每次請(qǐng)求都需要重新計(jì)算萧求。

可以發(fā)現(xiàn),為了使某些常用的信息具備更高的可讀性顶瞒,會(huì)對(duì)信息采用代碼量越少可讀性更高的表達(dá)形式夸政,不同的表達(dá)還需要獨(dú)立的信息處理。

異步處理

異步指一個(gè)執(zhí)行中的任務(wù)榴徐,拆開成多個(gè)子任務(wù)各自執(zhí)行守问。異步與同步處理相對(duì),同步指多個(gè)執(zhí)行中的子任務(wù)坑资,等待所有子任務(wù)執(zhí)行完再繼續(xù)執(zhí)行耗帕。異步的作用是使有I/O操作的任務(wù)最大化利用處理器的計(jì)算,以達(dá)到縮短任務(wù)的完成時(shí)間袱贮。

異步可以用多進(jìn)程仿便、多線程或其它技術(shù)實(shí)現(xiàn),常見實(shí)現(xiàn)技術(shù)有:

語言 異步技術(shù) 多異步依賴順序表達(dá) 返回值函數(shù)表達(dá) 返回值直接表達(dá) 處理非阻塞
javascript setTimeout/setInterval
異步請(qǐng)求
Promise
generator
async/await
web worker




















java Thread
Executor




C# Thread
Task
async/await








多異步依賴順序表達(dá)攒巍,指后一個(gè)異步處理需要前一個(gè)異步處理的返回值作為參數(shù)嗽仪,這種多異步依賴有兩種表達(dá),一種是嵌套表達(dá)柒莉,一種是順序表達(dá)闻坚。

嵌套表達(dá):

myAsyncMethod1().then(function(result1){
    myAsyncMethod2(result1).then(function(result2){
        console.log(result2);
    })
})

嵌套表達(dá)會(huì)造成異步嵌套地獄的現(xiàn)象,即形容代碼可讀性很混亂常柄。

順序表達(dá):

var result1 = await myAsyncMethod1();
var result2 = await myAsyncMethod2(result1);
console.log(result2);

返回值函數(shù)表達(dá),指返回值通過函數(shù)的參數(shù)返回搀擂,如:

myAsyncMethod1().then(function(result1){
    console.log(result1);
})

返回值直接表達(dá)西潘,指返回值通過賦值表達(dá)式直接表達(dá),如:

var result1 = await myAsyncMethod1();
console.log(result1);

處理非阻塞哨颂,指處理過程中喷市,是否會(huì)占用處理,而無法處理其它任務(wù)威恼。阻塞表現(xiàn)在假如異步中有死循環(huán)或計(jì)算量需要很長(zhǎng)時(shí)間品姓,軟件應(yīng)用的顯示畫面卡住無法展示新的內(nèi)容以及無法操作。

并行處理

并行處理指多個(gè)計(jì)算設(shè)備同時(shí)為一個(gè)任務(wù)的多個(gè)子任務(wù)同時(shí)計(jì)算箫措。簡(jiǎn)單理解就是有兩個(gè)具備計(jì)算能力的機(jī)器同時(shí)工作腹备,因此并行的前提一定是有多個(gè)具備獨(dú)力計(jì)算的機(jī)器。并行處理的作用是加大計(jì)算的數(shù)量以縮短任務(wù)的完成時(shí)間斤蔓。

并發(fā)與并行的區(qū)別:
順序:你吃飯吃到一半植酥,電話來了,你一直到吃完了以后才去接,這就說明你不支持并發(fā)也不支持并行友驮。
并發(fā):你吃飯吃到一半漂羊,電話來了,你停了下來接了電話卸留,接完后繼續(xù)吃飯走越,這說明你支持并發(fā)。
并行:你吃飯吃到一半耻瑟,電話來了,你一邊打電話一邊吃飯猪杭,這說明你支持并行艺挪。此處注意理解:是同時(shí)吃,同時(shí)說播歼,要真嚴(yán)格的說的話郭怪,需要2張嘴才是并行裆蒸。

多核處理器(CPU)
即然并行處理需要多個(gè)獨(dú)立計(jì)算萍桌,可以多臺(tái)計(jì)算機(jī),也可以多核處理器(CPU)芙沥。

要實(shí)現(xiàn)多核處理器處理同一個(gè)功能诲祸,只需將功能的處理拆分多個(gè)線程處理。

存儲(chǔ)

存儲(chǔ)器

顧名思義憨愉,指存儲(chǔ)數(shù)據(jù)的器物烦绳,對(duì)于學(xué)習(xí)計(jì)算機(jī)編程和手機(jī)編程,需要理解好內(nèi)存儲(chǔ)器和外存儲(chǔ)器配紫。


計(jì)算機(jī)存儲(chǔ)器類型

存儲(chǔ)空間
數(shù)據(jù)會(huì)占用一定的物理空間径密,組合后的數(shù)據(jù)也一樣會(huì)占用空間,可以存放數(shù)據(jù)的地方稱為數(shù)據(jù)空間躺孝。

內(nèi)存儲(chǔ)器

數(shù)據(jù)的運(yùn)算享扔,需要經(jīng)過內(nèi)存儲(chǔ)器,才能給到中央處理器進(jìn)行數(shù)據(jù)運(yùn)算植袍,故而叫內(nèi)存儲(chǔ)器惧眠,可簡(jiǎn)稱為內(nèi)存。
內(nèi)存儲(chǔ)器是一種隨機(jī)存儲(chǔ)器于个,存儲(chǔ)多份不同地址的數(shù)據(jù)氛魁,存儲(chǔ)的速度幾乎相似,將同一份數(shù)據(jù)拆開多份數(shù)據(jù)存儲(chǔ)厅篓,總速度不會(huì)太大影響秀存,存儲(chǔ)每一份數(shù)據(jù)的平均速度很快。
內(nèi)存儲(chǔ)器只能在通電情況下保持?jǐn)?shù)據(jù)存儲(chǔ)羽氮,斷電后存儲(chǔ)的數(shù)據(jù)會(huì)消失或链。

外存儲(chǔ)器

數(shù)據(jù)的運(yùn)算,外存儲(chǔ)器的數(shù)據(jù)需要先給到內(nèi)存儲(chǔ)器档押,才能給到中央處理器進(jìn)行數(shù)據(jù)運(yùn)算澳盐,故而叫外存儲(chǔ)器祈纯,可簡(jiǎn)稱為外存。
外存儲(chǔ)器是一種順序存儲(chǔ)器叼耙,存儲(chǔ)多份不同地址的數(shù)據(jù)腕窥,存儲(chǔ)的速度相差甚遠(yuǎn),將同一份數(shù)據(jù)拆開多份數(shù)據(jù)存儲(chǔ)筛婉,總速度變化很大油昂,存儲(chǔ)每一份數(shù)據(jù)的平均速度相對(duì)很慢。
外存儲(chǔ)器需要在通電情況下讀寫數(shù)據(jù)倾贰,斷電后已存儲(chǔ)的數(shù)據(jù)仍然可以保存著冕碟。

存儲(chǔ)器 讀寫規(guī)則 拆開讀寫時(shí)間 讀寫速度 數(shù)據(jù)持久性 空間成本
內(nèi)存儲(chǔ)器 隨機(jī)存儲(chǔ) 變化不大 通電存儲(chǔ)
外存儲(chǔ)器 順序存儲(chǔ) 變化很大 永久存儲(chǔ)

計(jì)算機(jī)的存儲(chǔ)器為何要區(qū)分內(nèi)外?
存儲(chǔ)器發(fā)展到目前為止匆浙,永久存儲(chǔ)的存儲(chǔ)器的讀寫速度跟不上通電存儲(chǔ)的存儲(chǔ)器的讀寫速度抑钟,通電存儲(chǔ)的存儲(chǔ)器在斷電后數(shù)據(jù)會(huì)消失芋酌,因此在數(shù)據(jù)儲(chǔ)存上需要內(nèi)存儲(chǔ)器與外存儲(chǔ)器共同配合完成計(jì)算機(jī)的存儲(chǔ)需要橙喘。

數(shù)據(jù)庫(kù)

指按照數(shù)據(jù)結(jié)構(gòu)來組織陆爽、存儲(chǔ)和管理數(shù)據(jù)的倉(cāng)庫(kù)。數(shù)據(jù)庫(kù)可以是用于內(nèi)存的數(shù)據(jù)庫(kù)软能,一般是用于外存的數(shù)據(jù)庫(kù)迎捺,用于內(nèi)存的數(shù)據(jù)庫(kù)不能持久存儲(chǔ),用于外存的數(shù)據(jù)庫(kù)可以持久存儲(chǔ)查排。

數(shù)據(jù)讀取

基于外存儲(chǔ)器的讀寫特點(diǎn)凳枝,批量讀取會(huì)比單條拆分讀取速度要快。
數(shù)據(jù)讀取關(guān)鍵在于對(duì)索引的查找算法的理解:
無索引查詢
如果一本漢語詞典里的字沒有按拼音排序跋核,要找到想要找的字是很因難的岖瑰。

多索引查詢
索引過多更新慢,索引過少查詢慢砂代,這是一個(gè)矛盾關(guān)系蹋订。如果系統(tǒng)需要建立很多索引,應(yīng)該怎么辦刻伊?

或過濾排序
查詢?nèi)湛记诒淼娜耸虏亢拓?cái)務(wù)部的考勤數(shù)據(jù)并按年齡進(jìn)行排列:

SELECT * FROM dayTable WHERE partName = '人事部' OR partName = '財(cái)務(wù)部' ORDER BY age ASC

這是一條很常見的或過濾排序的SQL查詢語句露戒,但在數(shù)據(jù)量很大的時(shí)候,就會(huì)出現(xiàn)查詢緩慢的清況捶箱,這個(gè)情況跟百度的查詢多個(gè)關(guān)鍵字并按權(quán)重排序顯示有些相似智什。

這里可以理解為“查詢?nèi)耸虏堪茨挲g排序的數(shù)據(jù)集合”與“查詢財(cái)務(wù)部按年齡排序的數(shù)據(jù)集合”的兩個(gè)集合的按年齡排序并集,在有索引的情況下單獨(dú)查詢兩個(gè)集合會(huì)很簡(jiǎn)單讼呢,再把兩個(gè)集合再組合起來排序撩鹿,如果數(shù)據(jù)量很大展示很多頁(yè)后的數(shù)據(jù)谦炬,就會(huì)有問題悦屏。

因此一般這個(gè)情況的業(yè)務(wù)場(chǎng)景的解決辦法可能會(huì)讓它不顯示太后面的數(shù)據(jù)节沦,只并集處理前面的幾千條數(shù)據(jù)體驗(yàn)速度不會(huì)受太大影響,當(dāng)然百度的處理會(huì)更復(fù)雜些础爬,可能會(huì)處理前第一頁(yè)就馬上給到瀏覽器展示效果甫贯,并異步預(yù)處理第2頁(yè)到50頁(yè)的查詢內(nèi)容,當(dāng)用戶點(diǎn)擊其它頁(yè)時(shí)就從已處理的數(shù)據(jù)中返回信息給用戶看蚜。

并集查詢
或過濾排序反應(yīng)的是其中并集查詢的一種叫搁,例如查詢?nèi)肼毴掌诖笥?020年1月1日且離職日期小于2020年12月31日的所有員工,在數(shù)據(jù)量很大的情形下供炎,一樣會(huì)出現(xiàn)緩慢的狀況渴逻。

數(shù)據(jù)寫入

基于外存儲(chǔ)器的讀寫特點(diǎn),批量寫入會(huì)比單條拆分寫入速度要快音诫。
數(shù)據(jù)寫入需要注意寫入的性能理解:
未持久寫入返回
數(shù)據(jù)只是寫入到數(shù)據(jù)庫(kù)的內(nèi)存儲(chǔ)器中惨奕,未寫入到外存儲(chǔ)器中,即數(shù)據(jù)已經(jīng)給到數(shù)據(jù)庫(kù)竭钝,但未持久保存就返回告訴程序已處理梨撞,此時(shí)程序馬上讀取數(shù)據(jù)可能并不能獲得寫入后的數(shù)據(jù),并且此時(shí)如果系統(tǒng)斷電或數(shù)據(jù)庫(kù)進(jìn)程停了香罐,未持久的數(shù)據(jù)會(huì)丟失卧波。

已持久寫入返回
指數(shù)據(jù)庫(kù)已把數(shù)據(jù)保存到外存儲(chǔ)器中,并建立好索引后返回給程序庇茫,程序此時(shí)馬上讀取數(shù)據(jù)是安全的港粱,但寫入的速度會(huì)比未持久寫入返回要慢很多,因?yàn)橥獯鎯?chǔ)器的讀寫速度要慢很多以及要處理索引旦签。

瀏覽器外存

表現(xiàn)層

瀏覽器外存數(shù)據(jù)類型有文本啥容、圖片、代碼文件顷霹。

瀏覽器外存數(shù)據(jù)空間類型有l(wèi)ocalStorage咪惠、cookie、sessionStorage淋淀、瀏覽器緩存遥昧,localStorage是本地存儲(chǔ),只存放文本數(shù)據(jù)類型朵纷,sessionStorage是會(huì)話存儲(chǔ)炭臭,主要用于存放會(huì)話數(shù)據(jù),只存放文本數(shù)據(jù)類型袍辞,cookie是瀏覽器早期僅有的用于長(zhǎng)時(shí)間存放數(shù)據(jù)的外存空間鞋仍,只存放文本數(shù)據(jù)類型,瀏覽器緩存用于存放請(qǐng)求返回的數(shù)據(jù)搅吁,一般用于存在代碼文件威创、圖片落午、文本。

sessionKey又名sessionId肚豺,用于會(huì)話密鑰身份的數(shù)據(jù)溃斋,是一個(gè)文件數(shù)據(jù),一般會(huì)存放在cookie或sessionStorage中吸申。

瀏覽器外存數(shù)據(jù)空間大小很有限梗劫,cookie空間大小一般是4K,localStorage空間大小一般是5M截碴,sessionStorage空間大小一般是5M割坠,不同瀏覽器外存空間大小會(huì)有差異。

瀏覽器外存數(shù)據(jù)時(shí)間存在有效期稠氮,cookie的數(shù)據(jù)有效期可針對(duì)不同數(shù)據(jù)進(jìn)行有效期設(shè)置彪薛,localStorage的數(shù)據(jù)有效期是永久性屋摇,sessionStorage的數(shù)據(jù)有效期是會(huì)話期揩魂,關(guān)閉頁(yè)面或關(guān)閉瀏覽器時(shí)清空數(shù)據(jù)。

瀏覽器外存演變歷史炮温,cookie最早是網(wǎng)景公司的前雇員Lou Montulli在1993年3月的發(fā)明火脉,localStorage和sessionStorage是2015年6月ECMAScript 6(ES6)發(fā)布的其中新增功能之一。

瀏覽器外存空間類型 可存放數(shù)據(jù)類型 數(shù)據(jù)空間大小 數(shù)據(jù)時(shí)間有效期 演變歷史
cookie 文本(sessionKey) 4K 設(shè)置期限 1993年
localStorage 文本 5M 永久期限 2015年es6
sessionStorage 文本(sessionKey) 5M 會(huì)話期限 2015年es6
瀏覽器緩存 代碼文件柒啤、圖片倦挂、文本 - 設(shè)置期限 -

尋址空間

顧名思義,尋址指尋找地址担巩,尋址空間指最大可尋找地址的空間大小方援。32位應(yīng)用程序的最大尋址空間是4GB,62位應(yīng)用程序的最大尋址空間是128GB涛癌。

位數(shù) 尋址空間
32位 4GB
64位 128GB

互聯(lián)

傳輸層

傳輸層中最為常見的兩個(gè)協(xié)議分別是傳輸控制協(xié)議TCP和用戶數(shù)據(jù)報(bào)協(xié)議UDP肯骇。TCP傳輸可靠相對(duì)較慢,UDP傳輸不可靠相對(duì)較快祖很,如:視頻不需要保證每一份數(shù)據(jù)傳輸都可靠笛丙,一般會(huì)使用UDP傳輸數(shù)據(jù)。

消息推送

消息推送是指通過客戶端與服務(wù)器端建立連接假颇,客戶端可以接收由服務(wù)器端不定時(shí)發(fā)送的消息胚鸯。

| 推送技術(shù) | 計(jì)算消耗 | 網(wǎng)絡(luò)帶寬消耗 | 連續(xù)推送及時(shí)性 | 瀏覽器兼容性 |
|--|--|--|--|--|--|
| 短輪詢(短連接) | 大 | 大 | 低 | 高 |
| 長(zhǎng)輪詢(短連接) | 中 | 中 | 中 | 高 |
| 長(zhǎng)連接| 低 | 低 | 高 | 一般 |

短輪詢,指在特定的的時(shí)間間隔(如每1秒)笨鸡,由客戶端對(duì)服務(wù)器發(fā)出網(wǎng)絡(luò)請(qǐng)求姜钳,然后由服務(wù)器返回最新的信息給客戶端坦冠,結(jié)束請(qǐng)求連接再在時(shí)間間隔后重新發(fā)送請(qǐng)求。

長(zhǎng)輪詢哥桥,指客戶端向服務(wù)端發(fā)起請(qǐng)求后將該請(qǐng)求掛起(不返回響應(yīng))辙浑,然后由服務(wù)器返回最新的信息給客戶端,結(jié)束請(qǐng)求連接再馬上重新發(fā)送請(qǐng)求拟糕。

長(zhǎng)連接判呕,指客戶端向服務(wù)端發(fā)起請(qǐng)求后將該請(qǐng)求掛起,然后由服務(wù)器返回最新的數(shù)據(jù)給客戶端送滞,請(qǐng)求連接保持不斷繼續(xù)等待響應(yīng)數(shù)據(jù)侠草。

信息推廣

robots.txt文件,用于授權(quán)搜索引擎犁嗅,位于網(wǎng)站根目錄下边涕。
sitemap.txt文件,用于告訴搜索引擎有哪些頁(yè)面信息褂微,位于網(wǎng)站根目錄下功蜓。

ajax不能信息推廣
ajax的作用是使得頁(yè)面可以局部刷新數(shù)據(jù),可以更好的用戶體驗(yàn)宠蚂,但并不是所有的搜索引擎都可以收錄到ajax的信息霞赫,到目前為止只有(Google 和 Bing)可以很好的搜錄ajax的內(nèi)容。

服務(wù)端渲染
指可以判斷是否是搜索引擎肥矢,如果是搜索引擎端衰,則在服務(wù)端執(zhí)行頁(yè)面并執(zhí)行初始化的ajax腳本,完全初始化工作后把網(wǎng)頁(yè)的全部?jī)?nèi)容返回給搜索引擎甘改。

預(yù)渲染
指通過服務(wù)端渲染旅东,預(yù)先處理好網(wǎng)頁(yè)內(nèi)容。再等客戶端請(qǐng)求時(shí)十艾,直接返回預(yù)先渲染好的頁(yè)面抵代。

架構(gòu)

“架”指用做支承的東西,如:骨架忘嫉、支架荤牍、書架、衣架庆冕,“構(gòu)”指構(gòu)造康吵、結(jié)成、組合访递,架構(gòu)意為用于支撐的構(gòu)造晦嵌。

模塊

“模”指具有一定模型的物體,“塊”指物體的其中一部分惭载,模塊意思是某個(gè)整體的一塊旱函。
模塊化意思是對(duì)事物內(nèi)部的成分進(jìn)行分類歸納后,形成大小不一的模塊描滔,把復(fù)雜的問題切分成細(xì)小的問題來解決棒妨。

在事物觀中的模塊就是把相關(guān)的事物或事物關(guān)系與規(guī)律進(jìn)行思考整理歸類,人類一直以來對(duì)事物的理解含长,就是采用模塊化的形式來理解和處理券腔。

在軟件開發(fā)的信息觀中的模塊就是把相關(guān)的信息(屬性)分到一塊,或相關(guān)的信息規(guī)則(方法)放到一塊茎芋,或相關(guān)的信息(屬性)以及信息規(guī)則(方法)放到一塊颅眶,人類依然無法避免的沿用模塊來理解和編程蜈出。

模塊性質(zhì):

  1. 接口(可用)田弥,模塊通過接口提供信息處理服務(wù),模塊可以有多個(gè)接口對(duì)應(yīng)多個(gè)信息處理服務(wù)铡原。
  2. 調(diào)用(使用)偷厦,模塊可以使用其它模塊的接口進(jìn)行調(diào)用。
  3. 成分燕刻,模塊由成分構(gòu)成只泼,成分可以是信息或信息規(guī)則。
  4. 信息卵洗,模塊可以有直接管理的信息请唱,即模塊可以具有一定的信息特征,信息的數(shù)據(jù)可以是在外存儲(chǔ)器或內(nèi)存儲(chǔ)器中过蹂,信息可以是基本數(shù)據(jù)類型十绑,也可以是數(shù)據(jù)集合,也可以是另一個(gè)模塊信息組酷勺。
  5. 信息規(guī)則本橙。每一個(gè)信息可以有一定的信息規(guī)則,例如年齡一定是數(shù)字脆诉。信息與信息之間可以有信息規(guī)則甚亭,例如出生日期與年齡是有關(guān)聯(lián)的。模塊與模塊的信息可以有信息規(guī)則击胜,則包含在它們的父模塊里亏狰,子模塊作為父模塊的成分。
  6. 信息隱蔽偶摔,模塊管理的信息可以對(duì)外部隱蔽骚揍、模塊的信息規(guī)則處理細(xì)節(jié)是對(duì)外隱蔽,外部只能通過接口去訪問,無法通過正常方式直接獲得隱蔽的信息以及處理細(xì)節(jié)中的臨時(shí)數(shù)據(jù)等信不,簡(jiǎn)單的講就是外部無法訪問其實(shí)現(xiàn)細(xì)節(jié)嘲叔。
  7. 嵌套,模塊的成分可以是模塊抽活,即模塊可以包含模塊硫戈。嵌套規(guī)則會(huì)表現(xiàn)在訪問順序,例如從外面走進(jìn)自己的睡房下硕,也要先進(jìn)大門丁逝,再進(jìn)睡房門。有訪問順序即為有嵌套規(guī)則的模塊梭姓,無訪問順序即為無嵌套規(guī)則的模塊霜幼。
  8. 內(nèi)聚,模塊內(nèi)部組成成分的相關(guān)聯(lián)程度誉尖。
  9. 耦合罪既,模塊間的關(guān)聯(lián)程度,更具體的意思是模塊間在交換信息過程中可能存在破壞信息規(guī)則的程度铡恕。

程序模塊
指通過調(diào)用接口可提供一定意義的數(shù)據(jù)處理能力琢感,由匯編程序、編譯程序探熔、裝入程序或翻譯程序作為一個(gè)整體來處理的一級(jí)獨(dú)立的驹针、可識(shí)別的程序指令,不可修改但可被使用的模塊诀艰,如:exe柬甥、dll、jar其垄。
代碼模塊
指通過調(diào)用接口可提供一定意義的數(shù)據(jù)處理能力苛蒲,由人類語言文字描述的程序代碼,即可修改和可被使用的模塊捉捅。
軟件模塊
指通過與人的交互操作可提供實(shí)際適用功能的數(shù)據(jù)處理能力撤防,并按照某種共同意義特征劃分的模塊。
功能模塊
指按照功能特征劃分出來的程序模塊棒口、代碼模塊或軟件模塊寄月。

軟件工程中的模塊

軟件工程中談到的模塊是指整個(gè)系統(tǒng)中一些相對(duì)獨(dú)立的程序單元,每個(gè)程序單元完成和實(shí)現(xiàn)一個(gè)相對(duì)獨(dú)立的軟件功能无牵。
模塊設(shè)計(jì)也叫詳細(xì)設(shè)計(jì)漾肮,是系統(tǒng)設(shè)計(jì)階段后續(xù)的一個(gè)軟件開發(fā)階段。在系統(tǒng)設(shè)計(jì)階段要把整個(gè)應(yīng)用問題分解成一個(gè)個(gè)獨(dú)立的功能部分茎毁,叫做程序模塊克懊。
每個(gè)程序模塊要有自己的名稱忱辅、標(biāo)識(shí)符、接口等外部特征谭溉。 模塊設(shè)計(jì)的結(jié)果是提交技術(shù)文檔《模塊設(shè)計(jì)說明書》墙懂。

不過模塊的概念,在現(xiàn)代軟件工程已經(jīng)不多使用了扮念。模塊概念后來發(fā)展成類和對(duì)象的概念损搬,現(xiàn)在又發(fā)展到組件的概念,近來又發(fā)展成微服務(wù)的概念柜与。換句話說巧勤,模塊已經(jīng)演變成其它不同的形態(tài)和概念代替了。不同形態(tài)類型的模塊弄匕,其性質(zhì)屬于模塊性質(zhì)颅悉,但模塊的嵌套規(guī)則、成分類型迁匠、信息規(guī)則等不同差異規(guī)則用不同的概念代替剩瓶,例如命名空間下包含類和命名空間,類包含屬性和方法柒瓣,規(guī)則不同采用不同的用詞代替儒搭。

從模塊本質(zhì)去解析其它模塊概念會(huì)更有利于更好的理解它和使用它吠架。

模塊具體是什么芙贫?
(1)模塊可以是一段程序代碼
(2)模塊可以是一個(gè)方法
(3)模塊可以是一個(gè)類
(4)模塊可以是一個(gè)命名空間下的類集合
(5)模塊可以是一個(gè)程序或類庫(kù)
(6)模塊可以是一個(gè)微服務(wù)

內(nèi)聚與耦合的拔河關(guān)系
內(nèi)聚程度越高,耦合程度越低傍药。
內(nèi)聚程度越低磺平,不代表耦合程度就越高。
耦合程度越高拐辽,內(nèi)聚程度越低拣挪。
耦合程度越低,不代表內(nèi)聚程度就越高俱诸。
內(nèi)聚程度與耦合程度可以同時(shí)很低菠劝,但不能同時(shí)很高。

解耦睁搭,全意應(yīng)該是指提高內(nèi)聚降低耦合的縮語赶诊,如果只是表示降低耦合并不代表提高內(nèi)聚。

內(nèi)聚

顧名思義园骆,指模塊內(nèi)部的聚集舔痪,具體指模塊內(nèi)部組成成分的相關(guān)聯(lián)程度。

內(nèi)聚程度越高锌唾,軟件各模塊和成分越容易理解锄码。例如家里的衣服放衣柜、蔬菜水果放冰箱、書籍放書架滋捶,擺放有序就很容易知道物品放在哪里痛悯。例如與行政相關(guān)的事情設(shè)立行政部門、與財(cái)務(wù)相關(guān)的設(shè)立財(cái)務(wù)部門重窟,事情安排有序就很容易知道找誰處理事情灸蟆,有利于加快人員之間的協(xié)調(diào)合作。

內(nèi)聚性質(zhì)表
| 內(nèi)聚 | 成分輸出相關(guān) | 成分處理相關(guān) | 成分順序相關(guān) | 成分特征相關(guān) |
|--|--|--|--|--|--|--|
| 偶然內(nèi)聚 | - | 否 | 否 | 否 |
| 邏輯內(nèi)聚 | - | - | - | 是 |
| 時(shí)間內(nèi)聚 | - | - | - | 是 |
| 過程內(nèi)聚 | - | - | 是 | 是 |
| 信息內(nèi)聚 | - | 是 | - | 是 |
| 順序內(nèi)聚 | - | 是 | 是 | 是 |
| 功能內(nèi)聚 | 是 | 是 | 是 | 是 |

-”表示是或否亲族。

成分輸出相關(guān)炒考,指各成分處理的結(jié)果輸出與模塊目標(biāo)結(jié)果輸出的相關(guān)性。例如某模塊根據(jù)打卡數(shù)據(jù)計(jì)算員工的工資數(shù)據(jù)霎迫,在計(jì)算過程中需要對(duì)員工的打卡數(shù)據(jù)計(jì)算成日考勤數(shù)據(jù)并保存在日考勤的數(shù)據(jù)表中斋枢,再根據(jù)日考勤數(shù)據(jù)計(jì)算成月考勤數(shù)據(jù)保存在月考勤數(shù)據(jù)中,再根據(jù)月考勤數(shù)據(jù)計(jì)算出工資結(jié)果知给,這個(gè)模塊的各成分結(jié)果有日考勤數(shù)據(jù)結(jié)果瓤帚、月考勤數(shù)據(jù)結(jié)果、工資數(shù)據(jù)結(jié)果涩赢,與模塊的目標(biāo)結(jié)果只有工資數(shù)據(jù)結(jié)果相關(guān)戈次,其它數(shù)據(jù)結(jié)果與模塊目標(biāo)相關(guān)性不大。如果中間中間成分處理的數(shù)據(jù)結(jié)果是一個(gè)臨時(shí)表只是為了當(dāng)前模塊使用筒扒,那中間成分的輸出數(shù)據(jù)結(jié)果忽略不參與模塊輸出的相關(guān)比較怯邪。

成分處理相關(guān),指各成分的處理結(jié)果會(huì)影響其它成分的處理結(jié)果花墩。

成分順序相關(guān)悬秉,指各成分的處理順序或代碼順序是否有一定的規(guī)則,不能隨意更改位置冰蘑。

成分特征相關(guān)和泌,指各成分是否有一種或多種相似的特征,例如信息內(nèi)聚的成分都處理同一個(gè)信息相關(guān)祠肥,時(shí)間內(nèi)聚的成分都需要在某一時(shí)間執(zhí)行的相似特征等武氓。

偶然內(nèi)聚

如果一個(gè)模塊的各成分之間毫無關(guān)系,則稱為偶然內(nèi)聚仇箱。模塊完成一組任務(wù)县恕,這些任務(wù)之間的關(guān)系松散,實(shí)際上沒有什么聯(lián)系工碾。

例子一:
有一個(gè)工廠(模塊)加工生產(chǎn)衣服弱睦,又加工生產(chǎn)礦泉水,這個(gè)工廠(模塊)加工生產(chǎn)的兩件事沒有任何關(guān)聯(lián)渊额,即為偶然內(nèi)聚况木。

例子二:

var getMyName = function(){
    var result = 1 + 2; //計(jì)算1+2
    console.log("hello"); //打印say hello
}

這個(gè)方法需要獲取我的名字垒拢,但方法里面做了兩件事情,與方法的需要沒有關(guān)聯(lián)火惊,它們之間也沒有關(guān)聯(lián)求类,與方法主題不符,即為偶然內(nèi)聚屹耐。

例子三:

var theApple = {
    sex:"boy",
    font:"宋體"
}

這個(gè)蘋果對(duì)象有兩個(gè)屬性尸疆,這兩個(gè)屬性與蘋果毫無關(guān)系,兩個(gè)屬性之間也毫無關(guān)系惶岭,即為偶然內(nèi)聚寿弱。

邏輯內(nèi)聚

幾個(gè)邏輯上相關(guān)的功能被放在同一模塊中腕侄,則稱為邏輯內(nèi)聚楼肪,如:圖書館日常、讀取各種不同類型外設(shè)的輸入仔掸。

例子一鸯旁,圖書館:

  1. 打掃衛(wèi)生
  2. 借書
  3. 還書
  4. 整理書籍
  5. 賣書

這5個(gè)行為只因?yàn)榕c圖書館相關(guān)噪矛,被放在一起,但是涉及許多數(shù)據(jù)集的操作铺罢,涉及多個(gè)角色的數(shù)據(jù)變更,如:書籍?dāng)?shù)據(jù)韭赘、財(cái)務(wù)數(shù)據(jù)楷怒、借還記錄巧娱。

例子二碉怔,讀取各種不同類型外設(shè)的輸入:

var device = {
    //獲取鼠標(biāo)數(shù)據(jù)
    getMouseData(){  },
    //獲取鍵盤數(shù)據(jù)
    getKeyboardData(){  },
    //獲取屏幕數(shù)據(jù)
    getScreenData(){ }
}

時(shí)間內(nèi)聚

如果一個(gè)模塊完成的功能必須在同一時(shí)間內(nèi)執(zhí)行,但這些功能只是因?yàn)闀r(shí)間因素關(guān)聯(lián)在一起禁添,則稱為時(shí)間內(nèi)聚撮胧,如:早上上班、系統(tǒng)初始化

例子一老翘,早上上班前:

  1. 刷牙
  2. 洗臉
  3. 換衣服

因?yàn)闀r(shí)間因素芹啥,事情放在一起處理锻离,刷牙、洗臉墓怀、換衣服并沒有先后順序汽纠。

例子二,系統(tǒng)初始化:

var system = {
    init(){
        this.logStartTime(); //記錄系統(tǒng)啟動(dòng)時(shí)間日志
        this.initCache(); //初始化數(shù)據(jù)緩存
        this.checkData(); //檢測(cè)啟動(dòng)數(shù)據(jù)
        this.startMessageService(); //啟動(dòng)消息服務(wù)
        //……
    },
    //記錄系統(tǒng)啟動(dòng)時(shí)間日志
    logStartTime(){},
    //初始化數(shù)據(jù)緩存
    initCache(){},
    //檢測(cè)啟動(dòng)數(shù)據(jù)
    checkData(){},
    //啟動(dòng)消息服務(wù)
    startMessageService(){}
    //……
}

過程內(nèi)聚

允許在調(diào)用前面的操作傀履,馬上調(diào)用后面的操作虱朵,即使兩者之間沒有數(shù)據(jù)進(jìn)行傳遞。意思是兩個(gè)操作有先后順序钓账,但不需要因?yàn)閿?shù)據(jù)處理的前后因果關(guān)系造成的先后順序碴犬,也可因數(shù)據(jù)處理的前后因果關(guān)系造成的先后順序。如:起床刷牙吃早餐梆暮、開電視找沙發(fā)

例子一翅敌,起床刷牙吃早餐:

  1. 起床
  2. 刷牙
  3. 吃早餐

這三件事情有先后關(guān)系,要先起床才能做其它事情惕蹄、要刷牙清理口腔細(xì)菌再來吃早餐蚯涮,但每一件事情的信息數(shù)據(jù)又是相互獨(dú)立的沒有因果關(guān)系,起床更新起床的數(shù)據(jù)信息卖陵、刷牙更新刷牙的數(shù)據(jù)信息遭顶、吃早餐更新吃早餐的數(shù)據(jù)信息,只是因?yàn)槿祟愖鍪逻^程的原因而有先后順序的聚集泪蔫。

例子二棒旗,開電視找沙發(fā):

  1. 開電源電源
  2. 找沙發(fā)坐著看

同樣,這兩件事情有先后關(guān)系撩荣,先坐沙發(fā)就沒有辦法觸碰電視的總電源開關(guān)铣揉,但這兩件事情的信息數(shù)據(jù)又是相互獨(dú)立的沒有因果關(guān)系,打開電視電源開關(guān)更新電視的電源操作的數(shù)據(jù)信息餐曹、坐沙發(fā)更新坐沙發(fā)的數(shù)據(jù)信息逛拱,只是因?yàn)槿祟愖鍪逻^程的原因而有先后順序的聚集。

通信內(nèi)聚(信息內(nèi)聚)

如果一個(gè)模塊的所有成分都操作同一數(shù)據(jù)集或生成同一數(shù)據(jù)集台猴,則稱為通信內(nèi)聚朽合,如:圖書館書籍管理、數(shù)據(jù)操作對(duì)象(DAO)

例子一饱狂,圖書館書籍管理:

  1. 新書入庫(kù)
  2. 舊書出庫(kù)
  3. 查找書籍

圖書館主要管理是目標(biāo)是書籍?dāng)?shù)據(jù)曹步,只對(duì)書數(shù)據(jù)的各種操作的聚集就是信息內(nèi)聚。

例子二休讳,數(shù)據(jù)操作對(duì)像(DAO):

var userDAO = {
    getUserById(id){ …… },
    deleteById(id){ …… },
    insertOne(name, age, sex){ …… }
    updateNameById(id){ …… }
}

順序內(nèi)聚

一個(gè)模塊的各個(gè)成分和同一個(gè)功能密切相關(guān)讲婚,而且一個(gè)成分的輸出作為另一個(gè)成分的輸入。這里需要注意一點(diǎn)是俊柔,每個(gè)成分會(huì)有處理結(jié)果更新于數(shù)據(jù)庫(kù)中筹麸,如:統(tǒng)計(jì)月考勤數(shù)據(jù)

例子一纳猫,統(tǒng)計(jì)月考勤數(shù)據(jù):

  1. 取得某員工的當(dāng)月的所有打卡數(shù)據(jù)
  2. 根據(jù)打卡數(shù)據(jù)統(tǒng)計(jì)日考勤數(shù)據(jù)存于日考勤表中
  3. 獲取該員工該月的日考勤數(shù)據(jù)
  4. 根據(jù)日考勤數(shù)據(jù)統(tǒng)計(jì)月考勤數(shù)據(jù)存于月考勤表中

順序內(nèi)聚可能會(huì)有多個(gè)結(jié)果產(chǎn)生,對(duì)于中間成分產(chǎn)生的結(jié)果竹捉,并不是該模塊的目標(biāo)芜辕,是附加的結(jié)果,該模塊只需要最終結(jié)果而產(chǎn)生多余的中間結(jié)果块差,這些中間結(jié)果并不是臨時(shí)數(shù)據(jù)侵续,會(huì)與其它模塊有一定的聯(lián)系,順序內(nèi)聚只要求各成分處理之間的相互聯(lián)系并得到功能的最終輸出結(jié)果憨闰,對(duì)于中間的輸出結(jié)果對(duì)其它模塊的影響不是順序內(nèi)聚的要求規(guī)則状蜗。

功能內(nèi)聚

模塊的所有成分對(duì)于完成單一的功能都是必須的。意思是模塊的成分為一個(gè)功能而聚集鹉动,如:根據(jù)需要的數(shù)據(jù)計(jì)算工資

例子一轧坎,根據(jù)需要的數(shù)據(jù)計(jì)算工資:

//定義一個(gè)模塊,對(duì)外接口只有計(jì)算工資
var wageAccounting = {
    //根據(jù)員工id和統(tǒng)計(jì)月份開始計(jì)算工資
    /*public*/ run(userId, month){
        //獲取員工某月份的所有打卡數(shù)據(jù)
        var cardData = this.getCardData(userId, month);
        //獲取員工某月份的所有請(qǐng)假數(shù)據(jù)
        var askOffData = this.getAskOffData(userId, month);
        //獲取員工某月份的加班數(shù)據(jù)
        var overtimeData = this.getOvertimeData(userId, month);
        //根據(jù)打卡數(shù)據(jù)計(jì)算正常上班時(shí)數(shù)
        var workHours = this.countWorkHours(cardData);
        //獲取員工每小時(shí)工資
        var hourlyWages = this.getHourlyWages(userId);
        //各種復(fù)雜計(jì)算
        ……
        ……
        ……
        //返回計(jì)算的工資結(jié)果
        return result;
    },
    
    //獲取員工某月份的所有打卡數(shù)據(jù)
    /*private*/ getCardData(userId, month){ …… },
    //獲取員工某月份的所有請(qǐng)假數(shù)據(jù)
    /*private*/ getAskOffData(userId, month){ …… },
    //獲取員工某月份的加班數(shù)據(jù)
    /*private*/ getOvertimeData(userId, month){ …… },
    //根據(jù)打卡數(shù)據(jù)計(jì)算正常上班時(shí)數(shù)
    /*private*/ countWorkHours(cardData){ …… },
    //獲取員工每小時(shí)工資
    /*private*/ getHourlyWages(userId){ …… }
}

這里的模塊成分的聚集只為了計(jì)算工資一個(gè)功能而聚集泽示。

耦合

“耦“古代指兩人并肩而耕缸血,“合”指相合,意思是某種相互行為下的結(jié)合械筛。人們常常討論的耦合捎泻,一般指模塊的耦合,意思是模塊間的關(guān)聯(lián)程度埋哟,更具體的意思是模塊間在交換信息過程中可能存在破壞信息規(guī)則的程度笆豁。

耦合程度越高,內(nèi)聚程度就會(huì)越低赤赊,軟件各模塊和成分就會(huì)越復(fù)雜闯狱,就會(huì)越難于理解和修改。

耦合的強(qiáng)弱程度決于各個(gè)模塊之間的接口的復(fù)雜程度抛计、調(diào)用模塊的方式以及哪些信息通過接口哄孤。

模塊間相互調(diào)用對(duì)耦合程度有影響嗎爷辱?
耦合的強(qiáng)弱取決于模塊之間的接口的復(fù)雜程度录豺、調(diào)用模塊的方式以及哪些信息通過接口饭弓,是否雙向相互調(diào)用對(duì)耦合程度沒什么影響。

耦合性質(zhì)表
| 耦合 | 外部數(shù)據(jù)用于只讀 | 外部數(shù)據(jù)用于功能 | 外部數(shù)據(jù)已預(yù)處理 | 外部數(shù)據(jù)隸屬模塊 |
|--|--|--|--|--|--|--|
| 非直接耦合 | 是 | - | 是 | 是 |
| 數(shù)據(jù)耦合 | 是 | 是 | 是 | 是 |
| 標(biāo)記耦合 | - | - | 是 | 是 |
| 控制耦合 | 是 | 否 | 是 | 是 |
| 外部耦合 | - | - | 是(簡(jiǎn)單) | 是(簡(jiǎn)單) |
| 公共耦合 | - | - | 否 | 否 |
| 內(nèi)容耦合 | - | - | 否 | 是 |

-”表示是或否媒抠。

外部數(shù)據(jù)弟断,指非隸屬于本模塊的數(shù)據(jù),例如外部模塊的數(shù)據(jù)集趴生、外部模塊的私有數(shù)據(jù)阀趴、外部模塊調(diào)用本模塊時(shí)傳遞進(jìn)來的參數(shù)昏翰。

外部數(shù)據(jù)用于只讀,指所使用的外部模塊的數(shù)據(jù)只用于只讀刘急,不會(huì)寫入數(shù)據(jù)進(jìn)行修改棚菊。

外部數(shù)據(jù)用于功能,指所使用的外部模塊的數(shù)據(jù)用于功能的計(jì)算相關(guān)叔汁,而不是用于在多功能選擇某一功能的控制信號(hào)统求。

外部數(shù)據(jù)已預(yù)處理,指所使用的外部模塊的數(shù)據(jù)据块,在使用前符合該外部數(shù)據(jù)模塊的規(guī)則安全下使用码邻。

外部數(shù)據(jù)隸屬模塊,指所使用的外部數(shù)據(jù)沒有對(duì)應(yīng)負(fù)責(zé)的隸屬模塊另假。

非直接耦合

兩個(gè)模塊之間沒有直接關(guān)系像屋,它們之間的聯(lián)系完全是通過主模塊的控制和調(diào)用來實(shí)現(xiàn)的。即兩模塊沒有任何聯(lián)系边篮,也沒有相同的需要寫入的公共參數(shù)數(shù)據(jù)己莺,可能會(huì)有只讀的預(yù)處理過的公共參數(shù)數(shù)據(jù)。

數(shù)據(jù)耦合

模塊之間通過參數(shù)來傳遞數(shù)據(jù)戈轿,那么被稱為數(shù)據(jù)耦合篇恒。數(shù)據(jù)耦合是最低的一種耦合形式,系統(tǒng)中一般都存在這種類型的耦合凶杖,因?yàn)闉榱送瓿梢恍┯幸饬x的功能胁艰,往往需要將某些模塊的輸出數(shù)據(jù)作為另一些模塊的輸入數(shù)據(jù)。

印記耦合

若一個(gè)模塊A通過接口向兩個(gè)模塊B和C傳遞一個(gè)公共參數(shù)智蝠,那么稱模塊B和C之間存在一個(gè)標(biāo)記耦合腾么。
公共參數(shù)是經(jīng)過模塊A預(yù)處理過,再給到模塊B和模塊C杈湾,即模塊B和摸塊C擁有相同引用的并預(yù)處理過的數(shù)據(jù)解虱。
如果公共參數(shù)是具有一定規(guī)則要求的數(shù)據(jù)結(jié)構(gòu),并且模塊B或模塊C會(huì)對(duì)公共參數(shù)進(jìn)行修改漆撞,這個(gè)情況使耦合程度提高殴泰,否則是耦合程度降低。

控制耦合

一個(gè)模塊通過接口向另一個(gè)模塊傳遞一個(gè)控制信號(hào)浮驳,接受信號(hào)的模塊根據(jù)信號(hào)值而進(jìn)行適當(dāng)?shù)膭?dòng)作悍汛,這種耦合被稱為控制耦合。
控制信號(hào)下至会,會(huì)使得幾個(gè)動(dòng)作成分只可能是信息內(nèi)聚离咐、邏輯內(nèi)聚、偶然內(nèi)聚,只要不是偶然內(nèi)聚的情況宵蛀,可以選擇使用控制信號(hào)昆著。

外部耦合

一組模塊都訪問同一全局簡(jiǎn)單變量而不是同一全局?jǐn)?shù)據(jù)結(jié)構(gòu),而且不是通過參數(shù)表傳遞該全局變量的信息术陶,則稱之為外部耦合凑懂。
簡(jiǎn)單變量并不是指一定是基本數(shù)據(jù)類型,簡(jiǎn)單變量意思是指外部數(shù)據(jù)的沒有使用規(guī)則限制梧宫,沒有預(yù)處理的情形下等同于預(yù)處理過接谨。而全局?jǐn)?shù)據(jù)結(jié)構(gòu)并不是一定要引用數(shù)據(jù)類型,而是指有一定使用規(guī)則的數(shù)據(jù)祟敛。
如果數(shù)據(jù)沒有使用規(guī)則的情況下疤坝,數(shù)據(jù)的隸屬模塊可以看成數(shù)據(jù)自身,隸屬模塊的接口就是數(shù)據(jù)自身的讀寫馆铁。

公共耦合

兩個(gè)或兩個(gè)以上的模塊共同引用一個(gè)全局?jǐn)?shù)據(jù)項(xiàng)跑揉,這種耦合被稱為公共耦合。在具有大量公共耦合的結(jié)構(gòu)中埠巨,確定究竟是哪個(gè)模塊給全局變量賦了一個(gè)特定的值是十分困難的历谍。
全局?jǐn)?shù)據(jù)項(xiàng)指的是具有一定使用規(guī)則的數(shù)據(jù),直接使用具有一定使用規(guī)則的數(shù)據(jù)辣垒,會(huì)容易出現(xiàn)潛在問題望侈,再尋找問題原因就會(huì)困難很多。
公共耦合與外部耦合的區(qū)別在于數(shù)據(jù)是否具有一定使用規(guī)則勋桶。

內(nèi)容耦合

當(dāng)一個(gè)模塊直接修改或操作另一個(gè)模塊的數(shù)據(jù)時(shí)脱衙,或一個(gè)模塊不通過正常入口而轉(zhuǎn)入另一個(gè)模塊時(shí),這樣的耦合被稱為內(nèi)容耦合例驹。內(nèi)容耦合是最高程度的耦合捐韩,應(yīng)該避免使用之。
最早用匯編語言編寫軟件的工程師鹃锈,模塊之間無法信息隱蔽荤胁,可以相互調(diào)用私有數(shù)據(jù)。高級(jí)編程語言則可以使用反射直接訪問其它模塊的私有屬數(shù)或成員屎债。這種訪問其它模塊的私有數(shù)據(jù)仅政,可以理解為直接訪問有使用規(guī)則的數(shù)據(jù),故而對(duì)耦合程度影響很大盆驹。

分層

顧名思義圆丹,指按照層次規(guī)則的拆分。分層是模塊化的一種方法召娜,是一種具有模塊間層級(jí)規(guī)則的模塊运褪,層級(jí)規(guī)則指相鄰層級(jí)的分層(模塊)可以相互直接調(diào)用,非相鄰的層級(jí)不能直接調(diào)用玖瘸。

分層包含模塊的性質(zhì):

  1. 接口(可用)秸讹,分層(模塊)通過接口提供信息處理服務(wù),分層(模塊)可以有多個(gè)接口對(duì)應(yīng)多個(gè)信息處理服務(wù)雅倒。
  2. 調(diào)用(使用)璃诀,分層(模塊)可以使用其它分層(模塊)的接口進(jìn)行調(diào)用。
  3. 成分蔑匣,分層(模塊)由多個(gè)信息處理的成分構(gòu)成劣欢。
  4. 信息,分層(模塊)可以有直接管理的信息裁良,即分層(模塊)可以具有一定的信息特征凿将,信息的數(shù)據(jù)可以是在外存儲(chǔ)器或內(nèi)存儲(chǔ)器中,信息可以是基本數(shù)據(jù)類型价脾,也可以是數(shù)據(jù)集合牧抵,也可以是另一個(gè)分層(模塊)信息組。
  5. 信息規(guī)則侨把。每一個(gè)信息可以有一定的信息規(guī)則犀变,例如年齡一定是數(shù)字。信息與信息之間可以有信息規(guī)則秋柄,例如出生日期與年齡是有關(guān)聯(lián)的获枝。
  6. 信息隱蔽,分層(模塊)管理的信息可以對(duì)外部隱蔽骇笔,分層(模塊)管理的信息可以對(duì)外部隱蔽省店、分層(模塊)的信息規(guī)則處理細(xì)節(jié)是對(duì)外隱蔽,外部只能通過接口去訪問笨触,無法通過正常方式直接獲得隱蔽的信息以及處理細(xì)節(jié)中的臨時(shí)數(shù)據(jù)等懦傍,簡(jiǎn)單的講就是外部無法訪問其實(shí)現(xiàn)細(xì)節(jié)。
  7. 內(nèi)聚旭旭,分層(模塊)內(nèi)部組成成分的相關(guān)聯(lián)程度谎脯。
  8. 耦合,分層(模塊)間的關(guān)聯(lián)程度持寄,更具體的意思是分層(模塊)間在交換信息過程中可能存在破壞信息規(guī)則的程度
  9. 嵌套源梭,分層(模塊)的成分可以是分層模塊或任意類型模塊,即分層(模塊)可以包含分層模塊或任意類型模塊稍味。
  10. 層級(jí)废麻,相鄰層級(jí)的分層(模塊)可以相互直接調(diào)用,非相鄰的層級(jí)不能直接調(diào)用模庐。

在分解復(fù)雜的軟件系統(tǒng)時(shí)烛愧,軟件設(shè)計(jì)者用得最多的技術(shù)之一就是分層。分層一般是軟件模塊化中屬于最大的模塊,然后各自的分層中再進(jìn)行細(xì)分小的模塊怜姿。

分層的目的

分層的目的是解耦慎冤,即提高內(nèi)聚和降低耦合。分層是一種具有模塊間層級(jí)規(guī)則的模塊沧卢,與模塊一樣蚁堤,也是將代碼拆分歸類,讓不同類型的代碼聚集到各自的分層中但狭。拆分模塊是內(nèi)聚的前提披诗,讓不同類型的代碼聚集到各自的分層中,讓模塊成分往分層中分類擺放立磁,使得代碼更容易理解呈队。分層即模塊化,模塊化的目的是提高內(nèi)聚和降低耦合唱歧。

分了層后就需要將代碼準(zhǔn)確放到不同的層中宪摧,如果代碼沒有準(zhǔn)確的放入不同的層中,等同物品胡亂擺放迈喉,會(huì)使得內(nèi)聚降低绍刮,也就是軟件的代碼模塊的理解性降低。

軟件三層架構(gòu)

指用三個(gè)以層次規(guī)則的模塊作為軟件的主體架構(gòu)挨摸,三層分別是“數(shù)據(jù)訪問層”孩革、“業(yè)務(wù)邏輯層”、“表現(xiàn)層”得运,也簡(jiǎn)稱為三層架構(gòu)膝蜈,是分層的一種應(yīng)用。


軟件三層架構(gòu)

數(shù)據(jù)訪問層

數(shù)據(jù)訪問層內(nèi)的每一個(gè)成分模塊代表一個(gè)數(shù)據(jù)概念表的處理模塊熔掺,處理著數(shù)據(jù)概念表的信息規(guī)則饱搏、表內(nèi)的信息與信息的規(guī)則。

業(yè)務(wù)邏輯層

業(yè)務(wù)邏輯層用于處理表與表間的信息規(guī)則置逻,處理不同子模塊間的信息規(guī)則推沸。從模塊性質(zhì)角度會(huì)發(fā)現(xiàn),數(shù)據(jù)訪問層與業(yè)務(wù)邏輯層的區(qū)別在于數(shù)據(jù)訪問層只處理簡(jiǎn)單模塊內(nèi)的信息規(guī)則券坞,業(yè)務(wù)邏輯層需要處理多個(gè)模塊內(nèi)的信息規(guī)則鬓催。

面向過程

面向過程是一種以過程為中心的編程思想,何為過程為中心恨锚,從字面意思還不好理解其含意宇驾。

用事物觀來解析的話,就是對(duì)事物不進(jìn)行分類擺放或歸納猴伶,例如把蘋果课舍、如何使用掃把塌西、掃把、如何吃蘋果很多信息和信息規(guī)則堆放在一起筝尾,當(dāng)要吃蘋果的時(shí)候捡需,沒有人會(huì)告訴你蘋果有多少種吃法(即開發(fā)工具不會(huì)提示),還要到處找如何吃蘋果才能吃忿等。

用軟件開發(fā)的信息觀來解析的話栖忠,就是信息和對(duì)應(yīng)的信息規(guī)則沒有綁定崔挖,例如找到了一個(gè)蘋果贸街,但不知道蘋果怎么吃,還要上網(wǎng)查怎么吃才能吃狸相。

即使把蘋果和如何吃蘋果擺在一起薛匪,開發(fā)工具也不會(huì)代碼提示蘋果如何吃,還是要自己尋找到那個(gè)方法脓鹃。

結(jié)構(gòu)體

C語言中的結(jié)構(gòu)體是模塊化的一種方法逸尖,是一種把相關(guān)的信息組織為一個(gè)整體來看待。
結(jié)構(gòu)體只有信息瘸右,沒有單個(gè)信息的規(guī)則娇跟、沒有結(jié)構(gòu)體內(nèi)信息與信息的規(guī)則。

數(shù)據(jù)表

數(shù)據(jù)表是模塊化的一種方法太颤,是一種把相關(guān)的信息組織為一個(gè)整體來看待苞俘。
數(shù)據(jù)表有信息,單個(gè)信息有簡(jiǎn)單規(guī)則(如:最大長(zhǎng)度)龄章,沒有數(shù)據(jù)表信息與信息之間的規(guī)則吃谣,數(shù)據(jù)表信息與數(shù)據(jù)表信息間有簡(jiǎn)單規(guī)則(如:表連接)。
數(shù)據(jù)表不具備嵌套規(guī)則做裙,即任意數(shù)據(jù)可以單獨(dú)直接訪問岗憋,不受訪問順序限制,即使是多對(duì)多的關(guān)系表也可以直接訪問锚贱。

面向?qū)ο?/h2>

面向?qū)ο笫悄K化的一種方法仔戈,是一種把相關(guān)的信息和信息規(guī)則組織為一個(gè)整體來看待。
對(duì)象可以有單個(gè)信息規(guī)則拧廊、信息與信息間的規(guī)則监徘、對(duì)象信息與對(duì)象信息間的規(guī)則。
對(duì)象具備嵌套規(guī)則卦绣,即對(duì)象可以包含對(duì)象耐量,具備訪問順序規(guī)則。
面向?qū)ο缶幊谭椒ㄊ悄壳澳K化最常用的方法滤港。

封裝廊蜒、繼承趴拧、多態(tài),是面向?qū)ο蟮娜筇匦陨蕉#庋b即模塊的信息隱藏著榴,繼承使得相同部分內(nèi)聚在父類,多態(tài)使得功能相似的方法可以取同名屁倔。

面向切面

面向切面的常用應(yīng)用場(chǎng)景有:日志記錄脑又、事務(wù)、權(quán)限驗(yàn)證锐借、數(shù)據(jù)驗(yàn)證问麸、監(jiān)控性能。

功能 功能
日志記錄 輔助功能
事務(wù) 主功能
權(quán)限驗(yàn)證 主功能
數(shù)據(jù)驗(yàn)證 主功能
監(jiān)控性能 輔助功能

面向切面的應(yīng)用場(chǎng)景并非全用于主功能钞翔,還需要加以區(qū)分严卖,像日志記錄、監(jiān)控代碼執(zhí)行性能布轿,也可以是用戶提出的業(yè)務(wù)需求哮笆,如果用戶不作要求這些輔助功能不是必需要的,有時(shí)因?yàn)楣净蜷_發(fā)需要汰扭,即軟件開發(fā)商自己的需要而需要這些輔助功能稠肘,有利于更好的調(diào)試軟件產(chǎn)品或保證軟件產(chǎn)品質(zhì)量。

事務(wù)萝毛、權(quán)限驗(yàn)證项阴、數(shù)據(jù)驗(yàn)證即使用戶不提出需求,如果不做好的話珊泳,用戶使用起來會(huì)出現(xiàn)各種問題鲁冯,因此這些功能也是主功能的組成成分,這些功能的代碼應(yīng)該與功能性的代碼聚集在一起才符合功能的完整聚集色查,如果使它們分離就不符合模塊化內(nèi)聚性薯演,使得系統(tǒng)更復(fù)雜,可讀性可理解性降低秧了。

輔助功能(日志記錄跨扮、監(jiān)控性能)與主功能屬于兩個(gè)功能目標(biāo),分別產(chǎn)生的兩個(gè)數(shù)據(jù)結(jié)果是相互獨(dú)立的验毡,成分處理的結(jié)果互不依賴衡创,但輔助功能又和主功能有相似的特征,即輔助功能是服務(wù)于主功能的晶通,為主功能做日志記錄璃氢、為主功能做監(jiān)控性能。

因此輔助功能與主功能是一種若即若離的狀態(tài)狮辽,應(yīng)該聚集在一起一也,又不應(yīng)該明顯的聚集在一起巢寡,例如現(xiàn)在要找一個(gè)功能方法對(duì)應(yīng)的性能監(jiān)控的代碼或日志記錄的代碼,例如現(xiàn)在要找整個(gè)系統(tǒng)所有相關(guān)的日志記錄代碼以便觀察日志代碼狀況椰苟。

面向切面是模塊化的一種方法聊疲,是一種可將輔助功能的代碼從主功能的代碼分離的技術(shù)塘装,需要通過預(yù)編譯或支持動(dòng)態(tài)代理特性的語言實(shí)現(xiàn),但最好只用于切分輔助功能牡昆,并且最好做到半分離半聚集狀態(tài)爱致。

面向接口

如果調(diào)用一個(gè)方法懂酱,需要傳一個(gè)對(duì)象的兩個(gè)屬性和這兩個(gè)屬性的規(guī)則方法脾还,這時(shí)會(huì)為兩屬性和規(guī)則方法定義一個(gè)接口缕棵,通過接口傳遞過去。
如果有一個(gè)功能京痢,需要返回一個(gè)對(duì)象的兩屬性和兩屬性的一個(gè)規(guī)則方法奶甘,這時(shí)會(huì)為兩屬性和規(guī)則方法定義一個(gè)接口,通過接口返回出去祭椰。

面向接口是模塊化的一種方法,用于聚集模塊的部分疲陕,即部分聚集方淤。為了使功能的所有成分是必要的而不使用類改用使用接口,類中不必要的成分用接口方式隱藏掉蹄殃,而不需要重新編寫一個(gè)類屬性和方法携茂,使得系統(tǒng)內(nèi)聚度更高,耦合性更低诅岩,即==接口的作用是解耦==讳苦。

面向信息

在實(shí)際的應(yīng)用軟件的業(yè)務(wù)邏輯方法中,為了使得所有成分是有必要的吩谦,就需要定義大量的接口鸳谜,為大量的接口而命名是費(fèi)腦的事情。

任意一個(gè)信息變成兩份放在同一個(gè)模塊中式廷,必然會(huì)有一個(gè)值相同的規(guī)則咐扭,例如在注冊(cè)頁(yè)面中,密碼信息和確認(rèn)密碼信息滑废,實(shí)際上都屬于用戶的密碼信息蝗肪。定義一個(gè)匿名接口,里面可以擴(kuò)充一個(gè)屬性變成兩個(gè)蠕趁,并自動(dòng)添加判斷兩密碼是否相同的方法薛闪。

假如人作為模塊,耳和口就是人的其中兩個(gè)成分俺陋,耳的行為(信息規(guī)則)是聽聲音豁延,口的行為(信息規(guī)則)是發(fā)聲音怀各,耳和口的組合使得人能學(xué)會(huì)語言并講話,兩者缺一不可术浪。如果現(xiàn)在有一個(gè)方法瓢对,只傳“口”進(jìn)去,則不能調(diào)用講話行為胰苏,如果只傳“耳”進(jìn)去硕蛹,則不能調(diào)用講話行為,如果同時(shí)傳“口”和“耳”進(jìn)去硕并,則可以調(diào)用講話行為法焰。

面向接口是模塊化的一種方法,是一種匿名的接口的方式倔毙,設(shè)定好信息后自動(dòng)組合信息規(guī)則到匿名接口中埃仪,當(dāng)然目前還沒有一種編程語言具備這種的特性,是筆者理論推理的一種實(shí)際應(yīng)用中的需要陕赃。

反模塊現(xiàn)狀案例

具備相似特征的成分聚集在一起卵蛉,是非常有利的,有利于培養(yǎng)新人么库、有利于代碼質(zhì)理傻丝、有利于代理更易于理解等,思考目前軟件開發(fā)中诉儒,還有哪些概念應(yīng)該聚集在一起卻沒有聚集的反模塊現(xiàn)狀案例:

更新

如果現(xiàn)在要尋找系統(tǒng)里葡缰,對(duì)某個(gè)表的某個(gè)字段的所有更新操作,以便對(duì)這個(gè)字段全局的理解和修改忱反,避免難以理解和修改容易出現(xiàn)bug泛释。
  1)如果用SQL字符串拼接更新語句,會(huì)發(fā)現(xiàn)沒太多辦法尋找温算。
  2)如果用ORM操作數(shù)據(jù)怜校,用專業(yè)開發(fā)工具跟蹤實(shí)體的字段,會(huì)找到字段用在計(jì)算米者、更新韭畸、讀取、賦值蔓搞、查詢表達(dá)式等各種代碼塊中胰丁。

查詢排序

如果現(xiàn)在要尋找系統(tǒng)里,對(duì)某個(gè)表的所有查詢排序操作喂分,以便確認(rèn)索引建立是否有多锦庸、有漏、字段順序有誤或潛在的低效索引蒲祈。
  1)如果用SQL字符串拼接更新語句甘萧,會(huì)發(fā)現(xiàn)沒太多辦法尋找萝嘁。
  2)如果用ORM操作數(shù)據(jù),用專業(yè)開發(fā)工具跟蹤實(shí)體類扬卷,會(huì)找到實(shí)體類用在計(jì)算牙言、更新、讀取怪得、賦值咱枉、查詢表達(dá)式、表連接條件等各種代碼塊中徒恋,即使找到了所有的查詢代碼塊蚕断,索引還會(huì)根據(jù)不同的邏輯條件會(huì)有不同的查詢,還需要根據(jù)邏輯推理索引種類入挣。

部分信息

如果有一個(gè)界面需要顯示用戶性名和年齡亿乳,使用ORM的會(huì)直接查詢一整個(gè)用戶信息返回給界面,然后只顯示性名和年齡径筏。
這是一個(gè)功能內(nèi)聚的案例葛假,看似所有成分都符合功能必需的,但是查詢出來的用戶其它信息卻不是必需的匠璧,這就違反了功能內(nèi)聚的要求桐款。

前端業(yè)務(wù)邏輯處理

如果有一個(gè)界面需要根據(jù)用戶的角色權(quán)限查詢不同的信息顯示,常見做法是先發(fā)送請(qǐng)求查詢當(dāng)前用戶的角色權(quán)限夷恍,再根據(jù)用戶的角色權(quán)限發(fā)送對(duì)應(yīng)的請(qǐng)求查詢信息顯示。從三層架構(gòu)中來講媳维,這里的判斷已經(jīng)不符合表現(xiàn)層的內(nèi)容酿雪,這個(gè)判斷的代碼應(yīng)該屬于業(yè)務(wù)邏輯層。

一對(duì)一特征

系統(tǒng)會(huì)把用戶信息放在用戶表侄刽,員工信息放在員工表指黎,學(xué)生信息放在學(xué)生表,教師信息放在教育表州丹,分開四個(gè)表醋安,這四個(gè)表似乎沒有相似特征,但這四個(gè)表符合一對(duì)一特征墓毒,符合一個(gè)用戶的多重身份的特征吓揪,應(yīng)該內(nèi)聚成一個(gè)用戶概念表,但可以是四個(gè)物理表組成所计,對(duì)寫業(yè)務(wù)邏輯的人來講柠辞,就只察覺到一個(gè)表。

子集特征

如果有一個(gè)表存放每個(gè)部門績(jī)效分?jǐn)?shù)最高的員工信息主胧,這個(gè)表的員工記錄是所有員工記錄的子集叭首,按照內(nèi)聚規(guī)則习勤,這時(shí)子表與主表應(yīng)該看成一個(gè)概念表,但可以是兩個(gè)物理表組成焙格,對(duì)寫業(yè)務(wù)邏輯的人來講图毕,就只察覺到一個(gè)表。

前端請(qǐng)求

一般來講眷唉,表現(xiàn)層只負(fù)責(zé)如何表現(xiàn)功能予颤,其它事情由業(yè)務(wù)邏輯層處理,筆者認(rèn)為這是表現(xiàn)層最極致的內(nèi)聚性厢破,請(qǐng)求只管往哪個(gè)頁(yè)面通知荣瑟,至于需要發(fā)送什么參數(shù)則由業(yè)務(wù)邏輯層自行從表現(xiàn)層的數(shù)據(jù)模型獲取,需要選擇哪個(gè)業(yè)務(wù)邏輯方法開始處理怎么處理也是業(yè)務(wù)邏輯層的事情摩泪。

數(shù)據(jù)緩存

數(shù)據(jù)緩存用于提高數(shù)據(jù)的讀寫速度笆焰,常常會(huì)發(fā)現(xiàn)數(shù)據(jù)緩存被當(dāng)成業(yè)務(wù)邏輯的緩存功能,從三層架構(gòu)來講见坑,數(shù)據(jù)緩存更應(yīng)該擺放在數(shù)據(jù)訪問層中嚷掠,對(duì)于業(yè)務(wù)邏輯層不需要知道數(shù)據(jù)是從緩存過來、還是從內(nèi)存過來荞驴、還是從外存過來不皆。

Session

Session是會(huì)話信息,包括會(huì)話開始時(shí)間熊楼、會(huì)話持續(xù)時(shí)間霹娄、會(huì)話登錄用戶等信息,如果現(xiàn)在要獲取持續(xù)時(shí)間超過2小時(shí)以上的會(huì)話信息鲫骗,又或者現(xiàn)在要獲取某部門的女性會(huì)話信息犬耻,計(jì)算出來就會(huì)有些工作量了。

那如果Session是一個(gè)表执泰,并且是數(shù)據(jù)訪問層的其中一個(gè)子模塊枕磁,像查詢條件一樣去查詢,就是直接的事情了术吝。

這說明Session本身的特征具備數(shù)據(jù)表特征计济,以往沒有將Session與數(shù)據(jù)表聯(lián)系起來,而是兩個(gè)獨(dú)立的概念排苍,沒有內(nèi)聚性沦寂。

以往Session是保存在內(nèi)存中,Session也應(yīng)該具備可以保存在數(shù)據(jù)庫(kù)中纪岁,這樣不會(huì)因?yàn)橄到y(tǒng)的調(diào)試重啟導(dǎo)致用戶需要重新登錄凑队,根據(jù)項(xiàng)目大小項(xiàng)目情況隨時(shí)更換不同的數(shù)據(jù)存儲(chǔ)策略。

不只是Session,請(qǐng)求域信息也可以看成數(shù)據(jù)訪問層的一個(gè)表模塊漩氨,例如獲取當(dāng)前并發(fā)請(qǐng)求數(shù)西壮,或獲取某個(gè)部門當(dāng)前并發(fā)請(qǐng)求數(shù),用表查詢的思維就很直接的獲取了叫惊。

不必要功能參數(shù)

例如有一個(gè)具有5個(gè)參數(shù)的方法款青,這個(gè)方法的代碼邏輯只用了其中三個(gè)參數(shù),其它兩個(gè)參數(shù)并沒有使用霍狰,這是不符合功能內(nèi)聚性抡草,功能內(nèi)聚性要求所有成分是必要,當(dāng)然現(xiàn)實(shí)編程中也很少見這樣的多余參數(shù)蔗坯,除了剛?cè)腴T的初級(jí)程序員康震。
如果現(xiàn)在不是5個(gè)參數(shù),而是只傳一個(gè)參數(shù)宾濒,這個(gè)參數(shù)是一個(gè)領(lǐng)域?qū)嶓w類腿短,實(shí)體類中有10個(gè)屬性,把這個(gè)實(shí)體類傳入方法中绘梦,方法的代碼邏輯只使用了其中3個(gè)屬性橘忱,這也是不符合功能內(nèi)聚性要求,這樣的方式特別是采用大量實(shí)體處理的系統(tǒng)中卸奉,是很常見的現(xiàn)象钝诚。

==這個(gè)現(xiàn)象很特別,為什么會(huì)出現(xiàn)這樣的現(xiàn)象榄棵?因?yàn)閺?qiáng)類型語言中類型都需要提前定義和命名類名凝颇,沒有用于參數(shù)的匿名類型,各種各樣的參數(shù)都定義成類和需要命名是很頭痛的事情疹鳄。==

在C#中可以采用元組祈噪,可用于參數(shù)的匿名類型。JAVA中筆者還沒發(fā)現(xiàn)可用于參數(shù)的匿名類型尚辑。

遇到上例中,其實(shí)只需要把無用的參數(shù)去掉盔腔,只需要留下3個(gè)參數(shù)即可杠茬。但實(shí)際應(yīng)用系統(tǒng)的情況會(huì)有需要多個(gè)有結(jié)構(gòu)的匿名類作為參數(shù),使得可讀性更好弛随。

不必要返回?cái)?shù)據(jù)

例如一個(gè)業(yè)務(wù)功能瓢喉,需要根據(jù)用戶的出生日期計(jì)算年齡,在ORM中舀透,會(huì)先取出整個(gè)用戶記錄栓票,然后只使用出生日期的數(shù)據(jù)計(jì)算出年齡,然后賦值到實(shí)體執(zhí)行保存。這里取出了多余的用戶其它信息走贪,不符合功能內(nèi)聚性佛猛,產(chǎn)生了不必要的成分,這在使用實(shí)體處理的系統(tǒng)中坠狡,是很常見的現(xiàn)象继找。

==這個(gè)現(xiàn)象很特別,為什么會(huì)出現(xiàn)這樣的現(xiàn)象逃沿?因?yàn)閺?qiáng)類型語言中類型都需要提前定義和命名類名婴渡,沒有用于方法返回的匿名類型,各種各樣的返回?cái)?shù)據(jù)都定義成不同的類和需要命名是很頭痛的事情凯亮。==

在C#中可以采用元組边臼,可用于方法返回的匿名類型。JAVA中筆者還沒發(fā)現(xiàn)可用于方法返回的匿名類型假消。

多特征

例如柠并,用SQL進(jìn)行多表連接查詢?cè)谲浖_發(fā)中很常見的事情,那這個(gè)只是查詢多表連接的信息應(yīng)該放到哪個(gè)模塊置谦?
例如堂鲤,有一個(gè)功能方法,需要對(duì)某員工清楚當(dāng)月月考勤數(shù)據(jù)和當(dāng)月日考勤數(shù)據(jù)媒峡,那這個(gè)方法應(yīng)該定義在員工業(yè)務(wù)邏輯類中瘟栖,還是日考勤的業(yè)務(wù)邏輯類中,還是月考勤的業(yè)務(wù)邏輯類中谅阿,還是放在業(yè)務(wù)邏輯的清理類中半哟?

常常會(huì)出現(xiàn)一些具有多特征的方法,在模塊化分類時(shí)签餐,容易放到其中一個(gè)特征相似的類中寓涨,但是方法卻具備多個(gè)特征。

取名

程序員在開發(fā)過程中氯檐,需要經(jīng)常給模塊或成分取名戒良,內(nèi)聚程度越高,取名也會(huì)具有內(nèi)聚相似冠摄,取名字的簡(jiǎn)單很多糯崎,效果提高,并且軟件內(nèi)使用的模塊名稱概念越少河泳,代碼結(jié)構(gòu)的理解會(huì)越清晰沃呢。

安全

垃圾回收處理

軟件開發(fā)中的“垃圾”指已經(jīng)不再使用的數(shù)據(jù),垃圾回收處理指對(duì)不再使用的數(shù)據(jù)進(jìn)行內(nèi)存回收處理拆挥。

垃圾數(shù)據(jù)
在一個(gè)方法里創(chuàng)建一個(gè)局部變量存放一個(gè)整數(shù)薄霜,等方法執(zhí)行完返回后,這個(gè)整數(shù)就不再使用變成了垃圾數(shù)據(jù),程序會(huì)自動(dòng)清理這個(gè)整數(shù)并回收所占內(nèi)存供其它數(shù)據(jù)使用惰瓜,這就是其中一種方式產(chǎn)生垃圾數(shù)據(jù)情形否副,其本上所有方式原理都差不多。

變量回收
即使空值的變量也會(huì)占用內(nèi)存鸵熟,變量是跟所在域綁定的副编,如函數(shù)參數(shù)變量、函數(shù)內(nèi)定義的變量在函數(shù)執(zhí)行完后流强,直接回收變量?jī)?nèi)存痹届。

引用計(jì)數(shù)器
指每一個(gè)引用數(shù)據(jù)類型,會(huì)有一個(gè)用于存放引用計(jì)數(shù)的內(nèi)存打月,用于表示引用數(shù)據(jù)類型的引用被多少個(gè)變量或?qū)傩該碛小?br> 當(dāng)變量回收時(shí)队腐,變量上的基本數(shù)據(jù)類型的數(shù)據(jù)會(huì)馬上被回收,變量上的引用數(shù)據(jù)類型的引用計(jì)數(shù)器將減1奏篙。當(dāng)引用數(shù)據(jù)類型的引用計(jì)數(shù)變成0時(shí)柴淘,表示數(shù)據(jù)已經(jīng)沒有任何用到的地方,此時(shí)引用數(shù)據(jù)類型將被馬上回收秘通。

相互引用的垃圾數(shù)據(jù)
在一個(gè)方法里創(chuàng)建一個(gè)“孩子”對(duì)象和一個(gè)“父親”對(duì)象分別賦值到兩個(gè)變量上为严,此時(shí)“孩子”對(duì)象和“父親”對(duì)象的引用計(jì)數(shù)都為1。
將“父親”對(duì)象賦值給孩子的“父親”屬性肺稀,將“孩子”對(duì)象添加到“父親”的孩子集合里第股,此時(shí)“父親”對(duì)象和“孩子”對(duì)象的引用計(jì)數(shù)都為2。
等方法執(zhí)行完返回后话原,方法內(nèi)的所有變量被回收夕吻,此時(shí)“孩子”對(duì)象和“父親”對(duì)象的引用計(jì)數(shù)都為1。
“孩子”對(duì)象和“父親”對(duì)象就成了相互引用的垃圾數(shù)據(jù)繁仁,但引用計(jì)數(shù)卻是1涉馅,不是0程序要如何判斷回收呢?
數(shù)據(jù)不能回收黄虱,內(nèi)存就不能被回收稚矿,內(nèi)存就會(huì)一直被占用,隨著方法重復(fù)調(diào)用捻浦,內(nèi)存就會(huì)占用越來越大盐捷,直到內(nèi)存消耗為止。

相互引用數(shù)據(jù)

主動(dòng)回收(析構(gòu)函數(shù))
在早期的編程語言中默勾,使用析構(gòu)函數(shù)處理相互引用的垃圾數(shù)據(jù),例如有一個(gè)主對(duì)象內(nèi)有一些屬性具有相互引用的對(duì)象聚谁,當(dāng)主對(duì)象不再使用計(jì)數(shù)為0時(shí)母剥,程序會(huì)調(diào)用主對(duì)象的析構(gòu)函數(shù),對(duì)內(nèi)部的相關(guān)引用數(shù)據(jù)類型的屬性進(jìn)行拆解,即將原來賦值的相互關(guān)系的屬环疼,重新將null賦值進(jìn)行习霹,主動(dòng)斷掉數(shù)據(jù)的關(guān)系即可。

如果是上例中方法內(nèi)創(chuàng)建的相互引用炫隶,則需要在方法執(zhí)行最后淋叶,編寫一段分別對(duì)“父親”對(duì)象和“孩子”對(duì)象的屬性賦空值,使其沒有相互引用關(guān)系伪阶,便可在方法執(zhí)行完后回收數(shù)據(jù)煞檩。

主動(dòng)回收(弱引用)
弱引用是使一個(gè)變量或?qū)傩裕跀?shù)據(jù)賦值給這個(gè)變量或?qū)傩詴r(shí)栅贴,不對(duì)數(shù)據(jù)的引用計(jì)數(shù)器做遞增或遞減斟湃。
假如“孩子”對(duì)象的父親屬性是一個(gè)弱引用屬性:
在一個(gè)方法里創(chuàng)建一個(gè)“孩子”對(duì)象和一個(gè)“父親”對(duì)象分別賦值到兩個(gè)變量上,此時(shí)“孩子”對(duì)象和“父親”對(duì)象的引用計(jì)數(shù)都為1檐薯。
將“父親”對(duì)象賦值給孩子的“父親”屬性凝赛,將“孩子”對(duì)象添加到“父親”的孩子集合里,此時(shí)“父親”對(duì)象的引用計(jì)數(shù)為1坛缕,“孩子”對(duì)象的引用計(jì)數(shù)為2墓猎。
等方法執(zhí)行完返回后,方法內(nèi)的所有變量被回收赚楚,此時(shí)“孩子”對(duì)象的引用計(jì)數(shù)為1毙沾,“父親”對(duì)象的引用計(jì)數(shù)則為0。
“父親”對(duì)象引用計(jì)數(shù)則為0被回收后直晨,此時(shí)“孩子”對(duì)象的引用計(jì)數(shù)變成0搀军,緊接著“孩子”對(duì)象將被回收。

弱引用也是一種主動(dòng)回收的方法勇皇,因?yàn)樾枰獙?duì)相關(guān)的屬性編寫一個(gè)標(biāo)記代碼罩句,標(biāo)記這個(gè)屬性是一個(gè)弱引用屬性,即仍然需要手動(dòng)處理敛摘。相對(duì)析構(gòu)函數(shù)的主動(dòng)回收方式门烂,編寫的代碼就少很多,因?yàn)橹恍枰帉懸粋€(gè)標(biāo)記代碼即可兄淫。

算法回收(垃圾回收機(jī)制)
由于需要編一段主動(dòng)回收的程序代碼屯远,相互引用的數(shù)據(jù)才能被釋放,但不能保障所有的相互引用的數(shù)據(jù)都進(jìn)行了主動(dòng)回收處理捕虽,有可能各種原因被遺漏慨丐,此時(shí)軟件占用內(nèi)存越來越大很難在代碼中找出原因。

在后面的編程語言中泄私,加入了自動(dòng)回收機(jī)制房揭,即通過一些算法备闲,可以計(jì)算出,哪些未被主動(dòng)回收的相互引用的數(shù)據(jù)是屬于垃圾數(shù)據(jù)捅暴,這些算法的其中一種大概原理是從程序的根開始遍歷一遍數(shù)據(jù)恬砂,如果數(shù)據(jù)不是垃圾數(shù)據(jù)總會(huì)能在樹節(jié)點(diǎn)中遍歷尋找得到,找不到的就是垃圾數(shù)據(jù)蓬痒,當(dāng)然這只是其中一種方法的原理泻骤,垃圾回收機(jī)制是多種算法并用。

算法回收性能
不管垃圾回收機(jī)制的算法有多先進(jìn)梧奢,但是從廣義上思考狱掂,仍有質(zhì)疑的點(diǎn),垃圾回收機(jī)制確實(shí)能保障遺漏的垃圾數(shù)據(jù)被回收處理粹断,但無法保證回收的算法性能足夠快符欠。

解決辦法:

  1. 通過持續(xù)的長(zhǎng)時(shí)間監(jiān)控垃圾回收機(jī)制,在回收相互引用的數(shù)據(jù)的回收量瓶埋,如有發(fā)現(xiàn)讓開發(fā)人員在代碼中繼續(xù)尋找未主動(dòng)回收的相互引用的數(shù)據(jù)希柿,如有發(fā)現(xiàn)使用弱引用處理。
  2. 通過宏觀管理的方式养筒,將系統(tǒng)切分成許多個(gè)足夠小的獨(dú)立軟件曾撤,相互協(xié)調(diào),如果其中某個(gè)軟件有問題晕粪,則想辦法解決挤悉,如果不能解決則重新編寫。(微服務(wù)架構(gòu))

請(qǐng)求方法(GET巫湘、POST)

GET請(qǐng)求和POST請(qǐng)求都可以響應(yīng)返回?cái)?shù)據(jù)装悲,獲取數(shù)據(jù)并不是GET請(qǐng)求獨(dú)有的。

GET請(qǐng)求和POST請(qǐng)求都不是決定是否安全的尚氛,決定安全由是否具有ssl加密通訊決定诀诊。通常情況下GET在提交有密碼表單時(shí),地址欄會(huì)顯示密碼阅嘶,在顯示上存在不安全属瓣,事實(shí)上GET也可以通過body發(fā)送數(shù)據(jù)。

GET請(qǐng)求和POST請(qǐng)求的URL長(zhǎng)度在http協(xié)議中是沒有規(guī)定限制長(zhǎng)度的讯柔,只是某些URL和web服務(wù)器會(huì)對(duì)GET請(qǐng)求的url有長(zhǎng)度限制抡蛙。

GET請(qǐng)求的出發(fā)點(diǎn)是安全的可重復(fù)調(diào)用執(zhí)行的,POST請(qǐng)求的出發(fā)點(diǎn)是不安全的不可重復(fù)調(diào)用執(zhí)行的魂迄。例如有時(shí)候?yàn)g覽器在剛在提交完表單后粗截,點(diǎn)后退時(shí)會(huì)提醒用戶,重復(fù)上次操作可能會(huì)有風(fēng)險(xiǎn)捣炬。

而有些操修改操作是安全可重復(fù)調(diào)用執(zhí)行的慈格,例如安全的可重復(fù)調(diào)用的添加或修改使用PUT請(qǐng)求怠晴,安全的可重復(fù)調(diào)用的刪除使用DELETE請(qǐng)求。

應(yīng)該如何理解使用呢浴捆?

請(qǐng)求方法 理解使用 參數(shù)明文 URL長(zhǎng)度限制
GET 安全獲取、安全修改
POST 非安全獲取稿械、非安全修改
PUT 安全獲取选泻、安全修改
DELETE 不需要

線程安全

如下代碼,開啟3個(gè)線程美莫,每個(gè)線程循環(huán)10次页眯。

public class Test implements Runnable {

    private static Integer count = 0;

    public void getCount() {
        count ++;
        System.out.println(count);
    }

    @Override
    public void run() {
        for(var i = 0; i < 10; i++) {
            this.getCount();
        }
    }
    
    public static void main(String[] args) {
        Test test1 = new Test();
        Test test2 = new Test();
        Test test3 = new Test();
        new Thread(test1).start();
        new Thread(test2).start();
        new Thread(test3).start();
    }
}

執(zhí)行后,得到以下結(jié)果:


線程安全例子

可以發(fā)現(xiàn)打印了兩個(gè)22厢呵,getCount里面是有兩步的窝撵,分別是count++和打印,現(xiàn)在一步一步分解講解襟铭,假如線程A執(zhí)行g(shù)etCount的第一步(count++)碌奉,即現(xiàn)在count值為1,然后線程B執(zhí)行g(shù)etCount的第一步(count++)寒砖,即現(xiàn)在count值為2赐劣,然后線程A執(zhí)行第二步打印,打印出2树瞭,然后線程B執(zhí)行g(shù)etCount的第二步冤馏,也打印出2何恶。

線程安全是由于多個(gè)線程分別執(zhí)行多個(gè)步驟的程序,并且多個(gè)線程程序訪問了一個(gè)相同的數(shù)據(jù)時(shí)咐汞,多個(gè)步驟可能存在同時(shí)執(zhí)行到中間的步驟,導(dǎo)致會(huì)有意外的結(jié)果儒鹿。

例如化撕,現(xiàn)在不是訪問一個(gè)簡(jiǎn)單變量,而是100個(gè)線程同時(shí)往List集合里加數(shù)據(jù)挺身,分別循環(huán)100次:

public class Test implements Runnable {

    private static List<int> list = 0;

    @Override
    public void run() {
        for(var i = 0; i < 100; i++) {
            list.add(0);
        }
    }
    
    public static void main(String[] args) {
        for(var i = 0; i < 100; i++){
            new Test().start();
        }
    }
}

很可能會(huì)出現(xiàn)程序執(zhí)行崩潰侯谁,原因是“l(fā)ist.add(0)”方法內(nèi)部是很多步驟的,而List又是內(nèi)置類型章钾,方法內(nèi)部會(huì)是一些原始程序墙贱,不能有半點(diǎn)差錯(cuò),否則會(huì)導(dǎo)致程序執(zhí)行崩潰贱傀。

線程安全導(dǎo)致的最嚴(yán)重后果是程序崩潰惨撇,并且程序崩潰還很難找出崩潰的問題源頭,因?yàn)槌绦虮罎⑹浅绦蝰R上中斷不能記錄錯(cuò)誤日志府寒。

單線程模型與多線程模型
由于線程安全具有崩潰的風(fēng)險(xiǎn)魁衙,JS執(zhí)行在客戶端的瀏覽器中报腔,瀏覽器不允許有這樣的情況出現(xiàn),因此JS采用單線程模型剖淀,即沒有多線程訪問同一個(gè)數(shù)據(jù)的可能纯蛾,就不會(huì)有線程安全的出現(xiàn)。

多線程模型如何解決線程安全
避免多個(gè)線程使用靜態(tài)數(shù)據(jù)或相同數(shù)據(jù)的可能性纵隔,如果有的話需要設(shè)置線程鎖即可翻诉,線程鎖可以使線程鎖范圍內(nèi)的多個(gè)步驟的程序必需執(zhí)行完才能下一個(gè)線程執(zhí)行,即同時(shí)最多只能有一個(gè)線程在線程鎖范圍內(nèi)執(zhí)行捌刮。

事務(wù)安全

事務(wù)安全是指多個(gè)程序同時(shí)操作同一份持久數(shù)據(jù)時(shí)碰煌,可能導(dǎo)致數(shù)據(jù)出現(xiàn)意外的結(jié)果,使得程序運(yùn)行跟著出現(xiàn)意外的情形绅作÷或指一個(gè)程序在操作多個(gè)持久的數(shù)據(jù)時(shí),操作到一半由于停電或其它因素導(dǎo)致程序中止俄认,多個(gè)持久數(shù)據(jù)處理到一半沒有完整處理好个少。

js注入安全(xss)

如果用戶可以在評(píng)論或文章內(nèi)容中添加JS代碼,使得進(jìn)來觀看內(nèi)容的用戶執(zhí)行這段JS代碼梭依,這段JS代碼可以偷取觀看用戶的sessionKey或數(shù)據(jù)稍算,對(duì)觀看用戶造成安全隱患。

sql注入安全

指web應(yīng)用程序?qū)τ脩糨斎霐?shù)據(jù)的合法性沒有判斷或過濾不嚴(yán)役拴,攻擊者可以在web應(yīng)用程序中事先定義好的查詢語句的結(jié)尾上添加額外的SQL語句糊探,在管理員不知情的情況下實(shí)現(xiàn)非法操作,以此來實(shí)現(xiàn)欺騙數(shù)據(jù)庫(kù)服務(wù)器執(zhí)行非授權(quán)的任意查詢河闰,從而進(jìn)一步得到相應(yīng)的數(shù)據(jù)信息科平。

通信安全(ssl)

指信息在網(wǎng)絡(luò)傳輸中被截取,通過ssl對(duì)傳輸中的數(shù)據(jù)進(jìn)行加密姜性,避免信息泄漏瞪慧。

線程異常安全

如下代碼中,在線程中拋出異常部念,會(huì)導(dǎo)致程序崩潰推出:

public class Test {
    public static void main(string[] args) {
        new Thread(()=>{
            throw new Exception();
        }).start();
    }
}

需要對(duì)每個(gè)線程做try catch處理:

public class Test {
    public static void main(string[] args) {
        new Thread(()=>{
            try{
                ……
            } catch(Exception){ }
        }).start();
    }
}

微服務(wù)架構(gòu)

微服務(wù)架構(gòu)指將系統(tǒng)切分成許多個(gè)足夠小的微服務(wù)軟件弃酌,多個(gè)微服務(wù)軟件間相互調(diào)用協(xié)調(diào),并且每一個(gè)獨(dú)立軟件使用各自的數(shù)據(jù)庫(kù)儡炼。

微服務(wù)架構(gòu)的主要作用與出發(fā)點(diǎn):

  1. 保障每一個(gè)微服務(wù)在宏觀上有足夠的內(nèi)聚性妓湘,因?yàn)槲⒎?wù)間數(shù)據(jù)庫(kù)各自獨(dú)立,被迫每一個(gè)微服務(wù)的每一行代碼都屬于各自的信息或信息規(guī)則乌询,大大降低軟件系統(tǒng)的總復(fù)雜度榜贴。但是宏觀上能保證內(nèi)聚性,微觀上不一定能保證內(nèi)聚性妹田,如果其中一個(gè)微服務(wù)隨著時(shí)間的推移代碼變得很臃腫唬党,導(dǎo)致很難修改鹃共,則可以直接放棄這個(gè)微服務(wù)重新寫一個(gè)新的微服務(wù)替換即可。
  2. 保障每一個(gè)微服務(wù)崩潰時(shí)互不影響驶拱,在單體應(yīng)用架構(gòu)中如果其中一個(gè)功能有線程安全或死循環(huán)等各種原因霜浴,會(huì)導(dǎo)致所有功能崩潰不能使用,在微服務(wù)架構(gòu)中如果其中一個(gè)微服務(wù)崩潰蓝纲,其它不相關(guān)的功能依然可以繼續(xù)運(yùn)作坷随。

微服務(wù)架構(gòu)是從宏觀角度思考問題,認(rèn)為程序員的水平各有不同驻龟,有高有低,因此需要尋找辦法缸匪,保障程序運(yùn)行和代碼質(zhì)量的風(fēng)險(xiǎn)翁狐。

宏觀上的功能切分并不代表代碼的內(nèi)聚性足夠好,功能切分讓信息彼此分離凌蔬,使得耦合性降低露懒,根據(jù)內(nèi)聚性與耦合性的拔河原理,耦合性降低并不意味著內(nèi)聚性就提高砂心,總的來講按功能切分會(huì)對(duì)內(nèi)聚性起到一定作用懈词,但仍需要監(jiān)督與調(diào)優(yōu)。

自動(dòng)

(未完待續(xù)辩诞,下期再見)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末坎弯,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子译暂,更是在濱河造成了極大的恐慌抠忘,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,188評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件外永,死亡現(xiàn)場(chǎng)離奇詭異崎脉,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)伯顶,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門囚灼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人祭衩,你說我怎么就攤上這事灶体。” “怎么了汪厨?”我有些...
    開封第一講書人閱讀 165,562評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵赃春,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我劫乱,道長(zhǎng)织中,這世上最難降的妖魔是什么锥涕? 我笑而不...
    開封第一講書人閱讀 58,893評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮狭吼,結(jié)果婚禮上层坠,老公的妹妹穿的比我還像新娘。我一直安慰自己刁笙,他們只是感情好破花,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,917評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著疲吸,像睡著了一般座每。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上摘悴,一...
    開封第一講書人閱讀 51,708評(píng)論 1 305
  • 那天峭梳,我揣著相機(jī)與錄音,去河邊找鬼蹂喻。 笑死葱椭,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的口四。 我是一名探鬼主播孵运,決...
    沈念sama閱讀 40,430評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼蔓彩!你這毒婦竟也來了治笨?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,342評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤粪小,失蹤者是張志新(化名)和其女友劉穎大磺,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體探膊,經(jīng)...
    沈念sama閱讀 45,801評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡杠愧,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,976評(píng)論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了逞壁。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片流济。...
    茶點(diǎn)故事閱讀 40,115評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖腌闯,靈堂內(nèi)的尸體忽然破棺而出绳瘟,到底是詐尸還是另有隱情,我是刑警寧澤姿骏,帶...
    沈念sama閱讀 35,804評(píng)論 5 346
  • 正文 年R本政府宣布糖声,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏蘸泻。R本人自食惡果不足惜琉苇,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,458評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望悦施。 院中可真熱鬧并扇,春花似錦、人聲如沸抡诞。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,008評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)昼汗。三九已至肴熏,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間顷窒,已是汗流浹背扮超。 一陣腳步聲響...
    開封第一講書人閱讀 33,135評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蹋肮,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,365評(píng)論 3 373
  • 正文 我出身青樓璧疗,卻偏偏與公主長(zhǎng)得像坯辩,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子崩侠,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,055評(píng)論 2 355

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

  • 這是16年5月份編輯的一份比較雜亂適合自己觀看的學(xué)習(xí)記錄文檔漆魔,今天18年5月份再次想寫文章,發(fā)現(xiàn)簡(jiǎn)書還為我保存起的...
    Jenaral閱讀 2,762評(píng)論 2 9
  • 面向?qū)ο笤瓌t:高內(nèi)聚、低耦合系瓢。多聚合阿纤、少繼承 2017年12月18日 19:28:38 望崖 閱讀數(shù) 13358 ...
    Rainysong閱讀 926評(píng)論 0 1
  • 前同事回南京,大家小聚了一次夷陋。 四個(gè)人欠拾,除了我,她們都在正規(guī)企業(yè)工作一年多骗绕,變化很大藐窄。而我沒有一絲專業(yè)的氣息。 改...
    大胡hu閱讀 244評(píng)論 0 0
  • 5.3 君子蘭酬土,開了哦荆忍,潮氣蓬勃,紅紅火火,朵大艷麗刹枉。也有說是朱頂紅的叽唱,我傻傻分不清。 陽(yáng)光透過鮮紅花瓣嘶卧,好明凈尔觉。...
    秭歸橙子和水果閱讀 383評(píng)論 0 0
  • 今天我市心理工作領(lǐng)導(dǎo)小組來我校了解學(xué)生心理問題,我做為學(xué)校的心理輔導(dǎo)員接待了他們芥吟,他們的到來是為了幫助我校...
    在水一方_2018閱讀 524評(píng)論 0 7