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的開會成員,


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

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

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

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



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

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

2014年11月30日 星期日

例外處理-物件導向語言的例外處理機制<1>

2014/11/29 23:31

最近向圖書館預約的書終於到手上了,這本書就是Teddy老師的『例外處裡設計的逆襲』,目前看了78頁,很多地方都是看一看就忘了,前面大部分是一生日常生活的例子,Teddy老師將這些例子以程式設計的觀點去討論和分析,還有加上自己許多生動的主觀感受,還挺佩服Teddy的文筆,在我看來很一般且沒什麼感受的事件上,竟能寫得屬此生動,甚至還可以將它轉由專業理論的觀點去描述,讀起來頗有趣,希望自己在讀到最後也能稍微吸收一點點這恐怖的感受吸收力。

70頁這邊開始,開始說明目前物件導向語言的例外處理機制,開頭就拋出了十個名詞:

1. Representation
2. Declaration
3. Signaling
4. Propagation
5. Attachment
6. Resolution
7. Continuation
8. Cleanup
9. Reliability Check
10. Concurrency

自己有先掃過大概一兩次,掃完之後在腦袋重新問自己一次,發現自己竟然一項也沒有辦法解釋,於是往前翻,重新擬定小小目標,先背其中4項就好...

Representation
這個名詞是在述說在程式語言中例外(Exception)所代表的形式,主要分為以下三種:
1. 符號(Symbol)
用整數或字串代表例外。
2. 資料物件(Data object) 
用物件(Object)代表一個例外,這個例外物件本身並不包含任何的例外處理流程。我常常寫的Java語言就是屬於這種表示形式。
3. 完整物件(Full object)
也是用一個物件代表例外,但是與資料物件不同的地方在於,這種類型的例外物件,本身包含了例外發生的處理流程。

Declaration
向外丟出的例外處理是否要宣告在函數介面上,主要分為以下四種:
1. 強制式
編譯器會強制要求你把例外丟出或者處理掉,Java的受檢例外(checked exception),就是屬於這種。
2. 選擇式
宣告或不宣告都可以,Java的非受檢例外(unchecked exception)屬於這種。
3. 不支援
例外不可以宣告在函數介面上,編譯器不會強制規範使用者實作丟出例外,C#屬於這種。
4. 混和式
同時支援上述方法中的兩種以上,就是混和式,廣義來說,Java也屬於混和式。

Signaling
發生例外時,將例外實例丟給例外接收者的動作。主要分為以下兩種:
1. 同步例外(Synchronous exception)
執行函式時,發生例外,可以被程式本身捕捉到。
2.非同步例外(Asynchronous exception)
這種例外通常和函式本身沒有直接關聯,書中TeddyJava中的OutOfMemory就是屬於這種例外。

目前的程式語言中,大部分說的例外處理都是關注在同步例外的處理上,至於非同步例外,發生時通常程式很難再救回來了,所以Teddy建議我們還是把程式資源清一清準備收工,以免越救越糟。

Propagation
例外的傳遞方式,分為以下兩種:
1. 外顯式(Explicit)
如果例外不想在這個函式處理,就必須把它往外丟,Java的受檢例外(check exception)就是屬於這種。
2. 內隱式(Implicit)
不須特別實作丟出例外或捕捉例外,程式就會自動將例外往外丟。


Teddy的書中,每個名詞都會舉一個具體的例子,來讓我們更了解這些名詞要表達的意思,即使自己寫過不少程式,但是對於這些細細分類的名詞,還是體會得很辛苦啊...
一直被灌輸"會用就好"的思維,養成習慣之後,很容易把不同類型的事物歸類成一樣的東西,或者把這些東西直接看成一個未知數X,然後幻想能不能用自己所會的一招打天下,我好像已經忘了該怎麼將理論慢慢的累積上去。


我要一層一層疊回來→Teddy Chen 提醒我的那些事

2014年11月22日 星期六

準備自己的時機

2014/11/22 13:47

最近看著碩二的學弟們在準備研發替代役,為了拿到公司的Offer,很用功地準備公司可能出的考試題目,也不忘利用網路資源收集別人的考試經驗,甚至以前不曾在實驗室讀的書,在這一陣子突然冒出很多本,儘管這樣努力的準備,還是免不了收到一些感謝函。

