posted @ 2006-11-23 23:47 killvin| 編輯 收藏
posted @ 2006-10-29 15:54 killvin| 編輯 收藏
We are dedicated to make Bindows work at least as well with Mozilla 1.4+ as it does with Internet Explorer 6.0 SP1. The Mozilla support is now integral part of Bindows and we will continue to develop, maintain and support it.
However, some issues are not solved yet and this document details them.
Known Issues
Web Services
We do not yet have a working SOAP web service client working with Mozilla. Mozilla has a built in web service client but it does not yet work with all the major web services platforms. We anticipate this to be resolve in a near future version of Bindows.
Graphs, Charts and Gauges
Graphs, charts and gauges are not supported. For the Bindows charts and gauges we rely on VML to do the drawing. Mozilla does not yet have a way to draw vector graphics at the client side without using a plugin. We consider several alternatives here but there is no time frame for a solution yet.
Miscellaneous
The caret is sometimes not shown in a focused textfield. This is a Mozilla bug and unless this is fixed in Mozilla this issue will remain.
Preferred size is not working consistently. Please report the cases where you are experiencing issues with the preferred size and we will see what can be done in those specific cases.
Icons in menu items works inconsistently between Mozilla versions. This is due to differences in the Mozilla toolkits used by different browsers.
Menu labels do not accept HTML. If you use HTML, the markup will be stripped.
The rendering of the group box is incorrect.
Labels with text align center and icon position set to top or bottom are a bit jumpy, ie. the icon move around depending on the state.
Dragging elements sometimes inconsistent. If an image is dragged an OS level drag and drop is initiated. Also, for some components a dragging will not work when the mouse leaves the browser window or enters a frame.
The upper border for the tab pages are not correctly drawn in Mozilla Firefox using Windows Classic. This is a Mozilla bug.
BiKeyboardEvent keyCode is sometimes incorrect in a keypress event (for special keys). The reason for this bug is that Internet Explorer and Mozilla are handling keyboard events differently.
Resize events are not fired on all BiComponents.
Focus and blur events are inconsistent when using BiRichEdit.
posted @ 2006-10-14 16:21 killvin| 編輯 收藏
Jsparse is a parse?to parse the schema file?with javascript.
If you are interested in it, you can vist the url
http://code.google.com/p/jsparse/
?
svn checkout http://jsparse.googlecode.com/svn/trunk/ jsparse
posted @ 2006-09-13 23:23 killvin| 編輯 收藏
ACE中的Double Checked Locking 模式
(作者:Douglas C. Schmidt ,by huihoo.org CORBA課題 Thzhang 譯 , Allen整理,制作)
意圖
無論什么時(shí)候當(dāng)臨界區(qū)中的代碼僅僅需要加鎖一次,同時(shí)當(dāng)其獲取鎖的時(shí)候必須是線程安全的,可以用Double Checked Locking 模式來減少競爭和加鎖載荷。動機(jī)
1、標(biāo)準(zhǔn)的單例。開發(fā)正確的有效的并發(fā)應(yīng)用是困難的。程序員必須學(xué)習(xí)新的技術(shù)(并發(fā)控制和防止死鎖的算法)和機(jī)制(如多線程和同步API)。此外,許多熟悉的設(shè)計(jì)模式(如單例和迭代子)在包含不使用任何并發(fā)上下文假設(shè)的順序程序中可以工作的很好。為了說明這點(diǎn),考慮一個(gè)標(biāo)準(zhǔn)的單例模式在多線程環(huán)境下的實(shí)現(xiàn)。單例模式保證一個(gè)類僅有一個(gè)實(shí)例同時(shí)提供了全局唯一的訪問這個(gè)實(shí)例的入口點(diǎn)。在c++程序中動態(tài)分配單例對象是通用的方式,這是因?yàn)閏++程序沒有很好的定義靜態(tài)全局對象的初始化次序,因此是不可移植的。而且,動態(tài)分配避免了單例對象在永遠(yuǎn)沒有被使用情況下的初始化開銷。
class Singleton
{
public:
static Singleton *instance (void)
{
if (instance_ == 0)
// Critical section.
instance_ = new Singleton;
return instance_;
}
void method (void);
// Other methods and members omitted.
private:
static Singleton *instance_;
};
應(yīng)用代碼在使用單例對象提供的操作前,通過調(diào)用靜態(tài)的instance方法來獲取單例對象的引用,如下所示:
Singleton::instance ()->method ();
2、問題:競爭條件。不幸的是,上面展示的標(biāo)準(zhǔn)單例模式的實(shí)現(xiàn)在搶先多任務(wù)和真正并行環(huán)境下無法正常工作。例如,如果在并行主機(jī)上運(yùn)行的多個(gè)線程在單例對象初始化之前同時(shí)調(diào)用Singleton::instance方法,Singleton的構(gòu)造函數(shù)將被調(diào)用多次,這是因?yàn)槎鄠€(gè)線程將在上面展示的臨界區(qū)中執(zhí)行new singleton操作。臨界區(qū)是一個(gè)必須遵守下列定式的指令序列:當(dāng)一個(gè)線程/進(jìn)程在臨界區(qū)中運(yùn)行時(shí),沒有其他任何線程/進(jìn)程會同時(shí)在臨界區(qū)中運(yùn)行。在這個(gè)例子中,單例的初始化過程是一個(gè)臨界區(qū),違反臨界區(qū)的原則,在最好的情況下將導(dǎo)致內(nèi)存泄漏,最壞的情況下,如果初始化過程不是冪等的(idempotent.),將導(dǎo)致嚴(yán)重的后果。
3、 通常的陷阱和弊端。實(shí)現(xiàn)臨界區(qū)的通常方法是在類中增加一個(gè)靜態(tài)的Mutex對象。這個(gè)Mutex保證單例的分配和初始化是原子操作,如下:
class Singleton
{
public:
static Singleton *instance (void)
{
// Constructor of guard acquires lock_ automatically.
Guard guard (lock_);
// Only one thread in the critical section at a time.
if (instance_ == 0)
instance_ = new Singleton;
return instance_;
// Destructor of guard releases lock_ automatically.
}
private:
static Mutex lock_;
static Singleton *instance_;
};
guard類使用了一個(gè)c++的習(xí)慣用法,當(dāng)這個(gè)類的對象實(shí)例被創(chuàng)建時(shí),它使用構(gòu)造函數(shù)來自動獲取一個(gè)資源,當(dāng)類對象離開一個(gè)區(qū)域時(shí),使用析構(gòu)器來自動釋放這個(gè)資源。通過使用guard,每一個(gè)對Singleton::instance方法的訪問將自動的獲取和釋放lock_。
即使這個(gè)臨界區(qū)只是被使用了一次,但是每個(gè)對instance方法的調(diào)用都必須獲取和釋放lock_。雖然現(xiàn)在這個(gè)實(shí)現(xiàn)是線程安全的,但過多的加鎖負(fù)載是不能被接受的。一個(gè)明顯(雖然不正確)的優(yōu)化方法是將guard放在針對instance進(jìn)行條件檢測的內(nèi)部:
static Singleton *instance (void)
{
if (instance_ == 0) {
Guard guard (lock_);
// Only come here if instance_ hasn't been initialized yet.
instance_ = new Singleton;
}
return instance_;
}
這將減少加鎖負(fù)載,但是不能提供線程安全的初始化。在多線程的應(yīng)用中,仍然存在競爭條件,將導(dǎo)致多次初始化instance_。例如,考慮兩個(gè)線程同時(shí)檢測 instance_ == 0,都將會成功,一個(gè)將通過guard獲取lock_另一個(gè)將被阻塞。當(dāng)?shù)谝痪€程初始化Singleton后釋放lock_,被阻塞的線程將獲取lock_,錯誤的再次初始化Singleton。 4、解決之道,Double Checked Locking優(yōu)化。解決這個(gè)問題更好的方法是使用Double Checked Locking。它是一種用于清除不必要加鎖過程的優(yōu)化模式。具有諷刺意味的是,它的實(shí)現(xiàn)幾乎和前面的方法一樣。通過在另一個(gè)條件檢測中包裝對new的調(diào)用來避免不必要的加鎖:
class Singleton
{
public:
static Singleton *instance (void)
{
// First check
if (instance_ == 0)
{
// Ensure serialization (guard constructor acquires lock_).
Guard guard (lock_);
// Double check.
if (instance_ == 0)
instance_ = new Singleton;
}
return instance_;
// guard destructor releases lock_.
}
private:
static Mutex lock_;
static Singleton *instance_;
};
第一個(gè)獲取lock_的線程將構(gòu)建Singleton,并將指針分配給instance_,后續(xù)調(diào)用instance方法的線程將發(fā)現(xiàn)instance_ != 0,于是將跳過初始化過程。如果多個(gè)線程試圖并發(fā)初始化Singleton,第二個(gè)檢測件阻止競爭條件的發(fā)生。在上面的代碼中,這些線程將在lock_上排隊(duì),當(dāng)排隊(duì)的線程最終獲取lock_時(shí),他們將發(fā)現(xiàn)instance_ != 0于是將跳過初始化過程。
上面Singleton::instance的實(shí)現(xiàn)僅僅在Singleton首次被初始化時(shí),如果有多個(gè)線程同時(shí)進(jìn)入instance方法將導(dǎo)致加鎖負(fù)載。在后續(xù)對Singleton::instance的調(diào)用因?yàn)閕nstance_ != 0而不會有加鎖和解鎖的負(fù)載。 通過增加一個(gè)mutex和一個(gè)二次條件檢測,標(biāo)準(zhǔn)的單例實(shí)現(xiàn)可以是線程安全的,同時(shí)不會產(chǎn)生過多的初始化加鎖負(fù)載。
適應(yīng)性
> 當(dāng)一個(gè)應(yīng)用具有下列特征時(shí),可以使用Double Checked Locking優(yōu)化模式:1、應(yīng)用包含一個(gè)或多個(gè)需要順序執(zhí)行的臨界區(qū)代碼。
2、多個(gè)線程可能潛在的試圖并發(fā)執(zhí)行臨界區(qū)。
3、臨界區(qū)僅僅需要被執(zhí)行一次。
4、在每一個(gè)對臨界區(qū)的訪問進(jìn)行加鎖操作將導(dǎo)致過多加鎖負(fù)載。
5、在一個(gè)鎖的范圍內(nèi)增加一個(gè)輕量的,可靠的條件檢測是可行的。
結(jié)構(gòu)和參與者
通過使用偽代碼能夠最好地展示Double Checked Locking模式的結(jié)構(gòu)和參與者,圖1展示了在Double Checked Locking模式有下列參與者:1、僅有一次臨界區(qū)(Just Once Critical Section,)。臨界區(qū)所包含的代碼僅僅被執(zhí)行一次。例如,單例對象僅僅被初始化一次。這樣,執(zhí)行對new Singleton的調(diào)用(只有一次)相對于Singleton::instance方法的訪問將非常稀少。
2、mutex。鎖被用來序列化對臨界區(qū)中代碼的訪問。
3、標(biāo)記。標(biāo)記被用來指示臨界區(qū)的代碼是否已經(jīng)被執(zhí)行過。在上面的例子中單例指針instance_被用來作為標(biāo)記。
4、 應(yīng)用線程。試圖執(zhí)行臨界區(qū)代碼的線程。
協(xié)作
圖2展示了Double Checked Locking模式的參與者之間的互動。作為一種普通的優(yōu)化用例,應(yīng)用線程首先檢測flag是否已經(jīng)被設(shè)置。如果沒有被設(shè)置,mutex將被獲取。在持有這個(gè)鎖之后,應(yīng)用線程將再次檢測flag是否被設(shè)置,實(shí)現(xiàn)Just Once Critical Section,設(shè)定flag為真。最后應(yīng)用線程釋放鎖。結(jié)論
使用Double Checked Locking模式帶來的幾點(diǎn)好處:1、最小化加鎖。通過實(shí)現(xiàn)兩個(gè)flag檢測,Double Checked Locking模式實(shí)現(xiàn)通常用例的優(yōu)化。一旦flag被設(shè)置,第一個(gè)檢測將保證后續(xù)的訪問不要加鎖操作。
2、防止競爭條件。對flag的第二個(gè)檢測將保證臨界區(qū)中的事件僅實(shí)現(xiàn)一次。
使用Double Checked Locking模式也將帶來一個(gè)缺點(diǎn):產(chǎn)生微妙的移植bug的潛能。這個(gè)微妙的移植問題能夠?qū)е轮旅腷ug,如果使用Double Checked Locking模式的軟件被移植到?jīng)]有原子性的指針和正數(shù)賦值語義的硬件平臺上。例如,如果一個(gè)instance_指針被用來作為Singleton實(shí)現(xiàn)的flag,instance_指針中的所有位(bit)必須在一次操作中完成讀和寫。如果將new的結(jié)果寫入內(nèi)存不是一個(gè)原子操作,其他的線程可能會試圖讀取一個(gè)不健全的指針,這將導(dǎo)致非法的內(nèi)存訪問。
在一些允許內(nèi)存地址跨越對齊邊界的系統(tǒng)上這種現(xiàn)象是可能的,因此每次訪問需要從內(nèi)存中取兩次。在這種情況下,系統(tǒng)可能使用分離的字對齊合成flag,來表示instance_指針。
如果一個(gè)過于激進(jìn)(aggressive)編譯器通過某種緩沖手段來優(yōu)化flag,或是移除了第二個(gè)flag==0檢測,將帶來另外的相關(guān)問題。后面會介紹如何使用volatile關(guān)鍵字來解決這個(gè)問題。
實(shí)現(xiàn)和例子代碼
ACE在多個(gè)庫組件中使用Double Checked Locking模式。例如,為了減少代碼的重復(fù),ACE使用了一個(gè)可重用的適配器ACE Singleton來將普通的類轉(zhuǎn)換成具有單例行為的類。下面的代碼展示了如何用Double Checked Locking模式來實(shí)現(xiàn)ACE Singleton。
// A Singleton Adapter: uses the Adapter
// pattern to turn ordinary classes into
// Singletons optimized with the
// Double-Checked Locking pattern.
template
class ACE_Singleton
{
public:
static TYPE *instance (void);
protected:
static TYPE *instance_;
static LOCK lock_;
};
template TYPE *
ACE_Singleton::instance ()
{
// Perform the Double-Checked Locking to
// ensure proper initialization.
if (instance_ == 0) {
ACE_Guard lock (lock_);
if (instance_ == 0)
instance_ = new TYPE;
}
return instance_;
}
ACE Singleton類被TYPE和LOCK來參數(shù)化。因此一個(gè)給定TYEP的類將被轉(zhuǎn)換成使用LOCK類型的互斥量的具有單例行為的類。
ACE中的Token Manager.是使用ACE Singleton的一個(gè)例子。Token Manager實(shí)現(xiàn)在多線程應(yīng)用中對本地和遠(yuǎn)端的token(一種遞歸鎖)死鎖檢測。為了減少資源的使用,Token Manager被按需創(chuàng)建。為了創(chuàng)建一個(gè)單例的Token Manager對象,只是需要實(shí)現(xiàn)下面的typedef:
typedef ACE_Singleton
Token Manager單例將被用于本地和遠(yuǎn)端的token死鎖檢測。在一個(gè)線程阻塞等待互斥量之前,它首先查詢Token Manager單例,來測試阻塞是否會導(dǎo)致死鎖狀態(tài)。對于系統(tǒng)中的每一個(gè)token,Token Manager單例維護(hù)一個(gè)持有token線程和所有阻塞等待在該token的線程記錄鏈表。這些數(shù)據(jù)將提供充足的檢測死鎖狀態(tài)的依據(jù)。使用Token Manager單例的過程如下:
// Acquire the mutex.
int Mutex_Token::acquire (void)
{
// If the token is already held, we must block.
if (mutex_in_use ()) {
// Use the Token_Mgr Singleton to check
// for a deadlock situation *before* blocking.
if (Token_Mgr::instance ()->testdeadlock ()) {
errno = EDEADLK;
return -1;
}
else
// Sleep waiting for the lock...
// Acquire lock...
}
變化
一種變化的Double Checked Locking模式實(shí)現(xiàn)可能是需要的,如果一個(gè)編譯器通過某種緩沖方式優(yōu)化了flag。在這種情況下,緩沖的粘著性(coherency)將變成問題,如果拷貝flag到多個(gè)線程的寄存器中,會產(chǎn)生不一致現(xiàn)象。如果一個(gè)線程更改flag的值將不能反映在其他線程的對應(yīng)拷貝中。另一個(gè)相關(guān)的問題是編譯器移除了第二個(gè)flag==0檢測,因?yàn)樗鼘τ诔钟懈叨葍?yōu)化特性的編譯器來說是多余的。例如,下面的代碼在激進(jìn)的編譯器下將被跳過對flag的讀取,而是假定instance_還是為0,因?yàn)樗鼪]有被聲明為volatile的。
Singleton *Singleton::instance (void)
{
if (Singleton::instance_ == 0)
{
// Only lock if instance_ isn't 0.
Guard guard (lock_);
// Dead code elimination may remove the next line.
// Perform the Double-Check.
if (Singleton::instance_ == 0)
// ...
解決這兩個(gè)問題的一個(gè)方法是生命flag為Singleton的volatile成員變量,如下:
private:
static volatile long Flag_; // Flag is volatile.
使用volatile將保證編譯器不會將flag緩沖到編譯器,同時(shí)也不會優(yōu)化掉第二次讀操作。使用volatile關(guān)鍵字的言下之意是所有對flag的訪問是通過內(nèi)存,而不是通過寄存器。
相關(guān)模式
Double Checked Locking模式是First-Time-In習(xí)慣用法的一個(gè)變化。First-Time-In習(xí)慣用法經(jīng)常使用在類似c這種缺少構(gòu)造器的程序語言中,下面的代碼展示了這個(gè)模式:
static const int STACK_SIZE = 1000;
static T *stack_;
static int top_;
void push (T *item)
{
// First-time-in flag
if (stack_ == 0) {
stack_ = malloc (STACK_SIZE * sizeof *stack);
assert (stack_ != 0);
top_ = 0;
}
stack_[top_++] = item;
// ...
}
第一次push被調(diào)用時(shí),stack_是0,這將導(dǎo)致觸發(fā)malloc來初始化它自己。
posted @ 2006-09-13 23:16 killvin| 編輯 收藏
IE
GET /mail HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/x-shockwave-flash, */*
Accept-Language: zh-cn
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Maxthon)
Host: mail.google.com
Connection: Keep-Alive
Cookie: gmailchat=killvin.liu@gmail.com/519974 ; PREF=ID=d68c481e542af276:NW=1:TM=1151742225:LM=1151742225:S=2qbdhg0_z3i-OAbW; SID=DQAAAG8AAACEdcjD2IZMNqZVatDbD62X8_U18oJuTVQc9XZUJi7MgCkM8sggJ8M5npZ35GXjdalT2o8QWPUve04tepy61MPv4v_EpILafg3JdIf8AFjD91aMT0tI5gb763FouV3e_2-C364HDO5Qzb4P4gjjgpHC
Firefox
GET /mail HTTP/1.1
Host: mail.google.com
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.3) Gecko/20060426 Firefox/1.5.0.3
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
我們可以注意到:如果用戶關(guān)閉了瀏覽器的Cookie選項(xiàng),在Firefox中對于新的請求是包含Cookie的信息的,然而IE卻恰恰相反!這也就直接用IE瀏覽一些網(wǎng)站所導(dǎo)致的Cookie校驗(yàn)失敗問題(比如即使用戶在使用過程中突然關(guān)閉Cookie,依然可以自由的訪問網(wǎng)站的各項(xiàng)服務(wù)),進(jìn)一步,如果某個(gè)網(wǎng)站是讀取依靠Cookie中的信息來驗(yàn)證用戶(尤其是那種保存客戶信息的提示),即使這個(gè)用戶離開或者關(guān)閉窗口,任何一個(gè)后來的人都可以輕松的瀏覽這個(gè)用戶的私有信息!這就是Cookie的最大的問題所在,當(dāng)然這是另外的話題,不屬于本次討論的范疇,這一次要說的是 如何避免IE瀏覽器下,用戶關(guān)閉Cookie的問題。
有一個(gè)思路,經(jīng)過測試我們發(fā)現(xiàn)IE瀏覽器只是在首次頁面請求的時(shí)候才會去讀取Cookie的值,所以,為了避免IE瀏覽器關(guān)閉Cookie的問題,可以在用戶請求某個(gè)鏈接的時(shí)候,先將用戶的Cookie存放在某處,并清空此時(shí)所有的Cookie值,再次的請求頁面,而這樣做的目的就是強(qiáng)迫IE讀取硬盤上的Cookie,如果此時(shí)用戶關(guān)閉了Cookie,就不會在請求的頭信息中看到Cookie信息;如果沒有關(guān)閉Cookie,就可以放心的將原先的Cookie寫回Reponse對象。
只是不知道Google的網(wǎng)站是否也是按照這個(gè)思路去解決此問題的?
posted @ 2006-07-02 21:53 killvin| 編輯 收藏
IE在處理COOKIE方面的問題
1。即使你提高了瀏覽器的隱私登記,在第一次打開窗口的時(shí)候,你獲取不到任何的Cookies對象(很顯然的結(jié)果),然而當(dāng)你再次刷新本頁面的,Cookie此時(shí)會奇跡般的出現(xiàn)!而在Firefox瀏覽器中按照以上的步驟,是不會出現(xiàn)這樣的情況的。
2。不僅如此,你還可以透過Action的處理,多次的往Cookie中增加Cookie的數(shù)量(當(dāng)然在Action中你依然可以自由的獲取到Cookie這個(gè)數(shù)組,并且不為空),然而讓人匪夷所思的是在Cookie的存放目錄下你是找尋不到任何的蛛絲馬跡的。而在Firefox沒有出現(xiàn)以上的情況。
-解決
1。在首次進(jìn)入頁面時(shí)查詢客戶端的Cookie,如果不存在則警告用戶,并要求再次的登陸。
2。在用戶登陸后,如果更改了瀏覽器的隱私級別,對于Firefox標(biāo)準(zhǔn)的瀏覽器,此時(shí)肯定不會再找到Cookie數(shù)組對象了,你需要做的僅僅只是將頁面調(diào)轉(zhuǎn)到登陸窗口;而在IE下就非常的麻煩了甚至無法解決,因?yàn)槟阋廊豢梢栽L問到原來的Cookie數(shù)組值,(比如,用IE在CSDN登陸后提高隱私級別,你依然可以登陸到其他的服務(wù)區(qū)域)此時(shí)沒有什么好的辦法,不過Google解決了這樣的問題,只是不知道如何解決的。
IE在處理Frame標(biāo)記的問題
1。如果你在某個(gè)頁面中嵌入了Frame標(biāo)簽,并且希望與這個(gè)嵌入的頁面共享某些存放在Session中的數(shù)據(jù),此時(shí)你需要將外部的sessionId傳入到frame標(biāo)記的頁面中。然而在IE中你可能并不能完全的享受這樣的邏輯,原因在于IE對于嵌入的頁面不會自動的傳遞sessionId,也許你碰巧可以,也許不行,也就是說完全是在IE的"掌控"之下。而在Firefox沒有出現(xiàn)這樣的情況。
-解決
為嵌入的頁面中所有的鏈接增加sessionId參數(shù)。
最好的辦法就是:說服客戶使用標(biāo)準(zhǔn)的瀏覽器Firefox!
posted @ 2006-07-01 15:53 killvin| 編輯 收藏
在Struts中我們經(jīng)常這樣循環(huán)的打印Message
<logic:messagesPresent message="true">
? <html:messages id="msg" message="true">
??? <div class="success">
????? <bean:write name="msg"/>
??? </div><br/>
? </html:messages>
</logic:messagesPresent>
查閱struts tag的文檔我們看到了關(guān)于messagesPresent的message屬性注釋如下
message |
By default the tag will retrieve the request scope bean it will iterate over from the |
也就是說在將message設(shè)置為true時(shí),會去request中尋找Globals.MESSAGE_KEY所代表的bean,然而我們在具體的Action使用ActionMessages類的時(shí)候往往是這樣的
ActionMessages messages = getErrors(request);
messages.add(ActionMessages.GLOBAL_MESSAGE , new ActionMessage(key , value0));
saveMessages(request,messages);
而往往困擾人的就在于為什么要給messages中放入名稱為"ActionMessages.GLOBAL_MESSAGE"的ActionMessage對象,而且還需要再次的調(diào)用saveErrors(request,messages)方法?
首先要說明的是你為ActionMessage起任何的名稱都沒有關(guān)系,因?yàn)锳ctionMessages本身維持著一個(gè)HashMap,而參數(shù)property就是這個(gè)HashMap中的key值,如果不存在則會建立相應(yīng)的key,并將需要保存的ActionMessage對象存入到這個(gè)key所對應(yīng)的List中。
??? public void add(String property, ActionMessage message) {
??????? ActionMessageItem item = (ActionMessageItem) messages.get(property);
??????? List list = null;
??????? if (item == null) {
??????????? list = new ArrayList();
??????????? item = new ActionMessageItem(list, iCount++, property);
??????????? messages.put(property, item);
??????? } else {
??????????? list = item.getList();
??????? }
??????? list.add(message);
??? }
至于為什么一定要調(diào)用saveMessages(request,messages)?看看它具體的實(shí)現(xiàn)邏輯就清楚了
??? protected void saveMessages(
??????? HttpServletRequest request,
??????? ActionMessages messages) {
??????? // Remove any messages attribute if none are required
??????? if ((messages == null) || messages.isEmpty()) {
??????????? request.removeAttribute(Globals.MESSAGE_KEY);
??????????? return;
??????? }
??????? // Save the messages we need
??????? request.setAttribute(Globals.MESSAGE_KEY, messages);
??? }
再對比前面介紹的messagesPresent標(biāo)簽的使用,是不是就清楚了呢?原來它是將ActionMessages對象保存在request中,并且名稱是Globals.ERROR_KEY!從而為tag的順利解析鋪平了道路。當(dāng)然按理你可以選擇將這樣的對象放置在任何的scope中,但Action只是提供了request , session兩種Scope(不過page , application不經(jīng)常使用,可以理解,但不提供相應(yīng)的結(jié)構(gòu)就不太好了)
至于messagesPresent標(biāo)簽是如何在scope中尋找ActionMessages對象
org.apache.struts.taglib.logic.MessagesPresentTag
??? protected boolean condition(boolean desired) throws JspException {
??????? ActionMessages am = null;
??????? String key = name;
??????? if (message != null && "true".equalsIgnoreCase(message)){
?????????? key = Globals.MESSAGE_KEY;
??????? }
??????? try {
??????????? am = TagUtils.getInstance().getActionMessages(pageContext, key);
???????????
??????? } catch (JspException e) {
??????????? TagUtils.getInstance().saveException(pageContext, e);
??????????? throw e;
??????? }
??????? Iterator iterator = (property == null) ? am.get() : am.get(property);
??????? return (iterator.hasNext() == desired);
??? }
org.apache.struts.taglib.TagUtils
?? public ActionErrors getActionErrors(PageContext pageContext, String paramName)
??????????? throws JspException {
??????? ActionErrors errors = new ActionErrors();
??????? Object value = pageContext.findAttribute(paramName);
??????? if (value != null) {
??????????? try {
??????????????? if (value instanceof String) {
??????????????????? errors.add(
??????????????????????????? ActionMessages.GLOBAL_MESSAGE,
??????????????????????????? new ActionMessage((String) value));
??????????????? } else if (value instanceof String[]) {
??????????????????? String keys[] = (String[]) value;
??????????????????? for (int i = 0; i < keys.length; i++) {
??????????????????????? errors.add(
??????????????????????????????? ActionMessages.GLOBAL_MESSAGE,
??????????????????????????????? new ActionMessage(keys[i]));
??????????????????? }
??????????????? } else if (value instanceof ActionErrors) {
??????????????????? errors = (ActionErrors) value;
??????????????? } else {
??????????????????? throw new JspException(
??????????????????????????? messages.getMessage(
??????????????????????????????????? "actionErrors.errors",
??????????????????????????????????? value.getClass().getName()));
??????????????? }
??????????? } catch (JspException e) {
??????????????? throw e;
??????????? } catch (Exception e) {
??????????????? log.debug(e, e);
??????????? }
??????? }
??????? return errors;
??? }
PageContext中的findAttribute會幫你在scope中尋找名稱為Globals.MESSAGE_KEY的ActionMessage對象。
注意
雖然Struts已經(jīng)聲明:不推薦使用ActionErrors & ActionError對象,但在一些遺留的系統(tǒng)中,依然還是可以看到其影子,所以如果你的系統(tǒng)不幸屬于這樣的兩種混合系統(tǒng),有以下的幾種方法可以參考
1。兩次調(diào)用messagesPresent,如下
<!-- Print ActionErrors Object -->
<logic:messagesPresent>
? <html:messages id="msg" message="true">
??? <div class="success">
????? <bean:write name="msg"/>
??? </div><br/>
? </html:messages>
</logic:messagesPresent>
<!-- Print ActionMessages Object -->
<logic:messagesPresent message="true">
? <html:messages id="msg" message="true">
??? <div class="success">
????? <bean:write name="msg"/>
??? </div><br/>
? </html:messages>
</logic:messagesPresent>
2.分別使用<html:messages> <html:errors>標(biāo)簽,當(dāng)然在老系統(tǒng)中需要調(diào)用Action的saveErrors方法,而在新的應(yīng)用中要調(diào)用saveMessages方法。
3.更換所有的ActionErrors為ActionMessages,并將所有調(diào)用saveErrors的地方更換成saveMessages,并將<html:errors>標(biāo)簽相應(yīng)的更換成<html:messages message="true"> - 推薦!
?
posted @ 2006-06-27 23:02 killvin| 編輯 收藏
第2章 并發(fā)問題及控制手段
什么是并發(fā)問題?假設(shè)有這么一家書吧,顧客可以到那里喝茶讀書。顧客拿著選好要讀的圖書到柜臺登記,然后找個(gè)地方去閱讀,臨走時(shí)將圖書歸還店家。有一天,一個(gè)顧客相中了一本書后正要拿去登記,另一個(gè)顧客的手也抓住了這僅有的一本書,并發(fā)問題出現(xiàn)了。兩個(gè)顧客要讀同一本書,互不相讓,這讓店主傷透了腦筋。這個(gè)案例僅僅是眾多并發(fā)問題中的一個(gè)微小部分,但從中我們可以看出并發(fā)問題主要出現(xiàn)在多個(gè)用戶對有限資源進(jìn)行訪問的時(shí)候,如果解決不好會直接影響系統(tǒng)的有效、正常運(yùn)行。數(shù)據(jù)庫是一個(gè)共享的資源,并發(fā)問題的出現(xiàn)是必不可免的,如何識別并發(fā)類型并加以控制是這一章重點(diǎn)要講述的內(nèi)容。
本章將分成兩大部分,一部分主要講Visual FoxPro中并發(fā)控制機(jī)制。VFP中并發(fā)控制相對簡單,數(shù)據(jù)加鎖的形式比較單一,非常適合作為初步了解并發(fā)問題的切入點(diǎn)。第二部分以SQL Server 2000、ADO.NET以及C#為主要工具,深入了解并發(fā)一致性問題、封鎖協(xié)議、事務(wù)隔離等內(nèi)容,難度相對較深。象一些更為深入的并發(fā)控制手段,例如多粒度封鎖和意象鎖等內(nèi)容在本章中將不做深入討論,感興趣可以參考相關(guān)書籍。
?
[實(shí)在不好意思COPY別人的成果,不過這篇文章出奇的精彩,將并發(fā)操作的來龍去脈說的清清楚楚,也是我正要找的,比JAVAEYE上面所謂的專家叫嚷著什么"悲觀鎖"、"樂觀鎖"而不解是原因要強(qiáng)的多!值得收藏]
posted @ 2006-04-06 10:57 killvin| 編輯 收藏
痛快!。。。人們總是認(rèn)為罵人是沒有素質(zhì)的象征,然而我到覺得要看對誰而言,如果你的面前是個(gè)謙虛、嚴(yán)謹(jǐn)而又懂得尊重別人的人,你根本就不可能讓自己憤怒,也不可能讓自己表現(xiàn)的很沒有素質(zhì);相反如果你的面前是個(gè)先入為主、自傲、不懂得尊重別人的人,你的憤怒就會在最短的時(shí)間內(nèi)激發(fā)出來。-對于小人,就要罵!
而這有與北大青鳥有什么關(guān)系呢?
在我的職業(yè)生涯里,有一段讓自己憤怒的培訓(xùn)經(jīng)歷,到今天我都為自己在這樣的培訓(xùn)部的學(xué)習(xí)經(jīng)歷而感到恥辱!甚至不愿意在簡歷里提及ACCP的字樣,而這樣的培訓(xùn)經(jīng)歷就是在北大青鳥(西安兆隆)里度過的。
我參加的是北大青鳥(西安兆隆)的第二期培訓(xùn),培訓(xùn)的課程涉及到數(shù)據(jù)庫、編程語言、職業(yè)素質(zhì)、項(xiàng)目實(shí)踐等,看上去非常的正規(guī),可是真正的學(xué)習(xí)效果卻是讓人非常的失望的!
首先,就是它的課程體系,完全的引入印度的教程,而翻譯的質(zhì)量非常的差,其實(shí)這到?jīng)]有什么,只是教程的講解范圍和深度都非常的淺(這還是第二期的培訓(xùn)),如果你只是按照它的教程我可以說你根本學(xué)不到任何有價(jià)值的東西,只是皮毛而已。-拿著淡薄的教學(xué)資料的同時(shí)你也就上了賊船了。
再次,就是它的老師的水平實(shí)在不敢恭維,(當(dāng)然并不是說根本就沒有好的老師,曾經(jīng)就遇到過一個(gè)講解JAVA與UML的老師,水平非常的高深,可惜ACCP沒有留住),比如編程語言中學(xué)習(xí)了VB,僅僅只是這一門課程就換了3個(gè)老師,最后是一位號稱是西工大的博士上的課,然而這位博士顯然是心思不再這里,除了講解課本上已經(jīng)有的代碼,根本不敢深入的講解原理,這門課程也就這樣混過去了。-如果這樣學(xué)習(xí)編程語言道不如自學(xué)來得輕松。
還有,就是所謂的項(xiàng)目實(shí)踐根本就不是老師帶的項(xiàng)目,而是一些書本上或者捏造出來的一些項(xiàng)目,比如圖書管理系統(tǒng)等,如果學(xué)員無法真正的理解需求,怎么去理解設(shè)計(jì),又如何來進(jìn)行實(shí)際的編碼呢?如果遇到圖書管理的專業(yè)問題來問誰呢?-別指望在他們宣傳的所謂的項(xiàng)目實(shí)踐中得到鍛煉。
在看看他們引以為傲的工作分配問題吧?就我個(gè)人的親身感受來言,這里會提供一些工作的機(jī)會,但都是一些小公司,而且往往是一些前三個(gè)月不給工資的公司;當(dāng)時(shí)我在我們班級里是比較認(rèn)真的一個(gè)(我是班里唯一的一個(gè)交了對項(xiàng)目分析文檔的學(xué)員,并且是項(xiàng)目實(shí)踐中的小組組長),可是在一次很好的面試機(jī)會面前,她們竟然由于工作的失誤忘記了給我打電話?!-如果這樣的工作分配策略也算作是給予你的答案的話,你一定會變得和我一樣的憤怒!
我沒有在ACCP學(xué)到任何的有用的東西,然而在真實(shí)的世界里卻學(xué)到了人們對于ACCP的看法,很多的技術(shù)經(jīng)理 、 技術(shù)總監(jiān)從骨子里非常的厭惡從北大青鳥出來的學(xué)生,對于他們開設(shè)的一些課程也是相當(dāng)?shù)姆锤校?dāng)時(shí)在西部世紀(jì)工作的時(shí)候,同組的就有和我一起上課的同班同學(xué),在他交了8000多元的學(xué)習(xí)費(fèi)用(總共的費(fèi)用接近1萬多元)后,得到的僅僅只是西部世紀(jì)的一張?jiān)囉猛ㄖ獑危鴹l件是必須無條件的為公司工作三個(gè)月!
這就是我在北大青鳥的學(xué)習(xí)經(jīng)歷,然而憤怒的不是這個(gè),卻是今天參加的面試經(jīng)歷,對照著自己的個(gè)人的工作經(jīng)歷我希望自己能夠成為一名培訓(xùn)部的老師,教給那些原來如我一樣的學(xué)生一些在實(shí)踐當(dāng)中有用的東西,而不是空洞的理論!所以我給ACCP投了自己的簡歷,然而讓我卻又一次的遇到了那個(gè)欺騙過我的咨詢師,不過她的記憶力也是非常的好,一眼就認(rèn)出了我(當(dāng)然了我是曾經(jīng)給她帶來獎金的人),在緊接著的面試過程中已經(jīng)變了味道,談?wù)摰脑掝}也不是具體項(xiàng)目技術(shù)的問題,(不是我笑話她與她談?wù)摷夹g(shù)問題根本就如同對牛彈琴)她顯然是一個(gè)沒有素質(zhì)的WOMAN,也可以肯定的是她根本沒有在外企工作過的經(jīng)歷,所以說話的詞匯以及與其如同大街上的潑婦一般,可以想見她一定是一個(gè)被ACCP嚴(yán)重洗過腦的人,而且是屬于那種技術(shù)失敗的產(chǎn)品,她無法接受別的培訓(xùn)部的名字,一旦你提起別的培訓(xùn)部的某個(gè)老師的水平如何如何的好,她就如同一個(gè)快被點(diǎn)燃的鞭炮一般,兩眼充滿了憤怒!
然而讓我最終和她一般的沒有素質(zhì)的大罵的是她對于我辭職的評點(diǎn),我很納悶的是她在不知道一件事情的原因的情況下,可以講述自己的觀點(diǎn)!并且是帶著教育的口吻,實(shí)在是人才呀!這就是北大青鳥的"人才力量",對于這樣的白癡級別的任務(wù)的觀點(diǎn),我只好打斷,因?yàn)樗踔吝B我在的那個(gè)單位的名字都不知道!!
實(shí)在是一場鬧劇,而她更像是個(gè)小丑,除了唧唧喳喳的重復(fù)一些"洗腦"的詞匯已經(jīng)不知道窗外的天氣了,可以預(yù)料北大青鳥的牌子必將會毀在這些個(gè)白癡的手中,世界需要白癡,那如同鮮花需要牛糞一樣,我們改變不了白癡的世界觀的,你能夠做的就是別被這臭烘烘的牛糞給熏臭了。
posted @ 2006-04-01 12:53 killvin| 編輯 收藏
[深入的思考] 為什么要采用java這個(gè)平臺?
從開發(fā)項(xiàng)目的類別角度看java平臺
基于B/S結(jié)構(gòu)的系統(tǒng),在這個(gè)方向上的競爭是激烈的,有專注于此的LAMP(Linux + Apache + Mysql + Php);也有剛剛興起的Rails(Ruby Frameworks)甚至是號稱快速開發(fā)的ASP.NET;當(dāng)然了java在這個(gè)領(lǐng)域里的MVC框架數(shù)都數(shù)不完,比如Struts . Webwork等,然而即便是如此,選擇java作為開發(fā)的理由也是不充分的,因?yàn)樵谶@個(gè)梯隊(duì)里java頂多排名最后。
基于C/S結(jié)構(gòu)的系統(tǒng),在這個(gè)方面java顯然沒有考慮周到,面對VB 、DELPHI、vc這些個(gè)如狼似虎的快速開發(fā)IDE,JAVA實(shí)在是顯得異常的淡薄,即使你找到了一個(gè)可以匹敵這些個(gè)ide的工具,面對第三方的組件又會成為一大障礙,所以java在這個(gè)方面又一次的輸了。
從java所強(qiáng)調(diào)的特性角度看java平臺
java的重點(diǎn)是業(yè)務(wù)邏輯!(我以前也是如此堅(jiān)信不移)可是誰有能夠說別的語言不注重業(yè)務(wù)邏輯呢,業(yè)務(wù)邏輯只是一個(gè)抽象的概念,java只是依靠ejb提出了業(yè)務(wù)組件而已,其他的語言在實(shí)現(xiàn)業(yè)務(wù)邏輯的時(shí)候也可以包裝成POJO的形式,看來這個(gè)觀點(diǎn)也是失敗的。
java強(qiáng)調(diào)的是跨平臺的優(yōu)勢!這可以理解為初級的、商業(yè)的、忽悠人的詞匯,面對眾多動態(tài)語言如Python,在若干平臺上的表現(xiàn),java又如何來強(qiáng)調(diào)自己這方面的優(yōu)勢呢?失敗
java支持分布式應(yīng)用的項(xiàng)目!可笑的言論,分布式根本不是值得炫耀的資本,在java之前的c/s項(xiàng)目中何嘗不是分布式的應(yīng)用呢?失敗
既然沒有了這些個(gè)優(yōu)勢,我們看看java到底還剩下些什么?對了其實(shí)就是應(yīng)用服務(wù)器!然而看過J2EE WITHOUT EJB的讀者肯定知道Spring所希望達(dá)到的目的,也就是脫離應(yīng)用服務(wù)器概念上的J2EE體系實(shí)現(xiàn),既然在作者的眼里APPLICATION SERVER只不過是一個(gè)忽悠人的詞匯,那么任何項(xiàng)目都選擇java作為開發(fā)的依據(jù)顯然就是自找苦吃,
那么什么情況下改選擇java作為開發(fā)的平臺呢?
<1> 如果你真的遇到了大型的系統(tǒng)開發(fā)任務(wù),恭喜你,你終于可以看到分布式對象、集群的優(yōu)勢了。
<2> 客戶是一個(gè)java的忠實(shí)fans或者是sun、ibm的金牌合作伙伴之類的,選擇java是不得已的,但記住并不能證明java是最好的實(shí)現(xiàn)方式
<3> 如果你只想關(guān)心業(yè)務(wù)邏輯的實(shí)現(xiàn),對于事務(wù)、緩存、查找等服務(wù)的實(shí)現(xiàn)沒有興趣的話,倒是不妨考慮采用ejb的形式,當(dāng)然前提是你不愿意在尋找合適的替代品的情況下。
<4> 如果項(xiàng)目迫切的尋找某種框架的支持,選擇java就是對的,你有眾多優(yōu)秀的、免費(fèi)的、可擴(kuò)展的、天才的框架可以選擇,更多的時(shí)候你是出于尷尬的境地,因?yàn)槿魏我粋€(gè)都讓你心動、而這樣的選擇往往是最痛苦、和快樂的。
正確的選擇
<1>
條件: 如果項(xiàng)目僅僅只是一個(gè)小型的網(wǎng)站系統(tǒng)
選擇: LAMP、Rails
<2>
條件: 項(xiàng)目規(guī)模中等
并且項(xiàng)目的時(shí)間比較緊,
項(xiàng)目可以架構(gòu)在windows的系統(tǒng)之上,
選擇: .Net? / Delphi
<3>
條件: 大型的系統(tǒng),有支持分布式對象、集群的要求;或者SUN / IBM的金牌合作伙伴 ; 想要尋找某種優(yōu)秀的框架來解決問題
選擇: java是不二的選擇,可是我想問一下,在現(xiàn)實(shí)中你能遇到這樣的項(xiàng)目嗎?
所以,從實(shí)際的角度出發(fā),我們面對的99%可能都是一些符合條件1,2的系統(tǒng),而選擇java實(shí)在是得不償失的。最后以一段Code Complete中的話來作為結(jié)束語
每個(gè)程序員都有很多的工具,但并不存在任何一個(gè)能夠適用于所有工作的工具,因地制宜的選擇正確工具是成為能有效編程的程序員的關(guān)鍵。
posted @ 2006-03-29 13:49 killvin| 編輯 收藏
作者簡介
XincChen是Xtremework公司創(chuàng)始人.a自從.NET推出以來,1他已使用.NET幫助很多行業(yè)的用戶開發(fā)了體現(xiàn)其商業(yè)理念的軟件產(chǎn)品.aXincChen是.NET和EAI方面的專家,1他與Microsoft和Accenture等多家技術(shù)領(lǐng)先的公司合作,1為它們的客戶提供了優(yōu)秀的解決方案.a在工作之余,1他喜歡讀書.c寫書.c以及靜靜地休息.aApress出版社的另一本書——《BizTalkc2002cDesigncandcImplementation》——也是出自他的筆下.aXincChen擁有哥倫比亞大學(xué)的統(tǒng)計(jì)學(xué)文科碩士學(xué)位,1現(xiàn)居國內(nèi),1正在籌建公司在北京的研發(fā)中心.a可通過xchen@Xtremework.com和作者取得聯(lián)系.
個(gè)人評論
這本書本來購買時(shí)的期望值非常的高,想必是一本細(xì)數(shù).NET框架類的圖書,結(jié)果卻大失所望,而這本書也就因?yàn)槠浼夹g(shù)上的薄弱而消弱了其價(jià)值的表現(xiàn)力,不過作為一本.NET入門級的圖書還是比較的合適,但在CSDN上竟然有四顆半的星的待遇實(shí)在不敢恭維。
而且作者的代碼顯然非常的粗造,竟然連起碼的業(yè)務(wù)級數(shù)據(jù)校驗(yàn)都沒有,在一些功能的分解上也是抹漿糊,可以想象作者并沒有深入的思考而僅僅是去實(shí)現(xiàn)功能而已,猜想這樣的框架很可能是作者對于以前工作的簡單抽象而已。
整體上本書除了第一章應(yīng)用框架介紹 、 第二章應(yīng)用框架解析比較的出彩,尤其是創(chuàng)造性的提出了業(yè)務(wù)假設(shè)(Business assumption)的概念還比較的有深度,其他的章節(jié)只是對于其SAF框架的介紹,但在技術(shù)實(shí)現(xiàn)上只是對于.NET的若干相關(guān)服務(wù)的簡單包裝而已,對于已經(jīng)在JAVA世界里的人來說,SAF框架其實(shí)就是Spring框架在.NET世界的簡單實(shí)現(xiàn)版本,但相對于Spring的技術(shù)實(shí)力,作者還需要努力才行,不過作者顯然是.NET方面的高手,對于.NET世界提供的雜亂無章的服務(wù)特性以及服務(wù)的原理非常的清楚,這也難怪在這樣的平臺上再去"多此一舉"的開發(fā)另外的框架,無論從技術(shù)上還是推廣上都非常的難!不過領(lǐng)略一下..NET的秀發(fā)也是多少有所收獲的 :)
再次強(qiáng)調(diào)這本書僅僅只能夠算作.NET方面的初級讀物,個(gè)人評星3.5 ,請朋友們謹(jǐn)慎購買。
posted @ 2006-03-24 14:22 killvin| 編輯 收藏
wfc是構(gòu)建在B/S結(jié)構(gòu)上的流程定義工具
具備以下的功能
1> 實(shí)現(xiàn)了B/S結(jié)構(gòu)上的工作流定義工具(沒有看到同類型的產(chǎn)品)。
2> 流程定義格式與具體的工作流格式相分離,并可以在此基礎(chǔ)上實(shí)現(xiàn)其他的流程定義工具產(chǎn)品。
3> 采用了Buffalo(XML-RPC的javascript實(shí)現(xiàn))實(shí)現(xiàn)與后端Servlet的綁定。
4> 可以對具體的節(jié)點(diǎn)進(jìn)行屬性的配置(配置后的數(shù)據(jù)會被綁定為java的List自動傳遞到后端)。
目前還需要改進(jìn)的
1> 修改目前工作流的圖標(biāo)(需要分支、狀態(tài)、合并這樣專業(yè)的圖標(biāo))
2> 解決瀏覽器的刷新問題。
3> 增加線段的表現(xiàn)形式選項(xiàng)
4> 增加曲線的表現(xiàn)形式,尤其是在多線段的情況下要自動調(diào)整為曲線的形式。
目前的WFC已經(jīng)被Michael Chen(buffalo的作者)收錄在其網(wǎng)站上!地址如下
http://demo.amowa.net/wfc
對于buffalo的關(guān)注早在作者剛發(fā)布的時(shí)候就已經(jīng)開始了,起初不太了解buffalo的作用,然而在具體的工作中尋找基于XML-RPC協(xié)議的產(chǎn)品時(shí)突然明白了它的價(jià)值,不過說簡單一點(diǎn)buffalo是實(shí)現(xiàn)了基于javascript的對象的序列化以及反序列化工作。
posted @ 2006-03-21 17:58 killvin| 編輯 收藏
通用類圖書
卓越獎: Prefactoring by Ken Pugh (O'Reilly)
生產(chǎn)力獎:
Innovation Happens Elsewhere: Open Source as Business Strategy by Ron Goldman, Richard P. Gabriel (Morgan Kaufmann)
Producing Open Source Software: How to Run a Successful Free Software Project by Karl Fogel (O'Reilly)
The Art of Project Management by Scott Berkun (O'Reilly)
技術(shù)類圖書
卓越獎:Agile Web Development with Rails by Dave Thomas, David Hansson, Leon Breedt and Mike Clark (Pragmatic Bookshelf)
生產(chǎn)力獎:
Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries by Krzysztof Cwalina and Brad Abrams (Addison-Wesley)
Practical Common Lisp by Peter Seibel (Apress)
Why Programs Fail: A Guide to Systematic Debugging by Andreas Zeller (Morgan Kaufmann)
企業(yè)項(xiàng)目管理
卓越獎: WelcomRisk 2.6 (Welcom)
生產(chǎn)力獎:
Corticon Business Rules Management 4.0 (Corticon)
JBoss 2 Portal (JBoss)
Visual Studio Team System 2005 (Microsoft)
數(shù)據(jù)庫引擎和數(shù)據(jù)工具
卓越獎: Microsoft SQL Server 2005 (Microsoft)
生產(chǎn)力獎:
Berkeley DB 4.4 (Sleepycat Software)
Google Maps API 2005 (Google)
MySQL 5.0 (MySQL)
缺陷跟蹤,變更和配置管理
卓越獎: Perforce SCM 2005 (Perforce)
生產(chǎn)力獎:
FogBugz 4.0 (Fog Creek)
Guiffy SureMerge 7.0 (Guiffy Software)
JIRA 3.4 (Atlassian Software)
設(shè)計(jì)和建模工具
卓越獎:Lattix LDM 2.0 (Lattix)
生產(chǎn)力獎:
Borland Together 2006 for Eclipse (Borland)
Enterprise Architect 6.0 (Sparx Systems)
MindManager Pro 6.0 (Mindjet)
開發(fā)環(huán)境
卓越獎: Visual Studio Team System 2005 (Microsoft)
生產(chǎn)力獎:
Eclipse SDK 3.1 (Eclipse.org)
IntelliJ IDEA 5.0 (JetBrains)
Komodo 3.5 (ActiveState)
類庫、框架和組建
卓越獎: .NET Framework 2.0 (Microsoft)
生產(chǎn)力獎:
Dundas Chart for .NET 5.0 (Dundas Software)
Qt 4.0 (Trolltech)
Spring Framework 1.2.6 (SpringFramework.org)
移動開發(fā)工具
卓越獎: Crossfire 5.6 (AppForge)
生產(chǎn)力獎:
Carbide.c++ Express (Nokia)
Flash Lite 2.0 (Adobe)
NetBeans IDE 4.1 (Sun Microsystems)
項(xiàng)目質(zhì)量管理
卓越獎: Rally 5.6 (Rally Software Development)
生產(chǎn)力獎:
CollabNet Enterprise Edition with Project Dashboard/Task Management 2005 (CollabNet)
QACenter Enterprise Edition 5.1 (Compuware)
TargetProcess Suite 1.4 (TargetProcess)
安全工具
卓越獎: Elemental Compliance System 1.4 (Elemental)
生產(chǎn)力獎:
CodeAssure 2.0 (Secure Software)
DevPartner SecurityChecker 1.0 (Compuware)
Fortify Security Tester 1.0 (Fortify)
測試工具
卓越獎:VMTN Subscription 2005 (VMware)
生產(chǎn)力獎:
Agitator 3.0 (Agitar Software)
AQtime 4.7 (AutomatedQA)
Clover 1.3 (Cenqua)
實(shí)用程序
卓越獎:Camtasia Studio 3.0 (TechSmith)
生產(chǎn)力獎:
DevPartner Studio 8 (Compuware)
Fog Creek Copilot 1.2 (Fog Creek Software)
ReSharper 1.5 (JetBrains)
Web開發(fā)工具
卓越獎: Rails 1.0 (rubyonrails.org)
生產(chǎn)力獎:
JBoss Application Server 4x (JBoss)
Macromedia Studio 8 2005 (Adobe)
Zend Studio - Enterprise Edition 5.0 (Zend)
名人堂產(chǎn)品獲獎?wù)?
?Visual Studio Professional Edition (Microsoft)
感慨
??? MS在這次的JOLT中屢獲殊榮,深思。。。
posted @ 2006-03-19 09:32 killvin| 編輯 收藏
很久都不罵人了,可是一不留心又看到了他寫了惡心文章,實(shí)在是讓人憤慨!這位板橋里人的"大名"是從透明的blog上知道的,首先就是感覺這個(gè)人的腦子有點(diǎn)問題!不去評論他發(fā)布的那個(gè)所謂的框架,就看看他寫的一些文章就足以知道這個(gè)人腦袋非常的混亂,在這樣混亂的情況下寫出來的文章也就可想而知了,最近這位所謂的"大俠"又開始害人了
你還在用if else嗎?- http://www.jdon.com/artichect/ifelse.htm
面向過程設(shè)計(jì)和面向?qū)ο笤O(shè)計(jì)的主要區(qū)別是:是否在業(yè)務(wù)邏輯層使用冗長的if else判斷。如果你還在大量使用if else,當(dāng)然,界面表現(xiàn)層除外,即使你使用Java/C#這樣完全面向?qū)ο蟮恼Z言,也只能說明你的思維停留在傳統(tǒng)的面向過程語言上。
-我很納悶了作者怎么可以從是否使用if else來判斷一個(gè)設(shè)計(jì)是否符合OO特性呢?我們看到的if else屬于語言這個(gè)層次的東西,而if else僅僅是完成邏輯判斷的語句;如果說作者的這個(gè)觀點(diǎn)成立的話,java、c#的語言發(fā)明者應(yīng)該早就明白或者預(yù)測到if else 的"不OO"的特性,也會考慮到在語言層面刪除這樣的邏輯判斷語句,但事實(shí)呢?發(fā)明者非但沒有刪除相反其他語言的發(fā)明者也一起發(fā)明了if else語句?!難道是大師們錯了?
還是以大家熟悉的論壇帖子為例子,如ForumMessage是一個(gè)模型,但是實(shí)際中帖子分兩種性質(zhì):主題貼(第一個(gè)根貼)和回帖(回以前帖子的帖子),這里有一個(gè)樸素的解決方案:
建立一個(gè)ForumMessage,然后在ForumMessage加入isTopic這樣判斷語句,注意,你這里一個(gè)簡單屬性的判斷引入,可能導(dǎo)致你的程序其他地方到處存在if else 的判斷。
如果我們改用另外一種分析實(shí)現(xiàn)思路,以對象化概念看待,實(shí)際中有主題貼和回帖,就是兩種對象,但是這兩種對象大部分是一致的,因此,我將ForumMessage設(shè)為表達(dá)主題貼;然后創(chuàng)建一個(gè)繼承ForumMessage的子類ForumMessageReply作為回帖,這樣,我在程序地方,如Service中,我已經(jīng)確定這個(gè)Model是回帖了,我就直接下溯為ForumMessageReply即可,這個(gè)有點(diǎn)類似向Collection放入對象和取出時(shí)的強(qiáng)制類型轉(zhuǎn)換。通過這個(gè)手段我消滅了以后程序中if else的判斷語句出現(xiàn)可能。
-作者在這里似乎列舉了一個(gè)例子,可是對于帖子和回帖這樣簡單的問題,只要遵守OO的設(shè)計(jì)師都會抽象出一個(gè)帖子的父類,然而這又能說明什么呢?在具體的業(yè)務(wù)邏輯中難道你不判斷傳遞過來的對象的類別?(現(xiàn)在主題貼與回帖的處理方法是不同的),同樣你無法避免在具體的編碼中使用if else的可能?!
最后總結(jié):將if else用在小地方還可以,如簡單的數(shù)值判斷;但是如果按照你的傳統(tǒng)習(xí)慣思維,在實(shí)現(xiàn)業(yè)務(wù)功能時(shí)也使用if else,那么說明你的思維可能需要重塑,你的編程經(jīng)驗(yàn)越豐富,傳統(tǒng)過程思維模式就容易根深蒂固,想靠自己改變很困難;建議接受專業(yè)頭腦風(fēng)暴培訓(xùn)。
用一句話總結(jié):如果你做了不少系統(tǒng),很久沒有使用if else了,那么說明你可能真正進(jìn)入OO設(shè)計(jì)的境地了。(這是本人自己發(fā)明的實(shí)戰(zhàn)性的衡量考核標(biāo)準(zhǔn))。
-顯然作者并不是去討論if else的語言問題,而是為自己的"洗腦培訓(xùn)"打廣告!并講這樣的問題上升到設(shè)計(jì)模式、禪的境界,可謂是煞費(fèi)苦心呀,沒有人說設(shè)計(jì)模式不好也沒有人懷疑禪的境界的高深,但不是作者這樣的人靠讀一兩篇文章或者發(fā)布個(gè)所謂的"毫無實(shí)際意義"的框架就可以領(lǐng)悟到的,還是那句話:長得丑不要緊,不要出來嚇人!不過我還要補(bǔ)充一句就是,不懂不要緊,不要亂說免得害人(因?yàn)槲覀兌贾罎妺D罵街的道理,雖然沒文化但確實(shí)能夠帶來眼球效應(yīng))。
posted @ 2006-03-10 11:49 killvin| 編輯 收藏
本來以為是Maxthon的問題(在鼠標(biāo)單擊的時(shí)候會關(guān)閉一些窗口,并且是隨機(jī)的?!)還就這樣的問題給作者寫了一封信?汗。。。經(jīng)過仔細(xì)的尋找原因,原來是自己的鼠標(biāo)的問題(這個(gè)鼠標(biāo)跟了我快7年了,Logitech最好的滾軸鼠標(biāo),要300多塊大洋)有點(diǎn)舍不得,又沒有辦法,該下崗了,一同下崗的也許還有我的鍵盤(TCL的手感級差!:( )
不過為了找原因我倒是廢了一番周折,下載和試用了N多的瀏覽器,也看了很多網(wǎng)上的評論對比文章,現(xiàn)在主流的瀏覽器主要就是Opera , Firefox, Maxthon , GreenBrowser , MyIE , TheWorld 等,然而在資源的利用率上這些個(gè)產(chǎn)品都非常的讓人失望,難道就沒有一款適合于程序員的胃口的瀏覽器?!
可喜的是偶發(fā)現(xiàn)了GOSURF這款瀏覽器,在眾多的瀏覽器中它的內(nèi)存占用率是最低的,而且它的作者似乎在這方面也是煞費(fèi)苦心,"一味"的強(qiáng)調(diào)速度,甚至對于鼠標(biāo)手這個(gè)及其流行的功能的加入也是非常的謹(jǐn)慎,可以看出作者是個(gè)很有個(gè)性的程序員,值得期待!
如果你和我一樣對資源的利用率近乎苛刻,可以考慮這樣的一款產(chǎn)品 http://gosurfbrowser.com/?ln=cn
posted @ 2006-03-07 17:42 killvin| 編輯 收藏
http://www-128.ibm.com/developerworks/cn/java/j-junit4.html
JUnit 是 Java? 語言事實(shí)上的 標(biāo)準(zhǔn)單元測試庫。JUnit 4 是該庫三年以來最具里程碑意義的一次發(fā)布。它的新特性主要是通過采用 Java 5 中的標(biāo)記(annotation)而不是利用子類、反射或命名機(jī)制來識別測試,從而簡化測試。在本文中,執(zhí)著的代碼測試人員 Elliotte Harold 以 JUnit 4 為例,詳細(xì)介紹了如何在自己的工作中使用這個(gè)新框架。注意,本文假設(shè)讀者具有 JUnit 的使用經(jīng)驗(yàn)。
JUnit 由 Kent Beck 和 Erich Gamma 開發(fā),幾乎毫無疑問是迄今所開發(fā)的最重要的第三方 Java 庫。正如 Martin Fowler 所說,“在軟件開發(fā)領(lǐng)域,從來就沒有如此少的代碼起到了如此重要的作用”。JUnit 引導(dǎo)并促進(jìn)了測試的盛行。由于 JUnit,Java 代碼變得更健壯,更可靠,bug 也比以前更少。JUnit(它本身的靈感來自 Smalltalk 的 SUnit)衍生了許多 xUnit 工具,將單元測試的優(yōu)勢應(yīng)用于各種語言。nUnit (.NET)、pyUnit (Python)、CppUnit (C++)、dUnit (Delphi) 以及其他工具,影響了各種平臺和語言上的程序員的測試工作。
然而,JUnit 僅僅是一個(gè)工具而已。真正的優(yōu)勢來自于 JUnit 所采用的思想和技術(shù),而不是框架本身。單元測試、測試先行的編程和測試驅(qū)動的開發(fā)并非都要在 JUnit 中實(shí)現(xiàn),任何比較 GUI 的編程都必須用 Swing 來完成。JUnit 本身的最后一次更新差不多是三年以前了。盡管它被證明比大多數(shù)框架更健壯、更持久,但是也發(fā)現(xiàn)了 bug;而更重要的是,Java 不斷在發(fā)展。Java 語言現(xiàn)在支持泛型、枚舉、可變長度參數(shù)列表和注釋,這些特性為可重用的框架設(shè)計(jì)帶來了新的可能。
JUnit 的停滯不前并沒有被那些想要廢棄它的程序員所打敗。挑戰(zhàn)者包括 Bill Venners 的 Artima SuiteRunner 以及 Cedric Beust 的 TestNG 等。這些庫有一些可圈可點(diǎn)的特性,但是都沒有達(dá)到 JUnit 的知名度和市場占有份額。它們都沒有在諸如 Ant、Maven 或 Eclipse 之類的產(chǎn)品中具有廣泛的開箱即用支持。所以 Beck 和 Gamma 著手開發(fā)了一個(gè)新版本的 JUnit,它利用 Java 5 的新特性(尤其是注釋)的優(yōu)勢,使得單元測試比起用最初的 JUnit 來說更加簡單。用 Beck 的話來說,“JUnit 4 的主題是通過進(jìn)一步簡化 JUnit,鼓勵更多的開發(fā)人員編寫更多的測試。”JUnit 4 盡管保持了與現(xiàn)有 JUnit 3.8 測試套件的向后兼容,但是它仍然承諾是自 JUnit 1.0 以來 Java 單元測試方面最重大的改進(jìn)。
注意:該框架的改進(jìn)是相當(dāng)前沿的。盡管 JUnit 4 的大輪廓很清晰,但是其細(xì)節(jié)仍然可以改變。這意味著本文是對 JUnit 4 搶先看,而不是它的最終效果。
posted @ 2006-03-05 13:10 killvin| 編輯 收藏
在這個(gè)暖暖的午后享受著陽光的溫暖的同時(shí),聽著CUSCO 的專輯實(shí)在是一種享受,我喜歡那種寧靜的音樂,因?yàn)樗鼛Ыo你的除了純凈還是純凈。。。。
不想被任何的人打擾,城市的喧鬧讓自己的思想變得復(fù)雜,而唯獨(dú)音樂才能夠真正的喚醒你心靈深處的東西,
posted @ 2006-03-04 13:23 killvin| 編輯 收藏