大綱:
- 使用開源代碼能提高你的google搜索的能力和英文能力
最近又做了一個商務類型的項目,我們使用了很多的開源的項目的代碼,他們不約而同的出了一些問題,讓我到處救火,google了無數的頁面,這個過程中發現搜索能力和英文閱讀能力。
首先遇到問題的是sitemesh,在tomcat下面一點問題都沒有,但是一轉到websphere下面后就發現首頁出錯了,而且是使用http://www.mydomain.com/這種方式出錯,但是如果訪問http://www.mydomain.com/welcome.do的方式就沒有錯,開始想過很多的解決方法,最后我們的一個同事點醒了我干脆把首頁那種默認的方式取消,就直接訪問welcome.do這樣就解決了,看來還是我太死板了。
然后遇到問題的是我們的jasperReports這個開源的報表工具,在windows下面一點問題都沒有,然后一移到aix的websphere里面,這不問題又來了,然后我就google了一天,沒有頭緒,都郁悶壞了,看上去沒有問題的都用不上,而且我們用的ibm的jdk,解決方案是sun的jdk的,暈倒,最后用了一個最傻的方法,在aix的圖形用戶界面下面運行webphere,這樣報表就出來了,都是xserver惹的禍,害我這兩天都編程了aix的系統管理員了在命令行下面搞了無數次,再暈。
Django最近搞了一下,還是比較有收獲的,準備用來開發一下原型,順便試試用它來直接開發一些輕量的應用試試,就是上次的提到的利用搜索引擎方式的銷售平臺也可以用這個平臺來搭建試試,腳本語言還是有無限可能的。
ajax其實也就是學習了一個javascript的庫叫做mochikit,它以python的方式來寫javascript,挺合我口味的。我們在項目里面用最多也就是在一些時間比較常的地方用用,提高一下用戶體驗。
最后要說的是最近的一個小心得,是關于“小馬過河”故事的,以前做選擇往往都是隨大流,看多數人使用什么我就選擇什么,如果這樣的話那么最近應該選擇的腳本語言是ruby,web框架應該是ror,但是最后我選擇了python、Django,一個是因為我的知識積累主要在python,而且另外一個是python的語法我比較喜歡,Django是因為需要一個快速開發的平臺,因為國內有limodou在推動,我就樂得其成了。
選擇是一個客觀+主觀的過程,是一個比較個人化的事情,如果有人拼命向你推薦什么東西你一定要提高警惕,不要忘記歷史啊,尤其是我國這種全民狂熱的歷史。

文章來源:
http://blog.donews.com/crabhn/archive/2006/04/25/845988.aspx
昨天和Aero同學(現在他不叫kevin了:)討論了關于企業知識管理的問題。我也提出了自己的一些觀點,這里作一個記錄:
1、系統的基礎blog、wiki、網摘、書評收藏(豆瓣)
2、系統的輸入就是這些系統里面的內容
3、系統的輸出分三類:
一個是對于自己,希望梳理自己的知識體系。
那么輸出中要體現個人的進步,也就是需要評估文章的價值,這里我提到可以利用各種條件給內容打分,blog可以以瀏覽的人數,回復的條數,鏈接的個數,也許是在alexa里面的排名,或者就簡單的使用在bsp這個系統里面的打分機制。wiki就是個人的修改的保留程度以及對內容的貢獻度。網摘也可以使用網摘自帶的排名功能。至于豆瓣嘛還是自帶的排名機制。這樣看來我們系統只需要維護自己的blog和wiki,而且根據Aero已經實現的方式blog可以同時和wiki互通,可以在發表blog的同時把文章發到wiki里面去,Aero覺得這個應該是一個選擇的方式,我覺得這里可以作成強制的,blog的文章一定會根據你選擇的標簽被聚類發表到相應的wiki模塊里面去,這樣就可以很方便的結合wiki和blog的優點,而且也符合用戶的使用方式,畢竟多數人不會主動的給wiki貢獻內容,而blog的方式更容易讓大家接受。
另外是需要對知識進行分類,這里Aero提出使用tag的方式,我覺得tag還是有點隨意,最好是在tag的基礎上進一步作文本聚類。這樣就可以在系統里面看到個人的進步,以及自己的知識體系。
二是對于別人,能夠在系統中得到你的整理得很好的一個知識體系的文集,也許就是一本質量很高的書籍,可以很容易得學習到你的知識。
三對于企業,能夠把所有人的知識體系匯總,能夠進一步形成企業知識的沉淀,而且管理層可以很容易的通過這個系統的輸出來分析企業員工的各種關注點,輔助管理工作。
我想還有很多東西沒有好好考慮到,也許需要把時間管理和工作日志管理也加到這個系統里面:)

