星期日, 10月 31, 2004

【蛀蟲時間】老鼠起舞,大象當心

老鼠起舞,大象當心

剛在華納看完午夜場電影,興頭一起想著反正也睡不著了,
心裡想著想著就順道轉往蹲男誠品蹲蹲吧,或許有啥米新書剛出來也說不定。

雖然已是凌晨二點多,店裡人潮依舊擁擠,
嘿~突然在新書區發現令人期盼已久熟悉的封面。
原來洪老大的新書已經出來啦~

趕緊先A一本起來翻翻,內容果然十分精彩,一翻下去就停不了手哩。
尤其看到後來那段神奇公式:-1 + 1 > 0 時才發現,
原來還與前段提攜部屬的故事有前後呼應呀~

若以部屬比喻為水的話,正說明了水可載舟、亦可覆舟的道理。
適時給予部屬機會、激勵使得部屬得以水漲自然也得以船高囉~
不汲汲於爭功諉過更是顯現主事者管理技巧上的高明。

講起神奇公式還真有那麼點神來一筆的味道,
相信洪老二次在書中提到這個事件不是偶然。
應該算是職場生涯上蠻滿意的一次經驗分享。
再仔細想想作回頭客的生意,後續服務好壞與否可真是重要呀~
(雖然這又讓我想起買ViewSonic液晶螢幕時慘痛的送修經驗 >_< )

不過不曉得是否因有編輯介入,抑或是洪老已離開昇陽的緣故,
比起Java週報時期洪老專欄時常火力四射,引起許多話題。
感覺這次洪老大火力尚未全開,批判M牌公司的力道似乎小了許多 :p

俗話雖講外來的和尚會唸經,但比起啥米管理剩經,
笑佛學不到的管理之類的書籍。
洪老本土化的管理及職場經驗分享反而更值得一讀喔。

--
看起來存書並不多,手腳再不快的朋友可能得等二刷囉~

星期五, 10月 29, 2004

Embedded a Scripting Engine in Java Apps

在開發應用系統時,使用者有時往往會需要動態地執行程序或更新某些參數。
例如像是電信業的計費公式為了因應三不五時要推出特惠方案而更動、
或是銀行業核准信用貸款的判斷準則等。

但這個時候您可能又不想大費周章地自已搞一套Parser
來解析處理這些公式或規則,
嘿嘿~那麼最好的選擇就是內嵌一個Scripting Engine進來。
而且目前開源項目中已有許多使用Java實作出來各種語法的
Scripting Engine可供我們選擇囉~

更棒的是不但如此,大部份開放源碼的Scripting Engine
還支援了BSF(Bean Scripting Framework)。
http://jakarta.apache.org/bsf/index.html
不過講起來Java的世界就這點很奇怪,Framework特別多,
啥米東東不來個Framework這些人身上好像是會癢 :p

好了~再廢話我怕您會想扁我。言歸正傳…而這個BSF又是個啥米東東哩?
簡單講嘛沒啥就是提供一個共通的介面
將各家不同實作的Scripting Engine包裝起來。
於是乎我們可以很輕易地在系統中切換各種不同Scripting語法,
不過有個前提是這些Scripting Engine有支援BSF。

如此一來便可輕鬆提供多種不同語法供使用者選擇,
這一點相信可帶給系統使用者很大的便利。
甚或是我們可以內建一些predefine function
讓使用者能更直覺地用邏輯概念來組合出其所需的功能出來。

下面介紹一下,小弟實驗過確認可在BSF下執行正常的幾個Scripting Engine:

Rhino: JavaScript for Java

http://www.mozilla.org/rhino/index.html

註記:
雖說目前FAQ上寫支援BSF的版本為Rhino 1.5R2 or Rhino 1.5R3。
但經實測似乎只有Rhino 1.5R2這版可運行正常。


JRuby: Ruby for Java

http://jruby.sourceforge.net/index.shtml


Jython: Python for Java

http://www.jython.org/index.html


BeanShell: Lightweight Scripting for Java

http://www.beanshell.org

