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

編程能力七段論

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

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

 前言

  程序員的編程技能隨著經(jīng)驗(yàn)的積累,會(huì)逐步提高。我認(rèn)為編程能力可以分為一些層次。

  下面通過(guò)兩個(gè)維度展開(kāi)編程能力層次模型的討論。

  一個(gè)維度是編程技能層次,另一個(gè)維度是領(lǐng)域知識(shí)層次。

 編程技能層次

  編程技能層次,指的程序員設(shè)計(jì)和編寫程序的能力。這是程序員的根本。

  0段—非程序員:

  初學(xué)編程者,遇到問(wèn)題,完全是懵懵懂懂,不知道該怎么編程解決問(wèn)題。也就是說(shuō),還是門外漢,還不能稱之為“程序員”。計(jì)算機(jī)在他面前還是一個(gè)神秘的黑匣子。

  1段—基礎(chǔ)程序員:

  學(xué)習(xí)過(guò)一段時(shí)間編程后,接到任務(wù),可以編寫程序完成任務(wù)。

  編寫出來(lái)的代碼,正常情況下是能夠工作的,但在實(shí)際運(yùn)行中,碰到一些特殊條件就會(huì)出現(xiàn)各類BUG。也就是說(shuō),具備了開(kāi)發(fā)Demo軟件的能力,但開(kāi)發(fā)的軟件真正交付給客戶使用,恐怕會(huì)被客戶罵死。

  程序員程序是寫好了,但到底為什么它有時(shí)能正常工作,有時(shí)又不行,程序員自己也不知道。

  運(yùn)行中遇到了bug,或者需求改變,需要修改代碼或者添加代碼,很快程序就變得結(jié)構(gòu)混亂,代碼膨脹,bug叢生。很快,就連最初的開(kāi)發(fā)者自己也不愿意接手維護(hù)這個(gè)程序了。

  2段—數(shù)據(jù)結(jié)構(gòu):

  經(jīng)過(guò)一段時(shí)間的編程實(shí)踐后,程序員會(huì)認(rèn)識(shí)到“數(shù)據(jù)結(jié)構(gòu)+算法=程序”這一古訓(xùn)的含義。他們會(huì)使用算法來(lái)解決問(wèn)題。進(jìn)而,他們會(huì)認(rèn)識(shí)到,算法本質(zhì)上是依附于數(shù)據(jù)結(jié)構(gòu)的,好的數(shù)據(jù)結(jié)構(gòu)一旦設(shè)計(jì)出來(lái),那么好的算法也會(huì)應(yīng)運(yùn)而生。

  設(shè)計(jì)錯(cuò)誤的數(shù)據(jù)結(jié)構(gòu),不可能生長(zhǎng)出好的算法。

  記得某一位外國(guó)先賢曾經(jīng)說(shuō)過(guò):“給我看你的數(shù)據(jù)結(jié)構(gòu)!”

  3段—面向?qū)ο螅?/h3>

  再之后,程序員就會(huì)領(lǐng)略面向?qū)ο蟪绦蛟O(shè)計(jì)的強(qiáng)大威力。大多數(shù)現(xiàn)代編程語(yǔ)言都是支持面向?qū)ο蟮。但并不是說(shuō),你使用面向?qū)ο缶幊陶Z(yǔ)言編程,你用上了類,甚至繼承了類,你就是在寫面向?qū)ο蟮拇a了。

  我曾經(jīng)見(jiàn)過(guò)很多用Java,Python,Ruby寫的面向過(guò)程的代碼。

  只有你掌握了接口,掌握了多態(tài),掌握了類和類,對(duì)象和對(duì)象之間的關(guān)系,你才真正掌握了面向?qū)ο缶幊碳夹g(shù)。

  就算你用的是傳統(tǒng)的不支持面向?qū)ο蟮木幊陶Z(yǔ)言,只要你心中有“對(duì)象”,你依然可以開(kāi)發(fā)出面向?qū)ο蟮某绦颉?/p>

  如,我用C語(yǔ)言編程的時(shí)候,會(huì)有意識(shí)的使用面向?qū)ο蟮募记蓙?lái)編寫和設(shè)計(jì)程序。用struct來(lái)模擬類,把同一類概念的函數(shù)放在一起模擬類。如果你懷疑用C語(yǔ)言是否能編寫出面向?qū)ο蟮拇a,你可以看一下Linux內(nèi)核,它是用C語(yǔ)言編寫的,但你也可以看到它的源代碼字里行間散發(fā)出的濃濃的“對(duì)象”的味道。

  真正掌握面向?qū)ο缶幊碳夹g(shù)并不容易。

  在我的技術(shù)生涯中,有兩個(gè)坎讓我最感頭疼。

  一個(gè)坎是Dos向Windows開(kāi)發(fā)的變遷過(guò)程中,框架的概念,很長(zhǎng)一段時(shí)間我都理解不了。Dos時(shí)代,都是對(duì)函數(shù)庫(kù)的調(diào)用,你的程序主動(dòng)調(diào)用函數(shù)。Windows時(shí)代,則換成了框架。就算是你的main程序,其實(shí)也是被框架調(diào)用的。UI線程會(huì)從操作系統(tǒng)獲取消息,然后發(fā)送給你的程序來(lái)處理。Java程序員熟悉的Spring框架,也是這樣一個(gè)反向調(diào)用的框架。

  現(xiàn)在因?yàn)?ldquo;框架”這個(gè)術(shù)語(yǔ)顯得很高大上,因此很多“類庫(kù)”/“函數(shù)庫(kù)”都自稱為“框架”。在我看來(lái)這都是名稱的濫用。

  “類庫(kù)”/“函數(shù)庫(kù)”就是我寫的代碼調(diào)用它們。

  “框架”就是我注冊(cè)回調(diào)函數(shù)到框架,框架來(lái)調(diào)用我寫的函數(shù)。

  另一個(gè)坎就是面向?qū)ο蟆:荛L(zhǎng)一段時(shí)間我都不知道應(yīng)該怎么設(shè)計(jì)類和類之間的關(guān)系,不能很好的設(shè)計(jì)出類層次結(jié)構(gòu)來(lái)。

  我記得當(dāng)時(shí)看到一本外國(guó)大牛的書,他講了一個(gè)很簡(jiǎn)單、很實(shí)用的面向?qū)ο笤O(shè)計(jì)技巧:“敘述問(wèn)題。然后把其中的名詞找出來(lái),用來(lái)構(gòu)建類。把其中的動(dòng)詞找出來(lái),用來(lái)構(gòu)建類的方法”。雖然這個(gè)技巧挺管用的,但也太草根了點(diǎn),沒(méi)有理論依據(jù),也不嚴(yán)謹(jǐn)。如果問(wèn)題敘述的不好,那么獲得的類系統(tǒng)就會(huì)是有問(wèn)題的。

  掌握面向?qū)ο笏枷氲耐緩綉?yīng)該有很多種,我是從關(guān)系數(shù)據(jù)庫(kù)中獲得了靈感來(lái)理解和掌握面向?qū)ο笤O(shè)計(jì)思想的。

  在我看來(lái),關(guān)系數(shù)據(jù)庫(kù)的表,其實(shí)就是一個(gè)類,每一行記錄就是一個(gè)類的實(shí)例,也就是對(duì)象。表之間的關(guān)系,就是類之間的關(guān)系。O-Rmapping技術(shù)(如Hibernate),用于從面向?qū)ο蟠a到數(shù)據(jù)庫(kù)表之間的映射,這也說(shuō)明了類和表確實(shí)是邏輯上等價(jià)的。

  既然數(shù)據(jù)庫(kù)設(shè)計(jì)和類設(shè)計(jì)是等價(jià)的,那么要設(shè)計(jì)面向?qū)ο笙到y(tǒng),只需要使用關(guān)系數(shù)據(jù)庫(kù)的設(shè)計(jì)技巧即可。

  關(guān)系數(shù)據(jù)庫(kù)表結(jié)構(gòu)設(shè)計(jì)是很簡(jiǎn)單的:

  1,識(shí)別表和表之間的關(guān)系,也就是類和類之間的關(guān)系。是一對(duì)一,一對(duì)多,多對(duì)一,還是多對(duì)多。這就是類之間的關(guān)系。

  2,識(shí)別表的字段。一個(gè)對(duì)象當(dāng)然有無(wú)數(shù)多的屬性(如,人:身高,體重,性別,年齡,姓名,身份證號(hào),駕駛證號(hào),銀行卡號(hào),護(hù)照號(hào),港澳通行證號(hào),工號(hào),病史,婚史etc),我們寫程序需要記錄的只是我們關(guān)心的屬性。這些關(guān)心的屬性,就是表的字段,也就是類的屬性。“弱水三千,我取一瓢飲”!

  4段—設(shè)計(jì)模式:

  曾經(jīng)在網(wǎng)上看到這樣一句話:“沒(méi)有十萬(wàn)行代碼量,就不要跟我談什么設(shè)計(jì)模式”。深以為然。

  記得第一次看Gof的設(shè)計(jì)模式那本書的時(shí)候,發(fā)現(xiàn)雖然以前并不知道設(shè)計(jì)模式,但在實(shí)際編程過(guò)程中,其實(shí)還是自覺(jué)使用了一些設(shè)計(jì)模式。設(shè)計(jì)模式是編程的客觀規(guī)律,不是誰(shuí)發(fā)明的,而是一些早期的資深程序員首先發(fā)現(xiàn)的。

  不用設(shè)計(jì)模式,你也可以寫出滿足需求的程序來(lái)。但是,一旦后續(xù)需求變化,那么你的程序沒(méi)有足夠的柔韌性,將難以為繼。而真實(shí)的程序,交付客戶后,一定會(huì)有進(jìn)一步的需求反饋。而后續(xù)版本的開(kāi)發(fā),也一定會(huì)增加需求。這是程序員無(wú)法回避的現(xiàn)實(shí)。

  寫UI程序,不論是Web,Desktop,Mobile,Game,一定要使用MVC設(shè)計(jì)模式。否則你的程序面對(duì)后續(xù)變化的UI需求,將無(wú)以為繼。

  設(shè)計(jì)模式,最重要的思想就是解耦,通過(guò)接口來(lái)解耦。這樣,如果將來(lái)需求變化,那么只需要提供一個(gè)新的實(shí)現(xiàn)類即可。

  主要的設(shè)計(jì)模式,其實(shí)都是面向?qū)ο蟮。因此,可以認(rèn)為設(shè)計(jì)模式是面向?qū)ο蟮母呒?jí)階段。只有掌握了設(shè)計(jì)模式,才能認(rèn)為是真正徹底掌握了面向?qū)ο笤O(shè)計(jì)技巧。

  我學(xué)習(xí)一門新語(yǔ)言時(shí)(包括非面向?qū)ο笳Z(yǔ)言,如函數(shù)式編程語(yǔ)言),總是會(huì)在了解了其語(yǔ)法后,看一下各類設(shè)計(jì)模式在這門語(yǔ)言中是如何實(shí)現(xiàn)的。這也是學(xué)習(xí)編程語(yǔ)言的一個(gè)竅門。

  5段--語(yǔ)言專家:

  經(jīng)過(guò)一段時(shí)間的編程實(shí)踐,程序員對(duì)某一種常用的編程語(yǔ)言已經(jīng)相當(dāng)精通了。有些人還成了“語(yǔ)言律師”,擅長(zhǎng)向其他程序員講解語(yǔ)言的用法和各種坑。

  這一階段的程序員,常常是自己所用語(yǔ)言的忠實(shí)信徒,常在社區(qū)和論壇上和其他語(yǔ)言的使用者爭(zhēng)論哪一種語(yǔ)言是最好的編程語(yǔ)言。他們認(rèn)為自己所用的語(yǔ)言是世界上最好的編程語(yǔ)言,沒(méi)有之一。他們認(rèn)為,自己所用的編程語(yǔ)言適用于所有場(chǎng)景。他們眼中,只有錘子,因此會(huì)把所有任務(wù)都當(dāng)成是釘子。

  6段--多語(yǔ)言專家:

  這一個(gè)階段的程序員,因?yàn)楣ぷ麝P(guān)系,或者純粹是因?yàn)閷?duì)技術(shù)的興趣,已經(jīng)學(xué)習(xí)和掌握了好幾種編程語(yǔ)言。已經(jīng)領(lǐng)略了不同編程語(yǔ)言不同的設(shè)計(jì)思路,對(duì)每種語(yǔ)言的長(zhǎng)處和短處有了更多的了解。

  他們現(xiàn)在認(rèn)為,編程語(yǔ)言并不是最重要的,編程語(yǔ)言不過(guò)是基本功而已。

  他們現(xiàn)在會(huì)根據(jù)不同的任務(wù)需求,或者不同的資源來(lái)選擇不同的編程語(yǔ)言來(lái)解決問(wèn)題,不再會(huì)因?yàn)闆](méi)有使用某一種喜愛(ài)的編程語(yǔ)言開(kāi)發(fā)而埋怨。

  編程語(yǔ)言有很多種流派和思想,有一些編程語(yǔ)言同時(shí)支持多種編程范式。

  靜態(tài)類型編程范式

  采用靜態(tài)類型編程范式的編程語(yǔ)言,其變量需要明確指定類型。代表語(yǔ)言:C,C++,Pascal,Objective-C,Java,C#,VB.NET,Swif,Golang。

  這樣做的好處是:

  1,編譯器可以在編譯時(shí)就能找出類型錯(cuò)誤。

  2,編譯器編譯時(shí)知道類型信息,就可以提高性能。

         這種范式認(rèn)為,程序員肯定知道變量的類型,你丫要是不知道變量的類型,那你就別混了!編譯時(shí),程序會(huì)報(bào)錯(cuò)。

        Swift和Go語(yǔ)言都是靜態(tài)類型編程語(yǔ)言,但它們都不需要明確指定類型,而是可以通過(guò)推斷由編譯器自動(dòng)確定其類型。

  動(dòng)態(tài)類型編程范式

  采用靜態(tài)類型編程范式的編程語(yǔ)言,其變量不需要明確指定類型。任意變量,可以指向任意類型的對(duì)象。代表語(yǔ)言:Python,Ruby,JavaScript。

  動(dòng)態(tài)類型的哲學(xué)可以用鴨子類型(英語(yǔ):ducktyping)這個(gè)概念來(lái)概括。JamesWhitcombRiley提出的鴨子測(cè)試可以這樣表述:“當(dāng)看到一只鳥(niǎo)走起來(lái)像鴨子、游泳起來(lái)像鴨子、叫起來(lái)也像鴨子,那么這只鳥(niǎo)就可以被稱為鴨子。”

  這種范式認(rèn)為,程序員肯定知道變量的類型和它支持的方法和屬性,你丫要是不知道變量的類型,那你就別混了!運(yùn)行時(shí)程序會(huì)崩潰!程序崩潰怨誰(shuí)?怨你自己?jiǎn)h,你不是合格的程序員!

  動(dòng)態(tài)類型的好處是:

  不需要明確定義接口和抽象類型。只要一個(gè)類型支持需要的方法和屬性,那么就OK。程序會(huì)相當(dāng)靈活和簡(jiǎn)單。C++,Java,C#視之為命脈的接口/基類,在動(dòng)態(tài)語(yǔ)言這里都視如無(wú)物!

  缺點(diǎn)是:

  1,如果類型不對(duì),編譯器也無(wú)法找到錯(cuò)誤,而是運(yùn)行時(shí)程序崩潰。

  2,因?yàn)榫幾g器不知道變量的類型,因此無(wú)法優(yōu)化性能。

  面向?qū)ο缶幊谭妒?/h3>

  面向?qū)ο缶幊谭妒,從上世紀(jì)70年代末開(kāi)始興起。它支持類和類的實(shí)例作為封裝代碼的模塊。代表語(yǔ)言:Smalltalk,C++,Objective-C,Java,C#,VB.NET,Swift,Go,Python,Ruby,ActionScritp,OCaml.

  早期編程語(yǔ)言都是面向過(guò)程的。就是順序,條件,循環(huán),構(gòu)成一個(gè)個(gè)函數(shù)。隨著代碼規(guī)模的增大,人們發(fā)現(xiàn)有必要對(duì)代碼進(jìn)行模塊化。一個(gè)概念對(duì)應(yīng)的代碼放在一個(gè)文件中,這樣便于并發(fā)開(kāi)發(fā)和進(jìn)行代碼管理。

  人們還發(fā)現(xiàn)了“程序=數(shù)據(jù)結(jié)構(gòu)+算法”的規(guī)律。因此,一個(gè)概念對(duì)應(yīng)的數(shù)據(jù)結(jié)構(gòu)和函數(shù)應(yīng)該放在一個(gè)文件中。這就是類的概念。

  面向?qū)ο缶幊谭妒,確實(shí)極大地提高了生產(chǎn)效率,因此得到了廣泛的應(yīng)用,因此在語(yǔ)言層面支持面向?qū)ο缶幊谭妒降恼Z(yǔ)言是極多的。

  C語(yǔ)言盡管在語(yǔ)言層面上并不支持面向?qū)ο缶幊谭妒,但現(xiàn)代的C語(yǔ)言開(kāi)發(fā)都會(huì)應(yīng)用面向?qū)ο蟮哪K化思想,把同一類的數(shù)據(jù)結(jié)構(gòu)和函數(shù)放在一個(gè)文件中,采用類似的命名方式。

  畢竟C語(yǔ)言沒(méi)有在語(yǔ)言層面上支持面向?qū)ο,因此就有很多程序員想給C語(yǔ)言添加面向?qū)ο笾С。其中的代表是C++和Objective-C。

  C++是一種新的語(yǔ)言,但大部分語(yǔ)言元素是和C兼容的。

  Objective-C是完全兼容的C的。Objective-C是給C添加了薄薄的一層語(yǔ)法糖以支持接口(就是其他語(yǔ)言的類)和協(xié)議(就是其他語(yǔ)言的接口)。甚至,Objective-C一開(kāi)始的實(shí)現(xiàn),就是一個(gè)C語(yǔ)言的預(yù)編譯器。Objective-C坦白講,除了添加的語(yǔ)法不太符合C流外,實(shí)際上其面向?qū)ο笙到y(tǒng)設(shè)計(jì)是相當(dāng)精妙的。喬布斯早年慧眼識(shí)珠,把Objective-C收人囊中,因?yàn)榉忾]于Apple/NextStep系統(tǒng)內(nèi),因此少有人知。隨著iOs系統(tǒng)的普及,Objective-C近幾年才名滿天下。

  函數(shù)式編程范式

  函數(shù)式編程范式,是一些數(shù)學(xué)家發(fā)明的編程語(yǔ)言,他們認(rèn)為程序就是數(shù)學(xué)函數(shù)嘛。代表語(yǔ)言:Lisp,Erlang,JavaScript,OCaml,Prog。

  有很多大牛極力鼓吹過(guò)函數(shù)式編程語(yǔ)言,認(rèn)為其極具革命性。但我認(rèn)為他們過(guò)高估計(jì)了函數(shù)式編程范式的威力,我并不認(rèn)為函數(shù)式編程范式相對(duì)于面向?qū)ο缶幊谭妒接泻胃呙髦帯?/p>

  函數(shù)式編程語(yǔ)言,核心就是函數(shù),它們沒(méi)有Class類的概念。但它的函數(shù)又不是傳統(tǒng)面向過(guò)程語(yǔ)言的函數(shù),它的函數(shù)支持“閉包”的概念。

  在我看來(lái),函數(shù)式編程語(yǔ)言的函數(shù),也就是“閉包”,說(shuō)白了,其實(shí)就是“類”。編程語(yǔ)言發(fā)展到今天,就是需要模塊化,就是需要把“數(shù)據(jù)結(jié)構(gòu)”和“算法”結(jié)合起來(lái)。不論何種語(yǔ)言,不把它們結(jié)合起來(lái)的編程方式,都是沒(méi)有出路的。

  面向?qū)ο缶幊陶Z(yǔ)言,用類把“數(shù)據(jù)結(jié)構(gòu)”和“算法”結(jié)合起來(lái)。類的核心是“數(shù)據(jù)結(jié)構(gòu)”,也就是其“屬性”,而不是“算法”,其“函數(shù)”。在類中,是函數(shù)依附于屬性。

  而函數(shù)式編程語(yǔ)言,用閉包把“數(shù)據(jù)結(jié)構(gòu)”和“算法”結(jié)合起來(lái)。是函數(shù)能夠抓取外部的字段。是“屬性”依附于“函數(shù)”。

  “類”本質(zhì)上和“閉包”是等價(jià)的,F(xiàn)在很多面向?qū)ο缶幊陶Z(yǔ)言都加上了對(duì)閉包的支持。觀察其代碼,我們可以發(fā)現(xiàn),它們實(shí)際上都是用“類”來(lái)實(shí)現(xiàn)“閉包”的。

  “類”和“閉包”誰(shuí)更易用?明顯是“類”。

  而“閉包”更簡(jiǎn)潔一些,因此“閉包”在面向?qū)ο缶幊陶Z(yǔ)言中常用來(lái)替換匿名類。只有一個(gè)函數(shù)的類,寫成一個(gè)類太麻煩,不如寫成閉包,更加簡(jiǎn)潔。

  吐槽一下OCaml語(yǔ)言,其前身Caml語(yǔ)言本身是一種挺好的函數(shù)式語(yǔ)言,硬生生添加了一套完整的面向?qū)ο髾C(jī)制,同時(shí)支持面向?qū)ο蠛秃瘮?shù)式編程范式,很容易像C++一樣腦裂的。

  也有很多面向?qū)ο笳Z(yǔ)言控看著JavaScript嫌煩,總是想把面向?qū)ο笾С痔砑拥絁avaScript上。ActionScript就是其中一種嘗試。我用過(guò),真的是和Java沒(méi)多少區(qū)別了。

  再吐槽一下ExtJS。當(dāng)初選型Web前端開(kāi)發(fā)框架時(shí)比較了ExtJS和JQuery。

  ExtJS明顯是Java高手開(kāi)發(fā)的,硬生生用JavaScript模擬Swing的設(shè)計(jì)思想,搞了一套UI庫(kù)。

  JQuery開(kāi)發(fā)者明顯是領(lǐng)悟了JavaScript的函數(shù)式編程范式,依據(jù)JavaScript的動(dòng)態(tài)函數(shù)式編程語(yǔ)言的特點(diǎn)打造了一套UI庫(kù),立刻秒殺ExtJS。

  由ExtJS和JQuery的故事,我們可以看到多語(yǔ)言編程能力是多么的重要。ExtJS的作者精通并喜愛(ài)Java,因此他把手術(shù)刀JavaScript當(dāng)做錘子Java使,一通亂敲,費(fèi)力不討好。

  函數(shù)式編程語(yǔ)言,還有尾遞歸等一些小技巧。尾遞歸可以不用棧,防止遞歸調(diào)用時(shí)棧溢出。

  模板編程范式

  模板編程,就是把類型作為參數(shù),一套函數(shù)可以支持任意多種類型。代表語(yǔ)言:C++。

  模板編程的需求,是在C++開(kāi)發(fā)容器庫(kù)的時(shí)候發(fā)明的。因?yàn)槿萜餍枰4嫒我忸愋偷膶?duì)象,因此就有了泛型的需求。

  C++的模板編程,是在編譯時(shí),根據(jù)源碼中的使用情況,創(chuàng)建對(duì)應(yīng)類型的代碼。除了C++這種方式,Java,C#也有類似的機(jī)制,叫做“泛型”,但它們的實(shí)現(xiàn)方式和C++的模板很不同。它們的編譯器不會(huì)生成新的代碼,而是使用強(qiáng)制類型轉(zhuǎn)換的方式實(shí)現(xiàn)。

  在沒(méi)有模板/泛型的編程語(yǔ)言中,怎樣在容器中存放對(duì)象呢?存取公共基類類型(Java,C#)的對(duì)象,或者void*指針(C)即可,取出時(shí)自己強(qiáng)制類型轉(zhuǎn)換為實(shí)際類型。動(dòng)態(tài)類型語(yǔ)言,不關(guān)心類型,更是無(wú)所謂了,隨便什么對(duì)象直接往容器里扔進(jìn)去,取出來(lái)直接用即可。

  一些C++高手又在模板的基礎(chǔ)上搞出了“模板元編程”。因?yàn)槟0寰幊蹋褪荂++的編譯器搞定的嘛,模板元編程就是讓編譯器運(yùn)算,編譯完結(jié)果也就算出來(lái)了。我不知道除了研究和炫技,這玩意有啥用?

  小結(jié)

  一門語(yǔ)言是否值得學(xué)習(xí),我認(rèn)為有幾個(gè)標(biāo)準(zhǔn):

  1,是否要用,要用就得學(xué),這么沒(méi)有疑問(wèn)的。畢竟我們都要吃飯的嘛。

  2,其語(yǔ)言特性是否給你耳目一新的感覺(jué)。如果是,那就值回票價(jià)了。如Go語(yǔ)言廢掉了異常,改用返回多值。我深以為然。我其實(shí)已經(jīng)主動(dòng)不用異常好多年了。因?yàn),我覺(jué)得既然C不支持異常也活得很好,為什么需要異常呢?出錯(cuò)了,返回錯(cuò)誤碼。無(wú)法挽回的錯(cuò)誤,直接Abort程序就可以嘛!而且,異常實(shí)際上是違反面向過(guò)程編程原則的。一個(gè)函數(shù)應(yīng)該只有一個(gè)入口一個(gè)出口。拋出異常就多了出口了。

  3,是否擅長(zhǎng)某一個(gè)領(lǐng)域。如果你手里只有一把錘子,那么你就只能把所有任務(wù)都當(dāng)做釘子猛錘一通。但如果工具箱里有多種工具,那面對(duì)不同的任務(wù)就得心應(yīng)手多了。

  7段—架構(gòu)設(shè)計(jì)

  還需要掌握架構(gòu)設(shè)計(jì)的能力,才能設(shè)計(jì)出優(yōu)秀的軟件。架構(gòu)設(shè)計(jì)有一些技巧:

  1,分層

  一個(gè)軟件通常分為:

  表現(xiàn)層--UI部分

  接口層--后臺(tái)服務(wù)的通訊接口部分

  服務(wù)層--實(shí)際服務(wù)部分

  存儲(chǔ)層—持久化存儲(chǔ)部分,存儲(chǔ)到文件或者數(shù)據(jù)庫(kù)。

        分層的軟件,可以解耦各個(gè)模塊,支持并行開(kāi)發(fā),易于修改,易于提升性能。

  2,SOA

  模塊之間通過(guò)網(wǎng)絡(luò)通訊互相連接,松耦合。每一個(gè)模塊可以獨(dú)立部署,可以增加部署實(shí)例從而提高性能。每一個(gè)模塊可以使用不同的語(yǔ)言和平臺(tái)開(kāi)發(fā),可以重用之前開(kāi)發(fā)的服務(wù)。SOA,常用協(xié)議有WebService,REST,JSON-RPC等。

  3,性能瓶頸

  1)化同步為異步。

  用內(nèi)存隊(duì)列(Redis),工作流引擎(JBpm)等實(shí)現(xiàn)。內(nèi)存隊(duì)列容易丟失數(shù)據(jù),但是速度快。工作流引擎會(huì)把請(qǐng)求保存到數(shù)據(jù)庫(kù)中。

  通過(guò)化同步請(qǐng)求為異步請(qǐng)求,基本上99.99%的性能問(wèn)題都可以解決。

  2)用單機(jī)并行硬件處理。

  如,使用GPU,F(xiàn)PGA等硬件來(lái)處理,提高性能。

  3)用集群計(jì)算機(jī)來(lái)處理。

  如,Hadoop集群,用多臺(tái)計(jì)算機(jī)來(lái)并行處理數(shù)據(jù)。

  自己的軟件棧中,也可以把一個(gè)模塊部署多份,并行處理。

  4)用cache來(lái)滿足請(qǐng)求。常用的內(nèi)容加熱cache后,大量的用戶請(qǐng)求都只是內(nèi)存讀取數(shù)據(jù)而已,性能會(huì)得到很大的提升。

  cache是上帝算法,記得好像它的性能只比最佳性能低一些,就好像你是上帝,能夠預(yù)見(jiàn)未來(lái)一樣,F(xiàn)在X86CPU遇到了主頻限制,CPU提升性能的主要途徑就是增加高速Cache了。

  4,大系統(tǒng)小做

  遇到大型系統(tǒng)不要慌,把它切分成多個(gè)模塊,用多個(gè)小程序,通過(guò)SOA協(xié)作來(lái)解決。這秉承了Unix的設(shè)計(jì)思想。Unix上開(kāi)發(fā)了大量單一目的的小程序,它主張用戶通過(guò)管道來(lái)讓多個(gè)小程序協(xié)作,解決用戶的需求。當(dāng)然,管道方式通訊限制太多,不夠靈活。因此,現(xiàn)在我們可以通過(guò)URI,通過(guò)SOA的方式來(lái)讓多個(gè)程序協(xié)作。Andorid和iOS上的應(yīng)用程序,現(xiàn)在都是通過(guò)URI實(shí)現(xiàn)協(xié)作的。這也算是Unix設(shè)計(jì)思想的現(xiàn)代發(fā)展吧?!

  5,Sharding切片

  現(xiàn)在有一個(gè)潮流,就是去IOE。I-IBM大型機(jī),O-Oracle數(shù)據(jù)庫(kù),E-EMC存儲(chǔ)。之前,大型系統(tǒng)常用IOE去架構(gòu),在大型機(jī)上部署一個(gè)Oracle數(shù)據(jù)庫(kù),Oracle數(shù)據(jù)庫(kù)用EMC存儲(chǔ)保存數(shù)據(jù)。IOE是當(dāng)今最強(qiáng)的計(jì)算機(jī),數(shù)據(jù)庫(kù)和存儲(chǔ)。但他們面對(duì)海量系統(tǒng)也有抗不住的一天。

  Oracle數(shù)據(jù)庫(kù)是Shareeverything的,它可以在一個(gè)計(jì)算機(jī)集群(服務(wù)器節(jié)點(diǎn)不能超過(guò)16個(gè))上運(yùn)行。計(jì)算機(jī)集群都共用一個(gè)存儲(chǔ)。

  去IOE運(yùn)動(dòng),標(biāo)志著ShareEverything模式的破產(chǎn)。必須使用ShareNothing,系統(tǒng)才能無(wú)限擴(kuò)展。

  用MySQL數(shù)據(jù)庫(kù)就可以應(yīng)付任意規(guī)模的數(shù)據(jù)了。前提是,你會(huì)Sharding分片。把大系統(tǒng)切分成若干個(gè)小系統(tǒng),切分到若干臺(tái)廉價(jià)服務(wù)器和存儲(chǔ)上。更Modern一些,就是切分到大量虛擬機(jī)上。

  如,鐵道部的12306網(wǎng)站。我們知道火車票都是從屬于某一列列車的。那么我們把每一個(gè)列車作為一個(gè)單元來(lái)切分,就可以把12306網(wǎng)站切分成幾千個(gè)模塊。一臺(tái)虛擬機(jī)可以承載若干個(gè)模塊。當(dāng)某些列車成為性能瓶頸之后,就可以把它們遷移到獨(dú)立的虛擬機(jī)上。即使最終有部分列出服務(wù)不可用,系統(tǒng)也不會(huì)完全不可用。

  12306網(wǎng)站,只有一個(gè)全局的部分,就是用戶登錄。這個(gè)可以交給第三方負(fù)責(zé)。如可以讓用戶用微信,微博,qq等賬戶登錄。

  也可以自己實(shí)現(xiàn)用戶登錄服務(wù)。還是用切片的方式用多臺(tái)Redis服務(wù)器提供服務(wù)。Redis服務(wù)器存儲(chǔ)每一個(gè)登錄用戶的sessionId和userId,角色,權(quán)限等信息。sessionId是隨機(jī)生成的,可選擇其部分bit用于標(biāo)識(shí)它在哪一個(gè)Redis服務(wù)器上。用戶登錄后,把sessionId發(fā)給客戶。用戶每次請(qǐng)求時(shí)把sessionId發(fā)回給服務(wù)器。服務(wù)器把sessionId發(fā)給Redis服務(wù)器查詢得到其用戶信息,對(duì)用戶請(qǐng)求進(jìn)行處理。如果在redis服務(wù)器上找不到sessionId,則讓用戶去登錄。即使所有注冊(cè)用戶同時(shí)登陸,也不需要太多的內(nèi)存。而且,可以在session內(nèi)存過(guò)多時(shí),刪除最早登陸的用戶的session,強(qiáng)制他再次登陸。同時(shí)活躍的用戶數(shù)不會(huì)太多。

 領(lǐng)域知識(shí)層次

  前面的所有層次,都是關(guān)注編程本身的技能,說(shuō)白了,就是基本功,本身并不能產(chǎn)生太大的價(jià)值。但有太多的程序員浪費(fèi)太多的時(shí)間在那些筑基的層次上。

  有些程序員特別喜歡鉆研編程語(yǔ)言,每有一種新的編程語(yǔ)言出來(lái)或者舊語(yǔ)言被熱炒,就會(huì)投入精力進(jìn)去研究。我就是其中之一,浪費(fèi)了很多精力在編程語(yǔ)言上,在奇技淫巧上。

  我覺(jué)得C++語(yǔ)言是一個(gè)特別大的坑。剛開(kāi)始是作為面向?qū)ο蟮腃被開(kāi)發(fā)的。后來(lái)發(fā)現(xiàn)了模板編程,就大力鼓吹模板編程和進(jìn)一步的模板元編程。最近又推出了C++11,C++14等新標(biāo)準(zhǔn),進(jìn)一步添加了很多新東西,函數(shù)式編程,類型推斷等。C++過(guò)分復(fù)雜,太多的坑消耗了大量程序員的大量精力。我使用C++時(shí),只使用面向?qū)ο蟛糠趾湍0宀糠,其他過(guò)于精深的特性都不使用。

  計(jì)算機(jī)科學(xué)是一個(gè)面相當(dāng)廣泛的學(xué)科,有很多領(lǐng)域知識(shí)需要和值得我們深入研究,我們才能寫出有價(jià)值的程序來(lái)。軟件必須要和行業(yè)結(jié)合起來(lái),要落地才有價(jià)值。僅僅研究編程技巧,不懂領(lǐng)域知識(shí)是寫不出有價(jià)值的程序的。

  計(jì)算機(jī)科學(xué)領(lǐng)域有很多,列舉一些如下:

  存儲(chǔ)----塊設(shè)備,文件系統(tǒng),集群文件系統(tǒng),分布式文件系統(tǒng),光纖SCSI,iSCSI,RAID等。

  網(wǎng)絡(luò)----以太網(wǎng),光纖網(wǎng),蜂窩網(wǎng)絡(luò),WIFI,VLAN等。

  計(jì)算機(jī)體系結(jié)構(gòu),主要就是CPU指令集。x86,ARM等。

  USB協(xié)議。需要知道URB包。

  PCI協(xié)議,PCI-E協(xié)議,F(xiàn)代計(jì)算機(jī)的外設(shè)都是PCI協(xié)議和PCI-E協(xié)議的。顯卡現(xiàn)在全是通過(guò) PCI-E協(xié)議連接到計(jì)算機(jī)上的。相對(duì)來(lái)說(shuō)減少了很多需要學(xué)習(xí)的知識(shí)。搞虛擬化就需要深入掌握PCI協(xié)議。

  圖像處理--圖像壓縮,視頻實(shí)時(shí)編碼等。

  3D游戲

  關(guān)系數(shù)據(jù)庫(kù)

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

  操作系統(tǒng)

  分布式操作系統(tǒng)

  編譯原理

  機(jī)器學(xué)習(xí)--現(xiàn)在大數(shù)據(jù)要用哦!

  了解這些領(lǐng)域知識(shí),也包括了解該領(lǐng)域現(xiàn)有的商用硬件、商用軟件和開(kāi)源軟件。很多時(shí)候,你要完成的工作,已經(jīng)有現(xiàn)成的工具了。你只要使用現(xiàn)成的工具就可以完成任務(wù),不需要進(jìn)行開(kāi)發(fā)。有時(shí)候,只需要組合現(xiàn)有的工具,寫一些腳本就可以完成任務(wù)。

  如,我一次要實(shí)現(xiàn)一個(gè)雙向同步任務(wù)。找到了一個(gè)優(yōu)秀的開(kāi)源軟件Unison,編寫一下配置文件就圓滿地完成了任務(wù)。不需要編寫任何代碼。

  還有一次,要做高可用,用Python調(diào)用了幾個(gè)開(kāi)源軟件就輕松實(shí)現(xiàn)了。

  編寫安裝程序,定制操作系統(tǒng),知道了操作系統(tǒng)的領(lǐng)域知識(shí),寫幾行腳本就可以輕松搞定。

  不具備領(lǐng)域知識(shí)的人,就可能不得不進(jìn)行大量無(wú)謂的開(kāi)發(fā),甚至開(kāi)發(fā)很久之后才發(fā)現(xiàn),這根本就是一條死路。 

  另外,扎實(shí)的領(lǐng)域知識(shí),可以大大提高編程調(diào)試、查錯(cuò)的能力。知道編譯器和編程語(yǔ)言運(yùn)行時(shí)工作原理,就能快速根據(jù)編譯錯(cuò)誤和警告信息修改代碼。

  知道操作系統(tǒng)底層運(yùn)行機(jī)制,就能快速找到運(yùn)行時(shí)錯(cuò)誤的問(wèn)題根源。如,有一次我編寫一個(gè)windows升級(jí)服務(wù)程序。它是一個(gè)windows服務(wù),需要執(zhí)行dos腳本,這個(gè)腳本會(huì)替換掉這個(gè)windows服務(wù)本身。發(fā)現(xiàn)有時(shí)腳本執(zhí)行無(wú)效,查了一晚上,發(fā)現(xiàn)當(dāng)windows服務(wù)安裝后,第一次啟動(dòng)就執(zhí)行腳本時(shí)就會(huì)有權(quán)限問(wèn)題,log都正確,但實(shí)際執(zhí)行這個(gè)腳本沒(méi)有任何效果。但一旦windows服務(wù)程序啟動(dòng)一次之后就ok。這必然是windows操作系統(tǒng)底層安全機(jī)制的問(wèn)題,因?yàn)槲覍?duì)Windows內(nèi)核了解不多,因此花了很長(zhǎng)時(shí)間才發(fā)現(xiàn)這個(gè)問(wèn)題,并對(duì)造成這個(gè)問(wèn)題的根源并不清楚。

  0段—領(lǐng)域知識(shí)菜鳥(niǎo)

  對(duì)領(lǐng)域知識(shí)沒(méi)有多少認(rèn)知,通過(guò)搜索引擎找到一些該領(lǐng)域的軟件和硬件的介紹性文章,按照文章指示配置和使用軟件。勉強(qiáng)能夠使用現(xiàn)有軟硬件。

  1段—領(lǐng)域知識(shí)行家

  了解領(lǐng)域內(nèi)常用硬件,深入掌握領(lǐng)域內(nèi)常用軟件的配置和使用技巧。能夠使用現(xiàn)有軟硬件熟練搭建解決方案,能夠解決實(shí)際工作中遇到的種種問(wèn)題。

  2段—領(lǐng)域知識(shí)專家

  當(dāng)你不僅僅掌握了該領(lǐng)域的軟件和工具,知道怎么用,還知道其原理,“知其然,也知其所以然”,就是該領(lǐng)域的知識(shí)專家了。

  你知道網(wǎng)絡(luò)協(xié)議的原理,你才能在網(wǎng)絡(luò)出現(xiàn)問(wèn)題時(shí)知道是哪里可能出現(xiàn)了問(wèn)題。是mac沖突,ip沖突,還是網(wǎng)絡(luò)環(huán)路?

  你知道存儲(chǔ)的原理,你才能知道為什么這種存儲(chǔ)方式不適合虛擬化,那種存儲(chǔ)方式適合虛擬化,另一種方式適合資料備份。

  你知道PCI協(xié)議,你才能知道你怎樣才能虛擬化一個(gè)硬件設(shè)備。

  你知道網(wǎng)卡硬件協(xié)議,你才能模擬出一個(gè)虛擬機(jī)能正常使用的虛擬網(wǎng)卡。

  你知道視頻編碼格式和原理,才能知道什么視頻格式占用帶寬最少,什么視頻格式占用CPU最少。

  你了解IntelVT/Amd V指令集,才能知道虛擬化是怎樣實(shí)現(xiàn)的。

  你明白工作流其實(shí)就是狀態(tài)機(jī),在遇到復(fù)雜工作流程時(shí),你才能知道怎樣設(shè)計(jì)滿足要求的工作流引擎。

  3段—科學(xué)家

  你是領(lǐng)域知識(shí)專家,但你的知識(shí)都是來(lái)自于書本,來(lái)自于其他人的。

  如果你滿足于當(dāng)領(lǐng)域知識(shí)專家,你只能拾人牙慧,永遠(yuǎn)別想超越。別人的研究成果,未必愿意告訴你。當(dāng)別人告訴你的時(shí)候,它可能已經(jīng)發(fā)現(xiàn)了更新的理論,并且新一代產(chǎn)品可能馬上就要發(fā)布了。

  科學(xué)家是探索未知,勇于創(chuàng)新的人,是推動(dòng)人類社會(huì)進(jìn)步的人。

  傳說(shuō),思科的一位高管曾經(jīng)半開(kāi)玩笑地說(shuō)過(guò):“如果思科停止了新技術(shù)的研發(fā),華為就會(huì)找不著方向”。這是在嘲笑華為只是處在領(lǐng)域知識(shí)專家的水平,只能山寨無(wú)法超越。我不知道華為的實(shí)際情況,但希望現(xiàn)在的華為已經(jīng)走到了領(lǐng)跑者的位置。

  歐文·雅各布斯發(fā)現(xiàn)了CDMA碼分多址的原理,并發(fā)現(xiàn)它在通訊上大有可為,組建了高通公司。高通公司主要以專利授權(quán)費(fèi)為生,它雇傭了大量科學(xué)家在通訊領(lǐng)域展開(kāi)研究。有人說(shuō)高通是專利流氓。這些人不明白知識(shí)的價(jià)值。在他們眼里,Windows的合理價(jià)格就應(yīng)該是5元錢,一張光盤的價(jià)格。iPhone就應(yīng)該是1000多元裸機(jī)的價(jià)格。高通是專利流氓,那你也流氓一個(gè)CDMA,LTE出來(lái)給我看看!

  X86芯片在設(shè)計(jì)上沒(méi)有考慮虛擬化。因此會(huì)有所謂的“虛擬化漏洞”出現(xiàn)。就是說(shuō),一些CPU特權(quán)指令執(zhí)行時(shí),在虛擬機(jī)環(huán)境下不會(huì)拋出異常,因此就無(wú)法切換到Host。這樣,X86芯片上就無(wú)法運(yùn)行虛擬機(jī)。

  VmWare公司是由美國(guó)的幾位科學(xué)家在1998年創(chuàng)建的。他們發(fā)現(xiàn)可以使用二進(jìn)制翻譯的技術(shù),在X86計(jì)算機(jī)上運(yùn)行虛擬機(jī)。

  Xen虛擬化軟件也是幾位科學(xué)家發(fā)明的。他們發(fā)現(xiàn)只要修改虛擬機(jī)操作系統(tǒng)和Host操作系統(tǒng)的內(nèi)核,在需要執(zhí)行“虛擬化漏洞”指令時(shí)直接調(diào)用Host的功能,就可以實(shí)現(xiàn)虛擬化,而且大大提高了虛擬機(jī)的運(yùn)行性能。

  后來(lái),Intel為自己的芯片添加了IntelVT指令集,Amd為自己的芯片添加了AmdV指令集,彌補(bǔ)了“虛擬化漏洞”。于是就有了KVM虛擬機(jī)軟件,它直接用CPU硬件指令實(shí)現(xiàn)虛擬化。 

  KVM在執(zhí)行CPU指令時(shí),是直接在物理CPU上運(yùn)行的,因此效率極高。但是,虛擬機(jī)運(yùn)行虛擬外設(shè)時(shí),就必須用軟件模擬,因此虛擬機(jī)的IO訪問(wèn)速度很慢。

  IBM科學(xué)家RustyRussell,借鑒了Xen的研發(fā)經(jīng)驗(yàn),創(chuàng)建了VirtIO技術(shù)。就是在虛擬機(jī)中編寫一套PCI虛擬設(shè)備和驅(qū)動(dòng),這套虛擬PCI設(shè)備有一塊虛擬設(shè)備內(nèi)存。這個(gè)虛擬設(shè)備內(nèi)存Host是可以訪問(wèn)的,虛擬機(jī)通過(guò)VirtIO驅(qū)動(dòng)程序也可以訪問(wèn)。也就是一塊內(nèi)存在虛擬機(jī)和Host中共享,這就解決了虛擬機(jī)的IO性能問(wèn)題。

  再講一個(gè)搜索引擎的故事:

  很久以前,我要給一個(gè)程序添加搜索功能。剛開(kāi)始使用sql查詢實(shí)現(xiàn),發(fā)現(xiàn)實(shí)在太慢了。后來(lái)找了開(kāi)源的Lucene項(xiàng)目。它使用反向索引技術(shù),通過(guò)在文件中創(chuàng)建反向索引,大大提高了搜索速度。

  Google的兩位創(chuàng)始人發(fā)現(xiàn)了html中l(wèi)ink的秘密,他們發(fā)現(xiàn)可以通過(guò)html頁(yè)面的link關(guān)系來(lái)為每一個(gè)html頁(yè)面設(shè)置權(quán)重。也就是PageRank算法。于是,Google的自動(dòng)搜索引擎擊敗了Yahoo人工分類的搜索引擎。

       OK,利用反向索引技術(shù)和PageRank,以及一個(gè)簡(jiǎn)單的html爬蟲(chóng)機(jī)器人,我們就可以創(chuàng)建一個(gè)搜索引擎了。但是,互聯(lián)網(wǎng)很大,每天產(chǎn)生大量新網(wǎng)頁(yè),要為整個(gè)互聯(lián)網(wǎng)建立反向索引是很困難的。

  若干年后Google又公開(kāi)了三篇論文:Googlefs,Mapreduce,Bigtable。于是Lucene項(xiàng)目的開(kāi)發(fā)者根據(jù)Google的Mapreduce論文開(kāi)發(fā)了Hadoop項(xiàng)目。MapReduce就是使用大量計(jì)算機(jī)存儲(chǔ)數(shù)據(jù)并計(jì)算,最后匯總結(jié)果。使用Hadoop+反向索引+PageRank,就可以創(chuàng)建搜索引擎了。Yahoo,Baidu等公司紛紛基于Hadoop開(kāi)發(fā)了自己的搜索引擎。

  但是,其他公司的搜索引擎效果還是沒(méi)法和Google相比。這一點(diǎn)我們程序員最清楚。像我,就總是翻墻出去,只為了Google一下。

  Google黑板報(bào)上發(fā)表了吳軍博士的一些文章,其中介紹了很多機(jī)器學(xué)習(xí)方面的知識(shí)。從文中可以知道,Google其實(shí)使用機(jī)器學(xué)習(xí)來(lái)分析搜集到的頁(yè)面。Google明顯不會(huì)把這個(gè)公式公開(kāi)出來(lái)。即使有一天Google真的公開(kāi)了這個(gè)公式,那么可以想見(jiàn)Google肯定又研發(fā)出了更加犀利的秘籍,山寨貨的搜索引擎效果還是比不上Google的。

  山寨是通向創(chuàng)新的必由之路。在成為領(lǐng)域的領(lǐng)頭羊和領(lǐng)導(dǎo)者之前,必然要經(jīng)過(guò)學(xué)習(xí),模仿的階段。但要成為行業(yè)的老大,成為Champion,必須勇于彎道超車,勇敢地走上創(chuàng)新之路,成為真正的科學(xué)家,真正的大牛! 

 總結(jié)

  編程能力可分為兩個(gè)維度:一個(gè)是編程技能水平,另一個(gè)是領(lǐng)域知識(shí)水平。

  有些程序員可能把精力都花在提升編程技能上了,領(lǐng)域知識(shí)知之甚少,這其實(shí)在日常工作中也是極其有害的。有些需求可能早已經(jīng)有了現(xiàn)成、開(kāi)源免費(fèi)的解決方案,或者只需要組合幾個(gè)現(xiàn)有軟件就可以快速搞定,而他們卻不得不自己花大量時(shí)間去開(kāi)發(fā)。另外,缺少領(lǐng)域知識(shí),在程序出現(xiàn)非預(yù)期狀況時(shí),很難快速定位到問(wèn)題的根源,很難解決bug。

標(biāo)簽: Google isp linux Mysql 安全 大數(shù)據(jù) 代碼 服務(wù)器 服務(wù)器存儲(chǔ) 互聯(lián)網(wǎng) 腳本 開(kāi)發(fā)者 漏洞 權(quán)限 數(shù)據(jù)庫(kù) 搜索 搜索引擎 網(wǎng)絡(luò)

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

上一篇:Java,傳奇的一生!

下一篇:10個(gè)所需的IT技能 助你職場(chǎng)成功