文章來源:
http://blog.donews.com/crabhn/archive/2006/03/07/755905.aspx
IOC容器大家都經常用了,但是不知道有沒有人注意到在web層我們也可以使用很好的“IOC容器”,就是可愛的sitemesh了,在使用sitemesh之前我們都是直接使用include來包裝頁面,把一個普通的頁面include head.jsp menu.jsp footer.jsp這樣就組裝好了一個頁面,但是這里這三個文件就和所有的這些使用他們的jsp硬編碼放在一起了,這就像我們在系統里面用new來生成一個instance,這樣頁面也一樣造成了很高的耦合度。這樣在頁面級別如果出現需要更改就非常的麻煩了,比如客戶說你這個頁腳我不想要這個,需要另外一個,或者菜單不放在左邊,我要放到右邊去了,這樣你就暈倒了,由于include到處都是,你要一個個找出來修改,也許你會說可以把它們變成空的文件就可以,當然可以,但是這畢竟不是最好的解決方式。
這時候你就可以看看sitemesh了,他和spring一樣,在配置文件里面配置頁面之間的關系,比如很多的前臺頁面都需要一個頁頭,一個菜單,一個頁腳,那么你就可以作一個頁面的模板,包括這些元素,但是在需要插入的地方作一個插入占位標簽,這樣sitemesh就會把被修飾的頁面的body部分抽取出來無縫地插入到頁面模板里面去。sitemesh理解html,這樣它就可以抽取指定的標簽到模板相應位置,比如title,比如body里面的onload事件還有head里面的javascript代碼。你不用擔心它會插錯位置。
這樣你就可以獨立的進行頁面的編寫,每個頁面只需要維護它自己的功能,至于它需要和哪些頁面來組合一概不知,這樣就把頁面級別的耦合全部去除,非常符合DRY(Don't Repeat Youself)原則。
如果sitemesh+web標準的css和無table的方式來設計頁面,就可以完完全全做到頁面的干干凈凈,而且顯示和內容完全分開,對于直接接觸到jsp源碼的程序員是一種享受了:)

文章來源:
http://blog.donews.com/crabhn/archive/2006/03/02/750132.aspx
我們在作訂單提交的時候需要作一個嵌套著對象和對象數組的form,例如:
class OrderForm extent ActionForm
{
Contract contract;
Consumer[] consumers;
...
...
}
然后在html form里面用點屬性的方式來進行提交:
<form ...>
<input name="contract.name"/>
...
<input name="consumers[0].name"/>
...
<input name="consumers[1].name"/>
...
</form>
我想當然這樣就可以提交過去了,因為以前我們有類似的代碼,我也沒有去看文檔(不過我去找了文檔也沒有看到,估計需要看源代碼:),但是提交失敗了,頁面完全出不來,而且代碼都沒有運行到Action里面去,說明struts在裝載Form的時候就出了Exception。我研究了一個天都沒有搞清楚,如果換成String數組的方式又太不直觀,這時候就郁悶了。
不過昨天睡覺前我又理了一下思路,想起自己可能是沒有初始化變量出錯了。Struts往沒有初始化過的變量里面set當然會有exception。:)
所以今天早上我就把Form改了一下:
class OrderForm extent ActionForm
{
Contract contract = new Contract();
Consumer[] consumers;
...
...
}
而consumers在Action里面初始化,把它根據需要初始化足夠的Consumer。
但是,最后發現還是出不來頁面。
這次也很直接,在xml配置里面把form的scope從request改成session,就ok了。
但是,struts還是沒有搞得太清楚。最近聽說struts和webwork合并了,作了一個Struts Ti,而且基于webwork2得核心,看來可以直接去看看webwork的文檔,看看什么時候有機會把它引入我們的項目里面來。