有一天晚上,看著學弟難得這個時候還待在實驗室,便隨口關心了一下最近面試的狀況,在此之前,已經耳聞他收到了幾張感謝函。

Brian:「最近面試如何?」

學弟:「收到很多感謝函,覺得自己好弱啊!」

Brian:「不用為了研發替代役準備啦!把你會的表現出來,剩下的就交給天吧!」

學弟:「可是我感覺我什麼都不會」

Brian:「考試例外,我想一般公司主要看得應該是人格特質,如果有機會和主管面試,只要很有信心地把自己的想法講出來,這樣就夠了。知識的累積不會是因為這兩天的準備而突飛猛進,就像學英文一樣。」

...

最近上Teddy的課,記得Teddy說過,「你怎麼知道你碩士班有辦法畢業?如果你碩士班不能畢業的話,去準備研發替代役有意義嗎?大部分的人都在為未來做準備,卻沒有想過,現在就開始做。以後的事情都是因著現在的行為而產生的。很多人都在規劃五年、十年後的人生,但你怎麼知道五年後、十年後,你會是你想像中的那個樣子嗎?」

被Teddy老師影響頗深,最近常常把Teddy的話拿來再和實驗室的學弟講一次。

活在當下→Teddy Chen 教我的那些事


2014年11月15日 星期六

讀博班的理由

2014/11/11 11:07

下午在工作學校走廊逛街時,突然遇到以前大學的班導 ---- Mr. 黃,我先用我擅長的高亢嗓音向Mr.黃問好,閒聊了幾句 ...




黃:「現在讀得怎樣?」

Brian (我):「還不錯啊!資格考都考完了,最近專注在修課,修完課之後會開始寫論文。」

黃:「讀得有興趣嗎?」

Brian:「還不錯耶!但是有興趣的地方跟實驗室做的方向有點不太一樣,比較偏向資工軟體設計。」

黃:「有興趣嗎?」

Brian:「嗯!修課的時候才發現自己對軟體工程非常有興趣!」

黃:「有興趣就好,興趣本來就是慢慢發現的,不要害怕跟別人做的不一樣!繼續加油!」



雖然對話很短,但是在對話的過程中,沒想到我竟然能夠不經過思考,直接的講出自己的熱情所在;我講出來的話,聽起來像是講給老師聽的,但實際上,自己好像是另外一位聽眾,透過自己講出來的話更加確信自己的興趣所在。

仔細想想一年前還是博一的時候,那時也是遇到 Mr. 黃 ,他用了一樣的開場白 :



黃:「博士班讀得怎樣?」

Brain:「實驗室剛轉型,一直在趕案子,有點不知道自己在做什麼,得不到成就感。」

黃:「先不要想太多,把資格考先考過,都考完了再回頭看看。」



那個時候Mr. 黃的話其實沒有安慰到我什麼,但有讓我重新找到繼續努力的目標,就是把資格考考過!!

一年過後的今天,我的三科資格考還真得都考過了,分數都高得非常驚人,滿足我大大的虛榮心。現在好像也找到了自己想努力的方向。
雖然實驗室的事務還是一樣的多,但是多了一分追求知識的熱情幫我頂著,好像就沒有這麼累了。雖說大家都說讀博班很不划算,碩班出去賺錢是CP值最高的選擇,但我也不知道怎麼的不小心進了博士班,一直不知道目的為何。
直到最近,Teddy老師的話,讓我找到我讀博班的強力理由。


除非你讀博班,否則碩班可能就是你最後能專心讀書的時光了!→Teddy Chen 教我的那些事

2014年11月8日 星期六

踏入Design Pattern的大門 〈1〉- 歡迎來到設計模式

本來想先學有關例外處理的程式設計方法,沒想到我想借的書都被別人借走了,只好在繼續搜尋有沒有什麼有關軟體設計開發的學科,於是在逛搞笑談軟工的過程中,翻到了有趣的名詞,"Design Pattern"。在看到這個名詞的時候,繼續在網路搜尋了一番,意外地在SildeShare搜到Teddy老師上課的PPT,翻閱了一下,原來是和程式設計有關的學科,接著繼續搜尋找找找找,看有沒有什麼書,適合我先拿來開刀的。Teddy老師推薦2本關於Design Pattern的書,適合新手,一本是"大話設計模式",一本是"深入淺出設計模式",本來想很貪心地把兩本都收藏到口袋,但是圖書館只剩下"深入淺出設計模式",不過也好,可以先專心讀完一本書。

