2014年12月27日 星期六

踏入Design Pattern的大門 〈2〉- 獨一無二的物件

2014/12/27 16:49-18:26

在經過C語言的長年洗禮後,前兩年因為開發Android的關係轉戰Java,剛開始寫Java時,自己還是用C語言的觀念去設計程式,在設計的時候常常會碰到一個麻煩的疑問:我的全域變數到底要放在哪裡?最後就創一個類別名叫Global,然後宣告成static method或static variable,透過呼叫靜態函式去使用全域變數,後來才明白,在物件導向的程式語言中,是沒有所謂的全域變數的,程式設計師必須先找到類別,再往下找該類別是否提供所需要的功能。


而在C語言的全域變數得概念,可以映射到一個設計模式(Design Pattern)中的獨體模式(Singleton Pattern),獨體模式顧名思義就是確保一個類別只有一個實體,而大家可以透過獨體類別的方法(Method)取得該類別的實體,使用此類別的人,無法使用new的方式自己產生實體。

先來看看獨體模式的類別圖:

圖1 取自 <<深入淺出設計模式>>


再來把類別圖實作一下:

圖2

其中第5~7行,是為了讓使用Singleton類別的人,不能用new的方式取得實例,如果要使用Singleton類別,須透過getInstance去取得實例。

第10行做了uniqueInstance的判斷,如果已經產生過實例,就把之前產生的實例直接回傳出去。


使用Singleton的程式碼如下:

圖3


這樣的設計在書中還討論到一個問題,在多線程的環境下,多個線程競爭,有兩個以上的線程同時執行圖2中的11行,使得有Singleton產生兩個實例,而線程中的操作其實是反映在不同的實例上。

在書中有提出三個解決方法:

1. 將getInstance()加上同步鎖(synchronized)

這樣做有個缺點,當getInstance被很多線程使用時,線程必須彼此等待,拖慢各自線程的執行速度。


2. 率先建立實體

在宣告uniqueInstance的同時,直接new出一個實例,但是這種方法在編譯時期就會產生實例,如果整個執行期沒有使用到此類別,就會造成不必要的記憶體浪費。

3. 利用『雙重檢查上鎖』

將getInstance中的程式碼稍作修改:



只有第一次執行的時候,才會因為同步鎖而拖慢速度,當uniqueInstance已經被建立實例後,就不會執行12-16行的程式碼。
在程式碼第4行的地方,出現volatile,我個人認為不寫volatile也可以達到一樣的效果。

書中有提到方法3只適用於Java 1.5以上的版本(含Java 1.5)。


獨體模式與一般直接使用static method的設計方法,好處在於獨體模式只有在用到的時候,才會產生實例,如果當我們的程式從頭到尾完全沒有使用到該獨體類別,就不會產生記憶體,這種特性稱為推延實體化,也就是當第一次使用的時候,才會產生實例占用記憶體空間,而static method的作法,是在編譯期就產生的實例,一執行程式就會占用記憶體。

其實在學Design Pattern之前,已經知道有這種撰寫法,學了之後才知道原來這種方法有個獨體模式的名稱。

在設計軟體的時候,難的不是叫人把功能做出來,有時候想要請分工的開發人員按照某種設計方法去撰寫程式,卻不知道要怎麼把想法表達給對方懂,或是已經照著自己的方法盡力詮釋之後,對方還是完全聽不懂,學了Design Pattern,讓程式設計師彼此有共通詞彙,在表達上可以更快速抓到對方所要的設計方式。


學過不代表已經了解,多看幾次有益無害→之前就知道Singleton的我學到的那些事

2014年12月20日 星期六

分享就是練習整理自己的思緒

2014/12/16 22:16-23:12

記得有次上課某T老師在課堂上問到:「一天有花超過一小時閱讀得請舉手。」,結果班上沒有半個人舉手,這時候我的心裡就想說,怎麼可能一天沒閱讀超過一小時,一定是大家太謙虛了不舉手。我個人覺得班上的每個人一定每天都有讀超過一小時。只不過我們習慣了填鴨式的教學,無意識間,自動養成了死背答案應付考試的習慣。我們都很會寫考卷,但當有人真正問你問題的時候,你卻說不出半個字,發現自己所讀的都是假的,腦袋整理不出任何自己的思路,而且T老師還很犀利,到時候問問題答不出來一定很糗,導致自己無法舉手。

今天在Linked In讀了《How to Avoid Looking Clueless》,這是一篇由Guy Kawasaki和Peg Fitzpatrick所撰寫的文章(讀這是為了增強自己的英文能力XD),裡面主要在闡述如何管理你的社群網站,避免自己看起來很無知。以下是他們提出的12個要點:

Dont Be an Orifice (不嘴砲)
Dont Tell People What to Share (不唆使別人該分享什麼)
Dont Buy Followers, Likes, or +1s (不用金錢增加追蹤者)
Dont Ask People to Follow You (不要求別人追蹤你)
Dont Ask People to Reshare Your Posts (不要求別人分享你的貼文)
Dont Annouce Your Unfollows (不要在乎取消的訂閱)
Dont Ask why People Unfollowed You (不要質問別人為什麼取消訂閱)
Dont Be a Pimp (不要成為一個皮條客)
Dont Swear (不要發誓)
Dont Call Yourself a Guru or an Expert (不要自稱是專家)
Dont Abdicate to an Agency (不要把帳號放棄給專業人士管理)
Dont Delegate Your Social Media to an Intern (別把社群委託給實習生)

