引言
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)容:
- 從廣義層面理解狹義貌矿,尋找更廣闊的意義。
- 從廣義層面保障狹義罪佳。狹義認(rèn)為靠人力能解決問題逛漫,廣義則認(rèn)為僅靠人力不能完全有效的解決問題總會(huì)有些意外出現(xiàn),并提出宏觀上管理的辦法解決赘艳。狹義認(rèn)為現(xiàn)有很多技術(shù)已經(jīng)問題不多酌毡,廣義認(rèn)為現(xiàn)在有很多技術(shù)還存在不確定因素,并提出些辦法來保障蕾管。
- 學(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)部設(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ù)
瀏覽器內(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ǔ)器配紫。
存儲(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ǔ)器的讀寫速度要慢很多以及要處理索引旦签。
瀏覽器外存
瀏覽器外存數(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ì):
- 接口(可用)田弥,模塊通過接口提供信息處理服務(wù),模塊可以有多個(gè)接口對(duì)應(yīng)多個(gè)信息處理服務(wù)铡原。
- 調(diào)用(使用)偷厦,模塊可以使用其它模塊的接口進(jìn)行調(diào)用。
- 成分燕刻,模塊由成分構(gòu)成只泼,成分可以是信息或信息規(guī)則。
- 信息卵洗,模塊可以有直接管理的信息请唱,即模塊可以具有一定的信息特征,信息的數(shù)據(jù)可以是在外存儲(chǔ)器或內(nèi)存儲(chǔ)器中过蹂,信息可以是基本數(shù)據(jù)類型十绑,也可以是數(shù)據(jù)集合,也可以是另一個(gè)模塊信息組酷勺。
- 信息規(guī)則本橙。每一個(gè)信息可以有一定的信息規(guī)則,例如年齡一定是數(shù)字脆诉。信息與信息之間可以有信息規(guī)則甚亭,例如出生日期與年齡是有關(guān)聯(lián)的。模塊與模塊的信息可以有信息規(guī)則击胜,則包含在它們的父模塊里亏狰,子模塊作為父模塊的成分。
- 信息隱蔽偶摔,模塊管理的信息可以對(duì)外部隱蔽骚揍、模塊的信息規(guī)則處理細(xì)節(jié)是對(duì)外隱蔽,外部只能通過接口去訪問,無法通過正常方式直接獲得隱蔽的信息以及處理細(xì)節(jié)中的臨時(shí)數(shù)據(jù)等信不,簡(jiǎn)單的講就是外部無法訪問其實(shí)現(xiàn)細(xì)節(jié)嘲叔。
- 嵌套,模塊的成分可以是模塊抽活,即模塊可以包含模塊硫戈。嵌套規(guī)則會(huì)表現(xiàn)在訪問順序,例如從外面走進(jìn)自己的睡房下硕,也要先進(jìn)大門丁逝,再進(jìn)睡房門。有訪問順序即為有嵌套規(guī)則的模塊梭姓,無訪問順序即為無嵌套規(guī)則的模塊霜幼。
- 內(nèi)聚,模塊內(nèi)部組成成分的相關(guān)聯(lián)程度誉尖。
- 耦合罪既,模塊間的關(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è)的輸入仔掸。
例子一鸯旁,圖書館:
- 打掃衛(wèi)生
- 借書
- 還書
- 整理書籍
- 賣書
這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)初始化
例子一老翘,早上上班前:
- 刷牙
- 洗臉
- 換衣服
因?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ā)
例子一翅敌,起床刷牙吃早餐:
- 起床
- 刷牙
- 吃早餐
這三件事情有先后關(guān)系,要先起床才能做其它事情惕蹄、要刷牙清理口腔細(xì)菌再來吃早餐蚯涮,但每一件事情的信息數(shù)據(jù)又是相互獨(dú)立的沒有因果關(guān)系,起床更新起床的數(shù)據(jù)信息卖陵、刷牙更新刷牙的數(shù)據(jù)信息遭顶、吃早餐更新吃早餐的數(shù)據(jù)信息,只是因?yàn)槿祟愖鍪逻^程的原因而有先后順序的聚集泪蔫。
例子二棒旗,開電視找沙發(fā):
- 開電源電源
- 找沙發(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)
例子一饱狂,圖書館書籍管理:
- 新書入庫(kù)
- 舊書出庫(kù)
- 查找書籍
圖書館主要管理是目標(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ù):
- 取得某員工的當(dāng)月的所有打卡數(shù)據(jù)
- 根據(jù)打卡數(shù)據(jù)統(tǒng)計(jì)日考勤數(shù)據(jù)存于日考勤表中
- 獲取該員工該月的日考勤數(shù)據(jù)
- 根據(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ì):
- 接口(可用)秸讹,分層(模塊)通過接口提供信息處理服務(wù),分層(模塊)可以有多個(gè)接口對(duì)應(yīng)多個(gè)信息處理服務(wù)雅倒。
- 調(diào)用(使用)璃诀,分層(模塊)可以使用其它分層(模塊)的接口進(jìn)行調(diào)用。
- 成分蔑匣,分層(模塊)由多個(gè)信息處理的成分構(gòu)成劣欢。
- 信息,分層(模塊)可以有直接管理的信息裁良,即分層(模塊)可以具有一定的信息特征凿将,信息的數(shù)據(jù)可以是在外存儲(chǔ)器或內(nèi)存儲(chǔ)器中,信息可以是基本數(shù)據(jù)類型价脾,也可以是數(shù)據(jù)集合牧抵,也可以是另一個(gè)分層(模塊)信息組。
- 信息規(guī)則侨把。每一個(gè)信息可以有一定的信息規(guī)則犀变,例如年齡一定是數(shù)字。信息與信息之間可以有信息規(guī)則秋柄,例如出生日期與年齡是有關(guān)聯(lián)的获枝。
- 信息隱蔽,分層(模塊)管理的信息可以對(duì)外部隱蔽骇笔,分層(模塊)管理的信息可以對(duì)外部隱蔽省店、分層(模塊)的信息規(guī)則處理細(xì)節(jié)是對(duì)外隱蔽,外部只能通過接口去訪問笨触,無法通過正常方式直接獲得隱蔽的信息以及處理細(xì)節(jié)中的臨時(shí)數(shù)據(jù)等懦傍,簡(jiǎn)單的講就是外部無法訪問其實(shí)現(xiàn)細(xì)節(jié)。
- 內(nèi)聚旭旭,分層(模塊)內(nèi)部組成成分的相關(guān)聯(lián)程度谎脯。
- 耦合,分層(模塊)間的關(guān)聯(lián)程度持寄,更具體的意思是分層(模塊)間在交換信息過程中可能存在破壞信息規(guī)則的程度
- 嵌套源梭,分層(模塊)的成分可以是分層模塊或任意類型模塊,即分層(模塊)可以包含分層模塊或任意類型模塊稍味。
- 層級(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)用。
數(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)存消耗為止。
主動(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ù)被回收處理粹断,但無法保證回收的算法性能足夠快符欠。
解決辦法:
- 通過持續(xù)的長(zhǎng)時(shí)間監(jiān)控垃圾回收機(jī)制,在回收相互引用的數(shù)據(jù)的回收量瓶埋,如有發(fā)現(xiàn)讓開發(fā)人員在代碼中繼續(xù)尋找未主動(dòng)回收的相互引用的數(shù)據(jù)希柿,如有發(fā)現(xiàn)使用弱引用處理。
- 通過宏觀管理的方式养筒,將系統(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):
- 保障每一個(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ù)替換即可。
- 保障每一個(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ù)辩诞,下期再見)