J2EE導論 | 疑惑篇
J2EE是Java程序員從新手進階的一個必經之路。要體會所謂的工業級代碼,就必須要融入和經歷更為復雜的開發、部署環境,需要同更多的模塊、組件做信息流交換,比較和使用不同的框架,逐一去琢磨和考察它們的必要性及優缺點。
這樣一種進階,注定了其過程必然是痛苦的。這不僅是因為你要掌控和關注的細節、模塊一下子陡然攀升,更因為這些增加的細節和模塊背后都蘊含著各種復雜的理論知識:網絡、web、程序構建。如果再考慮到你要使用的計算機,從一臺PC變成多臺服務器的交互,而部署環境從一直使用的eclipse自動化,變成多臺Linux的部署,各種不適合不理解一下子都全部爆發,實在是巨大的挑戰。
還記得當初最開始學習J2EE的時候,沒用到一個月時間,就從入門走向了放棄。太多繁雜的部署和配置文件,理論知識又弄得來似是而非,更為要命的是當初根本沒有什么軟件工程的思想和意識,就簡單粗暴地把這些繁瑣工作扣上了一個“苦力”的帽子。并且自我安慰道:這么多復雜的零碎,不就是農民工搬磚么,果然是碼農,我才不走這樣的路。而完全沒有意識到,這正是軟件工程思想的匱乏所導致的。
正是因為事務性的東西太多,所以你才需要有出色的工程能力,運用你的謀篇布局將復雜的管理任務,通過各種工具、技巧和構架,把它們逐一消磨,從而讓所有的細節都在自己的掌控之中,有條不紊地把一項浩繁的工程管理好。
我想,這一思想是一名優秀的軟件工程師,也是J2EE入門所必備的 ,那就是控制復雜度是所有工程師最本質的任務。如果出現了細節太過繁雜,讓自己深陷其中而無法解脫時,就一定要停下來跳出去思考,自己的整個工作流程應該做怎樣的優化和改進,應該如何重構自己的流程和組織,從而把整個團隊和工作流程理順,發揮出他們應有的實力。
也即是,當你面對復雜問題的時候,你不會用消極的放棄或者粗暴的貶低來逃避復雜度失控的現實,而是會更加積極地去尋求改進方案,讓自己更有條理更高效地完成任務。
懷揣著這一思想,就可以更為深入地探討J2EE對新人的挑戰和隱藏的深坑。在我看來學習Java,對新手來講有這么幾個坑:
1、不關注Java命令的運行
因為Eclipse的大而全,從而完全不會使用java的命令行,更不知道Java參數是些什么鬼。
或許一般的教科書會談到一點如何通過命令行去運行Java,但緊接著,后面會補充道,有了Eclipse我們就不需要關注這些繁瑣的細節。然后把Java命令行的東西永遠地拋到腦后。
話是沒錯,有了Eclipse,誰還會去關注那堆交互極差的命令行?
可正如我在前面所說,當你運行的機器,從個人PC變成了遠程端的Linux Server,你還能不關注命令行嗎?甚至,讓我問一個更為傻氣但往往卻能戳中新手痛點的一個問題:你使用的Linux Server端,很可能連圖形界面都沒有,請問如何使用你熟悉而又引以為傲的Eclipse呢?進一步,Eclipse都沒有,請問你如何debug呢?又如何加斷點,做你習以為常的單步調試,看著一條條的黃色加亮行debug?
從這個角度講,你或許就能夠理解:為什么單步調試并不總是一個好的方法。同樣地,為什么你需要學習不同的調試技術,為什么需要學會怎么寫log又如何依靠log來做debug。種種這些說法和論調,都會因為你使用工具、計算機的環境的改變而改變。
為什么你以前無法理解這些東西?
因為你以前只會使用一臺PC,不會同遠程端的Server打交道。更沒有什么嚴肅的工作和需求,逼迫你同Server打交道。即便是在PC上安裝了Linux,你或許也會困惑,為什么要用這堆東西呢?都說Linux好,可為什么自己感覺不到呢?原因就在于,Linux的通常使用環境,并不是作為個人PC來用的。它更多的是被當做Server端的操作系統來使用。你連使用場景都弄錯了,那又怎么可能理解和體會Linux的好處?
回到我文章開頭的那句話,我說“J2EE是Java程序員從新手進階的一個必經之路”。那么現在,我能更好地給出這個論斷的理由:因為有了J2EE相關項目的介入,你終于可以在一個真實需求的情境下,開始逐一發現你使用計算機的不同情況,進而真正去體會不同的論斷和說法。例如,這個部分我提到的關于Eclipse的那些問題。
所以,所謂的為什么軟件工程師需要實操、需要有真實的工作經驗,為什么它們有時候比學校的理論來得重要。這就是因為,“工作”本身會為你提供一個真實的需求,而不是學校書本里自己臆想的一個偽需求,來讓你一個個地去體會真實世界中的限制,進而再看到那些曾經在書本上但卻不以為意的解決方案或工具時,便會有一種大夢初醒的感覺。
2、不知道Java運行的是什么
同樣是因為過于依賴大而全的Eclipse,你逐漸會“忘記”,你運行Java的時候,到底在運行什么?;蛟S,你早已在書本上看過,Java源代碼需要經過編譯變成class字節碼,再由JVM把這堆字節碼變成所在平臺的機器碼,進而這堆機械碼被加載進內存運行。
可一旦要在Server端部署代碼,新手的第一反應很可能就是我上面提到的:我的Eclipse在哪里?沒有了Eclipse,我的Java怎么運行?
這其實就是完全沒有真正理解上面說的Java運行機制。要運行起來Java,有了JVM、有了class文件就夠了啊,你要Eclipse干嘛?
更進一步:OK,就算有class,我不需要通過Eclipse來做編譯,可那些jar包的依賴怎么玩兒?每次的jar的依賴都是靠Eclipse來做的連接,沒有了它,依賴關系怎么做?
這就又回到了第一部分提到的,根本不懂如何使用Java的命令行,更加不知道Java參數是些神馬鬼。更本質來講,你并不清楚Eclipse為你封裝、簡化的服務是些什么。你不了解,在Eclipse的背后,到底調動了那些命令來指揮你程序的運行,而這些調動的東西,如果不通過Eclipse又該通過什么方式被實現?
或許你可以辯解道,我曾經的編程工作確實不需要了解這些底層啊,因為了解了也沒用,我還是會用Eclipse來簡化我的工作。
所以咯,這就是學習J2EE的價值,強迫你弄懂這些細節,并且真的會在Server端的部署和開發中運用到。你不得不關注這些Java的依賴和build,從而更深入地理解Java的運行方式,進而才可以體會到為什么需要所謂的部署工具,從最簡單的makefile,到比較流行的Ant、Maven等。
3、服務器端的Java入口在那兒
這是另一個有點玄乎的問題,但同樣是因為長期在Eclipse環境下做開發導致的。要開發、測試你的程序,那么第一步,你至少要讓它運行起來。那么,通常的做法是什么呢?
那當然是在Eclipse中點開某個具有main函數的java文件,然后點擊Eclipse的運行按鈕。
等到了J2EE的環境下,你會驚訝地發現,你竟然不知道如何將自己寫的這堆代碼給跑起來。一來當然是因為那個老問題,Server端沒有Eclipse,我如何點擊運行按鈕?
再來,就算我知道可以通過Java命令行來開啟一個Java程序的運行,可是,隨便拿來一套J2EE的源代碼,你竟然找不到一個類是有main函數的!
這可一下子就傻眼了,main函數都沒有,你讓我如何使用Java命令行把整個代碼啟動起來?
且等后面再回答這個問題,讓我們再提一個有著相同理由的另一個問題。
4、數量繁多的配置文件和互補相關的源代碼
讓J2EE從新手走向放棄的另一大關鍵,就是“數量繁多的配置文件”和看起來“互不相關的源代碼”。隨便拿到一個J2EE的項目,就會發現各種xml和獨特格式的文件滿天飛。而隨便找一個java文件讀一段,就更加莫名其妙,似乎這個文件就是獨立存在的,沒有和別的java類的交互,聲明自己有哪些變量、提供好自己的setter/getter,然后,就TM沒有然后了!或許你以為這只是個特殊的文件,又接連抓過幾個java文件來看,發現都是這樣的風格。如此種種,當然會把一個newbie逼到抓狂。
你會因為無法把這些配置文件和類文件的功能連起來而抓狂,又同樣因為要不斷地切入切出各種種類繁多的文件類型而焦躁:搞這么多的文件類型的目的是什么?為什么需要它們、為什么需要這些獨立又互不關聯的文件?
要理解這個,就必須回到我們最開始說的關于工程師本質目標的思想:控制復雜度。
控制復雜度最基本的技術就是:分而治之,把一個復雜的問題分解為獨立的子問題。
這是一個看起來簡單,實則深不見底的技術。甚至可以這樣夸張地說,所有的工程上控制復雜度的技術,都是對這一條的直接/間接地使用,又或是通過復雜的其它技術的輔助,來實踐這一條技術。
將問題分而治之,有很多好處,其重要的就兩條:
-
一是把問題分解后,你就可以不必直接面對一個大問題,從而可以更好地通過各個擊破的方式將它解決。用最通俗的話來講,就是飯要一口一口地吃。你不會直接把一大碗飯倒入嘴里,而是各個擊破。
-
另一個是,當你把問題分解成獨立的子問題后,那么復雜度就從系統性的關聯復雜性,轉變為了一個個小模塊各自的復雜度。因為這個獨立性,你才得以獲得更好的穩定性。因為,就算是一個模塊突然出現了問題,由于它的獨立性,便可以只把損失限定在它這個模塊里,不會影響到系統別的方面。以這樣的方式,實實在在地把問題,限定在了一個更小的范圍,從而控制住了復雜度。
那么,配置文件、互不相關的源文件、以及Server端的J2EE代碼竟然沒有main函數,其實都是一系列關于“設計模塊、系統構架”的綜合技術對這一思想的體現。它們無疑都是為“分而治之”控制復雜度而服務的。
所以,當你有了這些疑問時,其實是最好的學習設計模式和系統構架的機會。因為你有了一個真實場景,從而會立刻能感受到現實的限制條件對你的逼迫。此時,你將會為這些限制而焦頭爛額。如果這時候,你去研究一下業界的成熟解決方案,就會很快發現它們都會和設計模式、系統設計搭上線。進而,你便能夠勢如破竹地理解清楚這些技術的精髓和存在的意義。
5、繁多的理論知識
由于J2EE涉及的環境很多,又是web應用,那么最基本的一點,便是網絡、web、Server端的軟件、Client端的軟件他們之間有什么區別和聯系。
還記得我最開始學習J2EE的時候,那簡直是胡子眉毛一把抓,且不說把網絡和web各種混淆,就連互聯網產品和傳統IT技術產品的區別都傻傻分不清楚。結果便是,各種概念混用。
而大部分的資料,會一個個地講解browser的運行方式,講解HTTP多么高深莫測,又提到Tomcat的Servlet多么本質,又或是Spring框架多么方便和利劍出鞘。可TM從來沒有誰把他們串起來,好好地說明他們的職能位置在哪里,在一條生產流水線的位置在哪里。
或許,這是因為這個東西恰好處在一個微妙的尷尬之地:會的人,會覺得這個東西太過簡單,拿出講解或許沒啥技術含量,有點不好意思。而不會的人呢,任憑他看多少細節的東西,反正就是不能把各個模塊安放在正確的位置,便總是打不通任督二脈,干著急。
我想,我的一個重要任務,便是對這些關聯性的東西,做一個細致的宏觀review,反正我的臉皮比較厚,不怕diss。
理清楚了這些潛藏在newbie內心模糊的疑問,我們才能在下一篇開始比較系統的自頂向下的技術細節討論。
不要小看這些問題的梳理。往往,一個newbie從入門走向放棄,就是因為感覺極端模糊,感覺到處都是問題,進而開始展開聯想,懷疑是不是自己有問題。而如果能夠理清楚自己的問題真正在哪里,就如同分而治之的思想那樣,你便能夠做到心中有數,只需要把不清晰的技術點,逐一攻破就好了,沒什么天塌下來的大事情。
近期回顧
《前端技術的碎碎念》
《放眼望去都是痛》
《網絡概念與快遞物流》
如果你喜歡我的文章或分享,請長按下面的二維碼關注我的微信公眾號,謝謝!

更多信息交流和觀點分享,可加入知識星球:

VIP贊賞專區:

浙公網安備 33010602011771號