看完這篇文章後,覺得作者並不是要表達「不懂就不要亂講」的概念。而是在強調,自己講出來的東西要經過自己的腦袋,不要別人要你怎麼認同你就怎麼認同。勇於表達自己的想法。PO出來要盡量以勉勵、立志為主,避免筆戰和裝懂的嘴砲。總之,分享為王道。

If you cant say something nice, dont say nothing at all.
(引用至文章內容)


如果你不能說出一些好的事情,就什麼事情都別說→小鹿斑比教我的那些事

2014年12月13日 星期六

例外處理是什麼?

2014/12/13 14:42-15:22

最近把Teddy的書【例外處理設計的逆襲】,當作故事書看,休息的時候就會拿出來閱讀一番,當我在閱讀的時候,實驗室的同學們就會很好奇地問說,例外處理是什麼?經過我的解釋之後,他們普遍都認為和return差不多,其實剛開始,我也認為和return error code沒什麼差別,但是經過自己有Java設計程式的經驗加上書中的洗腦,總算能有些體會。


以下是和同學的對話...

同學:「例外處理能幹嘛?」

我:「當你執行Function的時候,有錯誤就會產生例外,例外發生的時候會通知使用API的人。」

同學:「那和回傳錯誤代碼有什麼不一樣,使用API的人透過回傳值就可以知道API有沒有執行成功了啊!」

我:「確實和回傳錯誤代碼沒有什麼不一樣,但是就我目前的體會,有例外處理的程式碼,可讀性會比較高,正常流程區塊的程式碼與錯誤流程區塊的程式碼容易分辨。」

舉個例子,
假設現在有三個Function:FunctionA、FunctionB、FunctionC,這三個Function都有可能會執行失敗,而現在有一個流程,須要這三個Function依序動作,流程才算完成,如果執行過程中,有一個Function出錯就不能繼續往下執行,現在我們依Error code和exception個別寫一段程式碼,程式以Java撰寫。


1.        使用Error code,回傳0代表執行成功:

if(FunctionA() == 0) {
    if(FunctionB() == 0) {
        if(FunctionC() == 0) {
             // execute successfully
        } else{
// FunctionC failed
}
    }
     else {
     // FunctionB failed
}
}
else{
// FunctionA failed
}

2.        使用Exception,沒有發生Exception,代表執行成功:

try{
    FunctionA();
    FunctionB();
    FunctionC();
} catch(FlowException e) {
    e.printStackTrace();
}


看完這兩個例子,是否有一點點感覺呢?
在我們想要重新閱讀程式碼的時候,方法2一目了然,很容易找到正常程序的程式碼區塊,當例外發生的時候,FlowException會帶有產生例外的的詳細資訊。

雖然方法1可以更改程式碼架構,能達差不多的效果,但是不管怎麼改,還是需要去判斷它的回傳值,才決定要不要繼續執行下一個Function,而在方法二中,不需要每個Function都逐步檢查,當例外發生的時候,只須要觀察FlowException裡面所帶有的資訊,就知道我們流程哪裡有出錯。


當然例外處理的好處不僅止於這個例子,目前讀了Teddy書有一百頁,書中在討論的時候,常常會出現前幾章的專有名詞,本來對於一堆專有名詞毫無感覺,但讀到現在,總算能區分在書中前幾章就出現的Error、Fault、Failure和Exception間得差異啦!


要說服別人之前,要先說服自己→自己體會到的那些事

2014年12月6日 星期六

口頭承諾算不算承諾?

2014/12/06 14:37-16:01


這星期三的Seminar課程,請到一位來頭很大很大的講師(我忘記是誰了XD),演講至末端的時候,突然拋出了一個問題「在企業文化中,口頭承諾算不算是一種承諾?」,還請大家舉手,


講師:「覺得口頭承諾算是一種承諾的請舉手」


在業界經驗不算太少的我認為說(如果也業界人士比當然還是差一大截啦…),在業界中沒有白紙黑字的都馬不算數;有時候別人口頭答應完事情很多都沒有做到,尤其是同學之間更容易有這樣的狀況發生;在腦中快速閃過這些想法後,我舉了右手,而且有許多同學們的也跟我一樣舉了右手。

講師接著再問:「認為口頭承諾就是一種承諾的人舉手」

舉手的只有兩三隻小貓。
講師看到我們的反應後,向我們說了一個故事,故事內容大概是這樣:
      在台灣的某大公司A有一天,在和外商公B的人開會,討論合作的細部內容,訂定公司A的出貨日期,公司A的廠長承諾的出貨日期是515日,當公司B的人準備離開開會現場去搭飛機時,公司B的其中一個人,私下問了廠長是否能將出貨日期提早到55日,方便公司B繼續處理接下來的工作,廠長向他口頭承諾說了"可以",公司B的人也就這樣回國了。
到了五月五日這天,公司A無法如期出貨,造成公司B的損失,於是公司B向公司A記了一封e-mail,信件內容大致上是向公司A索賠300萬美金,因為公司A當初的承諾沒有確實達成。
公司A的總經理招集了當天的公司A的開會成員,


總經理問說:「當天我們有答應他們五月五日交貨嗎?」

廠長回答說:「我有口頭答應他們。」

其他成員附和說:「沒有寫合約,那我們就不用賠錢了啊,反正他們又沒有證據!」

總經理:「你們知道美國法庭,是要摸著聖經宣誓自己絕無說謊,如果真的鬧上法庭,你真的敢做這樣的宣示嗎?」



聽完了這樣的故事,才知道自己的口頭承諾原來是這麼地恐怖啊!千萬不要承諾自己沒有把握的事情,雖然自己有時候常常被主管逼著接收各種不合理的要求,但只要無法達成,也要適時地反映給主管啊!

口頭承諾就是一種承諾→不知名講師矯正我的那些事