註記:
若是您覺得您不太想去重新學習或適應另一套Scripting語法,
想使用一個支援Java語法的Scripting Engine的話。
您可以選擇使用BeanShell。


最後提供一個Expression Evaluator的範例程式,大家可以參考試試看囉 ^_^
對了!!!執行前要記得將各個要用到的
Scripting Engine相對應的jar檔設定到classpath下喔~

import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import org.apache.bsf.*;

public class ExpressionEvaluator
extends JFrame implements java.awt.event.ActionListener {
private JPanel ivjContentsPane = null;
private BorderLayout ivjContentsPaneBorderLayout = null;
private JLabel ivjLabel1 = null;
private JPanel ivjPanel1 = null;
private GridLayout ivjPanel1GridLayout = null;
private JPanel ivjPanel2 = null;
private BorderLayout ivjPanel2BorderLayout = null;
private JPanel ivjPanel3 = null;
private GridLayout ivjPanel3GridLayout = null;
private JPanel ivjPanel4 = null;
private JButton ivjButtonClearResults = null;
private JButton ivjButtonClearScript = null;
private JButton ivjButtonEvaluate = null;
private JComboBox ivjLanguageChoice = null;
private JTextArea ivjTextAreaResults = null;
private JTextArea ivjTextAreaScript = null;
private String language = "javascript";
BSFManager _mgr = null;
Hashtable _htEngines = null;

public ExpressionEvaluator() {
super();
initialize();
}

public ExpressionEvaluator(String title) {
super(title);
initialize();
}

public void actionPerformed(java.awt.event.ActionEvent e) {
if ( (e.getSource() == getButtonClearResults())) {
try {
getTextAreaResults().setText("");
}
catch (java.lang.Throwable ivjExc) {
handleException(ivjExc);
}

}
if ( (e.getSource() == getButtonEvaluate())) {
try {
this.buttonEvaluateClick();
}
catch (java.lang.Throwable ivjExc) {
handleException(ivjExc);
}

}
if ( (e.getSource() == getButtonClearScript())) {
try {
getTextAreaScript().setText("");
}
catch (java.lang.Throwable ivjExc) {
handleException(ivjExc);
}

}

}

public void buttonEvaluateClick() {
evaluate();
}

public void evaluate() {

language = getLanguageChoice().getName();
String scriptText = getTextAreaScript().getText();

System.out.println("Evaluating: {\n" + scriptText + "\n}");
System.out.println("Language: " + language);
Object oResult = null;
try {
getTextAreaResults().setForeground(java.awt.Color.black);
oResult = _mgr.eval(language, "Evaluator", 0, 0, scriptText);
}
catch (Exception ex) {
getTextAreaResults().setForeground(java.awt.Color.red);
oResult = "Exception: " + ex.getMessage();
ex.printStackTrace();
}
System.out.println("oResult:’" + oResult + "’");
getTextAreaResults().setText(oResult.toString());
}

private JButton getButtonClearResults() {
if (ivjButtonClearResults == null) {
try {
ivjButtonClearResults = new JButton();
ivjButtonClearResults.setName("ButtonClearResults");
ivjButtonClearResults.setText("Clear results");
}
catch (java.lang.Throwable ivjExc) {
handleException(ivjExc);
}
}
return ivjButtonClearResults;
}

private JButton getButtonClearScript() {
if (ivjButtonClearScript == null) {
try {
ivjButtonClearScript = new JButton();
ivjButtonClearScript.setName("ButtonClearScript");
ivjButtonClearScript.setText("Clear script");
}
catch (java.lang.Throwable ivjExc) {
handleException(ivjExc);
}
}
return ivjButtonClearScript;
}

private JButton getButtonEvaluate() {
if (ivjButtonEvaluate == null) {
try {
ivjButtonEvaluate = new JButton();
ivjButtonEvaluate.setName("ButtonEvaluate");
ivjButtonEvaluate.setBackground(Color.lightGray);
ivjButtonEvaluate.setText("Evaluate");
}
catch (java.lang.Throwable ivjExc) {
handleException(ivjExc);
}
}
return ivjButtonEvaluate;
}

private JPanel getContentsPane() {
if (ivjContentsPane == null) {
try {
ivjContentsPane = new JPanel();
ivjContentsPane.setName("ContentsPane");
ivjContentsPane.setLayout(getContentsPaneBorderLayout());
ivjContentsPane.setBackground(new Color(172, 179, 191));
getContentsPane().add(getPanel2(), "North");
getContentsPane().add(getPanel1(), "Center");
}
catch (java.lang.Throwable ivjExc) {
handleException(ivjExc);
}
}
return ivjContentsPane;
}

private java.awt.BorderLayout getContentsPaneBorderLayout() {
java.awt.BorderLayout ivjContentsPaneBorderLayout = null;
try {
ivjContentsPaneBorderLayout = new java.awt.BorderLayout();
ivjContentsPaneBorderLayout.setVgap(10);
ivjContentsPaneBorderLayout.setHgap(10);
}
catch (java.lang.Throwable ivjExc) {
handleException(ivjExc);
}

return ivjContentsPaneBorderLayout;
}

public BSFEngine getEngine(String langname) {
if (_htEngines != null) {
return (BSFEngine) (_htEngines.get(langname));
}
return null;
}

private JLabel getLabel1() {
if (ivjLabel1 == null) {
try {
ivjLabel1 = new JLabel();
ivjLabel1.setName("Label1");
ivjLabel1.setFont(new java.awt.Font("dialog", 1, 12));
ivjLabel1.setText("Language");
}
catch (java.lang.Throwable ivjExc) {
handleException(ivjExc);
}
}
return ivjLabel1;
}

private JComboBox getLanguageChoice() {
if (ivjLanguageChoice == null) {
try {
ivjLanguageChoice = new JComboBox();
ivjLanguageChoice.setName("javascript");
ivjLanguageChoice.setBackground(Color.white);
ivjLanguageChoice.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JComboBox cb = (JComboBox) e.getSource();
ivjLanguageChoice.setName( (String) cb.getSelectedItem());

}
});
}
catch (java.lang.Throwable ivjExc) {
handleException(ivjExc);
}
}
return ivjLanguageChoice;
}

