顯示在Client端的Flex介面是靠Macromedia Flash Player呈現的.
Flex基本的組成元件有:
- XML:描述AP介面
- ECMA Script Language(ActionScript):用MXML去處理System event和建構複雜的data model
- Class library
- Runtime service
- 編譯時會從MXML產生SWF檔案
顯示在Client端的Flex介面是靠Macromedia Flash Player呈現的.
Flex基本的組成元件有:
rmic 功能說明:
rmic 為遠端物件生成 stub 和 skeleton。 語法:
rmic [ options ] package-qualified-class-name(s) 補充說明:
rmic 編譯器根據編譯後的 Java 類(含有遠端物件實現)名,為遠端物件生成 stub 和 skeleton(遠端物件是指實現 java.rmi.Remote 介面的物件)。在 rmic 命令中所給的類必須是經 javac 命令成功編譯且是完全包限定的類。 命令選項
-classpath[路徑] 指定 rmic 用於查詢類的路徑。如果設置了該選項,它將覆蓋缺省值或 CLASSPATH 環境變數。目錄用冒號分隔。
-d[目錄] 指定類層次的根目錄。此選項可用來指定 stub 和 skeleton 檔的目標目錄。
-depend 使編譯器考慮重新編譯從其他類引用的類。 一般來說,它只重新編譯從源代碼引用的遺漏或過期的類。
-g 允許生成調試表格。調試表格含有行號和局部變數的有關資訊,即 Java 調試工具所使用的資訊。缺省情況下,只生成行號。
-J 與 -D 選項聯用,它將緊跟其後的選項( -J 與 -D 之間無空格)傳給 java 解釋器。
-keepgenerated 為 stub 和 skeleton 檔保留所生成的 .java 原始檔案,並將這些原始檔案寫到與 .class 檔相同的目錄中,如果要指定目錄,則使用 -d 選項。
-nowarn 關閉警告。如果使用該選項,則編譯器不輸出任何警告資訊。
-show 顯示 rmic 編譯器的 GUI(圖形用戶介面)。輸入一個或多個包限定類名(以空格分隔),並按回車鍵或“顯示”按鈕,創建 stub 和 skeleton。
-vcompat (缺省值)創建與 JDK 1.1 和 1.2 stub 協議版本都相容的 stub 和 skeleton。
-verbose 使編譯器和鏈結器輸出關於正在編譯哪些類和正在載入哪些類檔的資訊。
-v1.1 創建 JDK 1.1 stub 協議版本的 stub 和 skeleton。
-v1.2 只創建 JDK 1.2 stub 協議版本的 stub。
rmid 功能說明:
rmid 啟動啟動系統守護進程,以便能夠在 Java 虛擬機上註冊和啟動物件。 語法:
rmid [-port port] [-log dir] 補充說明:
rmid 工具啟動啟動系統守護進程。必須先啟動啟動系統守護進程,才能向啟動系統註冊可被啟動的物件或在 Java 虛擬機上啟動可被啟動的物件。 命令選項
-C<某些命令行選項> 指定一個選項,在創建每個 rmid 的子守護進程(啟動組)時,該選項以命令行參數的形式傳給該子守護進程。
-log[目錄] 指定目錄的名稱,啟動系統守護進程在該目錄中寫入其資料庫及相關資訊。缺省狀態下,將在執行 rmid 命令的目錄中創建一個 log 目錄。
-port[埠] 指定 rmid 的註冊服務程式所使用的埠。啟動系統守護進程將 ActivationSystem 與該註冊服務程式中的名稱java.rmi.activation.ActivationSystem 捆綁在一起。
-stop 停止 -port 選項所指定埠上的當前 rmid 調用。若未指定埠,則將停止在埠 1098 上運行的 rmid。
rmiregistry 功能說明:
rmiregistry 命令可在當前主機的指定埠上啟動遠端物件註冊服務程式。 語法:
rmiregistry [port] 補充說明:
rmiregistry 命令在當前主機的指定 port 上創建並啟動遠端物件註冊服務程式。如果省略 port,則註冊服務程式將在 1099 埠上啟動。rmiregistry 命令不產生任何輸出而且一般在後臺運行。遠端物件註冊服務程式是自舉命名服務。主機上的 RMI 伺服器將利用它將遠端物件綁定到名字上。客戶機即可查詢遠端物件並進行遠端方法調用。註冊服務程式一般用於定位應用程式需調用其方法的第一個遠端物件。該物件反過來對各應用程式提供相應的支援,用於查找其他物件。java.rmi.registry.LocateRegistry 類的方法可用於在某台主機或主機和埠上獲取註冊服務程式操作。java.rmi.Naming 類的基於 URL 的方法將對註冊服務程式進行操作,並可用于查詢遠端物件、將簡單(字串)名稱綁定到遠端對象、將新名稱重新綁定到遠端對象(覆蓋舊綁定)、取消遠端對象的綁定以及列出綁定在註冊服務程式上的 URL。
serialver 功能說明:
serialver 命令返回 serialVersionUID。 語法:
serialver [ 命令選項 ] 補充說明:
serialver 以適於複製到演變類的形式返回一個或多個類的 serialVersionUID。不帶參數調用時,它輸出用法行。 命令選項
-show 顯示一個簡單的用戶介面。輸入完整的類名並按回車鍵或“顯示”按鈕可顯示 serialVersionUID。
jarsigner 功能說明: 為 Java 歸檔 (JAR) 檔產生簽名,並校驗已簽名的 JAR 檔的簽名。 語法:
jarsigner [ 命令選項 ] jar-file alias
jarsigner -verify [ 命令選項 ] jar-file 補充說明:
jarsigner 工具用於兩個目的:
1:為 Java 歸檔 (JAR) 檔簽名
2:校驗已簽名的 JAR 檔的簽名和完整性 命令選項
-keystore[url] 指定密鑰倉庫的 URL。缺省值是用戶的宿主目錄中的 .keystore 檔,它由系統屬性“user.home”決定。
-storetype[storetype] 指定要被實例化的密鑰倉庫類型。默認的密鑰倉庫類型是安全屬性檔中 "keystore.type" 屬性值所指定的那個類型,由 java.security.KeyStore 中的靜態方法 getDefaultType 返回。
-storepass[password] 指定訪問密鑰倉庫所需的口令。這僅在簽名(不是校驗)JAR 檔時需要。在這種情況下,如果命令行中沒有提供 -storepass 選項,用戶將被提示輸入口令。
-keypass[password] 指定用於保護密鑰倉庫項(由命令行中指定的別名標出)的私鑰的口令。使用 jarsigner 為 JAR 檔簽名時需要該口令。如果命令行中沒有提供口令,且所需的口令與密鑰倉庫的口令不同,則將提示用戶輸入它。
-sigfile[file] 指定用於生成 .SF 和 .DSA 文件的基本檔案名。
-signedjar[file] 指定用於已簽名的 JAR 檔的名稱。
-verify 如果它出現在命令行中,則指定的 JAR 檔將被校驗,而不是簽名。如果校驗成功,將顯示“jar verified”。如果試圖校驗未簽名的 JAR 檔,或校驗被不支援的演算法(例如未安裝 RSA 提供者時使用的 RSA)簽名的 JAR 檔,則將有如下顯示: "jar is unsigned. (signatures missing or not parsable)" 。
-certs 如果它與 -verify 和 -verbose 選項一起出現在命令行中,則輸出將包括 JAR 檔的每個簽名人的證書資訊。
-verbose 如果它出現在命令行中,則代表“verbose”模式,它使 jarsigner 在 JAR 簽名或校驗過程中輸出額外資訊。
-internalsf 過去,JAR 檔被簽名時產生的 .DSA(簽名塊)檔包含一個同時產生的 .SF 檔(簽名檔)的完整編碼副本。這種做法已被更改。為了減小輸出 JAR 檔的整個大小,缺省情況下 .DSA 檔不再包含 .SF 檔的副本。但是如果 -internalsf 出現在命令行中,將採用舊的做法。該選項主要在測試時有用;實際上不應使用它,因為這樣將消除有用的優化。
-sectionsonly 如果它出現在命令行中,則 JAR 檔被簽名時生成的 .SF 檔(簽名檔)將不包括含有整個清單檔的散列的頭。它僅包含 與 JAR 中每個單獨的原始檔案相關的資訊和散列。該選項主要在測試時有用;實際上不應使用它,因為這樣將消除有用的優化。
-J[javaoption] 將指定的 javaoption 串直接傳遞到 Java 解釋器。((jarsigner 實際上是解釋器的一個 “wrapper”)。該選項不應含有任何空格。它有助於調整執行環境或記憶體使用。要獲得可用的解釋器選項的清單,可在命令行鍵入 java -h 或 java -X。
keytool 功能說明: 管理由私鑰和認證相關公鑰的 X.509 證書鏈組成的密鑰倉庫(資料庫)。還管理來自可信任實體的證書。 語法:
keytool [ 命令 ] 補充說明:
keytool 是個密鑰和證書管理工具。它使用戶能夠管理自己的公鑰/私鑰對及相關證書,用於(通過數位簽名)自我認證(用戶向別的用戶/服務認證自己)或資料完整性以及認證服務。它還允許用戶儲存他們的通信對等者的公鑰(以證書形式)。
native2ascii 功能說明: 將含有本地編碼字元(既非 Latin1 又非 Unicode 字元)的檔轉換為 Unicode 編碼字元的檔。 語法:
native2ascii [options] [inputfile [outputfile]] 補充說明:
Java 編譯器和其他 Java 工具只能處理含有 Latin-1 和/或 Unicode 編碼(udddd 記號)字元的檔。native2ascii 將含有其他字元編碼的檔轉換成含 Latin-1 和/或 Unicode 編碼字元的檔。若省略 outputfile,則使用標準輸出設備輸出。此外,如果也省略 inputfile,則使用標準輸入設備輸入。 命令選項
-reverse 執行相反的操作:將含 Latin-1 和/或 Unicode 編碼字元的檔轉換成含本地編碼字元的檔。
-encoding[encoding_name] 指定轉換過程使用的編碼名稱。缺省的編碼從系統屬性 file.encoding 中得到。
appletviewer 功能說明:
Java applet 流覽器。appletviewer 命令可在脫離萬維網流覽器環境的情況下運行 applet。 語法:
appletviewer [ threads flag ] [ 命令選項 ] urls ... 補充說明:
appletviewer 命令連接到 url 所指向的文檔或資源上,並在其自身的視窗中顯示文檔引用的每個 applet。注意:如果 url 所指向的文檔不引用任何帶有 OBJECT、EMBED 或 APPLET 標記的 applet,那麼 appletviewer 就不做任何事情。 命令選項
-debug 在 Java 調試器 jdb 中啟動 appletviewer,使您可以調試文檔中的 applet。
-encoding[編碼名稱] 指定輸入 HTML 檔的編碼名稱。
-J[javaoption] 將 javaoption 字串作為單個參數傳給運行 appletviewer 的 Java 解釋器。參數不能含有空格。由多重參數組成的字串,其中的每個參數都必須以首碼 -J 開頭,該首碼以後將被除去。這在調整編譯器的執行環境或記憶體使用時將很有用。
extcheck 功能說明:
extcheck 檢測目標 jar 檔與當前安裝方式擴展 jar 檔間的版本衝突。 語法:
extcheck [ -verbose ] targetfile.jar 補充說明:
extcheck 實用程式檢查指定 Jar 檔的標題和版本與 JDK TM 軟體中所安裝的擴展是否有衝突。在安裝某個擴展前,可以用該實用程式查看是否已安裝了該擴展的相同版本或更高的版本。
extcheck 實用程式將 targetfile.jar 檔清單的 specification-title 和 specification-version 頭與當前安裝在擴展目錄下所有 Jar 檔的相對應的頭進行比較(缺省擴展目錄為 jre/lib/ext)。extcheck 實用程式比較版本號的方式與 java.lang.Package.isCompatibleWith 方法相同。若未檢測到衝突,則返回代碼為 0。如果擴展目錄中任何一個 jar 檔的清單有相同的 specification-title 和相同的或更新的 specification-version 號,則返回非零錯誤代碼。如果 targetfile.jar 的清單中沒有 specification-title 或 specification-version 屬性,則同樣返回非零錯誤代碼。 命令選項
-verbose 對擴展目錄中的 Jar 檔進行檢查時,列出檔。此外,還報告目標 jar 檔的清單屬性及所有衝突的 jar 檔。
jar 功能說明:
Java歸檔工具 語法:
jar [ 命令選項 ] [manifest] destination input-file [input-files] 補充說明:
jar 工具是個java應用程式,可將多個檔合併為單個JAR歸檔檔。jar是個多用途的存檔及壓縮工具,它基於ZIP和ZLIB壓縮格式。然而,設計 jar的主要目的是便於將java applet或應用程式打包成單個歸檔檔。將applet或應用程式的元件(.class 檔、圖像和聲音)合併成單個歸檔檔時,可以用java代理(如流覽器)在一次HTTP事務處理過程中對它們進行下載,而不是對每個元件都要求一個新連接。這大大縮短了下載時間。jar還能壓縮檔,從而進一步提高了下載速度。此外,它允許applet的作者對檔中的各個項進行簽名,因而可認證其來源。jar工具的語法基本上與tar命令的語法相同。 命令選項
-c 在標準輸出上創建新歸檔或空歸檔。
-t 在標準輸出上列出內容表。
-x[file] 從標準輸入提取所有檔,或只提取指定的檔。如果省略了file,則提取所有檔;否則只提取指定檔。
-f 第二個參數指定要處理的jar檔。在-c(創建)情形中,第二個參數指的是要創建的jar檔的名稱(不是在標準輸出上)。在-t(表(
最近看到台灣高鐵的徵人廣告
就和 leader 閒聊
在我們閒聊的期間
我們分析了台灣高鐵的客戶群
我們覺得臺灣高鐵的客戶群應該是一些商務的人士
不過要賺錢的話應該會很拼吧
畢竟我們都覺得所花的錢和所買來的價值並不划算
但是卻會使高鐵附近的商家或地價繁榮起來
這就是金山理論
在早期人家都說舊金山產金,不過到那邊真正滔的到金的畢竟還是在少數
反而那邊的商家荷包飽飽
所以我也覺得會使附近的商家或地價上漲
至於高鐵會不會賺錢,則得看營運後的策略了。
今天聊到在 Excel 寫 VBA
在業界 Excel 是一個很重要的軟體
因為 Excel 的試算功能以及資料庫結合的很不錯
導致很多公司利用它來製作報表
前提當然是要寫個 VBA 囉!否則這就沒意義了
不管幾個報表,寫個 Add in,提供一些報表清單給 user
真的對企業來講是個不錯的工具
而且花費應該也是比較省的
聊到這突然發現 MS 的 Office System 真是強大
因為 Office 幾乎都可以做
若把 Office System 給玩透了話,再加上客製化的 add in,肯定比自己寫一套 AP 好用
可以把普通的Java程式做成真正的exe,也就是單一個exe就可以在沒有安裝JVM的機器上運行。這樣的工具常見的有JET和gcj.前者是收費的,而且做出來的exe還是需要一堆dll我比較推薦使用gcj. http://www.thisiscool.com/gcc_mingw.htm他有windows和Linux版,直接下載zip包,不需要安裝,裏面有不少例子,一些build的批次檔案。
從原理來說gcj自己實現了JVM規範,也就是你編寫一個HelloWorld.java,其中的main方法為System.out.println("foo");當使用gcj把它做成exe(大約2M),運行這個exe時,會啟動裏面的一個小型jvm,在這上面跑HelloWorld
//曾有人把整個eclipse ide用gjc做成了linux gtk下的native程式
至於圖示,我一年多前用gcj時似乎不支援,不過好像有不少win32的程式可以抽取和更改exe的圖示
其實,把Java做成純exe實在是 吃力不討好 。 有很多限制,檔又大
我比較傾向另幾種做法:
. 使用InstallAnywhere等工具,製作一個exe的安裝包用戶可以選擇使用他機器上的JRE或是這個安裝包內的JRE來運行程式這是很常見的一種做法,如JBuilder就是這麼做的。這樣的好處是不要求對方機器上裝有JRE,而且你原來的程式不需要任何改動。
InstallAnywhere中一個壓縮的JRE大概是8M
. 製作成可執行的jar,也就是在META-INF的MANIFEST檔制定Main-Class可以通過命令行java -jar jarfile.jar來執行,windows默認的把*.jar使用javaw -jar打開,所以有些機器上可以直接雙擊jar運行。
. 制作偽exe,其實和上一種做法是一樣的,只不過做成exe,調用系統的java.exe來運行它,這樣的工具有nativeJ,exe4j等
btw,像JET/gcj這樣的技術是很先進的,.NET在運行機制上和Java類似,但到現在還是沒有成熟的做成真正exe的工具一定程度上也說明微軟對.NET的信心,以及把基於運行時的軟體做成純exe的意義不大
剛接觸java很容易產生你這樣的想法等你Java瞭解多了,就會感覺到Java不像VB,Delphi只是一個語言,而是一個平臺。
jar是最常用的部署單元,做成exe沒什麼意思。
-- Bill Joy MIT BBS上說微軟電話面試的一道題就是“Who do you think is the best coder, and why?”。我覺得挺有意思的,也來湊個熱鬧。排名不分先後。心目中的編程高手 (1)
Bill Joy, 前任Sun的首席科學家,當年在Berkeley時主持開發了最早版本的BSD。他還是vi和csh的作者。當然,Csh Programming Considered Harmful 是另一個話題樂。據說他想看看自己能不能寫個作業系統,就在三天裏寫了個自己的Unix, 也就是BSD的前身。當然是傳說了,但足見他的功力。另一個傳說是,1980年初的時候,DARPA讓BBN在Berkley Unix里加上BBN開發的TCP/IP代碼。但當時還是研究生的B伯伯怒了,拒絕把BBNTCP/IP加入BSD,因為他覺得BBN的TCP/IP寫得不好。於是B伯伯出手了,端的是一箭封喉,很快就寫出了高性能的伯克利版TCP/IP。當時BBN和DARPA簽了巨額合同開發TCP/IPStack,誰知他們的代碼還不如一個研究生的好。於是他們開會。只見當時B伯伯穿個T-shirt出現在會議室(當時穿T-shirt不象現在,還是相當散漫的哈)。只見BBN問:你怎麼寫出來的?而B伯伯答:簡單,你讀協議,然後編程就行了。最令偶暈倒的是,B伯伯碩士畢業後決定到工業界發展,於是就到了當時只有一間辦公室的Sun, 然後他就把Sparc設計出來樂。。。象這種軟硬通吃的牛人,想不佩服都不行的說。據Bill Joy的同事說,一般開會的時候B伯伯總是拿一堆雜誌漫不經心地讀。但往往在關鍵之處,B伯伯發言,直切要害,提出漂亮的構想,讓同事們徹底崩潰。對了,他還是Java Spec和JINI的主要作者之一。心目中的編程高手 (2)
-- John Carmack John Carmack,id Software的founder和Lead Programmer。上個月和一個搞圖形的師兄聊天,他竟然不知道John Carmack, 也讓偶大大地暈了一把。不過也許搞研究的和搞實戰的多少有些隔吧。想必喜歡第一人稱射擊遊戲的都知道J哥哥。90年代初只要能在PC上搞個小動畫都能讓人驚歎一番的時候,J哥哥就推出了石破天驚的Castle Wolfstein, 然後再接再勵,doom, doomII, Quake...每次都把3-D技術推到極致。J哥哥的簡歷上說自己的專長是"Exhaust 3-D technology",真是牛人之言不我欺的說。做J哥哥這樣的人是很幸福的,因為各大圖形卡廠家一有了新產品就要向他“進貢” ,不然如果他的遊戲不支持哪種卡,哪種卡基本就會夭折樂。當初MS的Direct3D也得聽取他的意見,修改了不少API。當然,J哥哥在結婚前十數年如一日地每天編程14小時以上,也是偶們凡人望塵莫及的。對了,J哥哥高中肆業(?),可以說是自學成才。不過呢,誰要用這個例子來為自己學習不好辯護,就大錯特錯了。那 Leonardo Da Vinci還是自學成才呢(人是私生子,不能上學)。普通人和天才還是有區別的。對了,其實偶們叫“達分奇”是相當不對的,因為Vinci是地名,而Da Vinci就是從Vinci來的人的意思。換句話說,Leonardo Da Vinci就是“從Vinci來的Leonardo”的意思。叫別人“Da Vinci”就不知所謂樂。嗯,扯遠了,打住。心目中的編程高手 (3)
-- David Cutler David Cutler,VMS和Windows NT的首席設計師,去微軟前號稱矽谷最牛的kernel開發員。當初他和他的手下在微軟一周內把一個具備基本功能的bootable kernel寫出來,然後說:“who can't write an OS in a week?",也是牛氣沖天的說。順便說一句,D爺爺到NT3.5時,管理1500名開發員,自己還兼做設計和編程,不改coder本色啊。D爺爺天生脾氣火爆,和人爭論時喜歡雙手猛擊桌子以壯聲勢。:-) 日常交談F-word不離口。他面試秘書時必問:"what do you think of the word '****'?" ,讓無數美女刹羽而歸。終於有一天,一個同樣火爆的女面對這個問題脫口而出:"That's my favorite word"。於是她被錄取樂,為D爺爺工作到NT3.5發佈。心目中的編程高手 (4)
-- Donald E. Knuth Don Knuth。高爺爺其實用不著偶多說。學編程的不知道他就好像學物理的不知道牛頓,學數學的不知道歐拉,學音樂的不知道莫札特,學Delphi的不知到 Anders Hejlsberg,或者學Linux不知道Linus Torvalds一樣,不可原諒啊。:-)為了讓文章完整,就再羅唆幾句吧。高爺爺本科時就開始給行行色色的公司寫各種稀奇古怪的編譯器掙外快了。他賣給別人時收一兩千美元,那些公司拿了code,加工一下賣出去就是上萬上十萬。不過也沒見高爺爺不爽過,學者本色的說。想想那可是60年代初啊,高爺爺寫編譯器寫多了,順帶就搞出了個Attribute Grammar和LR(k),大大地造福後人啊。至於高爺爺在CalTech的編程比賽(有Alan Kay得眾多高高手參加)總是第一,寫的Tex到86年就code freeze,還附帶2^n美分獎勵等等都是耳熟能詳,偶就不饒舌樂。順便說一下,高老大爺是無可爭議的寫作高手。他給Concrete Mathematics 寫的前言可謂字字鏗鏘,堪為前言的典範。他的技術文章也是一絕,文風細緻,解釋精當,而且沒有學究氣,不失輕快跳脫。記得幾年前讀Concrete Mathematics,時不時開懷大笑,讓老媽極其鬱悶,覺得我nerdy到家,不可救藥。其實呢,子非魚,安知魚之樂,更不知那完全是高爺爺的功勞。說到寫作高手,不能不提Stephen A. Cook。他的文章當年就被我們的寫作老師極力推薦,號稱典雅文風的樣本。庫爺爺一頭銀髮,身材頎長,總是面帶謙和的微笑,頗有仙風道骨,正好和他的仙文相配的說。高爺爺其實還是開源運動的先驅。雖然他沒有象Richard Stallman那樣八方奔走,但他捐獻了好多作品,都可以在網上看到,比如著名的Mathematical Writing,MMIXWare,The Tex Book等,更不用說足以讓他流芳百世的Tex樂。心目中的編程高手 (5)
-- Ken Thompson Ken Thompson,C語言前身B語言的作者,Unix的發明人之一(另一個是Dennis M. Riche老大,被尊為DMR),Belle(一個厲害的國際象棋程式)的作者之一, 作業系統Plan 9的主要作者(另一個是大牛人Rob Pike, 前不久被google挖走了)。Ken爺爺也算是電腦歷史上開天闢地的人物了。1969年還是電腦史前時代,普通人都認為只有大型機才能運行通用的作業系統,小型機只有高山仰止的份兒。至於用高階語言來寫作業系統,更是笑談。Ken爺爺自然不是池中物,於是他和DMR怒了,在1969年到1970間用彙編在PDP-7上寫出了UNIX的第一個版本。他們並不知道,一場轟轟烈烈的UNIX傳奇由此拉開了序幕。Ken爺爺在1971年又把Unix用C重寫,於是C在隨後20年成就了不知多少豪傑的夢想和光榮。Ken爺爺還有段佳話:裝了UNIX的PDP-11最早被安裝在Bell Lab裏供大家日常使用。很快大家就發現Ken爺爺總能進入他們的帳戶,獲得最高許可權。Bell Lab裏的科學家都心比天高,當然被搞得鬱悶無比。於是有高手怒了,跳出來分析了UNIX代碼,找到後門,修改代碼,然後重新編譯了整個UNIX。就在大家都以為“這個世界清淨了”的時候,他們發現Ken爺爺還是輕而易舉地拿到他們的帳戶許可權,百思不解後,只好繼續鬱悶。誰知道這一鬱悶,就鬱悶了14年,直到Ken爺爺道出個中緣由。原來,代碼裏的確有後門,但後門不在Unix代碼裏,而在編譯Unix代碼的C編譯器裏。每次C編譯器編譯UNIX的代碼,就自動生成後門代碼。而整個Bell Lab的人,都是用Ken爺爺的C編譯器。心目中的編程高手 (6)
-- Rob Pike Rob Pike, AT&T Bell Lab前Member of Technical Staff ,現在google研究作業系統。羅伯伯是Unix的先驅,是貝爾實驗室最早和Ken Thompson以及Dennis M. Ritche開發Unix的猛人,UTF-8的設計人。他還在美國名嘴David Letterman的晚間節目上露了一小臉,一臉憨厚地幫一胖子吹牛搞怪。讓偶佩服不已的是,羅伯伯還是1980年奧運會射箭的銀牌得主。他也是個頗為厲害的業餘天文學家,設計的珈瑪射線望遠鏡差點被NASA用在太空梭上。他還是兩本經典,The Unix Programming Environment 和 The Practice of Programming 的作者之一。如果初學者想在編程方面精益求精,實在該好好讀讀這兩本書。它們都有中文版的說。羅伯伯還寫出了Unix下第一個基於點陣圖的視窗系統,並且是著名的blit 終端的作者。當然了,羅伯伯還是號稱銳意革新的作業系統,Plan9,的主要作者。可惜的是,Plan9並沒有引起多少人的注意。羅伯伯一怒之下,寫出了振聾發聵的雄文 Systems Software Research is Irrelevant,痛斥當下系統開發不思進取,固步自封的弊病。雖然這篇文章是羅伯伯含忿出手,頗有偏激之詞,但確實道出了系統開發的無奈:開發週期越來越長,代價越來越大,用戶被統一到少數幾個系統上,結果越來越多的活動是測量和修補,而真正的革新越來越少。就在羅伯伯鬱悶之極的時候,google登門求賢來樂。如果說現在還有一家大眾公司在不遺餘力地把系統開發推向極致的話,也就是google 樂。隨便看看google的成果就知道了。具有超強容錯和負載平衡能力的分散式檔系統GFS (現在能夠用100,000台廉價PC搭起一個巨型分佈系統,並且高效便宜地進行管理的系統也不多哈),大規模機器學習系統(拼寫檢查,廣告匹配,拼音搜尋。。。哪個都很牛的說),更不用說處理海量平行計算的各式google服務了。Rob在System Software Research is Irrelevant裏蕭瑟地說現在沒有人再關心系統研究的前沿成果了。想不到他錯了,因為google關心。google網路了大批功成名就的牛人,還有大量初生牛犢般博士做開發,顯然不是沒事耍酷,而是因為它們的開發總是試圖吸取系統研究的最新成果。 想必Rob Pike在google很幸福。願他做出更棒的系統。心目中的編程高手 (7)
-- Dennis M. Ritchie 既然Ken Thompson是我的偶像,新聞組上人稱DMR的Dennis M. Ritchie自然也是,畢竟兩人共同締造了UNIX,而Dennis幾乎獨力把C搞大(當然,C的前身是B,而B是Ken Thompson一手做出來的)。J 兩人1983年分享圖靈獎,是有史以來少數幾個因工程項目得獎的工程師(本來是唯一的一對兒,但Alan Kay才因為SmallTalk得獎,所以就成了唯二的樂) 。一個人一生能做出一個卓越的系統已經不易,DMR的C和UNIX長盛不衰近30年,至今生機勃勃,DMR此生可以無憾的說。D爺爺也算有家學淵源:他老爸在AT&T貝爾實驗室工作了一輩子,並在電路設計方面卓有成就,還出了本頗有影響的書The Design of Switching Circuits,據說在交換理論和邏輯設計方面有獨到的論述。當然,D爺爺和他老爸是不同時代的人:他老爸的研究成形于電晶體發明之前,而D爺爺的工作離了電晶體就玩兒不轉樂。:-D不要看D爺爺搞出了C,其實他最愛的編程語言是Alef,在Plan9上運行,支援並行編程。Alef的語法和C相似,但資料類型和執行方式都和C大大不同。說到語言,D爺爺對後來人有非常中肯的建議:抱著學習的目的來開發你自己的語言,不要冀望於它被眾人接受。這個建議不光對語言開發有用,也適用於其他大型系統的開發。別的不說,DMR後來領導自己的團隊在1995年和1996分別推出了Plan9和 Inferno作業系統,又用多少人知道呢?其實,D爺爺當初也沒想過C會風行世界。他開發C的初衷和 Eric S. Raymond在Cathedral and Bazaar裏闡述的一樣,就是要消除自己對現有工具的不爽之處。誰知D爺爺無心插柳,C竟然受到眾多程式師的狂熱擁戴,連D爺爺自己都大惑不解。在一次採訪中D爺爺說大概那是因為C的抽象程度碰巧既滿足了程式師的要求, 又容易實現。當然C一度是Unix上的通用語言也是原因。但不管怎麼說,D爺爺對編程語言出色的審美意識奠定了C廣為流傳的基礎。最後八卦一下。D爺爺的業餘愛好和NBA大牛Karl Malone一樣:開卡車。不過D爺爺更喜歡開NASCAR,而KM獨愛巨無霸。J D爺爺自稱心中不供偶
今天和 leader 討論著嵌入式系統
以下是我們的結論:
在這個忙碌的社會裡
若是出現了一個有智慧的電冰箱,它可以記錄容量、以及種類和網際網路連線
而在產品已經量化的時候
user 可以輕易的在辦公室連上家裡的冰箱
把今天下班的要吃的菜輸入(包括:蛋要煎3分鐘、菜要加3個單位的塩炒5分鐘...等)
透過冰箱的傳輸帶送到煮菜鍋裡面烹調
回到家就可以品嚐美味了
也可以在網路上互相交流彼此的菜單,讓每個人都有機會品嚐大江南北的美食
不過這先決條件得要把產品量化(例如:加3個單位的塩)
否則即使可以交換菜單也嚐不到一模一樣的美食
biggie(原作)
隨著Refactoring技術和XP軟體工程技術的廣泛推廣,單元測試的作用在軟體工程中變得越來越重要,而一個簡明易學、適用廣泛、高效穩定的單元測試框架則對成功的實施單元測試有著至關重要的作用。在java編程語句環境裏,Junit Framework是一個已經被多數java程式師採用和實證的優秀的測試框架,但是多數沒有嘗試Junit Framework的程式師在學習如何Junit Framework來編寫適應自己開發專案的單元測試時,依然覺得有一定的難度,這可能是因為Junit隨框架代碼和實用工具附帶的用戶指南和文檔的著重點在於解釋單元測試框架的設計方法以及簡單的類使用說明,而對在特定的測試框架(Junit)下如何實施單元測試,如何在專案開發的過程中更新和維護已經存在的單元測試代碼沒有詳細的解釋。因此本文檔就兩個著重點對Junit所附帶的文檔進行進一步的補充和說明,使Junit能被更多的開發團隊採用,讓單元測試乃至Refactoring、XP技術更好在更多的開發團隊中推廣。
本文將以代碼方式展示ant+junit進行整體測試的方法,並生成測試報告,發送給開發人員的信箱
將junit.jar放在ant_home/lib下,然後編寫build.xml文件
build.xml
<?xml version="1.0" encoding="gb2312"?>
<!--測試文件,並將測試報告發送到開發人員指定的信箱 by biggie(biggie@hns-soft.com)-->
<project name="test" default="build" basedir=".">
<property environment="env"/>
<property name="j2ee" value="env.j2ee_home"/>
<property name="base.dir" value="." />
<!--定義測試原始檔案-->
<property name="src" value="${base.dir}/test" />
<!--定義輸出位置-->
<property name="classes" value="${base.dir}/defaultroot/WEB-INF/classes"/>
<!--定義lib-->
<property name="lib" value="${base.dir}/lib"/>
<!--定義classpath-->
<path id="appclasspath">
<pathelement path="${java.class.path}"/>
<fileset dir="${base.dir}/defaultroot/WEB-INF/lib">
<include name="*.jar"/>
</fileset>
<pathelement location="${base.dir}/defaultroot/WEB-INF/classes"/>
<pathelement location="D:/j2sdkee1.3.1/lib/j2ee.jar"/>
</path>
<!--initialization-->
<target name="init">
<tstamp/>
<mkdir dir="${classes}"/>
</target>
<target name="compiletest" depends="init">
<!--javac-->
<javac srcdir="${src}" destdir="${classes}" debug="off">
<classpath refid="appclasspath"/>
<include name="**/*.java" />
</javac>
</target>
<target name="build" depends="compiletest,run">
<tstamp/>
<exec executable="${base.dir}/email.bat" >
</exec>
</target>
<target name="run">
<junit>
<classpath refid="appclasspath"/>
<classpath>
<pathelement location="${base.dir}/defaultroot/WEB-INF/classes"/>
</classpath>
<formatter type="xml"/>
<test name="test.AllTests" haltonfailure="no" outfile="result"/>
</junit>
<junitreport todir="./report">
<fileset dir=".">
<include name="result.xml"/>
</fileset>
<report format="noframes" todir="./report"/>
</junitreport>
</target>
</project>
生成測試報告後,調用emai.bat檔,執行一發送郵件操作。為實現群發,所以我採用的是別外寫一應用程式發送郵件,當然您也可以用ant直接發送郵件。程式師第7期有相關文章介紹,這裏我就不多說了。
本文提供的是一個思路,你還可以實現更強大的功能,分佈測試整體測試等等.
1 ant是什麼?
Apache ant 是一個基於 Java的生成工具。生成工具在軟體發展中用來將源代碼和其他輸入檔轉換為可執行檔的形式(也有可能轉換為可安裝的產品映射形式)。隨著應用程式的生成過程變得更加複雜,確保在每次生成期間都使用精確相同的生成步驟,同時實現盡可能多的自動化,以便及時產生一致的生成版本
2 下載、安裝ant 安裝ant下載.zip檔,解壓縮到c:ant1.3(後面引用為%ant_HOME%)
2.1 在你運行ant之前需要做一些配置工作。
• 將bin目錄加入PATH環境變數。
• 設定ant_HOME環境變數,指向你安裝ant的目錄。在一些OS上,ant的腳本可以猜測ant_HOME(Unix和Windos NT/2000)-但最好不要依賴這一特性。
• 可選地,設定JAVA_HOME環境變數(參考下面的高級小節),該變數應該指向你安裝JDK的目錄。注意:不要將ant的ant.jar檔放到JDK/JRE的lib/ext目錄下。ant是個應用程式,而lib/ext目錄是為JDK擴展使用的(如JCE,JSSE擴展)。而且通過擴展裝入的類會有安全方面的限制。
2.2 運行ant
運行ant非常簡單,當你正確地安裝ant後,只要輸入ant就可以了。
沒有指定任何參數時,ant會在當前目錄下查詢build.xml文件。如果找到了就用該檔作為buildfile。如果你用 -find 選項。ant就會在上級目錄中尋找buildfile,直至到達檔系統的根。要想讓ant使用其他的buildfile,可以用參數 -buildfile file,這裏file指定了你想使用的buildfile。
可以指定執行一個或多個target。當省略target時,ant使用標籤<project>的default屬性所指定的target。
命令行選項總結:ant [options] [target [target2 [target3] ...]]
Options:
-help print this message
-projecthelp print project help information
-version print the version information and exit
-quiet be extra quiet
-verbose be extra verbose
-debug print debugging information
-emacs produce logging information without adornments
-logfile file use given file for log output
-logger classname the class that is to perform logging
-listener classname add an instance of class as a project listener
-buildfile file use specified buildfile
-find file search for buildfile towards the root of the filesystem and use the first one found
-Dproperty=value set property to value 例子ant使用當前目錄下的build.xml運行ant,執行缺省的target。ant -buildfile test.xml使用當前目錄下的test.xml運行ant,執行缺省的target。ant -buildfile test.xml dist使用當前目錄下的test.xml運行ant,執行一個叫做dist的target。ant -buildfile test.xml -Dbuild=build/classes dist使用當前目錄下的test.xml運行ant,執行一個叫做dist的target,並設定build屬性的值為build/classes。
3 編寫build.xml
ant的buildfile是用XML寫的。每個buildfile含有一個project。
buildfile中每個task元素可以有一個id屬性,可以用這個id值引用指定的任務。這個值必須是唯一的。(詳情請參考下面的Task小節)
3.1 Projects
project有下麵的屬性:
Attribute Description Required
name 項目名稱. No
default 當沒有指定target時使用的缺省target Yes
basedir 用於計算所有其他路徑的基路徑。該屬性可以被basedir property覆蓋。當覆蓋時,該屬性被忽略。如果屬性和basedir property都沒有設定,就使用buildfile檔的父目錄。 No專案的描述以一個頂級的<description>元素的形式出現(參看description小節)。
一個專案可以定義一個或多個target。一個target是一系列你想要執行的。執行ant時,你可以選擇執行那個target。當沒有給定target時,使用project的default屬性所確定的target。
3.2 Targets
一個target可以依賴於其他的target。例如,你可能會有一個target用於編譯程序,一個target用於生成可執行檔。你在生成可執行檔之前必須先編譯通過,所以生成可執行檔的target依賴於編譯target。ant會處理這種依賴關係。
然而,應當注意到,ant的depends屬性只指定了target應該被執行的順序-如果被依賴的target無法運行,這種depends對於指定了依賴關係的target就沒有影響。
ant會依照depends屬性中target出現的順序(從左到右)依次執行每個target。然而,要記住的是只要某個target依賴於一個target,後者就會被先執行。
<target name="A"/>
<target name="B" depends="A"/>
<target name="C" depends="B"/>
<target name="D" depends="C,B,A"/>假定我們要執行target D。從它的依賴屬性來看,你可能認為先執行C,然後B,最後A被執行。錯了,C依賴於B,B依賴於A,所以先執行A,然後B,然後C,最後D被執行。
一個target只能被執行一次,即時有多個target依賴於它(看上面的例子)。
如果(或如果不)某些屬性被設定,才執行某個target。這樣,允許根據系統的狀態(java version, OS, 命令行屬性定義等等)來更好地控制build的過程。要想讓一個target這樣做,你就應該在target元素中,加入if(或unless)屬性,帶上target因該有所判斷的屬性。例如:
<target name="build-module-A" if="module-A-present"/>
<target name="build-own-fake-module-A" unless="module-A-present"/>如果沒有if或unless屬性,target總會被執行。
可選的description屬性可用來提供關於target的一行描述,這些描述可由-projecthelp命令行選項輸出。
將你的tstamp task在一個所謂的初始化target是很好的做法,其他的target依賴這個初始化target。要確保初始化target是出現在其他target依賴表中的第一個target。在本手冊中大多數的初始化target的名字是"init"。
target有下麵的屬性:
Attribute Description Required
name target的名字 Yes
depends 用逗號分隔的target的名字列表,也就是依賴表。 No
if 執行target所需要設定的屬性名。 No
unless 執行target需要清除設定的屬性名。 No
description 關於target功能的簡短描述。 No
3.3 Tasks
一個task是一段可執行的代碼。
一個task可以有多個屬性(如果你願意的話,可以將其稱之為變數)。屬性只可能包含對property的引用。這些引用會在task執行前被解析。
下面是Task的一般構造形式:
<name attribute1="value1" attribute2="value2" ... />這裏name是task的名字,attributeN是屬性名,valueN是屬性值。
有一套內置的(built-in)task,以及一些可選task,但你也可以編寫自己的task。
所有的task都有一個task名字屬性。ant用屬性值來產生日誌資訊。
可以給task賦一個id屬性:
<taskname id="taskID" ... />這裏taskname是task的名字,而taskID是這個task的唯一識別字。通過這個識別字,你可以在腳本中引用相應的task。例如,在腳本中你可以這樣:
<script ... >
task1.setFoo("bar");
</script>設定某個task實例的foo屬性。在另一個task中(用java編寫),你可以利用下面的語句存取相應的實例。
project.getReference("task1").注意1:如果task1還沒有運行,就不會被生效(例如:不設定屬性),如果你在隨後配置它,你所作的一切都會被覆蓋。
注意2:未來的ant版本可能不會相容這裏所提的屬性,因為很有可能根本沒有task實例,只有proxies。
3.4 Properties
一個project可以有很多的properties。可以在buildfile中用property task來設定,或在ant之外設定。一個property有一個名字和一個值。property可用於task的屬性值。這是通過將屬性名放在"${"和"}"之間並放在屬性值的位置來實現的。例如如果有一個property builddir的值是"build",這個property就可用於屬性值:${builddir}/classes。這個值就可被解析為build/classes。
內置屬性
如果你使用了<property> task 定義了所有的系統屬性,ant允許你使用這些屬性。例如,${os.name}對應作業系統的名字。
要想得到系統屬性的列表可參考the Javadoc of System.getProperties。
除了Java的系統屬性,ant還定義了一些自己的內置屬性:
basedir project基目錄的絕對路徑 (與<project>的basedir屬性一樣)。ant.file buildfile的絕對路徑。ant.version ant的版本。ant.project.name 當前執行的project的名字;由<project>的name屬性設定.ant.java.version ant檢測到的JVM的版本; 目前的值有"1.1", "1.2", "1.3" and "1.4".
例子
<project name="MyProject" default="dist" basedir=".">
<!-- set global properties for this build -->
<property name="src" value="."/>
<property name="build" value="build"/>
<property name="dist" value="dist"/>
<target name="init">
<!-- Create the time stamp -->
<tstamp/>
<!-- Create the build directory structure used by compile -->
<mkdir dir="${build}"/>
</target>
<target name="compile" depends="init">
<!-- Compile the java code from ${src} into ${build} -->
<javac srcdir="${src}" destdir="${build}"/>
</target>
<target name="dist" depends="compile">
<!-- Create the distribution directory -->
<mkdir dir="${dist}/lib"/>
<!-- Put everything in ${build} in
已經有無數的文章介紹過 ant 了, 我就不再介紹 ant 的安裝,配置了.每個使用 ant 的朋友都有一套自己的組織方式, 現在我把我的方式寫出來供大家參考, 也免得自己忘記.
1. 目錄結構劃分
假設你有一個工作目錄為: /home/camry/work, 以下簡稱 work
為了適應多個專案的進行, 我配置了一套基本的配置檔放在 work/common
下. 目錄結構是這樣的:
work/common/
build_common.xml # 這個檔包含基本的構建操作
common.xml # 這個檔為 build_common.xml 作配置,
基本上不用改動.
build_tomcat.xml # 這個檔包含了與tomcat合作的基本操作.
tomcat.xml # 這個檔為 build_tomcat.xml 作配置,
基本上只需要配置一次.
build.xml # 這個檔是每個專案都需要的 build 配置,
但是基本上也不需要改動了.
build.properties # 這個檔為 build.xml 做配置,
與具體的專案相關.
usage.txt # 這個檔說明了構建過程中的各種操作.
lib/ # 這個目錄放置一些公用的 jar 包免得重複.
checkstyle-all-3.4.jar # 用於代碼檢查
httpunit.jar # 用於 http 單元測試
junit.jar # 用於單元測試
servlet-api.jar # 用於編寫 servlet 相關檔
template/ # 這個目錄是套專案模版, 一個項目開始時
將把這個目錄的資料複製到專案目錄下以便
直接使用.
bin/ # 這個目錄放置可執行檔
build/ # 這個目錄放置構建時需要的輔助檔
checkstyle_checks.xml # 這個檔是 checkstyle 的配置檔
java.header # 這個檔也是 checkstyle 配置檔
用於說明你的 java 文件的頭部構造
dist/ # 這個目錄放置目標檔
classes/ # 編譯後產生的 class 檔放在這
lib/ # 打包後產生的 jar 檔放這
lib/ # 這個目錄放置專案相關的 jar 檔
src/ # 這個目錄放置源代碼
build.xml # 這個檔是用於與 cvs 配合工作的配置檔
main/ # 這個目錄中放置主要的源代碼
test/ # 這個目錄中放置測試代碼
後續的文章中會詳細介紹所有的配置檔.
Windows 的 registry 檔案存放在每個帳號底下的 NTUSER.DAT(Document and Settingid)
備起它就可以備起整個 registry 檔
如今JAVA語言在全世界範圍正如火如荼般的流行,它廣泛的應用在INTERNET的資料庫、多媒體、CGI、及動態網頁的製作方面。
作者因最近分析一些JAVA程式,對JAVA的反編譯進行了一番瞭解,下面將我所瞭解的情況作以下介紹,希望對JAVA愛好者有所幫助。
JAVA是採用一種稱做“位元組編碼”的程式結構,分為小程式(嵌入到HTML檔中)和應用程式(直接在命令狀態下執行)兩種類型。無論哪種結構,一旦用JAVAC 命令編譯後,均變成尾碼為CLASS的同名可執行檔。這種檔是不可閱讀的代碼。
經查閱了SUN公司的JDK(JDK1.1.3)文檔資料後,我找到了一個據稱是可反編譯JAVA的JAVAP檔(EXE),這個檔位於JDK BIN 下面,經按說明使用後,感到失望,原來這個“反編譯”僅可反編譯出JAVA程式的資料區(定義)、若干方法和類的引用等。這裏我用了一個簡單例子來說明問題。
JAVA的根源程式hello_java.java如下:
import java.applet.*;
import java.awt.*;
public class hello_java extends Applet
{
public void paint(Graphics g)
{
g.drawString("Hello Java!
",20,20);
}
}
經用反編譯命令:
javap -c -package -public
-private hello_java hello.java
得到的反編譯結果(hello.java)如下:(有關javap命令的選擇參數請見其使用說明,這裏-c表示選擇了反編譯)
Compiled from hello_java.java
public synchronized class
hello_java extends java.applet.Applet
/* ACC_SUPER bit set */
{
public void paint(java.awt.Graphics);
public hello_java();
Method void paint(java.awt.Graphics)
0 aload_1
1 ldc #1
3 bipush 20
5 bipush 20
7 invokevirtual #6
10 return
Method hello_java()
0 aload_0
1 invokespecial #5 ()V>
4 return
}
從上述結果不難看出該反編譯未能將根源程式全譯出來,像語句g.drawString("Hello Java!
",20,20);就沒有。隨著程式量增加,未能編譯的JAVA語句還會更多。所以這個反編譯程序僅能起個參考作用。
幸虧有了INTERNET,筆者通過YAHOO很快找到了一個JAVA反編譯“自由軟體”(SHAREWARE),http: //www.inter.nl.net/users/H.P.van.Vliet/mocha.htm 。這個軟體叫MOCHA,據說是一位30來歲的加拿大的研究生所完成,僅是個“?”版,原因是這位叫做H.P.VAN.VLIET的小夥子患癌逝世了,十分可惜呀!
經使用MOCHA反編譯軟體,感到這個軟體十分好用,筆者試反編譯多個JAVA程式,均得到很好的結果。
這裏給出如何使用這個軟體,首先,用WINZIP等將"mocha-b1.zip" 解開得到"mocha.zip"文件,"mocha.zip"不須再解開,這個包內包括了反編譯的類檔,只需將其拷貝到JDK所在的目錄下,如:c: jdkin 此外,須設置路徑:SET CLASSPATH=c:myclasses;c:jdkinmocha.zip
MOCHA用法:
java mocha.Decompiler [-v] [-o]
Class1.class Class2.class ...
"java" 調用Java虛擬機
"mocha.Decompiler" 指示要進行JAVA反編譯
"-v" 選擇詳細輸出
"-o" 選寫入已有的.mocha 文件
"ClassX.class" 指出要反編譯類名
注意,不需給出輸出的JAVA檔案名,因為MOCHA自動產生一個與CLASS同名但副檔名為MOCHA的JAVA原始檔案。對於上例,可用命令:
java mocha.Decompiler [-v] [-o]
hello_java.class
得到的原始檔案:
/* Decompiled by Mocha from hello_java.class */
/* Originally compiled from hello_java.java */
import java.applet.Applet;
import java.awt.Graphics;
public synchronized class hello_java extends Applet
{
public void paint(Graphics g)
{
g.drawString("Hello Java!
", 20, 20);
}
public hello_java()
{
}
}
我們不難發現,此檔與編譯前的JAVA原始檔案完全一樣!筆者曾經用MOCHA反編譯出最大為80K的原始檔案,均取得成功。
在此,筆者向英年早逝的VLIET表示敬意,感謝他給我們留下這個工具軟體。
昨天一口氣把最後五集給看完了
這齣真是感人阿
讓我幾度落淚
深深的打動我的心
是我太脆弱了嗎?
或許吧!到現在都還會想到我的前女友
唉...到底何時才能找到另外一個愛我,我也愛的人呢?
感情這種東西真是複雜!
人說計畫趕不上變化
這句話說的真是不錯
本來有信心把整個專案給進行完畢的
可是卻出現了變局
組長要被調去支援別的部門
在群龍無首的狀態下
不知道我下一步棋該怎麼走
該放棄還是繼續做下去呢?
少了組長真的是讓我們士氣大減阿
今天 user 來公司看程式
結果我的程式居然 safe
真是太棒了
終於增加了一點點的信心了
哈哈哈,真希望以後的程式也都可以順利通過