超清首页国产亚洲丝袜,日日摸日日碰夜夜爽亚洲,亚洲色欲久久久综合网http://www.tkk7.com/xixuui/category/14683.htmlzh-cnWed, 23 Jan 2008 18:22:05 GMTWed, 23 Jan 2008 18:22:05 GMT60一道看似簡單的面試題http://www.tkk7.com/xixuui/archive/2008/01/21/176849.html阿輝阿輝Mon, 21 Jan 2008 14:11:00 GMThttp://www.tkk7.com/xixuui/archive/2008/01/21/176849.htmlhttp://www.tkk7.com/xixuui/comments/176849.htmlhttp://www.tkk7.com/xixuui/archive/2008/01/21/176849.html#Feedback1http://www.tkk7.com/xixuui/comments/commentRss/176849.htmlhttp://www.tkk7.com/xixuui/services/trackbacks/176849.html

阿輝 2008-01-21 22:11 發(fā)表評論
]]>
《源代碼就是設(shè)計》敏捷開發(fā)論文http://www.tkk7.com/xixuui/archive/2007/07/17/130743.html阿輝阿輝Tue, 17 Jul 2007 02:09:00 GMThttp://www.tkk7.com/xixuui/archive/2007/07/17/130743.htmlhttp://www.tkk7.com/xixuui/comments/130743.htmlhttp://www.tkk7.com/xixuui/archive/2007/07/17/130743.html#Feedback0http://www.tkk7.com/xixuui/comments/commentRss/130743.htmlhttp://www.tkk7.com/xixuui/services/trackbacks/130743.html這是一篇偉大的論文,該文撰寫于1992年,作者在當(dāng)時就能有這樣的反思,實在是非常了不起。

至今,我仍能記起當(dāng)我頓悟并最終產(chǎn)生下面文章時所在的地方。那是1986年的夏天,我在加利福尼亞中國湖海軍武器中心擔(dān)任臨時顧問。在這期間,我有幸參加了一個關(guān)于Ada的研討會。討論當(dāng)中,有一位聽眾提出了一個具有代表性的問題,“軟件開發(fā)者是工程師嗎?”我不記得當(dāng)時的回答,但是我卻記得當(dāng)時并沒有真正解答這個問題。于是,我就退出討論,開始思考我會怎樣回答這樣一個問題。現(xiàn)在,我無法肯定當(dāng)時我為什么會記起幾乎10年前曾經(jīng)在Datamation雜志上閱讀過的一篇論文,不過促使我記起的應(yīng)該是后續(xù)討論中的某些東西。這篇論文闡述了工程師為什么必須是好的作家(我記得該論文談?wù)摼褪沁@個問題——好久沒有看了),但是我從該論文中得到的關(guān)鍵一點是:作者認(rèn)為工程過程的最終結(jié)果是文檔。換句話說,工程師生產(chǎn)的是文檔,不是實物。其他人根據(jù)這些文檔去制造實物。于是,我就在困惑中提出了一個問題,“除了軟件項目正常產(chǎn)生的所有文檔以外,還有可以被認(rèn)為是真正的工程文檔的東西嗎?”我給出的回答是,“是的,有這樣的文檔存在,并且只有一份——源代碼。”

把源代碼看作是一份工程文檔——設(shè)計——完全顛覆了我對自己所選擇的職業(yè)的看法。它改變了我看待一切事情的方式。此外,我對它思考的越多,我就越覺得它闡明了軟件項目常常遇到的眾多問題。更確切地說,我覺得大多數(shù)人不理解這個不同的看法,或者有意拒絕它這樣一個事實,就足以說明很多問題。幾年后,我終于有機(jī)會把我的觀點公開發(fā)表。C++ Journal中的一篇有關(guān)軟件設(shè)計的論文促使我給編輯寫了一封關(guān)于這個主題的信。經(jīng)過幾封書信交換后,編輯Livleen Singh同意把我關(guān)于這個主題的想法發(fā)表為一篇論文。下面就是這篇文章。

——Jack Reecves, December,22,2001

什么是軟件設(shè)計?
Jack W.Reeves, 1992

面向?qū)ο蠹夹g(shù),特別是C++,似乎給軟件界帶來了不小的震動。出現(xiàn)了大量的論文和書籍去描述如何應(yīng)用這項新技術(shù)。總的來說,那些關(guān)于面向?qū)ο蠹夹g(shù)是否只是一個騙局的問題已經(jīng)被那些關(guān)于如何付出最小的努力即可獲得收益的問題所替代。面向?qū)ο蠹夹g(shù)出現(xiàn)已經(jīng)有一段時間了,但是這種爆炸式的流行卻似乎有點不尋常。人們?yōu)楹螘蝗魂P(guān)注它呢?對于這個問題,人們給出了各種各樣的解釋。事實上,很可能就沒有單一的原因。也許,把多種因素的結(jié)合起來才能最終取得突破,并且這項工作正在進(jìn)展之中。盡管如此,在軟件革命的這個最新階段中,C++本身看起來似乎成為了一個主要因素。同樣,對于這個問題,很可能也存在很多種理由,不過我想從一個稍微不同的視角給出一個答案:C++之所以變得流行,是因為它使軟件設(shè)計變得更容易的同時,也使編程變得更容易。

雖然這個解釋好像有點奇特,但是它卻是深思熟慮的結(jié)果。在這篇論文中,我就是想要關(guān)注一下編程和程序設(shè)計之間的關(guān)系。近10年來,我一直覺得整個軟件行業(yè)都沒有覺察到做出一個軟件設(shè)計和什么是真正的軟件設(shè)計之間的一個微妙的不同點。只要看到了這一點,我認(rèn)為我們就可以從C++增長的流行趨勢中,學(xué)到關(guān)于如何才能成為更好的軟件工程師的意義深遠(yuǎn)的知識。這個知識就是,編程不是構(gòu)建軟件,而是設(shè)計軟件。

幾年前,我參見了一個討論會,其中討論到軟件開發(fā)是否是一門工程學(xué)科的問題。雖然我不記得了討論結(jié)果,但是我卻記得它是如何促使我認(rèn)識到:軟件業(yè)已經(jīng)做出了一些錯誤的和硬件工程的比較,而忽視了一些絕對正確的對比。其實,我認(rèn)為我們不是軟件工程師,因為我們沒有認(rèn)識到什么才是真正的軟件設(shè)計。現(xiàn)在,我對這一點更是確信無疑。

任何工程活動的最終目標(biāo)都是某些類型的文檔。當(dāng)設(shè)計工作完成時,設(shè)計文檔就被轉(zhuǎn)交給制造團(tuán)隊。該團(tuán)隊是一個和設(shè)計團(tuán)隊完全不同的群體,并且其技能也和設(shè)計團(tuán)隊完全不同。如果設(shè)計文檔正確地描繪了一個完整的設(shè)計,那么制造團(tuán)隊就可以著手構(gòu)建產(chǎn)品。事實上,他們可以著手構(gòu)建該產(chǎn)品的許多實物,完全無需設(shè)計者的任何進(jìn)一步的介入。在按照我的理解方式審查了軟件開發(fā)的生命周期后,我得出一個結(jié)論:實際上滿足工程設(shè)計標(biāo)準(zhǔn)的惟一軟件文檔,就是源代碼清單。

對于這個觀點,人們進(jìn)行了很多的爭論,無論是贊成的還是反對的都足以寫成無數(shù)的論文。本文假定最終的源代碼就是真正的軟件設(shè)計,然后仔細(xì)研究了該假定帶來的一些結(jié)果。我可能無法證明這個觀點是正確的,但是我希望證明:它確實解釋了軟件行業(yè)中一些已經(jīng)觀察到的事實,包括C++的流行。

在把代碼看作是軟件設(shè)計所帶來的結(jié)果中,有一個結(jié)果完全蓋過了所有其他的結(jié)果。它非常重要并且非常明顯,也正因為如此,對于大多數(shù)軟件機(jī)構(gòu)來說,它完全是一個盲點。這個結(jié)果就是:軟件的構(gòu)建是廉價的。它根本就不具有昂貴的資格;它非常的廉價,幾乎就是免費(fèi)的。如果源代碼是軟件設(shè)計,那么實際的軟件構(gòu)建就是由編譯器和連接器完成的。我們常常把編譯和連接一個完整的軟件系統(tǒng)的過程稱為“進(jìn)行一次構(gòu)建”。在軟件構(gòu)建設(shè)備上所進(jìn)行的主要投資是很少的——實際需要的只有一臺計算機(jī)、一個編輯器、一個編譯器以及一個連接器。一旦具有了一個構(gòu)建環(huán)境,那么實際的軟件構(gòu)建只需花費(fèi)少許的時間。編譯50 000行的C++程序也許會花費(fèi)很長的時間,但是構(gòu)建一個具有和50 000行C++程序同樣設(shè)計復(fù)雜性的硬件系統(tǒng)要花費(fèi)多長的時間呢?