private JPanel getPanel1() {
if (ivjPanel1 == null) {
try {
ivjPanel1 = new JPanel();
ivjPanel1.setName("Panel1");
ivjPanel1.setLayout(getPanel1GridLayout());
getPanel1().add(getTextAreaScript(),
getTextAreaScript().getName());
ivjPanel1.add(getTextAreaResults());
}
catch (java.lang.Throwable ivjExc) {
handleException(ivjExc);
}
}
return ivjPanel1;
}

private java.awt.GridLayout getPanel1GridLayout() {
java.awt.GridLayout ivjPanel1GridLayout = null;
try {
ivjPanel1GridLayout = new java.awt.GridLayout(2, 1);
}
catch (java.lang.Throwable ivjExc) {
handleException(ivjExc);
}

return ivjPanel1GridLayout;
}

private JPanel getPanel2() {
if (ivjPanel2 == null) {
try {
ivjPanel2 = new JPanel();
ivjPanel2.setName("Panel2");
ivjPanel2.setLayout(getPanel2BorderLayout());
getPanel2().add(getPanel3(), "South");
getPanel2().add(getPanel4(), "North");
}
catch (java.lang.Throwable ivjExc) {
handleException(ivjExc);
}
}
return ivjPanel2;
}

private java.awt.BorderLayout getPanel2BorderLayout() {
java.awt.BorderLayout ivjPanel2BorderLayout = null;
try {
ivjPanel2BorderLayout = new java.awt.BorderLayout();
ivjPanel2BorderLayout.setVgap(5);
ivjPanel2BorderLayout.setHgap(5);
}
catch (java.lang.Throwable ivjExc) {
handleException(ivjExc);
}

return ivjPanel2BorderLayout;
}

