2008年10月14日 星期二

static 的使用時機

首先大致了解一下 static 這個修飾字,及使用規則。

static 是屬於類別層級的修飾字,在記憶體裡面只存有一份,不論我們 new 了幾個物件,該成員或函示始終指向同一個記憶體位置。而 static 成員只能被 static 成員呼叫或存取。

在使用的時機方面,static 是在任何物件運作之前就會被呼叫的,因此我們也常常使用
main method 來作測試,再來就是常見的公用 method,類似 Utilites,與不會改變的常數等等。

下列有個例子舉的很好,可以拿來說明:

public class StaticModifier
{
int counter1 = 0;
static int counter2 = 0;

public void Increase(String s)
{
counter1++;
counter2++;
System.out.print(s + "'s counter1 = " + counter1);
System.out.println("; counter2(static) = " + counter2);
}

public static void main(String argv[])
{
StaticModifier sta1 = new StaticModifier();
StaticModifier sta2 = new StaticModifier();

sta1.Increase("sta1");
sta1.Increase("sta1");
sta2.Increase("sta2");
}
}
程式輸出為:
sta1's counter1 = 1; counter2(static) = 1
sta1's counter1 = 2; counter2(static) = 2
sta2's counter1 = 1; counter2(static) = 3
Reference:
http://www.javaworld.com.tw/jute/

2008年10月12日 星期日

Override equals(), override hashCode()

這項規則可以參考 java.lang.Object 的規格書

1. 在同一個應用程式執行期間, 對同一個物件呼叫 hashCode(), 必須回傳相同的整數結果
2. 如果兩個物件被 equals(Object) 視為相等, 則這兩個物件呼叫 hashCode() 必須獲得相同的整數結果
3. 如果兩個物件被 equals(Object) 視為不相等, 則這兩個物件呼叫 hashCode() 不必獲得相同的整數結果

若要方便產生這些原始碼,也可以參閱 commons.lang.builder
org.apache.commons.lang.builder

另外我們可以研究一下 java.lang.Object, java.lang.String 底下的原始碼
java.lang.Object

public boolean equals(Object obj) {
return (this == obj);
}
java.lang.String
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = count;
if (n == anotherString.count) {
char v1[] = value;
char v2[] = anotherString.value;
int i = offset;
int j = anotherString.offset;
while (n-- != 0) {
if (v1[i++] != v2[j++])
return false;
}
return true;
}
}
return false;
}
很明顯的,equals()在比較是否 reference 到同一個記憶體位置,若為 String 物件,則比對物件的內容。

2008年10月7日 星期二

利用 JAD 將程式碼反組譯心得

最近有一項 task 還蠻有趣的,由於 Production 上的 JAR 檔案與版本控制上的程式碼不盡相同,因此每次改程式的方式,都是從測試機將 JAR 檔抓下來再將修好的 .class 檔案放進去測試,但這樣比較有風險,因為我們不知道放進去的程式會不會影響到其它的 binary 檔案。

為了作調整,將 Production 與 SVN 裡面的程式碼作同步是勢在必行了,但是 binary 檔案與 java 的格式本來就不同,那要如何作比較? 這裡提供一個簡單的方法,利用 jad.exe 將我們從 SVN checkout 的檔案反組譯,這樣他跟 JAR 檔就有比較的基準了。

每次 build 的檔案是從版本控制上下來的程式碼,比較容易追朔、也降低了風險,最重要的是我們可以確定測試機、與正式機的內容是一樣的。

2008年10月2日 星期四

開發產品軟體雜感

由於在軟體界已逾四年,碰過比較有印象的產品有ATG(電子商務平台),跟目前要開發的產品Firewire CMS(內容管理系統)。ATG是一個滿成熟的平台,在四五年前,就已經有controller-->manager-->類似hibernate OR mapping 的觀念,並擁有自己的 taglib,也就是整套都在他自己的環境下被封裝好了,需要照著產品自訂的流程跟API來作開發。

最近碰的這套是內容管理系統,以開發的角度來說是較容易些。因為他的 development guide 只定義了自己的API跟 taglib,除了要懂這些標籤跟少數的API,其實就沒有什麼太多技術面的問題,剩下的都是比較屬於如何利用他自己的流程、介面來管理內容。

而台灣自製的軟體產品我大概碰過兩套,都是跟知識管理有關係的,其中一套設計的比較好、利用struts,EJB來建構,裡面也有很多的design pattern可以參考跟學習,當然如果不作分散式的處理,使用EJB實在有點大材小用,也增加開發的額外負擔。

當我們的專案碰到產品時,應該不能以寫程式的角度來看,不然我們可能會認為,這些功能我用struts, spring 都作的出來,為什麼要增加額外的負擔再去學這些流程。而這些流程跟技術,都有一定的道理存在。

例如 CMS 強調的就是產品上稿,與產品之間的關連性,只要將這些element與關連建起來,利用他自製的tag,就可以很容易的將這些功能表現出來。

雖然我們能夠在這既有的 framework 上發揮的點並不多,但是這些產品畢竟都還是 java-based的,可以從開發的流程去檢討、可以試著整進CI、作適度的 refactoring,都可以有助於專案的品質。