把源代碼看作是軟件設(shè)計的另外一個結(jié)果是,軟件設(shè)計相對易于創(chuàng)作,至少在機(jī)械意義上如此。通常,編寫(也就是設(shè)計)一個具有代表性的軟件模塊(50至100行代碼)只需花費(fèi)幾天的時間(對它進(jìn)行完全的調(diào)試是另外一個議題,稍后會對它進(jìn)行更多的討論)。我很想問一下,是否還有任何其他的學(xué)科可以在如此短的時間內(nèi),產(chǎn)生出和軟件具有同樣復(fù)雜性的設(shè)計來,不過,首先我們必須要弄清出如何來度量和比較復(fù)雜性。然而,有一點是明顯的,那就是軟件設(shè)計可以 極為迅速地變得非常龐大。

假設(shè)軟件設(shè)計相對易于創(chuàng)作,并且在本質(zhì)上構(gòu)建起來也沒有什么代價,一個不令人吃驚的發(fā)現(xiàn)是,軟件設(shè)計往往是難以置信的龐大和復(fù)雜。這看起來似乎很明顯,但是問題的重要性卻常常被忽視。學(xué)校中的項目通常具有數(shù)千行的代碼。具有10 000行代碼(設(shè)計)的軟件產(chǎn)品被它們的設(shè)計者丟棄的情況也是有的。我們早就不再關(guān)注于簡單的軟件。典型的商業(yè)軟件的設(shè)計都是由數(shù)十萬行代碼組成的。許多軟件設(shè)計達(dá)到了上百萬行代碼。另外,軟件設(shè)計幾乎總是在不斷地演化。雖然當(dāng)前的設(shè)計可能只有幾千行代碼,但是在產(chǎn)品的生命期中,實際上可能要編寫許多倍的代碼。

盡管確實存在一些硬件設(shè)計,它們看起來似乎和軟件設(shè)計一樣復(fù)雜,但是請注意兩個有關(guān)現(xiàn)代硬件的事實。第一,復(fù)雜的硬件工程成果未必總是沒有錯誤的,在這一點上,它不存在像軟件那樣讓我們相信的評判標(biāo)準(zhǔn)。多數(shù)的微處理器在發(fā)售時都具有一些邏輯錯誤:橋梁坍塌,大壩破裂,飛機(jī)失事以及數(shù)以千計的汽車和其他消費(fèi)品被召回——所有的這些我們都記憶猶新,所有的這些都是設(shè)計錯誤的結(jié)果。第二,復(fù)雜的硬件設(shè)計具有與之對應(yīng)的復(fù)雜、昂貴的構(gòu)建階段。結(jié)果,制造這種系統(tǒng)所需的能力限制了真正能夠生產(chǎn)復(fù)雜硬件設(shè)計公司的數(shù)目。對于軟件來說,沒有這種限制。目前,已經(jīng)有數(shù)以百計的軟件機(jī)構(gòu)和數(shù)以千計的非常復(fù)雜的軟件系統(tǒng)存在,并且數(shù)量以及復(fù)雜性每天都在增長。這意味著軟件行業(yè)不可能通過仿效硬件開發(fā)者找到針對自身問題的解決辦法。倘若一定要說出有什么相同之處的話,那就是,當(dāng)CAD和CAM可以做到幫助硬件設(shè)計者創(chuàng)建越來越復(fù)雜的設(shè)計時,硬件工程才會變得和軟件開發(fā)越來越像。

設(shè)計軟件是一種管理復(fù)雜性的活動。復(fù)雜性存在于軟件設(shè)計本身之中,存在于公司的軟件機(jī)構(gòu)之中,也存在于整個軟件行業(yè)之中。軟件設(shè)計和系統(tǒng)設(shè)計非常相似。它可以跨越多種技術(shù)并且常常涉及多個學(xué)科分支。軟件的規(guī)格說明往往不固定、經(jīng)常快速變化,這種變化常常在正進(jìn)行軟件設(shè)計時發(fā)生。同樣,軟件開發(fā)團(tuán)隊也往往不固定,常常在設(shè)計過程的中間發(fā)生變化。在許多方面,軟件都要比硬件更像復(fù)雜的社會或者有機(jī)系統(tǒng)。所有這些都使得軟件設(shè)計成為了一個困難的并且易出錯的過程。雖然所有這些都不是創(chuàng)造性的想法,但是在軟件工程革命開始將近30年后的今天,和其他工程行業(yè)相比,軟件開發(fā)看起來仍然像是一種未受過訓(xùn)練(undisciplined)的技藝。

一般的看法認(rèn)為,當(dāng)真正的工程師完成了一個設(shè)計,不管該設(shè)計有多么復(fù)雜,他們都非常確信該設(shè)計是可以工作的。他們也非常確信該設(shè)計可以使用公認(rèn)的技術(shù)建造出來。為了做到這一點,硬件工程師花費(fèi)了大量的時間去驗證和改進(jìn)他們的設(shè)計。例如,請考慮一個橋梁設(shè)計。在這樣一個設(shè)計實際建造之前,工程師會進(jìn)行結(jié)構(gòu)分析——他們建立計算機(jī)模型并進(jìn)行仿真,他們建立比例模型并在風(fēng)洞中或者用其他一些方法進(jìn)行測試。簡而言之,在建造前,設(shè)計者會使用他們能夠想到的一切方法來證實設(shè)計是正確的。對于一架新型客機(jī)的設(shè)計來說,情況甚至更加嚴(yán)重;必須要構(gòu)建出和原物同尺寸的原型,并且必須要進(jìn)行飛行測試來驗證設(shè)計中的種種預(yù)計。

對于大多數(shù)人來說,軟件中明顯不存在和硬件設(shè)計同樣嚴(yán)格的工程。然而,如果我們把源代碼看做是設(shè)計,那么就會發(fā)現(xiàn)軟件工程師實際上對他們的設(shè)計做了大量的驗證和改進(jìn)。軟件工程師不把這稱為工程,而稱它為測試和調(diào)試。大多數(shù)人不把測試和調(diào)試看作是真正的“工程”——在軟件行業(yè)中肯定沒有被看作是。造成這種看法的原因,更多的是因為軟件行業(yè)拒絕把代碼看作設(shè)計,而不是任何實際的工程差別。事實上,試驗?zāi)P汀⒃鸵约半娐吩囼灠逡呀?jīng)成為其他工程學(xué)科公認(rèn)的組成部分。軟件設(shè)計者之所以不具有或者沒有使用更多的正規(guī)方法來驗證他們的設(shè)計,是因為軟件構(gòu)建周期的簡單經(jīng)濟(jì)規(guī)律。

第一個啟示:僅僅構(gòu)建設(shè)計并測試它比做任何其他事情要廉價一些,也簡單一些。我們不關(guān)心做了多少次構(gòu)建——這些構(gòu)建在時間方面的代價幾乎為零,并且如果我們丟棄了構(gòu)建,那么它所使用的資源完全可以重新利用。請注意,測試并非僅僅是讓當(dāng)前的設(shè)計正確,它也是改進(jìn)設(shè)計的過程的一部分。復(fù)雜系統(tǒng)的硬件工程師常常建立模型(或者,至少他們把設(shè)計用計算機(jī)圖形直觀地表現(xiàn)出來)。這就使得他們獲得了對于設(shè)計的一種“感覺”,而僅僅去檢查設(shè)計是不可能獲得這種感覺的。對于軟件來說,構(gòu)建這樣一個模型既不可能也無必要。我們僅僅構(gòu)建產(chǎn)品本身。即使正規(guī)的軟件驗證可以和編譯器一樣自動進(jìn)行,我們還是會去進(jìn)行構(gòu)建/測試循環(huán)。因此,正規(guī)的驗證對于軟件行業(yè)來說從來沒有太多的實際意義。

這就是現(xiàn)今軟件開發(fā)過程的現(xiàn)實。數(shù)量不斷增長的人和機(jī)構(gòu)正在創(chuàng)建著更加復(fù)雜的軟件設(shè)計。這些設(shè)計會被先用某些編程語言編寫出來,然后通過構(gòu)建/測試循環(huán)進(jìn)行驗證和改進(jìn)。過程易于出錯,并且不是特別的嚴(yán)格。相當(dāng)多的軟件開發(fā)人員并不想相信這就是過程的運(yùn)作方式,也正因為這一點,使問題變得更加復(fù)雜。