private JPanel getPanel3() {
if (ivjPanel3 == null) {
try {
ivjPanel3 = new JPanel();
ivjPanel3.setName("Panel3");
ivjPanel3.setLayout(getPanel3GridLayout());
getPanel3().add(getButtonEvaluate(),
getButtonEvaluate().getName());
getPanel3().add(getButtonClearScript(),
getButtonClearScript().getName());
getPanel3().add(getButtonClearResults(),
getButtonClearResults().getName());
}
catch (java.lang.Throwable ivjExc) {
handleException(ivjExc);
}
}
return ivjPanel3;
}

private java.awt.GridLayout getPanel3GridLayout() {
java.awt.GridLayout ivjPanel3GridLayout = null;
try {
ivjPanel3GridLayout = new java.awt.GridLayout();
ivjPanel3GridLayout.setColumns(3);
}
catch (java.lang.Throwable ivjExc) {
handleException(ivjExc);
}

return ivjPanel3GridLayout;
}

private JPanel getPanel4() {
if (ivjPanel4 == null) {
try {
ivjPanel4 = new JPanel();
ivjPanel4.setName("Panel4");
ivjPanel4.setLayout(new java.awt.BorderLayout());
getPanel4().add(getLabel1(), "West");
getPanel4().add(getLanguageChoice(), "Center");
}
catch (java.lang.Throwable ivjExc) {
handleException(ivjExc);
}
}
return ivjPanel4;
}

private JTextArea getTextAreaResults() {
if (ivjTextAreaResults == null) {
try {
ivjTextAreaResults = new JTextArea();
ivjTextAreaResults.setName("TextAreaResults");
ivjTextAreaResults.setBackground(Color.lightGray);
ivjTextAreaResults.setFont(new java.awt.Font(
"monospaced", 1, 12));
ivjTextAreaResults.setEditable(false);
}
catch (java.lang.Throwable ivjExc) {
handleException(ivjExc);
}
}
return ivjTextAreaResults;
}

private JTextArea getTextAreaScript() {
if (ivjTextAreaScript == null) {
try {
ivjTextAreaScript = new JTextArea();
ivjTextAreaScript.setName("TextAreaScript");
ivjTextAreaScript.setBackground(Color.white);
ivjTextAreaScript.setEditable(true);
}
catch (java.lang.Throwable ivjExc) {
handleException(ivjExc);
}
}
return ivjTextAreaScript;
}

private void handleException(Throwable exception) {

System.out.println(
"--------- UNCAUGHT EXCEPTION ---------");
exception.printStackTrace(System.out);
}

private void initConnections() {
getButtonClearResults().addActionListener(this);
getButtonEvaluate().addActionListener(this);
getButtonClearScript().addActionListener(this);
}

private void initialize() {
setName("ExpressionEvaluator");
setTitle("BSF Expression Evaluator");
setSize(426, 240);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container cp = this.getContentPane();

cp.setLayout(new BorderLayout());
cp.setBackground(new java.awt.Color(228, 223, 228));
cp.setForeground(new java.awt.Color(0, 48, 104));
cp.add(getContentsPane(), "Center");

initConnections();
initializeBSF();
}

protected void initializeBSF() {
if (_mgr == null) {

System.out.println("Initializing");
_mgr = new BSFManager();
_mgr.registerScriptingEngine("", "", new String[] {});
getLanguageChoice().addItem("javascript");
getLanguageChoice().addItem("ruby");
getLanguageChoice().addItem("jython");
getLanguageChoice().addItem("beanshell");
}
}

public static void main(java.lang.String[] args) {
try {
ExpressionEvaluator aExpressionEvaluator = new
ExpressionEvaluator();
aExpressionEvaluator.setVisible(true);
}
catch (Throwable exception) {
exception.printStackTrace();
}
}
}

星期日, 10月 10, 2004

願景VS畫大餅

夢想總是美好的而夢醒後的現實卻是那麼地殘酷。
描繪美好願景與畫大餅之間往往只是一線之隔。
但其實有沒有開誠佈公把如何實踐願景的部份,
拿出來與整個團隊討論是很重要的一件事。

