» Publishers, Monetize your RSS feeds with FeedShow: More infos (Show/Hide Ads)
Date: Saturday, 09 Jul 2005 22:32
/**
* @deprecated 本 blog 已經停用請改用下面的網址
*
* @link 新Blog:JavaWorld jroller
*/
public void viewXexexBlog() ;
Date: Thursday, 07 Jul 2005 10:56
我們新專案已完成 phase I 了,爽!

這 張圖是我們 (六個人) 三個月來 pair 的成果,Y軸是每天 continuous integration 的 test case 的數量 (yes, 每天都是 success build)。四月初到四月中旬都是在分析需求,所以沒有增加 testcase。四月中開始則每天以20到30個 test case 不等,持續穩定的增加。最後七月總共1200 個 unit test。空白的部份則是週休二日。
雖然說穩定增加,其實裡面有兩週 (五月初和六月初)線是水平的。五月初那次是寫到400個test case 後發現架構有問題,所以整週都在做 refactoring (事後證明 refactoring 是對的) 六月初那次是大家去三天員工旅遊的啦~~~ 所以線也是平的 :-)
專案的平台是 Struts + Hibernate + Spring,除了JSP 之外,全部都寫了 Unit case。不知這樣的架構三個月 1200 個 test case 會不會算太少太慢?網路上從來沒看過相關文獻說....
我 們第一個專案 是 Struts + Hibernate平台,共 1500 個 Test Case,當時 Struts 並沒有寫 Unit Test,所以大多數是 business, database 相關的 test case。你猜總共要跑多久?總共要 40 分鐘!寫到後來每次都要等很久..... 沒力啊.... 而這新的專案呢? 1200 個 只需要 4 分鐘 (包含建立資料庫) ,非常非常地快,開發的節奏完全不一樣了,讚!這都歸功於 Spring, Easymock, 與新版 Ant 的功能,強力推薦大家使用!
pair 的成員上次提過了,三個男 + 三個女的 (我們這男女開發員比例約為 1:1)
第一組:
(主導性高) 重度感染 Test 的 男 developer (症狀是每天逼大家寫 Test)
(主導性低) 中間程度之男Developer (但不熟. Hibernate /Unit test ... )
第二組:
(主導性高) 正值懷孕的中上程度女 developer (我沒寫錯,你也沒看錯,是 "懷孕")
(主導性低) 中間程度之女 Developer (配合度高)
第三組:
(主導性中) 男新人,不過底子夠,自學性強
(主導性中) 女 java 新手,背景是 procedure, database SQL 出身,不過她是整個 team 裡最熟 domain 的。
第一組曾發生過內亂,"Test 男" 嫌 "不熟男" 程度跟不上。氣的想自己寫算了。後來 "不熟男"發奮圖強,所以暫時先合解。"Test 男" 也改變了做法,pair 的時候都讓 "不熟男" 操作鍵盤,好好訓練。現在 pair 經過三個月後,"不熟男" 漸漸有點成績出來了。雖說獨當一面還不大夠,但是已經可以獨立維護程式了,終於變 "熟男" 了。
第二組在技術和經驗都沒什麼問題啦,她們後來也寫了最多的 test case。比較大的問題是 "懷孕女" 正值懷孕期間.... 還好跟她搭當的是我們 team 中配合度極佳的 女 developer,所以一切相安無事。不過 "配合女" 由於鍵盤都被主導性極強的 "懷孕女"搶走,所以對 pair programming 不是有好感,還是希望能自己寫,有自己的發揮空間。
第三組是個人最擔心的一 組... 因為兩個人都是第一次在這裡開發 java 專案,前兩組的都有過舊專案的 "教訓",所以都會採取比較正確的寫法。三個月下來,雖然 code 有一些暇疵,不過還是漂亮的完成了任務。"底子夠男" 脾氣比 "Test 男" 好多了,跟新手 pair 比較有耐心。"女java新手" 除了 web 那些有的沒的學不大起來之外,其他的邊學邊寫之下也頗成氣候的。而且她對 domain 熟,抓的方向會比較準。有趣的是 "女 java 新手" 開發完後的結論是:"還是 procedure 好寫......"
如果這次不是這樣 pair,比方說改成 "Test 男" + "女java新手",也許 "女java新手" 會比較了解為何 java 要這麼複雜,為何所有程式都要寫 test。又如將 "不熟男" + "配合女" 一起 pair,那自然就不會有衝突,"配合女" 也拿的到鍵盤,比較有機會發揮了。再將 "懷孕女" + "底子夠男" pair,那麼這一組的程式就不會有暇疵,"底子夠男" 可直接吸收 "懷孕女" 的經驗,而 "底子夠男" 脾氣較好,比較不會影響 "懷孕女" 的胎氣...
當然這樣想是事後諸葛啦,誰知道這樣的 pair 會不會有新的問題咧?
(上面那一段用的詞句有點奇怪,希望大家看的懂啦...)
Anyway, 個人對這次 pair 的感受是 --
(1) pair programming 是最好的教育訓練的工具。原本高中低手都有,三個月後大家的水準馬上都拉上來了。未來我想 pair 的配對選擇方式應該會以教育訓練為第一個考量。
(2) pair programming 減輕很多壓力!不論是設計或是撰寫,你都有 partner 可以商量,分擔責任,我們 team 裡沒有專職的 SA/SD,所以 pair design 適時的發揮效用。另外,想請假也有 "完整" 代理人。而且你不用花時間維護太多的文件,你隨時都有接班人,文件自然能寫精簡一點啦
(3) 不用說,code quality 自然是標準水平以上了。如果這個專案是六個人分開寫,我真的不知道會變成什麼樣子... 就算三個月生東西出來了,大概也不能用吧....
總結。pair programming 不可能風平浪靜.... 有很多問題一一待克服.... 我們這先天的優點是男女比例一樣,我想如果是清一色的男性,那困難會大上很多。三個月下來,我相信我們 team 已經跨過 XP 的門檻了,相信未來的專案會繼續採用 XP -- 因為我們已經嘗到甜頭啦!