當(dāng)前大多數(shù)的軟件過程都試圖把軟件設(shè)計的不同階段分離到不同的類別中。必須要在頂層的設(shè)計完成并且凍結(jié)后,才能開始編碼。測試和調(diào)試只對清除建造錯誤是必要的。程序員處在中間位置,他們是軟件行業(yè)的建造工人。許多人認(rèn)為,如果我們可以讓程序員不再進(jìn)行“隨意的編碼(hacking)”并且按照交給他們的設(shè)計去進(jìn)行構(gòu)建(還要在過程中,犯更少的錯誤),那么軟件開發(fā)就可以變得成熟,從而成為一門真正的工程學(xué)科。但是,只要過程忽視了工程和經(jīng)濟(jì)學(xué)事實,這就不可能發(fā)生。

例如,任何一個現(xiàn)代行業(yè)都無法忍受在其制造過程中出現(xiàn)超過100%的返工率。如果一個建造工人常常不能在第一次就構(gòu)建正確,那么不久他就會失業(yè)。但是在軟件業(yè)中,即使最小的一塊代碼,在測試和調(diào)試期間,也很可能會被修正或者完全重寫。在一個創(chuàng)造性的過程中(比如:設(shè)計),我們認(rèn)可這種改進(jìn)不是制造過程的一部分。沒有人會期望工程師第一次就創(chuàng)建出完美的設(shè)計。即使她做到了,仍然必須讓它經(jīng)受改進(jìn)過程,目的就是為了證明它是完美的。

即使我們從日本的管理方法中沒有學(xué)到任何東西,我們也應(yīng)該知道由于在過程中犯錯誤而去責(zé)備工人是無益于提高生產(chǎn)率的。我們不應(yīng)該不斷地強(qiáng)迫軟件開發(fā)去符合不正確的過程模型,相反,我們需要去改進(jìn)過程,使之有助于而不是阻礙產(chǎn)生更好的軟件。這就是“軟件工程”的石蕊測試。工程是關(guān)于你如何實施過程的,而不是關(guān)于是否需要一個CAD系統(tǒng)來產(chǎn)生最終的設(shè)計文檔。

關(guān)于軟件開發(fā)有一個壓倒性的問題,那就是一切都是設(shè)計過程的一部分。編碼是設(shè)計,測試和調(diào)試是設(shè)計的一部分,并且我們通常認(rèn)為的設(shè)計仍然是設(shè)計的一部分。雖然軟件構(gòu)建起來很廉價,但是設(shè)計起來卻是難以置信的昂貴。軟件非常的復(fù)雜,具有眾多不同方面的設(shè)計內(nèi)容以及它們所導(dǎo)致的設(shè)計考慮。問題在于,所有不同方面的內(nèi)容是相互關(guān)連的(就像硬件工程中的一樣)。我們希望頂層設(shè)計者可以忽視模塊算法設(shè)計的細(xì)節(jié)。同樣,我們希望程序員在設(shè)計模塊內(nèi)部算法時不必考慮頂層設(shè)計問題。糟糕的是,一個設(shè)計層面中的問題侵入到了其他層面之中。對于整個軟件系統(tǒng)的成功來說,為一個特定模塊選擇算法可能和任何一個更高層次的設(shè)計問題同樣重要。在軟件設(shè)計的不同方面內(nèi)容中,不存在重要性的等級。最低層模塊中的一個不正確設(shè)計可能和最高層中的錯誤一樣致命。軟件設(shè)計必須在所有的方面都是完整和正確的,否則,構(gòu)建于該設(shè)計基礎(chǔ)之上的所有軟件都會是錯誤的。

為了管理復(fù)雜性,軟件被分層設(shè)計。當(dāng)程序員在考慮一個模塊的詳細(xì)設(shè)計時,可能還有數(shù)以百計的其他模塊以及數(shù)以千計的細(xì)節(jié),他不可能同時顧及。例如,在軟件設(shè)計中,有一些重要方面的內(nèi)容不是完全屬于數(shù)據(jù)結(jié)構(gòu)和算法的范疇。在理想情況下,程序員不應(yīng)該在設(shè)計代碼時還得去考慮設(shè)計的這些其他方面的內(nèi)容。

但是,設(shè)計并不是以這種方式工作的,并且原因也開始變得明朗。軟件設(shè)計只有在其被編寫和測試后才算完成。測試是設(shè)計驗證和改進(jìn)過程的基礎(chǔ)部分。高層結(jié)構(gòu)的設(shè)計不是完整的軟件設(shè)計;它只是細(xì)節(jié)設(shè)計的一個結(jié)構(gòu)框架。在嚴(yán)格地驗證高層設(shè)計方面,我們的能力是非常有限的。詳細(xì)設(shè)計最終會對高層設(shè)計造成的影響至少和其他的因素一樣多(或者應(yīng)該允許這種影響)。對設(shè)計的各個方面進(jìn)行改進(jìn),是一個應(yīng)該貫穿整個設(shè)計周期的過程。如果設(shè)計的任何一個方面內(nèi)容被凍結(jié)在改進(jìn)過程之外,那么對于最終設(shè)計將會是糟糕的或者甚至無法工作這一點,就不會覺得奇怪了。

如果高層的軟件設(shè)計可以成為一個更加嚴(yán)格的工程過程,那該有多好呀,但是軟件系統(tǒng)的真實情況不是嚴(yán)格的。軟件非常的復(fù)雜,它依賴于太多的其他東西。或許,某些硬件沒有按照設(shè)計者認(rèn)為的那樣工作,或者一個庫例程具有一個文檔中沒有說明的限制。每一個軟件項目遲早都會遇到這些種類的問題。這些種類的問題會在測試期間被發(fā)現(xiàn)(如果我們的測試工作做得好的話),之所以如此是因為沒有辦法在早期就發(fā)現(xiàn)它們。當(dāng)它們被發(fā)現(xiàn)時,就迫使對設(shè)計進(jìn)行更改。如果我們幸運(yùn),那么對設(shè)計的更改是局部的。時常,更改會波及到整個軟件設(shè)計中的一些重要部分(莫非定律)。當(dāng)受到影響的設(shè)計的一部分由于某種原因不能更改時,那么為了能夠適應(yīng)影響,設(shè)計的其他部分就必須得遭到破壞。這通常導(dǎo)致的結(jié)果就是管理者所認(rèn)為的“隨意編碼”,但是這就是軟件開發(fā)的現(xiàn)實。

例如,在我最近工作的一個項目中,發(fā)現(xiàn)了模塊A的內(nèi)部結(jié)構(gòu)和另一個模塊B之間的一個時序依賴關(guān)系。糟糕的是,模塊A的內(nèi)部結(jié)構(gòu)隱藏在一個抽象體的后面,而該抽象體不允許以任何方法把對模塊B的調(diào)用合入到它的正確調(diào)用序列中。當(dāng)問題被發(fā)現(xiàn)時,當(dāng)然已經(jīng)錯過了更改A的抽象體的時機(jī)。正如所料,所發(fā)生的就是把一個日益增長的復(fù)雜的“修正”集應(yīng)用到A的內(nèi)部設(shè)計上。在我們還沒有安裝完版本1時,就普遍感覺到設(shè)計正在衰退。每一個新的修正很可能都會破壞一些老的修正。這是一個正規(guī)的軟件開發(fā)項目。最后,我和我的同事決定對設(shè)計進(jìn)行更改,但是為了得到管理層的同意,我們不得不自愿無償加班。

在任何一般規(guī)模的軟件項目中,肯定會出現(xiàn)像這樣的問題,盡管人們使用了各種方法來防止它的出現(xiàn),但是仍然會忽視一些重要的細(xì)節(jié)。這就是工藝和工程之間的區(qū)別。如果經(jīng)驗可以把我們引向正確的方向,這就是工藝。如果經(jīng)驗只會把我們帶入未知的領(lǐng)域,然后我們必須使用一開始所使用的方法并通過一個受控的改進(jìn)過程把它變得更好,這就是工程。

我們來看一下只是作為其中很小一點的內(nèi)容,所有的程序員都知道,在編碼之后而不是之前編寫軟件設(shè)計文檔會產(chǎn)生更加準(zhǔn)確的文檔。現(xiàn)在,原因是顯而易見的。用代碼來表現(xiàn)的最終設(shè)計是惟一一個在構(gòu)建/測試循環(huán)期間被改進(jìn)的東西。在這個循環(huán)期間,初始設(shè)計保持不變的可能性和模塊的數(shù)量以及項目中程序員的數(shù)量成反比。它很快就會變得毫無價值。

在軟件工程中,我們非常需要在各個層次都優(yōu)秀的設(shè)計。我們特別需要優(yōu)秀的頂層設(shè)計。初期的設(shè)計越好,詳細(xì)設(shè)計就會越容易。設(shè)計者應(yīng)該使用任何可以提供幫助的東西。結(jié)構(gòu)圖表、Booch 圖、狀態(tài)表、PDL等等——如果它能夠提供幫助,就去使用它。但是,我們必須記住,這些工具和符號都不是軟件設(shè)計。最后,我們必須創(chuàng)建真正的軟件設(shè)計,并且是使用某種編程語言完成的。因此,當(dāng)我們得出設(shè)計時,我們不應(yīng)該害怕對它們進(jìn)行編碼。在必要時,我們必須應(yīng)該樂于去改進(jìn)它們。