往往看到一些領導者講好聽是在描繪願景,講難聽點就是畫大餅。
如果無法與伙伴們一起挽著袖口下來實踐,思想上的巨人、行動上的侏儒,
面對一意孤行的領導者最終我們只能對他說:千山您獨行、不必相送囉~

當然民主的討論對公司發展未必是件好事,
人多嘴雜往往導引而來天馬行空的意見更多。
但是一個好的領導者應該要像傳教士般不停地傳達自已的信仰,
慢慢引導及轉化讓追隨者真心相信這個願景,
接著才能一起努力實踐,
不是領導者的、你的、也不是我的,而是大家共同的願景。

若是上下交相賊,同床異夢的團隊。
那難保每個人的心態不會如同國共抗日時,
共產黨所謂七分發展,二分應付、一分抗日囉~
理想的狀況應該是讓理念相同的人自然結合,
而有不同理想的人就讓他去尋別的夢吧。
當每個人都為自已的理念奮鬥的時候,整個團隊自然能發揮最大效益。
即使最後不見得能到達夢中的彼岸,但至少大家一起努力過也能使心中無悔吧。

邂逅套裝美女

下午出門辦事情,辦完想說反正人都已經出來了,就順便去誠品逛逛,補充一下精神食糧吧~在雜誌區翻完當期雜誌,呣~轉去電腦資訊區看看有沒有出啥米新書。剛從架上隨便抽了本新書翻翻。突然背後冒了個聲音,

'先生,可以請教一個問題嗎?'
是個身著套裝的美女。真可憐假日還要上班,看起來有點像才剛下班的樣子。
有點被嚇到,回頭指了指自已。
"呃~妳在問我嗎?"
'是呀~我家裡的電腦有點問題,想請教一下'
(接著講了一堆啥米開不了機的狀況,聽起來有點像中毒的樣子)
心中OS:呃~不是每個站在這翻電腦書的人都懂怎麼解毒啦~

沒辦法,輸人不輸陣~美女當前面子還是要顧,
反正亂掰她也不懂,硬著頭皮開始掰:
"呃~有可能是電腦中毒囉~""你有開機片嗎?要用乾淨的開機片開機,然後再試試用掃毒軟體掃掃看喔~"
'.......................................................................................................................'
果然不出所料,看著她水汪汪的大眼睛一副無辜又無助的樣子,
一副就是聽我在講火星話的樣子,看來已經成功的唬住她了。
順手在架上挑了本那種199的PCHOME出的入門書。
"妳看喔~這本書有step by step,妳可以買這本回去試試看。"
'ㄛ~謝謝你ㄋ。'

看著她拿著書翻閱,呣~該是功成身退的時刻到了,正回頭準備要閃去找別的書翻翻。突然又被她叫住。
'ㄝ~你可不可以留電話給我呀~'
"呃~妳要我電話..........做啥?"
'ㄛ~醬我回家弄不出來還可以再打給你問呀~'
心中再度OS:我咧~大小姐,有沒有搞錯,我又不是在光華賣電腦的。
蠻無奈的留了電話給她。互道了珍重再見後。

看著她興高采烈抱著書去結帳,轉過身的我,心中還是不免有點忐忑不安地想著,
她該不會真的打來問吧。

待續.....(如果她有打來問的話)

- - - -
好吧~我承認這篇是很單純的嘴砲炫耀文
【以上故事中所提及任何個人、團體、場所,如有雷同,純屬虛構!!! 】

星期六, 10月 09, 2004

【蛀蟲時間】管理的樂章

管理的樂章
真是好久沒好好把一本書啃完了。
講起來會發現這本書還真有點故事,
其實這本書是宣明智先生在今週刊上的專欄集結整理而成,

而其實平常我是不看今週刊的,
多半我都是中午吃過飯經過便利商店買個飲料時,
順便翻翻架上的商業週刊或是壹週刊,