利用這星期五上課時間的三個小時,進入Design Pattern的世界,在書的一開始,大部分都會有其他人對此書的稱讚,很多人名都很熟悉,連GoF四人幫都很稱讚這本書,這時候在心中暗自竊笑,我會不會借一本比聖經還厲害的書,讀完後應該可以變成設計模式之神吧XD。

講了這麼多垃圾話,開始談談第一章的內容吧!

作者用模擬鴨子系統的例子,從一開始不怎麼好的方法進化到很威的方法,達到程式碼重複利用性很高,且需要修改的地方也獨立出來,在往後需求持續增加的時候做到程式碼最小幅度的修改。

把一群演算法獨立封裝,可以在程式執行期指定所須演算法,這就是Design Pattern中的第一個模式"Strategy Design"。

書中的第一章,不直接點出這章是要學什麼設計模式,用一個故事,讓你體驗某種設計模式的好處,最後才揭露這種設計模式的正式名稱,讓你深刻體驗到這種設計模式真的能創造出可再利用、可擴充、可維護的程式,而且你會對使用的時機印象非常深刻。


針對介面寫程式,不是針對實踐寫程式→深入淺出設計模式教我的那些事

2014年11月1日 星期六

重新燃起對閱讀的興趣

最近上了北科大資工所的課,課程名稱為【敏捷與精實軟體開發】,第一眼看到課程的名稱,我的心中就燃起了熊熊烈火,開始幻想在修完這門課後的我,軟體開發的速度不知道會快到什麼地步,在這學期開始之前的暑假,用郵件先向老師打聲招呼稍微打聽課程內容,和老師的個性。老師回信的內容很犀利,馬上使我貼上"難過"的標籤。
學期到現在,課程過一半,其實老師的上課模式很特別,沒有半點實作,上課也不是單純的瘋狂灌輸理論知識。每一堂課丟給我們的作業,大部分都是閱讀一些資料,資料內容依照辦理,不含半點數學理論推倒,讀起來還算有趣,文章內容一致性的都在探討導向軟體開發的問題,許多前輩對於軟工的想法。
每一次的上課都會上演一場辯論賽,老師拼命地丟問題,坐著的我們開始胡亂回答,回答的過程中只要有一點點意思含糊的名詞出現,老師就一定會抓住你的模糊名詞繼續往下問,看到其他同學辯輸老師就會讓我很害怕地上去挑戰。
說來也是因為他的期中考,在上課之前,我早已將老師的經歷打探清楚,發現老師的部落格很有料,沒想到在網路上就可以看到老師分享的眾多有趣內容,順便幫各位鄉民們分享,部落格網址在這邊《搞笑談軟工》,剛開始讀的時候,只是隨便晃眼個看了幾下,讀完之後沒感覺也看不太懂,直到上課的期中考,老師也說了不會考背的東西,除了上課的資料隨意讀了一下之後,繼續回去翻著老師的部落格,殊不知越看越有感覺,於是對於軟體工程的領域很有興趣,一不小心就讀了好多有關軟工及老師在部落格中分享的知識,在課堂上老師也一直提醒說要多讀書,最激勵的我的是以下這段話:「大部分的工程師都不讀書的,你們覺得為什麼我現在可以在外面到處教人敏捷開發,就是因為我有讀書,才可以這樣招搖撞騙,你們只要稍微讀一點書,就可以贏過外面大部分的工程師了。」,這句話很洗腦,老師放出的這句話,一直在我腦中繞阿繞著的,繞一繞著地把閱讀興趣就這樣地繞到我身上。
我還發現老師的一個習慣,他的部落格是每天都發一篇呢!這也是我很久很久很久以前一直很想做到的目標,從今天開始,就...一個禮拜發一篇吧XD。

沒有最好,只有更好 → Teddy Chen 教我的那些事。