至今,還沒有任何設(shè)計符號可以同時適用于頂層設(shè)計和詳細(xì)設(shè)計。設(shè)計最終會表現(xiàn)為以某種編程語言編寫的代碼。這意味著在詳細(xì)設(shè)計可以開始前,頂層設(shè)計符號必須被轉(zhuǎn)換成目標(biāo)編程語言。這個轉(zhuǎn)換步驟耗費(fèi)時間并且會引入錯誤。程序員常常是對需求進(jìn)行回顧并且重新進(jìn)行頂層設(shè)計,然后根據(jù)它們的實際去進(jìn)行編碼,而不是從一個可能沒有和所選擇的編程語言完全映射的符號進(jìn)行轉(zhuǎn)換。這同樣也是軟件開發(fā)的部分現(xiàn)實情況。

也許,如果讓設(shè)計者本人來編寫初始代碼,而不是后來讓其他人去轉(zhuǎn)換語言無關(guān)的設(shè)計,就會更好一些。我們所需要的是一個適用于各個層次設(shè)計的統(tǒng)一符號。換句話說,我們需要一種編程語言,它同樣也適用于捕獲高層的設(shè)計概念。C++正好可以滿足這個要求。C++是一門適用于真實項目的編程語言,同時它也是一個非常具有表達(dá)力的軟件設(shè)計語言。C++允許我們直接表達(dá)關(guān)于設(shè)計組件的高層信息。這樣,就可以更容易地進(jìn)行設(shè)計,并且以后可以更容易地改進(jìn)設(shè)計。由于它具有更強(qiáng)大的類型檢查機(jī)制,所以也有助于檢測到設(shè)計中的錯誤。這就產(chǎn)生了一個更加健壯的設(shè)計,實際上也是一個更好的工程化設(shè)計。

最后,軟件設(shè)計必須要用某種編程語言表現(xiàn)出來,然后通過一個構(gòu)建/測試循環(huán)對其進(jìn)行驗證和改進(jìn)。除此之外的任何其他主張都完全沒有用。請考慮一下都有哪些軟件開發(fā)工具和技術(shù)得以流行。結(jié)構(gòu)化編程在它的時代被認(rèn)為是創(chuàng)造性的技術(shù)。Pascal使之變得流行,從而自己也變得流行。面向?qū)ο笤O(shè)計是新的流行技術(shù),而C++是它的核心。現(xiàn)在,請考慮一下那些沒有成效的東西。CASE工具,流行嗎?是的;通用嗎?不是。結(jié)構(gòu)圖表怎么樣?情況也一樣。同樣地,還有Warner-Orr圖、Booch圖、對象圖以及你能想起的一切。每一個都有自己的強(qiáng)項,以及惟一的一個根本弱點——它不是真正的軟件設(shè)計。事實上,惟一一個可以被普遍認(rèn)可的軟件設(shè)計符號是PDL,而它看起來像什么呢?

這表明,在軟件業(yè)的共同潛意識中本能地知道,編程技術(shù),特別是實際開發(fā)所使用的編程語言的改進(jìn)和軟件行業(yè)中任何其他東西相比,具有壓倒性的重要性。這還表明,程序員關(guān)心的是設(shè)計。當(dāng)出現(xiàn)更加具有表達(dá)力的編程語言時,軟件開發(fā)者就會使用它們。

同樣,請考慮一下軟件開發(fā)過程是如何變化的。從前,我們使用瀑布式過程。現(xiàn)在,我們談?wù)摰氖锹菪介_發(fā)和快速原型。雖然這種技術(shù)常常被認(rèn)為可以“消除風(fēng)險”以及“縮短產(chǎn)品的交付時間”,但是它們事實上也只是為了在軟件的生命周期中更早地開始編碼。這是好事。這使得構(gòu)建/測試循環(huán)可以更早地開始對設(shè)計進(jìn)行驗證和改進(jìn)。這同樣也意味著,頂層軟件設(shè)計者很有可能也會去進(jìn)行詳細(xì)設(shè)計。

正如上面所表明的,工程更多的是關(guān)于如何去實施過程的,而不是關(guān)于最終產(chǎn)品看起來的像什么。處在軟件行業(yè)中的我們,已經(jīng)接近工程師的標(biāo)準(zhǔn),但是我們需要一些認(rèn)知上的改變。編程和構(gòu)建/測試循環(huán)是工程軟件過程的中心。我們需要以像這樣的方式去管理它們。構(gòu)建/測試循環(huán)的經(jīng)濟(jì)規(guī)律,再加上軟件系統(tǒng)幾乎可以表現(xiàn)任何東西的事實,就使得我們完全不可能找出一種通用的方法來驗證軟件設(shè)計。我們可以改善這個過程,但是我們不能脫離它。

最后一點:任何工程設(shè)計項目的目標(biāo)是一些文檔產(chǎn)品。顯然,實際設(shè)計的文檔是最重要的,但是它們并非惟一要產(chǎn)生的文檔。最終,會期望某些人來使用軟件。同樣,系統(tǒng)很可能也需要后續(xù)的修改和增強(qiáng)。這意味著,和硬件項目一樣,輔助文檔對于軟件項目具有同樣的重要性。雖然暫時忽略了用戶手冊、安裝指南以及其他一些和設(shè)計過程沒有直接聯(lián)系的文檔,但是仍然有兩個重要的需求需要使用輔助設(shè)計文檔來解決。

輔助文檔的第一個用途是從問題空間中捕獲重要的信息,這些信息是不能直接在設(shè)計中使用的。軟件設(shè)計需要創(chuàng)造一些軟件概念來對問題空間中的概念進(jìn)行建模。這個過程需要我們得出一個對問題空間中概念的理解。通常,這個理解中會包含一些最后不會被直接建模到軟件空間中的信息,但是這些信息卻仍然有助于設(shè)計者確定什么是本質(zhì)概念以及如何最好地對它們建模。這些信息應(yīng)該被記錄在某處,以防以后要去更改模型。

對輔助文檔的第二個重要需要是對設(shè)計的某些方面的內(nèi)容進(jìn)行記錄,而這些方面的內(nèi)容是難以直接從設(shè)計本身中提取的。它們既可以是高層方面的內(nèi)容,也可以是低層方面內(nèi)容。對于這些方面內(nèi)容中的許多來說,圖形是最好的描述方式。這就使得它們難以作為注釋包含在代碼中。這并不是說要用圖形化的軟件設(shè)計符號代替編程語言。這和用一些文本描述來對硬件科目的圖形化設(shè)計文檔進(jìn)行補(bǔ)充沒有什么區(qū)別。

決不要忘記,是源代碼決定了實際設(shè)計的真實樣子,而不是輔助文檔。在理想情況下,可以使用軟件工具對源代碼進(jìn)行后期處理并產(chǎn)生出輔助文檔。對于這一點,我們可能期望過高了。次一點的情況是,程序員(或者技術(shù)方面的編寫者)可以使用一些工具從源代碼中提取出一些特定的信息,然后可以把這些信息以其他一些方式文檔化。毫無疑問,手工對這種文檔保持更新是困難的。這是另外一個支持需要更具表達(dá)力的編程語言的理由。同樣,這也是一個支持使這種輔助文檔保持最小并且盡可能在項目晚期才使之變成正式的理由。同樣,我們可以使用一些好的工具;不然的話,我們就得求助于鉛筆、紙以及黑板。