文章來源:
http://blog.donews.com/crabhn/archive/2006/03/01/748078.aspx
在企業開發過程中最頭痛的就是DA層(Data Access)的開發了,關系數據庫這個冬冬最討人嫌了,我就因為討厭關系數據庫,大學有一段時間很討厭寫web程序。
這些問題主要都是因為以前都是直接用Sql和數據庫打交道,每次web項目一把以上的時間花在了DA層了。工作后接觸的第一種DA技術是Spring support的DAO編寫,這樣就可以減少了很多的代碼,而且我還寫了一個代碼生成器來自動生成代碼,這樣開發速度就上來了,但是就算是這樣我們還是很煩惱,因為單表的操作是簡單了,但是多表的操作也是很煩惱,我們是用java代碼建立了一個DBManger層專門用來組裝多表的,當然很多人都是用sql進行多表的拼裝,這樣運行效率高,但是我們當時是選擇了開發效率,所以多表都是在DBManager層用java代碼組裝的,沒有利用數據庫的特性,這樣增加了web服務器的負擔。而且在做查詢的時候特別苦惱,每次都是把整個List全部給load出來了,這樣更加耗費內存了。比如我們的訂單列表的功能現在還沒有多少個訂單的時候都慢得不行了,一個是因為我們每次都load所有的Order對象,二是把Order對象的子對象也全部都Load出來了,本來用戶只是想看其中幾個訂單而已,而且我們也沒有做緩存,總之我們原來項目里面的DA層真的是問題重重。
這兩天把Hibernate引入了我們現在新的項目中來了,開心啊,開心,給我們帶來了解決上述問題的曙光:
1、在開發效率上面,我們現在所有的工作就是建立數據表,根據數據表生成hbm.xml的表對應Java bean的映射,以及生成java代碼。而DAO只是需要一行代碼。多表的聯合也是定義在hbm.xml中的,整個過程看不到一行sql語句,開心。這樣我們體系結構里面的DBManager就沒有存在的必要了。而且DAO也只是需要做一個DAO,現在我們就只有Order的DAO了,所有的操作都在這里進行。
2、運行效率上,首先利用了延時加載,數據如果不用就不load出來,這樣我們的Web服務器就沒有那么大的負擔了,然后就是多表的操作自動生成多表聯合的Sql充分利用數據庫的特性,這樣也是減少web的負擔。
接著最重要的問題就是在做訂單列表的時候,這里真的要好好贊揚一下HQL,這個Hibernate的查詢語言,用完全面向對象的方式解決了我們所有的問題:
a、分頁問題:這里我們可以使用Query接口的來限制每次從第幾個開始最多獲取多少個數據,這樣就可以按頁獲取數據,而且可以利用sum來得到數據的總量,這樣分頁功能就可以很容易實現了。根據我的試驗,速度比原來快了一倍以上,而且原來根據數據量的增長還是線性下降的,而現在保持比較平穩的速度。
b、構造小對象的問題:這個問題來自于訂單列表的時候只是需要幾個簡單的字段,而不需要整個order,這個問題可以通過在HQL的select語句中利用new語句來構造一個小的order對象,這樣進一步節省了web服務器的內存:)
c、聯合表查詢:比如需要根據聯系人信息查order,而聯系人是order的一個子表,這個時候可以利用HQL很直觀的寫出這樣的查詢:eg:select new SmallOrder(order.a,order.b,order.c) from Order as order where order.contact.name='crab'(結合了b問題)這樣我們根本就不需要擔心客戶的bt要求,他想怎么查詢訂單我都可以很容易的給他加上查詢條件。
最后就是我們的產品模塊,原來為了能夠最大限度的擴展,利用了萬能表的方式,這樣什么產品都可以定義出來,但是這樣的設計不利于做報表和查詢,現在可以利用Hibernate重新設計產品模塊,也可以很方便的萬能化,但是查詢和報表就可以很方便了。
總之,Hibernate給我們項目帶來了真真實實的好處,從開發效率和運行效率上都是,特別是可以使用面向對象的方式去操作數據庫,這樣可以很面向對象地寫企業程序,可以帶來開發時候真實地快樂:)
還有一個最大的體會是Hibernate很少違反我的直覺,很多時候我只是覺得這個特性Hibernate應該支持,然后就試驗,然后就成功了,根本不需要去看文檔,這個和Python的“最少驚奇”原則妙曲同工。

文章來源:
http://blog.donews.com/crabhn/archive/2006/02/24/739825.aspx
昨天下午做了一個變更,變更了一個jsp頁面,但是頁面的修改不能體現出來,不過這個頁面比較特殊,是a.jsp include b.jsp,我們修改了b.jsp,但是在websphere上面死活顯示不出來我的修改,看來websphere判斷了a.jsp的修改日期,沒有判斷b.jsp的修改日期,下午試著清空了jsp的緩存區,可是沒有用,今天記起來jsp頁面是要編譯成servlet的,所以清空了全部的緩存,終于修改成功了:)

文章來源:
http://blog.donews.com/crabhn/archive/2006/02/22/737143.aspx