前幾天不小心翻到今週刊,咦~這專欄寫得真有意思。
有趣的小故事配上宣先生管理上實務的經驗。
再一翻翻原來都已經集結成冊啦。
二話不說就到誠品把它帶回家。

一口氣讀完除了一個爽字外,
還真是找不到第二個字來形容。
難得的是書中充滿著宣先生真誠分享其管理的心得與喜悅,
而非一般企業領導者所出版之個人公關形象書。

節錄幾段書中佳言:


‧簡報要秉持「解決問題,報告成果」的原則,而非「報告問題、解釋原因」
‧管理的秘訣就在於把複雜的事情簡化。‧管理就是共振,領導人扮演的就是共振源的角色,
就像樂團指揮,引領企業團隊奏出美妙的樂章。
‧市場常常無法用常理去判斷,遇有狀況,就面對它,
向它低頭,並趕快找出解決辦法。
‧用低價搶來的業務是最沒有價值的。真正的業務員應該要了解客戶的需求及公司的能力,
藉以提供客戶最佳服務,並獲得合理價格。
‧高科技成功的要素包含技術、團隊、創新、管理以及商業模式。
資金並不在其中,因為好的投資案不愁找不到資金。
‧管理的首要工作就是找到對的人,把人找對了,比做任何事情都來得重要。

--
喔~對了,即使是看過原先週刊上專欄的朋友,
這本書上還補充了不少後記及相關的照片及文件喲~
例如想看看宣先生五十年前是怎麼設計求職信嗎?
雜誌上沒有的,書中可是一樣都不少哩~ ^_^

憶起那段渾渾噩噩時期的童年往事

不知道為啥,今早起來時作了一個夢,
突然想到以前學生時代的一些事情。
那時實在非常的混,許多剛接觸BBS的人大概也會如此吧。
有段時間幾乎每天沉浸在打B的世界裡。

那時我老是呆在網路實驗室裡打B,
日也操,暝也操。最後連夜間部的學生都跟我很熟哩。
不過也因此發生不少趣事。

有次教師節要送卡片,身為班代的我想了一個點子,
在每張卡片上都附上一段打油詩。
記得上課最自由讓我印象最深的是教授組合語言的教授。
那時我寫的是:

最愛教授組合課,
可上網路真快樂,
只見教授賊賊笑,
網路統統被切掉。

呵~到現在我一想到教授剛收到卡片時的表情,
還是忍不住要從夢中笑醒~ XD

常態性加班管理症侯群

Type A:不思長進之標準豬頭
完全不會從錯誤決策中得到教訓,一而再再而三的反覆犯錯。
最後火燒屁股時反正就是這一千零一招。
沒有功勞也有苦勞、沒有苦勞也有疲勞,將帥無能累死三軍甚莫於此。

Type B:老奸巨滑之黑心羊頭
心機深沈以能壓榨員工最後一滴精血為樂。
凡事能拗盡量拗,規劃開發時程決不保留buffer time,
條條大路都是Happy Path一根腸子就可通到底。
美麗藍圖下盡是工程師的血淚,掛著羊頭賣狗肉甚莫於此。

有識者遇到患有此二種類型症狀的管理者,能即早看清現實就儘快轉換吧~
良禽擇木而棲,相信台灣還是有管理良好的工作環境在等著你。

該是到了停下腳步好好想想的時候

工作了幾年一直沒有好好休息一下,
終於逮著機會乘著這次準備轉換工作的空檔,
放了個長假到韓國玩了五天。

不過這次蠻冒險的,還沒找好後路,
就直接辭了目前的工作。
或許這樣也好吧,被工作填滿的生命,
已經漸漸失去了原有的光與熱。

富爸爸一書裡有個觀點不錯,
光憑著努力工作並不會導致成功,
唯有透過不斷的思考才能找出一條活路。

這個論點與孔子所言:「學而不思則罔,思而不學則殆」。
似乎有異曲同工之妙。乘著這段空檔好好看個幾本書。
沈潛一下充充電再出發。畢竟休息是為了走更長的路嘛。 ^_^
或許這段日子會比較有閒寫些遊記或讀書心得吧~