總結(jié)如下:
  實際的軟件運(yùn)行于計算機(jī)之中。它是存儲在某種磁介質(zhì)中的0和1的序列。它不是使用C++語言(或者其他任何編程語言)編寫的程序。
  程序清單是代表軟件設(shè)計的文檔。實際上把軟件設(shè)計構(gòu)建出來的是編譯器和連接器。
  構(gòu)建實際軟件設(shè)計的廉價程度是令人難以置信的,并且它始終隨著計算機(jī)速度的加快而變得更加廉價。
  設(shè)計實際軟件的昂貴程度是令人難以置信的,之所以如此,是因為軟件的復(fù)雜性是令人難以置信的,并且軟件項目的幾乎所有步驟都是設(shè)計過程的一部分。
  編程是一種設(shè)計活動——好的軟件設(shè)計過程認(rèn)可這一點,并且在編碼顯得有意義時,就會毫不猶豫的去編碼。
  編碼要比我們所認(rèn)為的更頻繁地顯現(xiàn)出它的意義。通常,在代碼中表現(xiàn)設(shè)計的過程會揭示出一些疏漏以及額外的設(shè)計需要。這發(fā)生的越早,設(shè)計就會越好。
  因為軟件構(gòu)建起來非常廉價,所以正規(guī)的工程驗證方法在實際的軟件開發(fā)中沒有多大用處。僅僅建造設(shè)計并測試它要比試圖去證明它更簡單、更廉價。
  測試和調(diào)試是設(shè)計活動——對于軟件來說,它們就相當(dāng)于其他工程學(xué)科中的設(shè)計驗證和改進(jìn)過程。好的軟件設(shè)計過程認(rèn)可這一點,并且不會試圖去減少這些步驟。
  還有一些其他的設(shè)計活動——稱它們?yōu)楦邔釉O(shè)計、模塊設(shè)計、結(jié)構(gòu)設(shè)計、構(gòu)架設(shè)計或者諸如此類的東西。好的軟件設(shè)計過程認(rèn)可這一點,并且慎重地包含這些步驟。
  所有的設(shè)計活動都是相互影響的。好的軟件設(shè)計過程認(rèn)可這一點,并且當(dāng)不同的設(shè)計步驟顯示出有必要時,它會允許設(shè)計改變,有時甚至是根本上的改變,
  許多不同的軟件設(shè)計符號可能是有用的——它們可以作為輔助文檔以及工具來幫助簡化設(shè)計過程。它們不是軟件設(shè)計。
  軟件開發(fā)仍然還是一門工藝,而不是一個工程學(xué)科。主要是因為缺乏驗證和改善設(shè)計的關(guān)鍵過程中所需的嚴(yán)格性。
  最后,軟件開發(fā)的真正進(jìn)步依賴于編程技術(shù)的進(jìn)步,而這又意味著編程語言的進(jìn)步。C++就是這樣的一個進(jìn)步。它已經(jīng)取得了爆炸式的流行,因為它是一門直接支持更好的軟件設(shè)計的主流編程語言。
  C++在正確的方向上邁出了一步,但是還需要更大的進(jìn)步。

后 記

當(dāng)我回顧幾乎10年前所寫的東西時,有幾點讓我印象深刻。第一點(也是和本書最有關(guān)的)是,現(xiàn)今,我甚至比那時更加確信我試圖去闡述的要點在本質(zhì)上的正確性。隨后的一些年中,許多流行的軟件開發(fā)方法增強(qiáng)了其中的許多觀點,這支持了我的信念。最明顯的(或許也是最不重要的)是面向?qū)ο缶幊陶Z言的流行。現(xiàn)在,除了C++外,出現(xiàn)了許多其他的面向?qū)ο缶幊陶Z言。另外,還有一些面向?qū)ο笤O(shè)計符號,比如:UML。我關(guān)于面向?qū)ο笳Z言之所以得到流行是因為它們允許在代碼中直接表現(xiàn)出更具表達(dá)力的設(shè)計的論點,現(xiàn)在看來有點過時了。

重構(gòu)的概念——重新組織代碼基礎(chǔ),使之更加健壯和可重用——同樣也和我的關(guān)于設(shè)計的所有方面的內(nèi)容都應(yīng)該是靈活的并且在驗證設(shè)計時允許改變的論點相似。重構(gòu)只是提供了一個過程以及一組如何去改善已經(jīng)被證實具有缺陷的設(shè)計的準(zhǔn)則。

最后,文中有一個敏捷開發(fā)的總的概念。雖然極限編程是這些新方法中最知名的一個,但是它們都具有一個共同點:它們都承認(rèn)源代碼是軟件開發(fā)工作中的最重要的產(chǎn)品。

另一方面,有一些觀點——其中的一些我在論文中略微談到過——在隨后的一些年中,對我來說變得更加重要。第一個是構(gòu)架,或者頂層設(shè)計的重要性。在論文中,我認(rèn)為構(gòu)架只是設(shè)計的一部分內(nèi)容,并且在構(gòu)建/測試循環(huán)對設(shè)計進(jìn)行驗證的過程中,構(gòu)架需要保持可變。這在本質(zhì)上是正確的,但是回想起來,我認(rèn)為我的想法有點不成熟。雖然構(gòu)建/測試循環(huán)可能揭示出構(gòu)架中的問題,但是更多的問題是常常由于改變需求而表現(xiàn)出來的。 一般來說,設(shè)計軟件是困難的,并且新的編程語言,比如:Java或者C++,以及圖形化的符號,比如:UML,對于不知道如何有效地使用它的人來說,都沒有多大的幫助。此外,一旦一個項目基于一個構(gòu)架構(gòu)建了大量的代碼,那么對該構(gòu)架進(jìn)行基礎(chǔ)性的更改,常常相當(dāng)于丟棄掉該項目并重新開始一個,這就意味著該項目沒有出現(xiàn)過。即使項目和機(jī)構(gòu)在根本上接受了重構(gòu)的概念,但是他們通常仍然不愿意去做一些看起來就像是完全重寫的事情。這意味著第一次就把它作對(或者至少是接近對)是重要的,并且項目變得越大,就越要如此。幸運(yùn)的是,軟件設(shè)計模式有助于解決這方面問題。

還有其他一些方面的內(nèi)容,我認(rèn)為需要更多地強(qiáng)調(diào)一下,其中之一就是輔助文檔,尤其是構(gòu)架方面的文檔。雖然源代碼就是設(shè)計,但是試圖從源代碼中得出構(gòu)架,可能是一個令人畏懼的體驗。在論文中,我希望能夠出現(xiàn)一些軟件工具來幫助軟件開發(fā)者自動地維護(hù)來自源代碼的輔助文檔。我?guī)缀跻呀?jīng)放棄了這個希望。一個好的面向?qū)ο髽?gòu)架通常可以使用幾幅圖以及少許的十幾頁文本描述出來。不過,這些圖(和文本)必須集中于設(shè)計中的關(guān)鍵類和關(guān)系。糟糕的是,對于軟件設(shè)計工具可能會變得足夠聰明,以至于可以從源代碼的大量細(xì)節(jié)中提取出這些重要方面的內(nèi)容這一點,我沒有看到任何真正的希望。這意味著還得必須由人來編寫和維護(hù)這種文檔。我仍然認(rèn)為,在源代碼完成后,或者至少是在編寫源代碼的同時去編文檔,要比在編寫源代碼之前去編寫文檔更好一些。

最后,我在論文的最后談到了C++是編程——并且因此是軟件設(shè)計——藝術(shù)的一個進(jìn)步,但是還需要更大的進(jìn)步。就算我完全沒有看到語言中出現(xiàn)任何真正的編程進(jìn)步來挑戰(zhàn)C++的流行,那么在今天,我會認(rèn)為這一點甚至要比我首次編寫它時更加正確。

——Jack Reeves, 2002年1月1日



阿輝 2007-07-17 10:09 發(fā)表評論
]]>
如何不將jdk運(yùn)行java程序http://www.tkk7.com/xixuui/archive/2007/05/10/116449.html阿輝阿輝Thu, 10 May 2007 04:39:00 GMThttp://www.tkk7.com/xixuui/archive/2007/05/10/116449.htmlhttp://www.tkk7.com/xixuui/comments/116449.htmlhttp://www.tkk7.com/xixuui/archive/2007/05/10/116449.html#Feedback0http://www.tkk7.com/xixuui/comments/commentRss/116449.htmlhttp://www.tkk7.com/xixuui/services/trackbacks/116449.html2、將jre1.5.0_10拷到apps目錄下
3、建立program.bat,將將下面內(nèi)容寫入該文件
set path="jre1.5.0_10\bin"
set classpath="jre1.5.0_10\lib;jre1.5.0_10\lib\rt.jar"
java -cp %classpath% -jar program.jar
@pause
4、雙擊program.bat即可運(yùn)行

阿輝 2007-05-10 12:39 發(fā)表評論
]]>
如何生成javadoc文檔http://www.tkk7.com/xixuui/archive/2006/10/30/77975.html阿輝阿輝Mon, 30 Oct 2006 02:00:00 GMThttp://www.tkk7.com/xixuui/archive/2006/10/30/77975.htmlhttp://www.tkk7.com/xixuui/comments/77975.htmlhttp://www.tkk7.com/xixuui/archive/2006/10/30/77975.html#Feedback0http://www.tkk7.com/xixuui/comments/commentRss/77975.htmlhttp://www.tkk7.com/xixuui/services/trackbacks/77975.html?
填寫如圖即可。


阿輝 2006-10-30 10:00 發(fā)表評論
]]>
java面試題集(轉(zhuǎn)) http://www.tkk7.com/xixuui/archive/2006/09/02/67221.html阿輝阿輝Fri, 01 Sep 2006 17:19:00 GMThttp://www.tkk7.com/xixuui/archive/2006/09/02/67221.htmlhttp://www.tkk7.com/xixuui/comments/67221.htmlhttp://www.tkk7.com/xixuui/archive/2006/09/02/67221.html#Feedback7http://www.tkk7.com/xixuui/comments/commentRss/67221.htmlhttp://www.tkk7.com/xixuui/services/trackbacks/67221.html基礎(chǔ)知識:
1.C++或Java中的異常處理機(jī)制的簡單原理和應(yīng)用。