這 張圖是我們 (六個人) 三個月來 pair 的成果,Y軸是每天 continuous integration 的 test case 的數量 (yes, 每天都是 success build)。四月初到四月中旬都是在分析需求,所以沒有增加 testcase。四月中開始則每天以20到30個 test case 不等,持續穩定的增加。最後七月總共1200 個 unit test。空白的部份則是週休二日。
雖然說穩定增加,其實裡面有兩週 (五月初和六月初)線是水平的。五月初那次是寫到400個test case 後發現架構有問題,所以整週都在做 refactoring (事後證明 refactoring 是對的) 六月初那次是大家去三天員工旅遊的啦~~~ 所以線也是平的 :-)
專案的平台是 Struts + Hibernate + Spring,除了JSP 之外,全部都寫了 Unit case。不知這樣的架構三個月 1200 個 test case 會不會算太少太慢?網路上從來沒看過相關文獻說....
我 們第一個專案 是 Struts + Hibernate平台,共 1500 個 Test Case,當時 Struts 並沒有寫 Unit Test,所以大多數是 business, database 相關的 test case。你猜總共要跑多久?總共要 40 分鐘!寫到後來每次都要等很久..... 沒力啊.... 而這新的專案呢? 1200 個 只需要 4 分鐘 (包含建立資料庫) ,非常非常地快,開發的節奏完全不一樣了,讚!這都歸功於 Spring, Easymock, 與新版 Ant 的功能,強力推薦大家使用!
pair 的成員上次提過了,三個男 + 三個女的 (我們這男女開發員比例約為 1:1)
第一組:
(主導性高) 重度感染 Test 的 男 developer (症狀是每天逼大家寫 Test)
(主導性低) 中間程度之男Developer (但不熟. Hibernate /Unit test ... )
第二組:
(主導性高) 正值懷孕的中上程度女 developer (我沒寫錯,你也沒看錯,是 "懷孕")
(主導性低) 中間程度之女 Developer (配合度高)
第三組:
(主導性中) 男新人,不過底子夠,自學性強
(主導性中) 女 java 新手,背景是 procedure, database SQL 出身,不過她是整個 team 裡最熟 domain 的。
第一組曾發生過內亂,"Test 男" 嫌 "不熟男" 程度跟不上。氣的想自己寫算了。後來 "不熟男"發奮圖強,所以暫時先合解。"Test 男" 也改變了做法,pair 的時候都讓 "不熟男" 操作鍵盤,好好訓練。現在 pair 經過三個月後,"不熟男" 漸漸有點成績出來了。雖說獨當一面還不大夠,但是已經可以獨立維護程式了,終於變 "熟男" 了。
第二組在技術和經驗都沒什麼問題啦,她們後來也寫了最多的 test case。比較大的問題是 "懷孕女" 正值懷孕期間.... 還好跟她搭當的是我們 team 中配合度極佳的 女 developer,所以一切相安無事。不過 "配合女" 由於鍵盤都被主導性極強的 "懷孕女"搶走,所以對 pair programming 不是有好感,還是希望能自己寫,有自己的發揮空間。
第三組是個人最擔心的一 組... 因為兩個人都是第一次在這裡開發 java 專案,前兩組的都有過舊專案的 "教訓",所以都會採取比較正確的寫法。三個月下來,雖然 code 有一些暇疵,不過還是漂亮的完成了任務。"底子夠男" 脾氣比 "Test 男" 好多了,跟新手 pair 比較有耐心。"女java新手" 除了 web 那些有的沒的學不大起來之外,其他的邊學邊寫之下也頗成氣候的。而且她對 domain 熟,抓的方向會比較準。有趣的是 "女 java 新手" 開發完後的結論是:"還是 procedure 好寫......"
如果這次不是這樣 pair,比方說改成 "Test 男" + "女java新手",也許 "女java新手" 會比較了解為何 java 要這麼複雜,為何所有程式都要寫 test。又如將 "不熟男" + "配合女" 一起 pair,那自然就不會有衝突,"配合女" 也拿的到鍵盤,比較有機會發揮了。再將 "懷孕女" + "底子夠男" pair,那麼這一組的程式就不會有暇疵,"底子夠男" 可直接吸收 "懷孕女" 的經驗,而 "底子夠男" 脾氣較好,比較不會影響 "懷孕女" 的胎氣...
當然這樣想是事後諸葛啦,誰知道這樣的 pair 會不會有新的問題咧?
(上面那一段用的詞句有點奇怪,希望大家看的懂啦...)
Anyway, 個人對這次 pair 的感受是 --
(1) pair programming 是最好的教育訓練的工具。原本高中低手都有,三個月後大家的水準馬上都拉上來了。未來我想 pair 的配對選擇方式應該會以教育訓練為第一個考量。
(2) pair programming 減輕很多壓力!不論是設計或是撰寫,你都有 partner 可以商量,分擔責任,我們 team 裡沒有專職的 SA/SD,所以 pair design 適時的發揮效用。另外,想請假也有 "完整" 代理人。而且你不用花時間維護太多的文件,你隨時都有接班人,文件自然能寫精簡一點啦
(3) 不用說,code quality 自然是標準水平以上了。如果這個專案是六個人分開寫,我真的不知道會變成什麼樣子... 就算三個月生東西出來了,大概也不能用吧....
總結。pair programming 不可能風平浪靜.... 有很多問題一一待克服.... 我們這先天的優點是男女比例一樣,我想如果是清一色的男性,那困難會大上很多。三個月下來,我相信我們 team 已經跨過 XP 的門檻了,相信未來的專案會繼續採用 XP -- 因為我們已經嘗到甜頭啦!
Date: Sunday, 15 May 2005 23:07
最近又看了一本 Pro Spring,喔~ 裡面的第十一章 (Designing and implementating spring-based applications) 真是太棒囉!很多建議都相當的實用,解決了許多困惑我很久的疑問。這樣子差不多可以整理出一個通用的開發架構了:
o J2EE without EJB
採用 Struts + Hibernate +Spring 三個 framework 開發專案,每個framework都提供較 j2ee 更簡單、更快速、更open的實作。
Struts Action/ActionForm, Hibernate DAO, Spring Service.... etc 從上到下所有的 java code 都依循 TDD 的方式開發。目前除了 jsp 之外,全部都要寫 unit test。
o 4 layers
啊,就先這樣就好了,以後有空在補。
o J2EE without EJB
採用 Struts + Hibernate +Spring 三個 framework 開發專案,每個framework都提供較 j2ee 更簡單、更快速、更open的實作。
- Struts 提供 presentation layer 的各項服務
- Hibernate 提供 domain layer 的 persistence 及 query 服務
- Spring 提供 transaction/mail/remoting... 等等 middle-ware 的服務
Struts Action/ActionForm, Hibernate DAO, Spring Service.... etc 從上到下所有的 java code 都依循 TDD 的方式開發。目前除了 jsp 之外,全部都要寫 unit test。
o 4 layers
- Presentation Layer - 與使用者互動
- Application Service Layer - 此層可明確表示 use case / user story / user requirement
- Domain Layer - domain problem mapping as domain objects interaction.
- Persistence Layer - 負責物件的儲存及查詢. (物件的中間生命週期)
- no DAO
- 進入 domain layer 前,先將資料轉換為 domain object,無論是從 database 來或是使用者輸入。
- domain object 間的 association,如果需要從 database query,盡可能改用 ORM 直接做associate ,而不是再透過 DAO 才連結。(除非 performance 的考量)
- no Service
- domain object 不應與任何 framework, container, context, enviroment... etc 等相關。所有存在於Domain Layer 的物件僅僅是互相連結的 POJO。
- Domain Object is not nessasary identical with Persistence Object(PO). just choose domain objects that need to persistence and query as PO.
- All Persistence Object's getter/setter should be in default package scope.
- Do not afraid introduceing new Class.
- Prefer immutable object. Immutable Object enforce you mapping domain problem to domain object correctly, and reduce maintain effort. Only Persistence Object has mutable characteristic.
- no getter/setter. Object's property is hidden and only expose behavior to public.
- no Singleton and no static. If you find something can apply singleton pattern, or design as static. It may be not belong to domain layer.
- Domain Object 會傳到 presentation layer 與使用者互動,會傳到 application layer 使用 middle-ware 服務、會扮演 PO 進入 persistence layer 儲存。
- 安全地跨全域的關鍵在於 Immutable。
- DTO is non-sense.
- ex. A Car has engine/wheel... etc. A engine can not work or sell directly. so typically Car class is Root of car/engine/wheel.
- ex. An engine Factory produce various engines and sell them to down-stream factory. Obviously now the engine is Root class for this domain.
- thin business logic
- coordinate:
- Root of Domain Object
- DAO
- Other middle-ware service (mail/remoting/transaction)
- each method is unit of work of user's single operation
- method boundary is transaction boundary, declare in Spring.
- Spring managed resources are all in this layer.
- Apply IoC in this layer heavily to make test easier. (flexible design)
- Every service is a interface and pair with at least one implementation: FooService/FooServiceImpl
- Not all database table has it's own DAO, only Root of Domain Object has DAO
- See Hibernate 3 Reference chap. 7 to choose best association for your ORM
- Efficiently use Hibernate's optimistic lock feature for concurrecy issue.
- Efficiently use Hibernate's lazy/cache/fetch join technique to improve ORM performance
- All POs have an primary key: 'Long id'. DO NOT use compose key !
- All POs' getter/setter scope is package default (private is better)
- Perfer HibernateTemplate and JdbcTemplate, with this we don't require additional interface for DAOs.
- ActionForm will be populated from Domain Object for user input.
- After user input, the ActionForm should convert user's input back to domain object if possible.
- It's ok that treat ActionForm as Domain Object and transfer into service layer, but use with care because ActionForm is highly mutable. If you want to protect Domain Layer and reuse ActionForm's code, Just let ActionForm implement Domain Object interface.
- each Action only call one method of a single service. (because of transaction boundary)
- Action's responsibility is to coordinate Invoking service method, ActionForm population, ActionForward flow, and compose ActionMessage... etc, nothing more.
- does nothing about business logic.
- All business exceptions are checked and user recoverable. if the exception is user un-recoverable, it should be classified as RuntimeException
- All business exception should extends 'BusinessException', the Root of all business exceptions
- If you want your business exception support i18n, use 'ResourceKeyBusinessException', which extends from 'BusinessException'
- Each module only has one its own Root business exception, and all rest of exceptions for this module should extends its own Root business exception
- This is checked exception, but you will not try to catch it except in Struts Action. business exception is 'user' recoverable, so it should always throw away until Struts Action. Struts Action catch Business Exception, convert to meaningful message and forward user to error page.
啊,就先這樣就好了,以後有空在補。
Date: Sunday, 15 May 2005 19:53
Spring ORM 替 Hibernate 的 API (Session and Query) 做了一番修整,也就是 HibernateTemplate ,它最主要的目的是 resource 控管及 exception 的轉換。有了這個 persistence layer 的 code 就可以大量的減少並且降低出錯的機會。然而這個 API 卻抹剎了 Hibernate API 的簡單易用優點,舉例來說,如果藉由 hibernateTemplate 控制 Hibernate Session (ex. Criteria),唯一的做法就是寫很難看的 Callback:
inner class + final.... 有夠難看。下面要介紹的是,利用 Spring AOP 的 AutoProxy 的功能,自動將 DAO 的所有 method 用 HibernateCallback 包起來。如此一來,便可以自由在 DAO 中自由存取 Hibernate Session 了:
總共需要三個 class:
第一個是 Advice,也就是將所有 method 都先用 HibernateCallback 包起來,然後將 Hibernate Session 放入 HibernateDAOWarpper 裡。
有了這個,再搭配上面的 Advice,我們就可以將所有 HibernateDAOWrapper 的 subclass 的所有 method 都用 HibernateCallback 包起來。Spring 的設定如下:
這個只要設一次就夠了。接下來我們再來看看主角:
呵,小的可憐,它的功能就是提供 getSession() 的 method 給 subclass 的 DAO 而已。這個 session 來自於 Advice,並且放在 ThreadLocal裡,因此是 thread-safe 的。使用方式就如上面的 javadoc 所說,將 DAO 直接 subclass 這個 Wrapper,並在 spring 裡定義即可。
這樣一來 DAO 就可以快快樂樂的用 Hibernate API 啦,爽!
(註:僅適用 Hibernate3,於 Hibernate 3.0.3 + Spring 1.2 final 測試 )
public MyData findByNo(final String no) {
final String hql = " select data from MyData data "
+ " where data.no = :no ";
HibernateCallback hc = new HibernateCallback() {
public Object doInHibernate(Session session) {
Query q = session.createQuery(hql);
q.setString("no", no);
return q.uniqueResult();
}
};
return (MyData) hibernateTemplate.execute(hc);
}
inner class + final.... 有夠難看。下面要介紹的是,利用 Spring AOP 的 AutoProxy 的功能,自動將 DAO 的所有 method 用 HibernateCallback 包起來。如此一來,便可以自由在 DAO 中自由存取 Hibernate Session 了:
總共需要三個 class:
第一個是 Advice,也就是將所有 method 都先用 HibernateCallback 包起來,然後將 Hibernate Session 放入 HibernateDAOWarpper 裡。
接下來就是 AutoProxyCreator,當它遇到 bean 的 class 為 HibernateDAOWrapper 的 subclass 時,它就會自動替該 bean 做 proxy。
public class HibernateDAOWrapperMethodInterceptor
implements MethodInterceptor {
private HibernateTemplate hibernateTemplate;
public Object invoke(final MethodInvocation methodInvocation)
throws Throwable {
try {
return hibernateTemplate.execute(new HibernateCallback() {
public Object doInHibernate(Session session)
throws HibernateException, SQLException {
HibernateDAOWrapper.currentSession.set(session);
try {
return methodInvocation.proceed();
} catch (Throwable e) {
if (e instanceof HibernateException) {
throw (HibernateException) e;
} else if (e instanceof SQLException) {
throw (SQLException) e;
} else {
//must re-throw as RuntimeException, and let
//hibernateTemplate deal with resource management
throw new ExceptionCarrier(e);
}
}
}
});
} catch (ExceptionCarrier e) {
throw e.throwable;
}
}
private static class ExceptionCarrier extends RuntimeException {
private Throwable throwable;
public ExceptionCarrier(Throwable t) {
this.throwable = t;
}
}
public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
this.hibernateTemplate = hibernateTemplate;
}
}
public class HibernateDAOWrapperAutoProxyCreator extends
AbstractAutoProxyCreator {
protected Object[] getAdvicesAndAdvisorsForBean(Class beanClass,
String beanName, TargetSource customTargetSource)
throws BeansException {
if (HibernateDAOWrapper.class.isAssignableFrom(beanClass)) {
return PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS;
} else {
return DO_NOT_PROXY;
}
}
}
有了這個,再搭配上面的 Advice,我們就可以將所有 HibernateDAOWrapper 的 subclass 的所有 method 都用 HibernateCallback 包起來。Spring 的設定如下:
<bean id="hibernateDAOWrapperAutoProxyCreator"
class="org.bioinfo.util.spring.dao.HibernateDAOWrapperAutoProxyCreator">
<property name="interceptorNames">
<list>
<value>hibernateDAOWrapperMethodInterceptor</value>
</list>
</property>
<!-- for use CGlib to create proxy,
(default to false, which will use Proxy if it detects interface presence) -->
<property name="proxyTargetClass">
<value>true</value>
</property>
</bean>
<bean id="hibernateDAOWrapperMethodInterceptor"
class="org.bioinfo.util.spring.dao.HibernateDAOWrapperMethodInterceptor">
<property name="hibernateTemplate">
<ref local="hibernateTemplate"/>
</property>
</bean>
這個只要設一次就夠了。接下來我們再來看看主角:
/**
* A special HibernateTemplate wrapper for DAO. You need to do:
*
* (1) Extends this class and use getSession() to obtain Hibernate3 Session
*
* <code>
* public class YourDAO extends HibernateDAOWrapper {
*
* public MyProject findByProjectCode(String code) {
* String hql = "select prj from MyProject prj where prj.code = :code";
*
* return (MyProject) getSession().createQuery(hql)
* .setString("code",code").uniqueResult();
* }
* }
* </code>
*
* (2) At your spring *.xml, just write one line:
*
* <code>
* <bean id="yourDAO" class="some.thing.YourDAO"></bean>
* </code>
*
* done !!
* @author ingram
*
*/
public abstract class HibernateDAOWrapper {
final static ThreadLocal currentSession = new ThreadLocal();
protected final Session getSession() {
return (Session) currentSession.get();
}
}
呵,小的可憐,它的功能就是提供 getSession() 的 method 給 subclass 的 DAO 而已。這個 session 來自於 Advice,並且放在 ThreadLocal裡,因此是 thread-safe 的。使用方式就如上面的 javadoc 所說,將 DAO 直接 subclass 這個 Wrapper,並在 spring 裡定義即可。
這樣一來 DAO 就可以快快樂樂的用 Hibernate API 啦,爽!
(註:僅適用 Hibernate3,於 Hibernate 3.0.3 + Spring 1.2 final 測試 )
Date: Monday, 25 Apr 2005 02:26
去年以來個人一直在 team 裡疾呼 unit-test 的重要。現在整個 team 裡除了幾個不曾跟 heavy-tester 一起合作的人之外,幾乎都了解 test 的好處和重要 (有些人是沒寫test 吃了大虧,有些人先是被逼著寫,後來嘗到了甜頭 )。去年的開發幾乎完全都是個人單打獨鬥,然後單純互相討論,今年這個新專案由六個人組成,好玩的是分工完之後就自動兩兩成對 pair 了。記得去年前 pair 時大家都哇哇叫,今年好像因為個別的不同理由不得不 pair 啊,目前 pair 的分配是:
A組沒有 pair 跟本做不下去,完全由資深帶領資淺,以免出差錯,不過資深的步調極快,資淺的步調極慢.........
C組的只能 pair 了,因為其中一人剛學 java.... 另一人功力夠,不過還沒實際作過專案,也沒有 test 的經驗
B組的都有 test 經驗,而且都能夠獨力作業,其實不 pair 好像也沒差,不過看起來 pair 的理由是有人可以互相討論,減輕壓力。
這是現在看到的現象,不知再過三個月會變成如何呢?呵呵,接下來討論一下經驗和構想吧:
- pair A -- 資深(主導性強) + test 新手
- pair B -- 資深(主導性強) + 中等
- pair C -- java 新手 + test 新手 (兩人主導性差不多)
A組沒有 pair 跟本做不下去,完全由資深帶領資淺,以免出差錯,不過資深的步調極快,資淺的步調極慢.........
C組的只能 pair 了,因為其中一人剛學 java.... 另一人功力夠,不過還沒實際作過專案,也沒有 test 的經驗
B組的都有 test 經驗,而且都能夠獨力作業,其實不 pair 好像也沒差,不過看起來 pair 的理由是有人可以互相討論,減輕壓力。
這是現在看到的現象,不知再過三個月會變成如何呢?呵呵,接下來討論一下經驗和構想吧:
- Personality
- Relax Time Control
- Standup Meeting
- Pair Rotating
Date: Sunday, 24 Apr 2005 13:22
Struts 的 Dispatch Action 已經行之有年了,有 Dispatch, Lookup, MappingDispatch... 好幾種可以用。但設定方法都很囉嗦 (網頁,程式,struts-config三者都要 hard-code String 在上面),而且適用的了 A ,就不能用在 B。例如雖然 DispatchAction 可以寫在 URL 上: /foo.do?method=saveOrder ,但是遇到一個 form 需要利用多個 submit button dispatch 時,就不行了。你得轉用 LookupDispatch,可是 LookupDispatch 又需要在 Action 定義一個很醜的 getKeyMethodMap() (裡面全部是 hard-code string)。接下來要分享一個通用 URL/submit button/struts-config.xml 三者設定的 SimpleDispatchAction:
嘿嘿,有了這個統合的 Dispatch,日子就好過多啦!我也另外用同樣的邏輯寫了個 SimpleDispatchActionForm,搭配起來用不錯。
package org.bioinfo.util.struts;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.springframework.web.struts.ActionSupport;
/**
* 簡化的 DispatchAction,並支援Spring的 ActionSupport (如不需要可以換回 Action)
*
* 使用方法:
*
* 繼承此 class,並定義各個 action method,比方說有兩個 method 分別做儲存和刪除:
*
* <code>
* public ActionForward save(ActionMapping mapping, ActionForm form,
* HttpServletRequest request, HttpServletResponse response)
* throws Exception {
* // orderService.save(....)
* }
*
* public ActionForward delete(ActionMapping mapping, ActionForm form,
* HttpServletRequest request, HttpServletResponse response)
* throws Exception {
* // orderService.delete(....)
* }
* </code>
*
* 有三種方式可以設定 dispatch 到哪個 method 上。
*
* (1) submit button 法,直接寫在 submit 的 property 上:
*
* <code>
* <html:form action="/some/work">
* .... some thing ....
*
* <html:submit property="dispatch=save" value="儲存"/>
* <html:submit property="dispatch=delete" value="刪除"/>
* </html:form>
* </code>
*
* 注意 property 裡面的值是 'dispatch=xxxx' 記得要寫等號與 method 名稱,
* 而且大小寫要對,不能空白。當網頁按下 "儲存" 時,則會執行 /some/work.do
* 的 save(...) 的 method。 如果按下 "刪除" 則執行 delete(...),
*
* 建議 -- 這種寫法通常是用在一個 Action 有多個 dispatch method,而每個 method
* 都共用同個 ActionForm
*
* (2) URL 法,接在 URL 後面:
*
* <code>
* <html:form action="/some/work?dispatch=save">
* 或是用 link 也可以
* <html:link action="/some/work?dispatch=save" />
* </code>
*
* 建議 -- 通常用在不需要 ActionForm 的 Action,或者是要將 submit button 法
* 寫成 url 時使用。
*
* (3) struts-config 法,直接寫死在 parameter='dispatch=foo' 上
*
* <code>
* <action
* path="/saveOrder"
* name="SaveOrderForm"
* type="antar.order.web.OrderDispatchAction"
* parameter="dispatch=save" >
* </action>
* <action
* path="/deleteOrder"
* name="DeleteOrderForm"
* type="antar.order.web.OrderDispatchAction"
* parameter="dispatch=delete" >
* </action>
* </code>
*
* 建議 -- 這種寫法通常是為了讓 Action 中每個 dispatch method 使用不同
* 的 ActionForm。一旦寫死在 struts-config 裡,該 mapping 的 path 就不能
* 與 URL 法 或是 submit button 法同時使用。
*
* 最後請注意同一個 request 上,URL 法不能與 submit button 法同時使用:
*
* <code>
* ...........錯誤範例...........
* <html:form action="/some/work?dispatch=save">
* .... some thing ....
* <html:submit property="dispatch=delete" value="刪除"/>
* </html:form>
* </code>
*
* @author ingram
*
*/
public abstract class SimpleDispatchAction extends ActionSupport {
private static final String KEY_VALUE_SEPERATOR = "=";
private final static String KEY = "dispatch";
private static final String VALID_PARAMETER_NAME_PATTERN = KEY + "\\"
+ KEY_VALUE_SEPERATOR + "[a-zA-Z0-9_]+";
private Class clazz = this.getClass();
private Class[] argTypes = new Class[] { ActionMapping.class,
ActionForm.class, HttpServletRequest.class,
HttpServletResponse.class };
private Map dispatchMethods = new HashMap();
public final ActionForward execute(ActionMapping mapping,
ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws Exception {
String methodName = getMethodName(request, mapping);
Method method = null;
try {
Object[] args = { mapping, form, request, response };
method = obtainDispatchMethod(methodName);
return (ActionForward) method.invoke(this, args);
} catch (NoSuchMethodException e) {
throw dealWithMethodProblem(methodName, e);
} catch (IllegalAccessException e) {
throw dealWithMethodProblem(methodName, e);
} catch (InvocationTargetException e) {
throw dealWithMethodProblem(methodName, e);
}
}
private RuntimeException dealWithMethodProblem(String methodName,
Exception e) {
return new RuntimeException(
"can not access dispatching method:["
+ methodName
+ "]. ", e);
}
private Method obtainDispatchMethod(String methodName)
throws NoSuchMethodException {
Method method = (Method) dispatchMethods.get(methodName);
if (method == null) {
method = clazz.getMethod(methodName, argTypes);
dispatchMethods.put(methodName, method);
}
return method;
}
static String getMethodName(HttpServletRequest request,
ActionMapping mapping) {
final List gatherAllMethodNames = new ArrayList();
for (Enumeration e = request.getParameterNames();
e.hasMoreElements();) {
String parameterName = (String) e.nextElement();
addMatchedParameter(gatherAllMethodNames, parameterName);
}
final String[] values = request.getParameterValues(KEY);
if (values != null) {
for (int i = 0; i < values.length; i++) {
gatherAllMethodNames.add(values[i]);
}
}
if (mapping.getParameter() != null) {
addMatchedParameter(gatherAllMethodNames
, mapping.getParameter());
}
if (gatherAllMethodNames.isEmpty()) {
throw new IllegalArgumentException(
"no 'dispatch=methodName' found in parameter");
} else if (gatherAllMethodNames.size() > 1) {
throw new IllegalArgumentException(
"\nMultiple dispatch parameter: " + gatherAllMethodNames
+ " Only one parameter is allowed.");
} else {
return (String) gatherAllMethodNames.iterator().next();
}
}
private static void addMatchedParameter(List gatherAllMethodNames,
String parameterName) {
if (parameterName.matches(VALID_PARAMETER_NAME_PATTERN)) {
gatherAllMethodNames
.add(parameterName.split(KEY_VALUE_SEPERATOR)[1]);
}
}
}
Date: Saturday, 16 Apr 2005 22:36
靠!真的想自殺,居然誤解了 EasyMock 這麼久!
長久以來,寫 mock 我都是一直在 test case 裡寫個 static inner mock class,供各個 test 使用。當初學這套方法時也調查了很多 tool,但是都沒有完美的 solution,當時的 easymock 只能套在 interface 上,完全不合用。而 Dynamock / jMock 族系的需要繼承特殊的 TestCase,而且他的 "錄製" 過程中呼叫 method 是用 method name 的,像這樣:
天啊,Subscriber.receive() 的呼叫是用 String,這樣 refactor method name 時不就掛了!!而且真的很難看懂他在幹嘛。所以... 就打消使用 mock tool 的念頭了...
昨個亂逛居然發現 easymock 已經有 extension 可以用在 class 上了!而且還是去年就有了!看看下面的這幾行標準的 easymock 使用:
居然一直停留在 mock tool 限制很多的印象裡... 該死!
靠~~~~
長久以來,寫 mock 我都是一直在 test case 裡寫個 static inner mock class,供各個 test 使用。當初學這套方法時也調查了很多 tool,但是都沒有完美的 solution,當時的 easymock 只能套在 interface 上,完全不合用。而 Dynamock / jMock 族系的需要繼承特殊的 TestCase,而且他的 "錄製" 過程中呼叫 method 是用 method name 的,像這樣:
mockSubscriber.expects(once()).method("receive").with( eq(message) );
天啊,Subscriber.receive() 的呼叫是用 String,這樣 refactor method name 時不就掛了!!而且真的很難看懂他在幹嘛。所以... 就打消使用 mock tool 的念頭了...
昨個亂逛居然發現 easymock 已經有 extension 可以用在 class 上了!而且還是去年就有了!看看下面的這幾行標準的 easymock 使用:
就是這麼簡單,唯一的限制是需要非 final 的 public constructor,不過這是小事啦!
private MockControl control;
private OrderDAO mockOrderDAO;
protected void setUp() throws Exception {
//MockClassControl 可以替 class 建立 Mock
control = MockClassControl.createStrictControl(OrderDAO.class);
mockOrderDAO = (OrderDAO) control.getMock();
}
public void testSaveOrder() {
//開始預錄
Order order = new Order();
//執行真正的 method 來錄製,而不是用 method name
mockOrderDAO.saveOrder(order);
control.replay();
//錄製完成
OrderServiceImpl service = new OrderServiceImpl();
service.setOrderDAO(mockOrderDAO);
service.saveCustomerOrder(order);
//比對錄製結果
control.verify();
}
居然一直停留在 mock tool 限制很多的印象裡... 該死!
靠~~~~
Date: Sunday, 03 Apr 2005 12:07
自從上個月買到了 mac mini 之後,這個月來總算圓了長久以來的 mac 夢,真是過足了癮。但是... 說真的,mac 真的只能當一台放在客廳的電腦,問題真不是普通的多...
What I love Mac:
哎.... 看來還是得回 Windows... 沒錢玩不起高貴的 Mac
What I love Mac:
- UI 的反應速度不錯,效果也很多,整體的感覺非常的 smooth。這是 windows/linux 遠遠及不上的。
- Dock 的概念很新,一開始用還不大能適應,因為程式關了視窗卻不是關掉程式本身,只能算是 Hide 而已。不過久而久之,你反而會習慣讓 OS 自己去管理開啟的程式,只要 RAM 夠大 就好 (個人是用 1g) 。完全不用去傷腦筋現在開了多少程式,多少視窗 (windows 的 task bar 就是這樣)
- Eye candy 很多,很炫很酷。show 給大家看時很爽~~
- 字形 smooth 之後很漂亮。
- PDF anywhere,這點就真的很強了。唯有 pdf 才是真正的 portable 文件啊!
- 好用的 expose ,視窗滑來滑去的好看,找起來也快,設定好之後用滑鼠就能操作,讚。
- 支援 MS Office, Oracle 9i/10g, Eclipse, Firefox, msn... 等等我每天必用的軟體。
- Unix based, built-in XWindow, open ldap, and cvs server... etc
- 支援 palm 的同步,光這個就打死 linux 了。
- 系統設定很簡單 (網路、硬體.... etc)
- 有免費的 remote desktop control 可用,有這個真的很方便。
- Virus/Spyware free !
- Mac mini: 超小台,可以當 notebook 用了。個人每天帶著這台上下班喔。
- 中文,中文!!支援中文實在太爛了。
- 首先 iTune 遇到非unicode 的 id3 tag 中文通通掛掉。是啊,網路上是有轉碼的程式可用,不過只要轉過一次就知道,掉字的掉字,亂碼的亂碼,還是不可行,而且只能轉 mp3,不能轉 mpc/ogg。
- 第 二,從 windows office 來的檔案打開後中文常常變亂碼。大概是 windows 和 OS X 處理中英字型混用的方式不大相同造成的,也有可能是 office 自己搞爛的。還有就是 office 2004 和一般 windows office 相容性很爛,常常排版都亂掉了,這當然是 MS 的錯 (而且錯的愚蠢) 。但不管是誰造成的,在 Mac 上就是別想好好用 office 了。
- 第三,中文字 Apple LiGothic 的英文字太小,但偏偏是系統字型,改都不能改,可憐的 台灣 Mac 族長久以來一直不斷忍受... 直到現在,大家還是在忍受...
- 第四,輸入中文時,有時候第一個字的英文,有時候會是中文,跳來跳去.... 很爛。
- 第五,palm 是支援了,不過中文上還是有些小問題。而且 palm 已經宣佈不在支援 Mac 了,真糟糕。
- keyboard binding 與 PC 系統相差太大。PC 都是以 ctrl 鍵當作指令的起點,而 Mac 則是 command 鍵,每個系統 keybinding 不一樣是理所當然... 不過當 Mac 在網頁上時就吃虧了。有些網頁可以用 hotkey 操作地,不過大多是設計給 PC 用的,這時就不相容啦。另外 unix 下的軟體也都是用 ctrl 操作的 (unix 可沒有 command key) 所以如果一旦同時操作 Unix terminal 和其他 OS X 原生軟體,你會發現一會要用 ctrl,一會要用 command,手忙腳亂,效率大減。
- java,java !! Eclipse 實在太慢了,eclipse 的反應速度跟不上我寫程式的節奏,寫程式變的一頓一頓的,超不爽!
- Firefox,Firefox !! Firefox 慢死了,受不了的慢~~~
- JDK 5.0 ! jdk 5.0 已經出半年了,到現在還沒有影子,不要跟我說那個什麼 Tiger preview,當其他 OS 已經有免費的可下載了,誰還要花一堆精神去搞不大能用的半成品 ?而且還非 OSX 10.4 才可用,可笑可笑。
- 雖 然是 Unix based 的系統,當你要裝 unix 的東東時... 比如 open ldap, cvs server... 時就會發現其實不能照 linux 的方式來裝,有很多地方要改,這也是理所當然,每個 OS 都有自己的設定方式。但是重點是資源少的可憐,甚至是沒有。而且 OSX 還綁了一個 netinfo,搞的都跟大家不一樣,找不到資料時就只好放棄... 。如果花了很多時間學習 OSX 上的 unix,投資報酬率很低的,因為好不容易學了一堆東西,你不見得有地方可以發揮,對工作上幫助並不大 (台灣有幾家公司用 OS X server ??)
- free 的軟體很多,但是完成度都不是很高,有哪個 Mac 軟體能像 foobar2000 一樣通吃所有格式,超強的 mass tag,外加極佳的音質? 有哪個 Mac 軟體能像 filezilla 一樣提供全功能的 ftp client,可以 queue file transfer?有哪個 Mac 軟體能像 xnview 一樣超快速的瀏覽圖片外加 batch 修改圖的功能?有哪個 Mac 軟體可以像 7-zip 一樣通吃所有格式,提供方便的 UI ? (7-zip windows 的 UI 並不怎麼樣,但是 Mac 的更不像話!)
- Eye candy 是不錯啦... 不過看久了 (我用了一個月) 就覺得沒什麼了,還是效率比較重要。
- Mac 的東西貴,太貴了。我現在買的是 apple 大放送的 mac mini,如果萬一未來被 Mac 綁死了,就只好繼續買 Mac,一台像樣的 powerbook 多少錢? 9萬元!天啊~~~
- Mac 上程式不好寫 or 不好最佳化
- Mac 的 (好) developer 少
- Mac 的硬體太慢
- 那些程式一開始就不是在 Mac 上寫的,是 port 過去的
哎.... 看來還是得回 Windows... 沒錢玩不起高貴的 Mac
Date: Sunday, 03 Apr 2005 02:50
Try to attach source codes for *.jar, then the auto-generated source (such as method) will comes with meaningful name, for example, A generated execute(...) method of Struts Action:
without attach source:
after attach Struts source codes to struts.jar:
Another tip is when you attach source codes, you can view java docs without assigning javadoc location. Eclipse will parse javadocs that inside attached source codes for you.
without attach source:
public ActionForward execute(lots of ugly arg0, arg1.... !!!
ActionMapping arg0,
ActionForm arg1,
HttpServletRequest arg2,
HttpServletResponse arg3
throws Exception {
}
after attach Struts source codes to struts.jar:
public ActionForward execute(whew! much better !
ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception {
}
Another tip is when you attach source codes, you can view java docs without assigning javadoc location. Eclipse will parse javadocs that inside attached source codes for you.
Date: Sunday, 20 Mar 2005 13:01
Steam boy 是建構在 "空想科學" 上的作品,空想科學就是用現在已知的科學去推演、幻想可能的科學產物,最有名的就是那些日本機器人動畫了。本片中不時會看到什麼壓力太小,閥門開開關關之類的動作,這些道理都是日常生活中可以理解的科學,只不過現實中不會造出這麼大的蒸氣城 (就嚴謹的科學來講也是做不出來的)。在日本到是有很多人迷空想科學的作品地,通常越寫實他們看的越是起勁,就像迷科幻小說那樣。相信他們看到這齣作品會痛苦流涕、感動不已吧...
就技術面來講,這片是無懈可擊了,可惜劇情上有點托的感覺... 不斷的重覆科學帶來的負面影響,兩個小時下來真的會覺得厭煩....
撇開男主角不提 (成長中的熱血少年... 沒新意) 那鍋女主角讓我嘖嘖稱奇。性格膽小、驕傲、大小姐脾氣、不懂事世... etc 缺點說不完。她有一幕很經典,就是她的管家說要跟英國開打了,她的回答居然是 "不淮輸" ! 真是讓人覺得又氣又好笑。跟男主角的互動也有不少有趣的橋段。跟宮崎駿的作品相比之下,差最多的就是她了,宮崎駿的作品的主角都是女性,不管有多少挫折,在荒亂的冒險中都會發揮女性特有的母性、而且勇敢去擁抱所愛。這樣的女性就像聖女一般令人可敬可佩,不過就是太夢幻了點... 可算得上是 "空想少女" 了。Steam boy 女主角就真實的多了。
Howl's Moving Castle 和 Steam Boy 各有優缺點,其實不該拿來相比的。不過若要說誰比較好看,我還是比較喜歡 Howl。
就技術面來講,這片是無懈可擊了,可惜劇情上有點托的感覺... 不斷的重覆科學帶來的負面影響,兩個小時下來真的會覺得厭煩....
撇開男主角不提 (成長中的熱血少年... 沒新意) 那鍋女主角讓我嘖嘖稱奇。性格膽小、驕傲、大小姐脾氣、不懂事世... etc 缺點說不完。她有一幕很經典,就是她的管家說要跟英國開打了,她的回答居然是 "不淮輸" ! 真是讓人覺得又氣又好笑。跟男主角的互動也有不少有趣的橋段。跟宮崎駿的作品相比之下,差最多的就是她了,宮崎駿的作品的主角都是女性,不管有多少挫折,在荒亂的冒險中都會發揮女性特有的母性、而且勇敢去擁抱所愛。這樣的女性就像聖女一般令人可敬可佩,不過就是太夢幻了點... 可算得上是 "空想少女" 了。Steam boy 女主角就真實的多了。
Howl's Moving Castle 和 Steam Boy 各有優缺點,其實不該拿來相比的。不過若要說誰比較好看,我還是比較喜歡 Howl。
Date: Tuesday, 01 Mar 2005 13:01
Date: Sunday, 27 Feb 2005 19:22
雖說這幾天玩 mac mini 玩到瘋了,哎… mac 實在另人又愛又恨啊,說來話長啊…
先不談這個,今個兒拿到了霍爾的 OST (Original SoundTrack)
!!!
真是好聽呀。opening 之後的 空中散步 圓舞曲,聽了之後腦中馬上回憶起蘇菲和霍爾在園遊會的上空漫遊的場景。這一幕配上這個音樂真是讚 (想不出啥好詞…) 隨後的是 さすらいのソフィー (流浪的蘇菲),這一段比較長,利用主題曲的不斷變奏來描寫流浪的各種情境。大概是一分半的左右吧,有一段不知是用什麼笛吹的,略帶著滄桑之意,這一段我 也很喜歡。サリマンの魔法陣~城への帰還 這一首前半是沙利曼的光魔法,那個像是異族的聲音聽來很詭異。後半則是坐飛機逃走,很有天空之城之影子 (誰叫它飛機要設定的這麼像咧 ?)
花園 這一首帶哀傷的氣氛,卻充滿了情感的張力,有點欲言又止的那種感覺…(我到底在說啥?) 後面的 戰火の戀 也有一部份跟這首很相似,不過戰火那段帶來的感受卻大不相同,比較像是充滿歷經苦難,終於開花結果的感覺。
除了以主旋律為主的音樂之外,其他的多半都是乒乒乓乓的打仗、奔走等等配樂,不適合單獨聽啦… 片頭和片尾都有一段叫 人生のメリーゴーランド (人生的 merrygo-round,旋轉木馬) 我想這就是主題旋律的名稱吧。啊,只要不放棄人生都還是大可轉圜的。
總之很好聽囉,這陣子不愁沒音樂聽了!推薦給大家~~
先不談這個,今個兒拿到了霍爾的 OST (Original SoundTrack)
!!!
真是好聽呀。opening 之後的 空中散步 圓舞曲,聽了之後腦中馬上回憶起蘇菲和霍爾在園遊會的上空漫遊的場景。這一幕配上這個音樂真是讚 (想不出啥好詞…) 隨後的是 さすらいのソフィー (流浪的蘇菲),這一段比較長,利用主題曲的不斷變奏來描寫流浪的各種情境。大概是一分半的左右吧,有一段不知是用什麼笛吹的,略帶著滄桑之意,這一段我 也很喜歡。サリマンの魔法陣~城への帰還 這一首前半是沙利曼的光魔法,那個像是異族的聲音聽來很詭異。後半則是坐飛機逃走,很有天空之城之影子 (誰叫它飛機要設定的這麼像咧 ?)
花園 這一首帶哀傷的氣氛,卻充滿了情感的張力,有點欲言又止的那種感覺…(我到底在說啥?) 後面的 戰火の戀 也有一部份跟這首很相似,不過戰火那段帶來的感受卻大不相同,比較像是充滿歷經苦難,終於開花結果的感覺。
除了以主旋律為主的音樂之外,其他的多半都是乒乒乓乓的打仗、奔走等等配樂,不適合單獨聽啦… 片頭和片尾都有一段叫 人生のメリーゴーランド (人生的 merrygo-round,旋轉木馬) 我想這就是主題旋律的名稱吧。啊,只要不放棄人生都還是大可轉圜的。
總之很好聽囉,這陣子不愁沒音樂聽了!推薦給大家~~
Date: Tuesday, 22 Feb 2005 23:30
當然,這不是補習班的 Training... 業界是不會有 open source 技術的 training course 的。過去我們這個 team 在採用技術時,都是先請顧問來教個一兩天 (Struts & Hibernate) 然後我們就開始自己 Coding 。而這一次要導入的是 Spring Framework,原因是…
事實證明,真的要讓大家做做 lab 才有用。有些人吸收很快,三兩下lab 就做完了。有些人則很明顯,我講的東西他大概吸收很有限… 一做 lab 就發現問題層出不窮。遇到這種情形,我真擔心導入 Spring 對我們 team 會不會太早或太苛求?個人是個 Java geek,就是那種很喜歡玩新的 或是自個兒打造 Framework 的那種人,玩這種東西比吃飯還簡單。但對於接觸不深的人就很麻煩了,要導入新技術,就要花很多時間拉拔這些人… 之前還未做 Training 時我就考慮很多這方面的問題,不過到是沒想到,TEAM 裡的技術之差異居然有這麼大。
念及至此,我反到覺得更要導入 spring 了,對那些 junior 的 programmer,更要強迫他們使用 spring。原因是 spring 提供許多便捷的工具,以及更不易出錯的架構。雖然那些不熟的人一開始可能不曉得為什麼要這樣做/那樣做。但最少,他們寫出來的,整體來講問題會比較少。像今天講課提到的 jdbcTemplate 就是個很好的例子。與其放任他們寫 free 的 jdbc code,倒不如要求他們用 jdbcTemplate,雖然一開始學會比較慢,但長期來看問題反到會比較少。
個人認為,除非 server-side java 有新的特別突破,我相信 Spring 應該是我們 team 導入的最後一個 Framework 了。剩下的,就是一直換新版這樣 (如 Hibernate2 -> Hibernate3... etc)。不單單是因為 Struts + Hibernate + Spring 已足夠應付開發的需求,也是因為 "玩" framework也該有個限度 (雖然我很喜歡玩...)。就技術層面來看,Team 裡(包括我自個兒) 下一個階段比較需要加強的是 domain 的設計及 performance 的 tuning。
我自己想用!前先日子花了很多工夫鑽研 Spring,發現真是棒啊!真的很想在我們的專案裡導入。可是呢,礙於其他人的對 Spring 的熟悉狀況不一,而且採用 spring 一開始並不會有立竿見影的效果,想要導入還真的不容易。為此,只好自己下海,充當起臨時教練。拿起現有所有可得的書東抄西湊的,總算弄了個 50 張投影片,這50張還只是 cover 一半而已 (spring 東西還真多)。今個兒就花了一整天跟組員介紹 Spring 的基礎,以及 persistence 相關的主題。另外,也設計了幾個小 LAB 讓大家練習練習。
事實證明,真的要讓大家做做 lab 才有用。有些人吸收很快,三兩下lab 就做完了。有些人則很明顯,我講的東西他大概吸收很有限… 一做 lab 就發現問題層出不窮。遇到這種情形,我真擔心導入 Spring 對我們 team 會不會太早或太苛求?個人是個 Java geek,就是那種很喜歡玩新的 或是自個兒打造 Framework 的那種人,玩這種東西比吃飯還簡單。但對於接觸不深的人就很麻煩了,要導入新技術,就要花很多時間拉拔這些人… 之前還未做 Training 時我就考慮很多這方面的問題,不過到是沒想到,TEAM 裡的技術之差異居然有這麼大。
念及至此,我反到覺得更要導入 spring 了,對那些 junior 的 programmer,更要強迫他們使用 spring。原因是 spring 提供許多便捷的工具,以及更不易出錯的架構。雖然那些不熟的人一開始可能不曉得為什麼要這樣做/那樣做。但最少,他們寫出來的,整體來講問題會比較少。像今天講課提到的 jdbcTemplate 就是個很好的例子。與其放任他們寫 free 的 jdbc code,倒不如要求他們用 jdbcTemplate,雖然一開始學會比較慢,但長期來看問題反到會比較少。
個人認為,除非 server-side java 有新的特別突破,我相信 Spring 應該是我們 team 導入的最後一個 Framework 了。剩下的,就是一直換新版這樣 (如 Hibernate2 -> Hibernate3... etc)。不單單是因為 Struts + Hibernate + Spring 已足夠應付開發的需求,也是因為 "玩" framework也該有個限度 (雖然我很喜歡玩...)。就技術層面來看,Team 裡(包括我自個兒) 下一個階段比較需要加強的是 domain 的設計及 performance 的 tuning。
Date: Sunday, 20 Feb 2005 18:18
終於拿到 Treo650 囉,不過跟 NX70 一比.. 怪怪:
怎麼沒有像 MS Import 的工具?
也沒有 Backup 的 tool...
鬧鐘的功能有跟沒有一樣... 只能設時間不能設日期...
而且連最基本的 File Manager 都沒有!太扯了!
也許 palm 本來就是這個樣子吧... 現在才知道 CLIE 的好啊~~
anyway, 找了很多軟體:
我要掌龍啦~~ 掌龍有沒有計畫要支援 Treo ? 還是已經....
anyway... 以上只是就字型的 complain.... 使用上還不錯啦,撘配前輩的 Unicode 補完計畫
+ 草蝦輸入法後,真的是如魚得水。他的 cManager 可以將字形放在記憶卡上,我只放 16x16 的在內建記憶體裡。不過令我驚訝的是即使是放在卡上,用起來也很快 (完全沒感覺有 delay) (Treo650+CJKOS+ATD 66x 1G SD card) 讀字型遠快於 (NX70 + 掌龍 + MS card 128M),於
是誰貢獻的多,就不清楚了。
ok, 回到主題,這個 player 還不錯用,加上Unicode補完計畫後,中日文都可正常顯示。也支援 Treo650 的 volume 控制 (左側邊的手機音量控制鍵),我大多數的音樂都是 ogg 的,跑起來也都正常,不會有什麼 delay。音質的話受限於 Treo650 硬體的限制... 所以... 不過,它提供 5 格的 Equalizer,還有 bass boost。equlizer 是建議一定要調,稍補硬體的不足。但是它的bass boost 就免了,破音連連,勸大家還是不要用吧...其他特異功能像是接電話/掛電話後都會直接回覆到剛播放的曲子,很方便。更扯的是 hot sync 時音樂也不會中斷,雖然聲音會一頓一頓的,但總比 hot sync 完還要去開一次來的方便許多。
音質不負責任主觀比較 (耳機為 Etymotic ER-4P + 隨便買的2.5->3.5轉接頭 )
iAudio M3 NX70 Tre650 Treo650
software -- built in player pockettunes Aeroplayer
tuning (enable BBE) (bass level 1) (enhance bass by eq) (enable bass boost)
飽滿 10 9 8 8.5
清昕 10 9 8 8.5
音場 10 9 8 8
註:
怎麼沒有像 MS Import 的工具?
也沒有 Backup 的 tool...
鬧鐘的功能有跟沒有一樣... 只能設時間不能設日期...
而且連最基本的 File Manager 都沒有!太扯了!
也許 palm 本來就是這個樣子吧... 現在才知道 CLIE 的好啊~~
anyway, 找了很多軟體:
- Card Export II 2.2
- FileZ 6.5
- zlauncher 5.10.3
- CJKOS 4.62 (港版附光碟)
我要掌龍啦~~ 掌龍有沒有計畫要支援 Treo ? 還是已經....
anyway... 以上只是就字型的 complain.... 使用上還不錯啦,撘配前輩的 Unicode 補完計畫
+ 草蝦輸入法後,真的是如魚得水。他的 cManager 可以將字形放在記憶卡上,我只放 16x16 的在內建記憶體裡。不過令我驚訝的是即使是放在卡上,用起來也很快 (完全沒感覺有 delay) (Treo650+CJKOS+ATD 66x 1G SD card) 讀字型遠快於 (NX70 + 掌龍 + MS card 128M),於
是誰貢獻的多,就不清楚了。
- PowerRun 1.3
- Agendus pro 9.02
- Textplus 5.6
- Palmary Clock 3.02
- pocket tunes deluxe 3.0.6
ok, 回到主題,這個 player 還不錯用,加上Unicode補完計畫後,中日文都可正常顯示。也支援 Treo650 的 volume 控制 (左側邊的手機音量控制鍵),我大多數的音樂都是 ogg 的,跑起來也都正常,不會有什麼 delay。音質的話受限於 Treo650 硬體的限制... 所以... 不過,它提供 5 格的 Equalizer,還有 bass boost。equlizer 是建議一定要調,稍補硬體的不足。但是它的bass boost 就免了,破音連連,勸大家還是不要用吧...其他特異功能像是接電話/掛電話後都會直接回覆到剛播放的曲子,很方便。更扯的是 hot sync 時音樂也不會中斷,雖然聲音會一頓一頓的,但總比 hot sync 完還要去開一次來的方便許多。
- Aeroplayer 5.1.1
- realplayer...
音質不負責任主觀比較 (耳機為 Etymotic ER-4P + 隨便買的2.5->3.5轉接頭 )
iAudio M3 NX70 Tre650 Treo650
software -- built in player pockettunes Aeroplayer
tuning (enable BBE) (bass level 1) (enhance bass by eq) (enable bass boost)
飽滿 10 9 8 8.5
清昕 10 9 8 8.5
音場 10 9 8 8
註:
- ER-4P 本來的 bass 就比較薄一點,所以個人偏好加一點 bass...
- 視 iAduio M3 為滿分的前提下比較
- 不論是 pocket tunes 或 Aeroplayer,如果不加強一點 eq 或是用 bass boost音樂都乾澀難以入耳....
- 除了 NX70 用 256K mp3 外,其於都是 ogg
Date: Friday, 18 Feb 2005 03:09
今個兒終於跟同事去看霍爾了,看完的第一個反應就是 惑爾 啊~ 真的是大大的不懂。原本還以為會有很感人的橋段,結果其實也還好嘛… (為此還被同事譏笑~~ )。不過回來的路上到是好好重新想了數遍... 這一齣戲的主軸,與其說是愛情故事,或是變幻莫測的魔法,我反到認為是 "內心的反映" (一時想不出好詞…)
整齣戲最讓人疑惑、驚喜的便是主人公 蘇菲 一會兒年輕一會兒變老。一開始蘇菲被詛咒時,頓時變得非常年老,90歲的外貌便像是蘇菲當時的內心:處在不確定、退縮、安於現狀的心態 (她不肯面對自己不想繼承家業,不想做帽子,而且一直對自己的外貌沒信心)。當後來她在莎利曼面前,義無反顧的直言她了解、愛護霍爾,她的外貌一瞬間回覆到原來最年輕的樣子,此刻她的外表正反應她內心充滿著勇氣、愛的樣子。後來有很多橋段都可看出,當她願意放開心胸,鼓起勇氣時,外貌便越來越年輕 (像是到花園,或是霍爾替她做了她老家的臥室);又像是她無法接受霍爾對她的讚美時,頓時便從年輕變為老婆婆... 這些一連串的變化,我想這是宮崎駿想要表達一個簡單的道理:當心深鎖,逃避時,你就像個很老的人一般,病厭厭的;而當打開心胸,勇敢擁抱時,你便整個人年輕了起來,神采飛揚。你的內心才是你真正的外貌。
說到最令我印象深刻的橋段,是當霍爾自卑於髮色變深,身體變成一沱綠泥時… 蘇菲彷彿看到了她自己一樣... 終於忍不住在大雨中痛哭... 這一段我覺得最另人動容。其他什麼戰爭、魔法的,我到覺得都還是其次…
宮崎駿的電影向來都會有關懷社會的一面,像是風之谷講的是環保,神隱少女則是諷刺現代人的暴食浪費,而霍爾則有人引申為現代的社會已經是高齡化的社會,鼓勵銀髮族 "人老心不老",勇於開創第二春。(不過我覺得這樣轉太硬了…)
總之... 霍爾算是不錯的電影啦,可是遠遠不及神隱少女當初帶給我的驚奇、感傷及快樂。建議有興趣的人到時可以租個 DVD 看看。不過,到電影院則免了吧。
整齣戲最讓人疑惑、驚喜的便是主人公 蘇菲 一會兒年輕一會兒變老。一開始蘇菲被詛咒時,頓時變得非常年老,90歲的外貌便像是蘇菲當時的內心:處在不確定、退縮、安於現狀的心態 (她不肯面對自己不想繼承家業,不想做帽子,而且一直對自己的外貌沒信心)。當後來她在莎利曼面前,義無反顧的直言她了解、愛護霍爾,她的外貌一瞬間回覆到原來最年輕的樣子,此刻她的外表正反應她內心充滿著勇氣、愛的樣子。後來有很多橋段都可看出,當她願意放開心胸,鼓起勇氣時,外貌便越來越年輕 (像是到花園,或是霍爾替她做了她老家的臥室);又像是她無法接受霍爾對她的讚美時,頓時便從年輕變為老婆婆... 這些一連串的變化,我想這是宮崎駿想要表達一個簡單的道理:當心深鎖,逃避時,你就像個很老的人一般,病厭厭的;而當打開心胸,勇敢擁抱時,你便整個人年輕了起來,神采飛揚。你的內心才是你真正的外貌。
說到最令我印象深刻的橋段,是當霍爾自卑於髮色變深,身體變成一沱綠泥時… 蘇菲彷彿看到了她自己一樣... 終於忍不住在大雨中痛哭... 這一段我覺得最另人動容。其他什麼戰爭、魔法的,我到覺得都還是其次…
宮崎駿的電影向來都會有關懷社會的一面,像是風之谷講的是環保,神隱少女則是諷刺現代人的暴食浪費,而霍爾則有人引申為現代的社會已經是高齡化的社會,鼓勵銀髮族 "人老心不老",勇於開創第二春。(不過我覺得這樣轉太硬了…)
總之... 霍爾算是不錯的電影啦,可是遠遠不及神隱少女當初帶給我的驚奇、感傷及快樂。建議有興趣的人到時可以租個 DVD 看看。不過,到電影院則免了吧。
Date: Monday, 14 Feb 2005 21:46
本來以為很久沒電動,本想對電動音樂的熱情該差不多熄了... 這一次玩了 OG2 後,那個ラトゥーニ的音樂真是讚啊 (雖然只是 GBA 音源),又給忍不住錄下去了。看來這種錄 BGM 的習慣是改不了:
17 Fairy Dang-Sing.mp3 按右鍵另存新檔後,將副檔名的 .bin 去掉即可
好聽好聽~~
17 Fairy Dang-Sing.mp3 按右鍵另存新檔後,將副檔名的 .bin 去掉即可
好聽好聽~~
Date: Monday, 14 Feb 2005 14:57
剛註冊了 flickr ,這玩意還真是漂亮啊~
圖片裡是我最近想敗的 Treo 650 配件 (啊 Treo 650 還沒入手就先想配件,真是太敗家囉)。可惜的是 TreoCentral 沒有賣到台灣... 氣死了 !
Normal Size:
<iframe height='630' width='720'
src="http://www.flickr.com/photos/xexex/sets/120058/show/" >
Cutted Size:
<iframe height='630' width='533'
src="http://www.flickr.com/photos/xexex/sets/120058/show/" >
圖片裡是我最近想敗的 Treo 650 配件 (啊 Treo 650 還沒入手就先想配件,真是太敗家囉)。可惜的是 TreoCentral 沒有賣到台灣... 氣死了 !
Date: Sunday, 13 Feb 2005 02:08
真是有夠久沒寫~~ 現在想想大概是因為後來的文章越寫越大篇,料雖然很多,但是反而變成寫BLOG 的阻力... 下次該寫一點點就好囉。
最近發生很多事:
這 個系統後來我導入了 Spring... (擅自導入到我負責的 module...)。當初因為它又需要額外的 xml 檔,使人望之卻步 (refactoring 的大敵 !) 嘗試用了一個月,只能說真是相見恨晚啊。Spring 真的是 J2EE 開發者的天堂。Spring 的 IoC 只是個吸引人的點子 (別家的用起來反而比較簡單) 真正誘人的是它幾乎整合了所有 J2EE 開發的所有工具:新增 (如 declarative Transaction)、修正 (如 HibernateException 變 unchecked)、簡化 (如 quautz scheduler)、超輕量 (一個 container 居然只要幾個 xml 檔,真是太扯囉)、潛力無窮 (AOP)… etc 太強啦:它可不只是超級萬能瑞士刀,它是小叮噹的四次元口袋!拿得出一卡車的工具且還比瑞士刀輕 !! 哇靠這種好康上哪找啊!
把 Spring 拿去跟 picocontainer / hivemind 去比的簡直是頭殼壞掉,這就像是拿 tomcat 和 oracle db 比一樣荒謬。
現 在還沒嘗試的還有 Spring web,不過好不容易我們的 team 都已經搞清楚 Struts 的脾氣了 (真的是愛恨交加)。如果真要再花半年 Train Spring web,寧可勸大家改學 Tapestry 還比較划算。啊~~~ 真是懷念以前寫 Tapestry 的時光啊。anyway 來看看最近 K 的書吧:
Spring 書推薦:
回 到 Spring 的正題,IoC。導入 IoC container 到系統... 目前我的感覺是有好有壞,好是好在一旦使用 IoC 的方式開發,程式會漸漸 decouple 並且 high coherence (這個詞真難翻,意思是模組的凝聚力高,該自己負責的功能就自己負責,不會跟其他模組混在一起。跟decouple的意思差不多) 壞是壞在很容易掉入 AnemicDomainModel 的陷阱。用了 Spring,物件該有的功能/行為,一不小心就會寫到最外面那一層的Service (facade)去了,原因是:
為此,又回去翻 domain 聖經 "DDD" (Domain Driven Design) ,有了一些新的感想:原來關鍵還是在 OOP 的設計 (value object 和 entity 合作)。這個等到有比較具體的想法和實際做過後再提吧。
最近發生很多事:
- 我 們的系統上線了~ 大概已經過了一個月吧,這個系統開發時導入 Unit Test 與 Continuous Integration。目前累積了大概 1500 個 unit test 吧,改需求/新增功能 都難不倒我們。 team 的人都說還好有 Test 這個 "安全網" ,不然喔上線後,不僅改功能無望,搞不好還得加班熬夜修東修西的。當初我嘗到 test 的甜頭後,便在 team 裡面不斷的 "叫囂" 說要大家寫 test ,現在總算是開花結果了。(個人用了很多嚴重的字眼逼大家寫… 還好結果不錯,不然我會被公X到死~~)
- 1500 個 unit test 要 run 多久? 加上 database 的 rebuild 大概要 30~40 分鐘。這真的太久囉。原因是我們用 ObjectMother 太多了,這個 ObjectMother 大多跟 DB (hibernate) 綁在一起,所以花了很多無謂的時間在 load hibernate configuration/insert/delete data上 ( ObjectMother with Hibernate 這個用起來太方便了,導致很多 test 都扯到 DB )。下個專案要多多改進 -- DB layer 還是要盡可能的 decouple from business logic啊
- bug 的數量與TestCase的數量成反比!還有什麼比這個更有說服力呢? Unit Test Rules !
oxoxoxoxoxoxoxo Spring 分隔線 xoxoxoxoxoxoxoxoxo
這 個系統後來我導入了 Spring... (擅自導入到我負責的 module...)。當初因為它又需要額外的 xml 檔,使人望之卻步 (refactoring 的大敵 !) 嘗試用了一個月,只能說真是相見恨晚啊。Spring 真的是 J2EE 開發者的天堂。Spring 的 IoC 只是個吸引人的點子 (別家的用起來反而比較簡單) 真正誘人的是它幾乎整合了所有 J2EE 開發的所有工具:新增 (如 declarative Transaction)、修正 (如 HibernateException 變 unchecked)、簡化 (如 quautz scheduler)、超輕量 (一個 container 居然只要幾個 xml 檔,真是太扯囉)、潛力無窮 (AOP)… etc 太強啦:它可不只是超級萬能瑞士刀,它是小叮噹的四次元口袋!拿得出一卡車的工具且還比瑞士刀輕 !! 哇靠這種好康上哪找啊!
Spring + Hibernate == 現在寫程式的人真幸福
把 Spring 拿去跟 picocontainer / hivemind 去比的簡直是頭殼壞掉,這就像是拿 tomcat 和 oracle db 比一樣荒謬。
現 在還沒嘗試的還有 Spring web,不過好不容易我們的 team 都已經搞清楚 Struts 的脾氣了 (真的是愛恨交加)。如果真要再花半年 Train Spring web,寧可勸大家改學 Tapestry 還比較划算。啊~~~ 真是懷念以前寫 Tapestry 的時光啊。anyway 來看看最近 K 的書吧:
Spring 書推薦:
- J2EE without EJB (不是全名,請自行查 google) 這本是founder Rod Johnson 自個兒寫的,講了好多大道理啊。前半本大說 EJB 的不是,舉證例例,我是看了一點就狂睡了,基本上嘗過 EJB 的苦頭,就不必再多花時間囉,可直接跳到後半看 Spring。這本是講 Spring 的原理最詳細的一本,時間夠的話,這本是第二本必看的書。
- Spring in Action, in Action 系列再下一成,這本是Spring 書中最簡單的一本,推薦入門者先看這一本。用 Spring 該具備的觀念都有提到,Spring 所有重要的功能都有涉獵。我常常就直接拿他的範例 code 給它這麼一 copy/past,就直接可用了。(其實也是因為 Spring的設定太簡單囉)
- Spring Live (Matt Raible 著) appfuse 的開發者。這本是 source beat 的電子書 (只出電子版) ,更特別的是出版後一年之內作者還會追加章節,現在出到第11章了。這本是最 practical 的一本。帶你用TDD 的方式使用 Spring,而且提供 Spring整合其他 framework 的各種作法 (超級多),還有很多實用的技巧。作者本身也是邊學邊寫完這一本的,所以很多大家會遇到的問題他都先碰到了。老實說作者原意是將這本寫成入門書的,其實定 位也是啦,只是他用的概念/framework 實在太多太廣 (光是 TDD 的開發方式就會讓有些人進不了門) 我覺得還是要在 java 界混久一點的人才適合看,作者的 blog 還蠻受歡迎,大家有空可以去瞧瞧。
- Pro Spring... 剛出… 還沒入手… 有800頁厚
- Professional Java Development with the Spring Framework 還沒出,不過是 Rod 那群人寫的,這一定是要入手的啦
- Better, Faster, Lighter Java (Bruse Tate 著,bitter java/ejb 作者) 很小本,純講理念的居多.... 我承認我看不去...
oxoxoxoxoxoxoxo Spring IoC 分隔線 xoxoxoxoxoxoxoxoxo
回 到 Spring 的正題,IoC。導入 IoC container 到系統... 目前我的感覺是有好有壞,好是好在一旦使用 IoC 的方式開發,程式會漸漸 decouple 並且 high coherence (這個詞真難翻,意思是模組的凝聚力高,該自己負責的功能就自己負責,不會跟其他模組混在一起。跟decouple的意思差不多) 壞是壞在很容易掉入 AnemicDomainModel 的陷阱。用了 Spring,物件該有的功能/行為,一不小心就會寫到最外面那一層的Service (facade)去了,原因是:
- service 那一層通常是 injection 的起點,這一層在整個 Application 中是一定要在 Spring 內設定的 (因為通常也是 Transaction 的 boundary )
- 再 加上 entity (通常是 PO, persistence object) 很難做 IoC ,為了能讓各種功能 "外包" 出去,自然而然的便在 service 層大興土木 (entity 大多是由 "new" 及 hibernate load from db 時產生的,這兩種生成方式不受 Spring 管,而且通常 entity 數量很大,讓所有 entity inject 相同的 bean 通常會有 performance 的考量) 。
- 最後由於 Spring 建議 bean 最好是在 container 裡是 singleton (這點沒錯)所以最好 bean 都要 thread safe,而最簡單的 thread safe 的寫法就是將 object 寫成 stateless...
為此,又回去翻 domain 聖經 "DDD" (Domain Driven Design) ,有了一些新的感想:原來關鍵還是在 OOP 的設計 (value object 和 entity 合作)。這個等到有比較具體的想法和實際做過後再提吧。
Date: Thursday, 30 Sep 2004 11:02
今天不談 java, 來談談前幾天拿到的 Gmail invite 吧。呼~~ 總算可以用這個 hacker's mail 了。
Gmail 目前只能用 UTF-8 寄信和收信
Gmail 目前不支援中文字的查詢
Gmail 的 contacts 使用技巧
Gmail 鍵盤快速鍵:
Gmail filter 技巧:
Gmail Address Alias (虛擬 Email )
假設你自己的 Gmail address 是 johnson@gmail.com,那麼可以用 "+" 加號來增加虛擬的 email,比方說:
像 是第一個代號你可以註冊在 amazon 裡,而第二個可以拿來註冊 ebay,第三個則是給你所有要好的朋友。最後的可以用在公事上。用這些虛擬 email 寄的信仍然會寄到 johnson@gmail.com,好處是你可以很輕易的用 filter 來做分類。比方說:
Gmail notifier
在你的工作列上放個小圖示,信件到來時會發個小通知給你。這個是一定要裝的啊!!你可以在 這裡 下載。
Gmail Java API
Gmail 已經有 java 的 API 可以使用了,是香港人寫的喔: http://g4j.sourceforge.net/
Gmail 不錯的相關資源
就這樣啦~~ 希望大家也用的愉快
Gmail 目前只能用 UTF-8 寄信和收信
- 優點:mail 中可同時顯示多國語言
- 缺點1:收到 big5 的信時,有時候會有掉字的情形,雖然不大嚴重,但還是個問題啊
- 缺 點2:部份 mail client 還不能正確顯示 UTF-8 的信件。我自己試 outlook 2003 是可以。其他舊的就不知道了。除此之外 web mail client 像是 hinet web mail 。因為是 browser based 的,所以會受限於 browser 的能力。用 IE 開啟 hinet web mail 時,UTF-8 的信還是被解讀成 big5..... 就變成亂碼了。而 FireFox 便顯示無誤。
Gmail 目前不支援中文字的查詢
- 任何中文字的查詢會回傳所有有中文字的信件,換句話說 ==> 不能搜尋中文
Gmail 的 contacts 使用技巧
- Gmail 現在已經支援用 .csv 檔直接 import contacts,但是還不支援中文的 import... 這一點真的很麻煩。沒有什麼解決技巧,就是 import 進去後,再把那些亂碼手動一一改回中文。
- 目 前 Gmail 的 contacts 還不支援 group,不過還是有方法可以做到的:新建一個新的 contacts,假設是 "friend" 好了,然後 email 處輸入
mail1@abc.com>,<mail2@gmail.com>,<mail3@xyz.com
這 樣的格式。注意每個 email 之間都用 >,< 隔開,並且頭尾不要加任何符號,這樣一來,每次你在 寄件人裡輸入 friend 時,它會找到這個 group,並且自動展開成<mail1@abc.com >,<mail2@gmail.com>,<mail3@xyz.com>
,也就是說它會幫你加上頭尾的 < 和 > 。這樣一來就可以直接寄整個群組了 - 如 果 import 舊 contacts 很麻煩的話。可以試著用你以前的郵件軟體,寄一封信給你所有的連絡人(要包括你的Gmail address),信件內容就說明你即將更換新的 email 帳號。然後回到 Gmail 收這封信,然後再將這封信回覆給所有的人,這次信件的內容就可以通知大家你的新 Gmail address 了。 經過這個步驟,Gmail 便會自動將你所有回覆的人加到 contacts 裡。
Gmail 鍵盤快速鍵:
- 要使用快速鍵,先到 setting 將 Keyboard shortcuts on 打開。
- j 和 k 可以移動游標,而 x 則可以圈選 check box 。 (跟 vi 很像的啦)
- u 可以 update 目前的信箱,這個很常用
- y 是 archive,這個 archive 在每個信箱的意義都不一樣喔,想知道可以去查 Gmail 的 help
- ! 則是 report spam ,這個我也很常按。
- c 是 compose, r 是 reply, a 是 reply all, f 是 forward,這四個鍵如果加上 shift,就會開新的視窗編輯
- 複合鍵 gi --> go to inbox, ga --> go to All Mail, gs --> go to starred mail
Gmail filter 技巧:
- filter 在進行條件篩選時,可以同時篩選多個 email ,文法如下:
(my@gmail.com) OR ( xyz@cityhunter.com) OR (test@ggg.com)每個 email 都用 () 括住,中間用大寫的 OR 隔開 (一定要大寫)。寫好後會變成像這樣:
From:((my@gmail.com) OR ( xyz@cityhunter.com) OR (test@ggg.com))這樣子只要其中一個 mail 符合就算符合了 (可以用 test search 先試試)
- filter 各項條件間關係都是 "AND",也就是說當你設成
From:(xyz@cityhunter.com)要兩者同時成立的 mail 才會被篩選出來。目前好像還沒辦法將條件間設成 "OR" 的關係
to:(my@gmail.com)
- 雖然網頁上說最多只能 20 個 filter,其實是可以超過的喔!
Gmail Address Alias (虛擬 Email )
假設你自己的 Gmail address 是 johnson@gmail.com,那麼可以用 "+" 加號來增加虛擬的 email,比方說:
johnson+amazon@gmail.com
johnson+ebay@gmail.com
johnson+friend@gmail.com
johnson+office@gmail.com
像 是第一個代號你可以註冊在 amazon 裡,而第二個可以拿來註冊 ebay,第三個則是給你所有要好的朋友。最後的可以用在公事上。用這些虛擬 email 寄的信仍然會寄到 johnson@gmail.com,好處是你可以很輕易的用 filter 來做分類。比方說:
- 設一個
to:((johnson+amazon@gmail.com) OR (johnson+ebay@gmail.com))
這樣的 filter,然後收到信時 apply 一個 "shopping" 的 label ,如此一來所有 amazon 和 ebay 寄給你的信都會自動加上 shopping 的 label 。 - 同理,再加一個 filter ---- to:(johnson+friend@gmail.com) ,然後 apply "good friend" label.....
- 依此類推便可以很巧妙的分類各種信件,而且每個虛擬 email 的使用地方都不大一樣,多少能防止垃圾郵件的氾濫喔。
Gmail notifier
在你的工作列上放個小圖示,信件到來時會發個小通知給你。這個是一定要裝的啊!!你可以在 這裡 下載。
Gmail Java API
Gmail 已經有 java 的 API 可以使用了,是香港人寫的喔: http://g4j.sourceforge.net/
Gmail 不錯的相關資源
- 輸入 email 就可以拿到 invite:invite spooler,不過別忘了如果有多的 invite 也要記得捐贈喔!
- 最大的 Gmail Forum (英文)
- 30 個以上Gmail 實用技巧:Jim's Tips.com (英文)
- Blog:Gmail Gem (英文)
- Blog:Getting more out of Gmail (英文)
- Blog:Gmail 測試筆記
- Blog:Yuchen 的 Gmail 網路日誌
就這樣啦~~ 希望大家也用的愉快
» © All content and copyrights belong to their respective authors.«
» © FeedShow - Online RSS Feeds Reader







