下一次程式有比較大的突破,是理解物件導向(Object-Oriented, 簡稱OO) 的概念。
在學生時期,雖然碩班也是資工所,但是主要是用 Matlab 作數學矩陣的運算。畢竟 C 並不是有 OO 概念語言,所以其實一直以來都沒有受到 OO 程式的訓練,現在回想來也是滿神奇的。其中最神奇的是,我在清大甚至有修過 Java的課程,Java 可以說是非常硬派的 OO 程式語言。結果我即使以不低的分數過了,但還是完全沒有 OO 的概念。
而 OO 的概念的建立,是在我人生中第一份找到的工作,那家公司有個過去還滿知名的螢幕錄影軟體叫 PowerCam。我在那間公司是負責開發一個類似微軟 Office 的 Power Point 的簡報軟體,算是一種 CAD (computer-aided design)軟體,就是「小畫家」啦!用的技術是微軟的 C#,其實是完全照抄 Java 幾乎一模一樣的語言,所以也是一個硬派的 OO 語言。且圖形也是非常適合用 OO 概念實作的,例:三角形、方形、多邊形、都是繼承圖形。就在那時,我買了第一本歐萊禮 O’reiley 「深入淺出」系列的書籍。
當然除了這些外,那家公司帶我的導師(mentor)程式非常強,也是一個奇人。先稱他為阿元好了。阿元原來在科技廠寫筆電攝影機的韌體約6~7年,幾乎每天都用盡心力加班完成其它工程師數倍的工作,寫的code速度快,品質又好,可說是公司最強的工程師。直到有一天健檢後發現因為長年的熬夜加班,身體出了非常多的問題,危在旦夕。公司賺錢也並沒有給予他更豐厚的報酬,他自己卻賠上人生。犧牲奉獻那麼多只是成為不新貴、單身、身體又差的阿宅,阿元憤而離職後,就到了這間我任職,不到十人的小公司爽領薪水。
阿元下班絕對準時,公司第一個走的就是他,而且會叫我一起走。因為事情實在做太快了,下午常有空閒時間。幾乎每天下午他都帶我去公司樓下的萊爾富喝咖啡…
雖然阿元好像是在打混養老的工程師,但其實只是因為公司的需求對他來講太容易了,幾乎都被他秒殺。因為當我這個菜鳥給他做code
review時,每次都被他修理地體無完膚,可以說是嗆爆,我想出來的好方法會被他隨便舉幾個反例就推翻,讓我差愧無地自容。不過也是這樣的「批評指教」,糾正及給予了我許多寫程式的方法跟觀念,有些習慣直到現在我都還在用呢!(比如commit
code 之前一定重檢查,聽起來很瞎,不過很多人不檢查的,觀察一下code裡的 print,
console.log吧! )
說明一下 Code Review 是辛苦寫完程式碼後,把程式碼給別人「欣賞」的流程,目的是減少「當局者迷」的情形,且他人也會建議更好的寫法。只是工程師通常都很玻璃心,畢竟程式碼有點像是「創作的文章」,而且高學歷的理工工程師過去在學校很少被批評(或罵),常看到很多工程師會在code review崩潰…生氣爆怒,我還看過有人哭的…。
總之,Code Review 加上 OO 的確為我的程式職涯奠定良好基礎。
小記
其實呢,寫程式讓電腦運作跟有無物件導向的觀念是沒有什麼關係的。那為什麼要學 OO ?我個人認為有幾點優點:
- 程式分工、模組化
- 好懂
- 較易維護
假設今天寫一個計算咖啡價錢的程式:一杯咖啡小杯30元,大杯50元,加奶15元 非 OO 寫法:
def coffee_price(size, milk: false)
price = size == 'S' ? 30 : 50 # 如果size 'S' 則是30元,否則是50元
price += 15 if milk # 如果 mlik 是 true 的話,加 15元
price # 返回價錢
endcoffee_price('S') # $30
coffee_price('L') # $50
coffee_price('L', milk: true) # $65
現在改 OO 寫法
class Coffeeattr_reader :price, :size
def initialize(size)
@size = size
@price = @size == 'S' ? 30 : 50
end def add_mlik
@price += 15 # 加 15 元
self # 返回物件自己
end
endCoffee.new('S').price # 返回30
Coffee.new('L').price # 返回50
Coffee.new('L').add_milk.price # 返回65
這樣看來OO的方式根本把事情變更複雜了啊?搞什麼啊!本來5行程式暴增到10幾行
別急…代誌不是憨人想的那麼簡單…軟體界有個定律,就是:不會變的事只有變更這件事(only unchange thing is change)
今天如果有人想加雙份牛奶,原來的寫法就只能改了
不過OO的寫法可以直接 call 兩次 :add_milk
Coffee.new('L').add_milk.add_milk.price # 返回80基本上就是把程式要做的事分的越細,就越容易複用:這也是 OO 的 Single Responsibility 原則
留言
張貼留言