當(dāng)JAVA程序違反了JAVA的語義規(guī)則時,JAVA虛擬機(jī)就會將發(fā)生的錯誤表示為一個異常。違反語義規(guī)則包括2種情況。一種是JAVA類庫內(nèi)置的語義檢查。例如數(shù)組下標(biāo)越界,會引發(fā)IndexOutOfBoundsException;訪問null的對象時會引發(fā)NullPointerException。另一種情況就是JAVA允許程序員擴(kuò)展這種語義檢查,程序員可以創(chuàng)建自己的異常,并自由選擇在何時用throw關(guān)鍵字引發(fā)異常。所有的異常都是java.lang.Thowable的子類。

2. Java的接口和C++的虛類的相同和不同處。

由于Java不支持多繼承,而有可能某個類或?qū)ο笠褂梅謩e在幾個類或?qū)ο罄锩娴姆椒ɑ驅(qū)傩裕F(xiàn)有的單繼承機(jī)制就不能滿足要求。與繼承相比,接口有更高的靈活性,因為接口中沒有任何實現(xiàn)代碼。當(dāng)一個類實現(xiàn)了接口以后,該類要實現(xiàn)接口里面所有的方法和屬性,并且接口里面的屬性在默認(rèn)狀態(tài)下面都是public static,所有方法默認(rèn)情況下是public.一個類可以實現(xiàn)多個接口。

3. 垃圾回收的優(yōu)點和原理。并考慮2種回收機(jī)制。

Java語言中一個顯著的特點就是引入了垃圾回收機(jī)制,使c++程序員最頭疼的內(nèi)存管理的問題迎刃而解,它使得Java程序員在編寫程序的時候不再需要考慮內(nèi)存管理。由于有個垃圾回收機(jī)制,Java中的對象不再有“作用域”的概念,只有對象的引用才有“作用域”。垃圾回收可以有效的防止內(nèi)存泄露,有效的使用可以使用的內(nèi)存。垃圾回收器通常是作為一個單獨的低級別的線程運(yùn)行,不可預(yù)知的情況下對內(nèi)存堆中已經(jīng)死亡的或者長時間沒有使用的對象進(jìn)行清楚和回收,程序員不能實時的調(diào)用垃圾回收器對某個對象或所有對象進(jìn)行垃圾回收。回收機(jī)制有分代復(fù)制垃圾回收和標(biāo)記垃圾回收,增量垃圾回收。

4. 請說出你所知道的線程同步的方法。

wait():使一個線程處于等待狀態(tài),并且釋放所持有的對象的lock。

sleep():使一個正在運(yùn)行的線程處于睡眠狀態(tài),是一個靜態(tài)方法,調(diào)用此方法要捕捉InterruptedException異常。

notify():喚醒一個處于等待狀態(tài)的線程,注意的是在調(diào)用此方法的時候,并不能確切的喚醒某一個等待狀態(tài)的線程,而是由JVM確定喚醒哪個線程,而且不是按優(yōu)先級。

Allnotity():喚醒所有處入等待狀態(tài)的線程,注意并不是給所有喚醒線程一個對象的鎖,而是讓它們競爭。

5. 請講一講析構(gòu)函數(shù)和虛函數(shù)的用法和作用。

6. Error與Exception有什么區(qū)別?

Error表示系統(tǒng)級的錯誤和程序不必處理的異常,

Exception表示需要捕捉或者需要程序進(jìn)行處理的異常。

7. 在java中一個類被聲明為final類型,表示了什么意思?

表示該類不能被繼承,是頂級類。

8. 描述一下你最常用的編程風(fēng)格。

9. heap和stack有什么區(qū)別。

棧是一種線形集合,其添加和刪除元素的操作應(yīng)在同一段完成。棧按照后進(jìn)先出的方式進(jìn)行處理。

堆是棧的一個組成元素

10. 如果系統(tǒng)要使用超大整數(shù)(超過long長度范圍),請你設(shè)計一個數(shù)據(jù)結(jié)構(gòu)來存儲這種超大型數(shù)字以及設(shè)計一種算法來實現(xiàn)超大整數(shù)加法運(yùn)算)。

public class BigInt()

{

int[] ArrOne = new ArrOne[1000];

String intString="";

public int[] Arr(String s)

{

intString = s;

for(int i=0;i<ArrOne.leght;i++)

{

11. 如果要設(shè)計一個圖形系統(tǒng),請你設(shè)計基本的圖形元件(Point,Line,Rectangle,Triangle)的簡單實現(xiàn)

12,談?wù)刦inal, finally, finalize的區(qū)別。

  final?修飾符(關(guān)鍵字)如果一個類被聲明為final,意味著它不能再派生出新的子類,不能作為父類被繼承。因此一個類不能既被聲明為 abstract的,又被聲明為final的。將變量或方法聲明為final,可以保證它們在使用中不被改變。被聲明為final的變量必須在聲明時給定初值,而在以后的引用中只能讀取,不可修改。被聲明為final的方法也同樣只能使用,不能重載。

  finally?再異常處理時提供 finally 塊來執(zhí)行任何清除操作。如果拋出一個異常,那么相匹配的 catch 子句就會執(zhí)行,然后控制就會進(jìn)入 finally 塊(如果有的話)。

  finalize?方法名。Java 技術(shù)允許使用 finalize() 方法在垃圾收集器將對象從內(nèi)存中清除出去之前做必要的清理工作。這個方法是由垃圾收集器在確定這個對象沒有被引用時對這個對象調(diào)用的。它是在 Object 類中定義的,因此所有的類都繼承了它。子類覆蓋 finalize() 方法以整理系統(tǒng)資源或者執(zhí)行其他清理工作。finalize() 方法是在垃圾收集器刪除對象之前對這個對象調(diào)用的。

13,Anonymous Inner Class (匿名內(nèi)部類) 是否可以extends(繼承)其它類,是否可以implements(實現(xiàn))interface(接口)?

  匿名的內(nèi)部類是沒有名字的內(nèi)部類。不能extends(繼承) 其它類,但一個內(nèi)部類可以作為一個接口,由另一個內(nèi)部類實現(xiàn)。

?

14,Static Nested Class 和 Inner Class的不同,說得越多越好(面試題有的很籠統(tǒng))。

  Nested Class (一般是C++的說法),Inner Class (一般是JAVA的說法)。Java內(nèi)部類與C++嵌套類最大的不同就在于是否有指向外部的引用上。具體可見http: //www.frontfree.net/articles/services/view.ASP?id=704&page=1

  注: 靜態(tài)內(nèi)部類(Inner Class)意味著1創(chuàng)建一個static內(nèi)部類的對象,不需要一個外部類對象,2不能從一個static內(nèi)部類的一個對象訪問一個外部類對象

第四,&和&&的區(qū)別。

  &是位運(yùn)算符。&&是布爾邏輯運(yùn)算符。

15,HashMap和Hashtable的區(qū)別。

?

  都屬于Map接口的類,實現(xiàn)了將惟一鍵映射到特定的值上。

?

  HashMap 類沒有分類或者排序。它允許一個 null 鍵和多個 null 值。

  Hashtable 類似于 HashMap,但是不允許 null 鍵和 null 值。它也比 HashMap 慢,因為它是同步的。

16,Collection 和 Collections的區(qū)別。

  Collections是個java.util下的類,它包含有各種有關(guān)集合操作的靜態(tài)方法。

  Collection是個java.util下的接口,它是各種集合結(jié)構(gòu)的父接口。

17,什么時候用assert。

  斷言是一個包含布爾表達(dá)式的語句,在執(zhí)行這個語句時假定該表達(dá)式為 true。如果表達(dá)式計算為 false,那么系統(tǒng)會報告一個 Assertionerror。它用于調(diào)試目的:

assert(a > 0); // throws an Assertionerror if a <= 0

斷言可以有兩種形式:

assert Expression1 ;

assert Expression1 : Expression2 ;

  Expression1 應(yīng)該總是產(chǎn)生一個布爾值。

  Expression2 可以是得出一個值的任意表達(dá)式。這個值用于生成顯示更多調(diào)試信息的 String 消息。

  斷言在默認(rèn)情況下是禁用的。要在編譯時啟用斷言,需要使用 source 1.4 標(biāo)記:

  javac -source 1.4 Test.java

  要在運(yùn)行時啟用斷言,可使用 -enableassertions 或者 -ea 標(biāo)記。

  要在運(yùn)行時選擇禁用斷言,可使用 -da 或者 -disableassertions 標(biāo)記。

  要系統(tǒng)類中啟用斷言,可使用 -esa 或者 -dsa 標(biāo)記。還可以在包的基礎(chǔ)上啟用或者禁用斷言。

  可以在預(yù)計正常情況下不會到達(dá)的任何位置上放置斷言。斷言可以用于驗證傳遞給私有方法的參數(shù)。不過,斷言不應(yīng)該用于驗證傳遞給公有方法的參數(shù),因為不管是否啟用了斷言,公有方法都必須檢查其參數(shù)。不過,既可以在公有方法中,也可以在非公有方法中利用斷言測試后置條件。另外,斷言不應(yīng)該以任何方式改變程序的狀態(tài)。

18,GC是什么? 為什么要有GC? (基礎(chǔ))。

  GC是垃圾收集器。Java 程序員不用擔(dān)心內(nèi)存管理,因為垃圾收集器會自動進(jìn)行管理。要請求垃圾收集,可以調(diào)用下面的方法之一:

System.gc()

Runtime.getRuntime().gc()

19,String s = new String("xyz");創(chuàng)建了幾個String Object?

  兩個對象,一個是“xyx”,一個是指向“xyx”的引用對象s。

20,Math.round(11.5)等於多少? Math.round(-11.5)等於多少?

  Math.round(11.5)返回(long)12,Math.round(-11.5)返回(long)-11;

21,short s1 = 1; s1 = s1 + 1;有什么錯? short s1 = 1; s1 += 1;有什么錯?

  short s1 = 1; s1 = s1 + 1;有錯,s1是short型,s1+1是int型,不能顯式轉(zhuǎn)化為short型。可修改為s1 =(short)(s1 + 1) 。short s1 = 1; s1 += 1正確。

22,sleep() 和 wait() 有什么區(qū)別? 搞線程的最愛

  sleep()方法是使線程停止一段時間的方法。在sleep 時間間隔期滿后,線程不一定立即恢復(fù)執(zhí)行。這是因為在那個時刻,其它線程可能正在運(yùn)行而且沒有被調(diào)度為放棄執(zhí)行,除非(a)“醒來”的線程具有更高的優(yōu)先級 (b)正在運(yùn)行的線程因為其它原因而阻塞。

  wait()是線程交互時,如果線程對一個同步對象x 發(fā)出一個wait()調(diào)用,該線程會暫停執(zhí)行,被調(diào)對象進(jìn)入等待狀態(tài),直到被喚醒或等待時間到。

23,Java有沒有g(shù)oto?

  Goto?java中的保留字,現(xiàn)在沒有在java中使用。

?

24,數(shù)組有沒有l(wèi)ength()這個方法? String有沒有l(wèi)ength()這個方法?

  數(shù)組沒有l(wèi)ength()這個方法,有l(wèi)ength的屬性。

  String有有l(wèi)ength()這個方法。

25,Overload和Override的區(qū)別。Overloaded的方法是否可以改變返回值的類型?

  方法的重寫Overriding和重載Overloading是Java多態(tài)性的不同表現(xiàn)。重寫Overriding是父類與子類之間多態(tài)性的一種表現(xiàn),重載Overloading是一個類中多態(tài)性的一種表現(xiàn)。如果在子類中定義某方法與其父類有相同的名稱和參數(shù),我們說該方法被重寫 (Overriding)。子類的對象使用這個方法時,將調(diào)用子類中的定義,對它而言,父類中的定義如同被“屏蔽”了。如果在一個類中定義了多個同名的方法,它們或有不同的參數(shù)個數(shù)或有不同的參數(shù)類型,則稱為方法的重載(Overloading)。Overloaded的方法是可以改變返回值的類型。

26,Set里的元素是不能重復(fù)的,那么用什么方法來區(qū)分重復(fù)與否呢? 是用==還是equals()? 它們有何區(qū)別?

  Set里的元素是不能重復(fù)的,那么用iterator()方法來區(qū)分重復(fù)與否。equals()是判讀兩個Set是否相等。

  equals()和==方法決定引用值是否指向同一對象equals()在類中被覆蓋,為的是當(dāng)兩個分離的對象的內(nèi)容和類型相配的話,返回真值。



阿輝 2006-09-02 01:19 發(fā)表評論
]]>
MyEclipse+struts+Hibernate配置開發(fā)(轉(zhuǎn)) http://www.tkk7.com/xixuui/archive/2006/09/02/67220.html阿輝阿輝Fri, 01 Sep 2006 17:16:00 GMThttp://www.tkk7.com/xixuui/archive/2006/09/02/67220.htmlhttp://www.tkk7.com/xixuui/comments/67220.htmlhttp://www.tkk7.com/xixuui/archive/2006/09/02/67220.html#Feedback0http://www.tkk7.com/xixuui/comments/commentRss/67220.htmlhttp://www.tkk7.com/xixuui/services/trackbacks/67220.html

  建議:

  如果你還不清楚struts和hibernate的一些基本原理,希望能先去了解一下這方面的相關(guān)內(nèi)容。

  推薦:

  Hibernate中文手冊》作者認(rèn)為要學(xué)Hibernate看這個就足夠了,里面幾乎包括了所有的細(xì)節(jié),不過可能不太適合快速入門。

  地址:http://www.hibernate.org/hib_docs/v3/reference/zh- cn/html_single/

  關(guān)于struts的資料就很多了,這里推薦一個可以下載一些入門教程的網(wǎng)站。

  地址:http://www.wnetw.com/jclub/index.jsp

  強(qiáng)烈建議入門的朋友先了解一下基本的原理!否則本文可能對你沒有任何幫助。

  相關(guān)工具下載:(注意版本)

  mysql5.0 http://www.mysql.org
  eclipse 3.1.1 http://www.eclipse.org
  myeclipse4.0.3 http://www.myeclipseide.com
  tomcat5.5

  安裝:

  關(guān)于tomcat和mysql的安裝就不多說了,需要注意的是最好保證你的 jdk是1.5的版本,并配置好你的環(huán)境變量,不然可能會遇到一些問題。

  把eclipse解開,再去安裝剛下載的myeclipse,在安裝的時候需要把路徑指定到剛才解開的eclipse上,由于myeclipse是個收費(fèi)軟件,所以需要注冊。不過一般按照Chinese的習(xí)慣,去google一個注冊碼就可以了:}

  開發(fā)環(huán)境部署:

  好了,現(xiàn)在保證你的mysql和tomcat服務(wù)能夠正常啟動,myeclipse能夠正常打開(如果不能,可以去找一下相關(guān)的說明或者給作者留言)。下面我們就要開始真正的開始部署一個傳說中的tomcat+struts+hibernate+mysql結(jié)構(gòu)的工程了!(faint!前言就寫的我好累)

  首先,在myeclipse里新建一個工程。在左邊的Package Exporler面版里點右鍵選擇new->project…

  在跳出菜單里選擇MyEclipse->J2EE Projects->Web Project。

  點擊next后進(jìn)入如下畫面:


  工程名為:test

  結(jié)束后點擊Finish。

  好了,如果成功的話你就會在 Package Exporler里看到一個新的test工程!現(xiàn)在我們先配置一下數(shù)據(jù)庫方面的東西。首先在你的mysql 里建立一個數(shù)據(jù)庫webases,再在里面新建一個表admin,里面三個字段分別為id,name,password其中id為自動取值的主鍵(mysql具體的操作可以自己找資料,不是本文涉及范圍)。

  再回到myeclipse ,選中window->Open Perspective->Other…

  可以看到現(xiàn)在跳出一個名為Select Perspective的菜單,在里面選中MyEclipse Databases Exporler,可以看到現(xiàn)在到了下面的頁面。

  按以上圖示輸入相關(guān)字段后點擊Finish便建立了一個數(shù)據(jù)庫連接,在新出現(xiàn)的JDBC for Mysql上點右鍵,選擇Open connection…,確認(rèn)用戶名和密碼正確后點OK,如果一切順利的話你會看到下面的畫面:

  這說明你已經(jīng)和數(shù)據(jù)庫建立了正確的連接。現(xiàn)在我們再回到window->Open Perspective- >Other…里的MyEclipse,也就是我們剛進(jìn)來的時候看到的畫面。

  右鍵點擊你剛建立的工程 test并選擇MyEclipse->Add struts Capabilities…在跳出的菜單里按照如下輸入并確定:

  好了,現(xiàn)在你已經(jīng)為你的工程增加了struts,接下來和上面一樣在右鍵工程后選擇MyEclipse- >Add Hibernate Capabilities…一路確定下來為你的工程添加Hibernate。(為方便起見我們在選擇路徑時把HibernateSessionFactory.java放在了src/com下面,其實最好建立個單獨的目錄如 src/com/hibernate)

  為了更好的演示我們不建立通常的登陸頁面而是建立個注冊頁面。選擇 src目錄下的hibernate.cfg.xml文件。照如下填寫并保存。這樣hibernate就為你建立了數(shù)據(jù)庫的連接池。

  下面我們再選擇WebRoot/WEB-INF/struts-config.xml文件,在畫面中點擊右鍵選擇new- >Form, Action and JSP。如下填寫

  再選擇JSP選項,如下

  最后選擇Finish。

  再新建一個一個success.jsp的頁面,

  在剛才struts- config.xml文件里右鍵選擇addAdmin選擇Properties,在菜單里選擇Forwords,再點add,如下圖填寫

  最后你的struts-config.xml就是下面這個樣子:


  下面我們轉(zhuǎn)到hibernate。換到剛才我們建立數(shù)據(jù)庫的頁面,選擇你的admin的表點右鍵選擇Create Hibernate Mapping。選擇好打包路徑后選擇Finish。如圖:

  在你剛才選擇的路徑下(我為方便是src/com/yourcompanyname/)下新建立的文件 AdminDAOFactory.java文件并輸入以下內(nèi)容:

package com.yourcompanyname;

import java.util.Iterator;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;

import com.hibernate.SessionFactory;

public class AdminDAOFactory {
?Session session;
?Transaction tx;
?public void add(Admin admin) throws HibernateException {
??/**
?? * Creation Date: 11-17-2005
?? * TODO Add a new admin user.
?? * @param An object of Admin
?? * @return void
?? * @author Coder Guo
?? */
??try {
???session = SessionFactory.currentSession();
???tx = session.beginTransaction();
???//Add a new admin
???session.save(admin);
???tx.commit ();
??}catch(HibernateException e){
???throw e;
??}finally{
???if (tx!=null) {
????tx.rollback();
???}
???SessionFactory.closeSession();
??}
?}
}

?再打開com.yourcompany.struts.action下的AddAdminAction.java添加(其中如果有錯誤選中好按ctrl+shift+o自動添加包)

public class AddAdminAction extends Action {

?// --------------------------------------------------------- Instance Variables

?// --------------------------------------------------------- Methods

?/**
? * Method execute
? * @param mapping
? * @param form
? * @param request
? * @param response
? * @return ActionForward
? * @author Coder Guo
? */
?public ActionForward execute(
??ActionMapping mapping,
??ActionForm form,
??HttpServletRequest request,
??HttpServletResponse response) {
??AddAdminForm addAdminForm = (AddAdminForm) form;
??
??// TODO Add a new admin
??Admin admin = new Admin();
??admin.setName(addAdminForm.getName ());
??admin.setPassword(addAdminForm.getPassword ());
??AdminDAOFactory adminDAO = new AdminDAOFactory ();
??adminDAO.add(admin);
??
??return mapping.findForward("success");
?}

}

?再打開com.yourcompanyname.struts.form下的AddAdminForm.java,修改(如果有錯誤按照上面說的方法導(dǎo)入包)
?public ActionErrors validate(
??ActionMapping mapping,
??HttpServletRequest request) {

??// TODO Auto-generated method stub
??ActionErrors errors = new ActionErrors();
??
??Session session = SessionFactory.currentSession();
??Transaction tx = session.beginTransaction ();
??Query query = session.createQuery("select admin from Admin as admin where admin.name = '" + this.name + "'");
??Iterator it = query.iterate ();
??if (it.hasNext()){
???errors.add ("addAdmin.err.name",new ActionMessage("form.addAdmin.err.name"));
??}
??tx.commit();
??SessionFactory.closeSession ();
??return errors;
?}

?public void reset(ActionMapping mapping, HttpServletRequest request) {

??// TODO Auto-generated method stub
??this.name=null;
??this.password=null;
?}

  再打開com\yourcompanyname\struts下的ApplicationResource.properties在這里面添加錯誤信息:

Form.addAdmin.err.name=err

  最后,(汗,好累啊-_-!)打開addAdmin.jsp修改成如下:

<%@ page contentType="text/html; charset=utf-8"%>
<%@ page language="java"%>
<%@ taglib uri="<%@ taglib uri="

<script language = "javascript">
<!--
function
check(){
?if (loginForm.userName.value == "" || loginForm.password.value == ""){
??alert("請輸入完整的信息!");
??loginForm.userName.focus();
??return false;
?}
}
//-->
</script>
?
?<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html:html>
? <head>
??? <html:base />
???
??? <title>login.jsp</title>
??? <link href="css/webcss.css" rel="stylesheet" type="text/css">
???
??? <meta http-equiv="pragma" content="no- cache">
??? <meta http-equiv="cache-control" content="no- cache">
??? <meta http-equiv="expires" content="0">???
??? <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
??? <meta http- equiv="description" content="This is my page">
? </head>
?

? <body>
? <center>
? ?<p>&nbsp;</p>
? ?<p>&nbsp;</p>
? ?<table width="300" border="0" cellpadding="0" cellspacing="0">
? ?<html:form action="/addAdmin" focus="name" method="GET">
??? ?<tr align="center" valign="middle">
????? ?<td colspan="2" class="typt_normal">新增管理員</td>
??? ?</tr>
??? ?<tr>
????? ?<td width="100" align="center" valign="middle" class="typt_normal">名稱: </td>
????? ?<td width="200" align="left"><html:text property="name" styleClass="text_s"/><html:errors property="addAdmin.err.name"/></td>
??? ?</tr>
??? ?<tr>
????? ?<td width="100" align="center" valign="middle" class="typt_normal">密碼: </td>
????? ?<td width="200" align="left"><html:password property="password" styleClass="text_s"/></td>
??? ?</tr>
??? ?<tr>?
????? ?<td colspan="2" align="center" valign="middle"><html:submit value="提交" onclick="return check ();"/><html:reset value="重置"></html:reset></td>
????? ?</tr>
?</html:form>
? ?</table>
?</center>
?</body>

</html:html>

  其中可以看到如何在struts的標(biāo)簽中使用javascript的方法。

  配置好myeclipse于tomcat的連接。在window->Preferences做如下設(shè)定:

  在項目文件點右鍵->“myeclipse”->“Add and remove project deployment”,如下圖:

  好了,我們的配置工作基本結(jié)束了,在myeclipse上開啟tomcat服務(wù)

  現(xiàn)在打開瀏覽器,輸入

  http://127.0.0.1:8080/test/addAdmin.jsp就可以看到你的jsp頁面了!



阿輝 2006-09-02 01:16 發(fā)表評論
]]>
常用數(shù)據(jù)庫JDBC連接寫法(轉(zhuǎn)) http://www.tkk7.com/xixuui/archive/2006/08/30/66745.html阿輝阿輝Wed, 30 Aug 2006 15:43:00 GMThttp://www.tkk7.com/xixuui/archive/2006/08/30/66745.htmlhttp://www.tkk7.com/xixuui/comments/66745.htmlhttp://www.tkk7.com/xixuui/archive/2006/08/30/66745.html#Feedback0http://www.tkk7.com/xixuui/comments/commentRss/66745.htmlhttp://www.tkk7.com/xixuui/services/trackbacks/66745.html1. MySQL(http://www.mysql.com)mm.mysql-2.0.2-bin.jar
Class.forName( "org.gjt.mm.mysql.Driver" );
cn = DriverManager.getConnection( "jdbc:mysql://MyDbComputerNameOrIP:3306/myDatabaseName", sUsr, sPwd );   閱讀全文

阿輝 2006-08-30 23:43 發(fā)表評論
]]>
主站蜘蛛池模板: 国产V亚洲V天堂A无码| 亚洲人成网站在线播放vr| 国产精品V亚洲精品V日韩精品| 黄色一级视频免费观看| 性生交片免费无码看人| 久久亚洲精品无码网站| 久久亚洲精品无码播放| 91av免费观看| 猫咪免费人成网站在线观看入口 | 国产成人亚洲精品蜜芽影院| 免费视频中文字幕| 天堂在线免费观看| 国产成人A亚洲精V品无码| 中文字幕免费视频| 亚洲中文无码线在线观看| 久久久久久99av无码免费网站 | 亚洲日本va在线视频观看| 日韩在线视频播放免费视频完整版| 亚洲精品无码鲁网中文电影| 一区二区三区四区免费视频 | 亚洲av无码成h人动漫无遮挡| 久久久久久精品成人免费图片| 亚洲国产高清视频| 免费精品国产自产拍观看| 久久国产乱子免费精品| 人人狠狠综合久久亚洲| 国产男女猛烈无遮挡免费视频| 国产成人久久AV免费| 亚洲三级电影网址| 免费av欧美国产在钱| 亚洲狠狠色丁香婷婷综合| 国产精品视频免费一区二区三区| 亚洲成av人片在www鸭子| 国产青草视频在线观看免费影院| 国内精品免费视频精选在线观看| 亚洲第一成年网站视频| 亚洲M码 欧洲S码SSS222| 国产1000部成人免费视频| 国产精品亚洲精品| 亚洲精品在线免费观看视频| 免费国产成人午夜电影|