2010年8月14日 星期六
重構與否,不要陷入迷思
不過常常重構也是產生更多問題的開始,例如已經穩定的產品,工程師為了要加入一些設計模式而造成出貨時間的延宕。在台灣大多數的公司都沒有系統架構師這個職位,所以都由工程師來擔任設計,一開始所思考的想法便不是宏觀大局的眼界,日後才會需要一直改...
寫程式的初衷是要達到它的功能,並不是為了要做出藝術品,這就是我的觀點,因為使用者不會在意背後到底是怎麼做的,如果能讓人用的滿意,就是好產品!
2009年1月12日 星期一
維護的重要性
"對於日前桃園機場境管電腦大當機事件, 最後還是內政部長廖了以親自指揮, 才叫得動這套系統創始的資深工程師章毅昌上陣解決問題, 而面對這套只有「少數人才懂」的電腦系統, 移民署已決定更換。"
不知道大家對這新聞有何想法?
為什麼開放原始碼觀念帶給我們如此大的震撼?
為什麼近年來技術增長的如此快速?
為什麼Google產品能夠如此強大?
因為他們都採取"讓越多人瞭解, 讓越多人能輕易的上手"這種觀念, 唯有如此產品或技術才能以倍數發展或散佈
寫軟體, 不是自己寫了幾百支檔案, 能夠運作正常就洋洋自得。一個公司裡, 最講求的部分絕對包括效率, 當然人員的流動性也必須考慮進去, 當接手的人必須花比原開發時間多一倍甚至兩倍去閱讀程式碼, 進而重構(Refactoring), 途中更必須承擔毀損舊有結構的風險, 這時候你才會把當初懶惰, 不以為意的想法(不寫說明文件, 詳細註解, 物件設計藍圖等...)丟置在一旁, 並深深警惕自己下次不要再犯(雖然再犯率和煙毒犯假釋出獄的機率差不多...很高), 但至少你學到一個經驗, 不過在這當中老闆已經燒掉多少薪水了?一個人一個月加上詢問原開發者半個月...。
台灣早期很多軟體都是這樣的做法, 我把它稱之為偉人模式, 因為總是有個很厲害的工程師獨自(或帶領)寫出一套大型軟體, 當然箇中奧妙也只有他自己知道, 接下來的幾十年, 維護的人來來去去, 一知半解的祈求著不要crash。比較倒楣的就是碰到類似桃園機場的狀況, 客戶再也不使用該軟體。
近年來架構設計的觀念從國外引入, 慢慢的大家也開始著重這一塊, 為了寫出易擴展好維護的軟體, 會把類別說明當作教科書來寫, 當然由於文件齊全, 接手的人又可以使用擴展手法不更動到既有程式, 不但時程縮短許多, 也能做到版本控管。
並不是指早期的軟體很糟糕, 那是因為環境使然, 而是說軟體始終是一個跟著時間一同前進的東西, 要做到長久當初設計時就應該把眼光放遠, 尤其是現在進步速度如此之快, 擴展已經是見怪不怪的事情, 不, 應該是必備!
做為一個老闆, 你覺得留住一個人十年簡單還是做出一套軟體能夠方便擴充功能, 架構良好讓來來去去員工維護簡單?
2008年11月26日 星期三
設計原則大集合
設計原則是一群能夠被應用到設計或撰寫程式碼的工具或技術,讓程式更好維護,更具有彈性與擴展力。
1. 開閉原則 (OCP, Open Close Principle)
"類別應該允許擴展而開放, 禁止修改而關閉" --- 例如: 你寫出一個完美的類別,當同事想要使用時,你所建構的類別當然不允許直接修改其中內容而變成兩個不同類別(禁止修改),同時必須能夠以達成他人目的繼承覆寫(允許擴展)。 但是...OCP的重點並不在於繼承,而是"彈性",所以只要記住大方向(類似封裝與抽象的意涵),你也可以使用合成等方式達到此目的。
2. 自我不重複原則 (DRY, Don't Repeat Yourself Principle)
"抽取類別中重複的程式碼,置放於單一地方" --- 這個道理淺而易懂,假如這次專案中一堆類別裡都有copy-paste的程式碼,哪裡用到哪裡就放,半年後打開來修改應該會有一點當初到底在做甚麼的感覺...偉大的軟體其中一個重點就是好維護,就算工程師多厲害,寫出來難以維護的軟體就是垃圾,能夠輕易修改達成用戶需求才是王道,而且DRY原則如果做不好,表示架構流程設計有很大問題。
3. 單一責任原則 (SRP, Single Responsibility Principle)
"系統中每一個物件都應該聚焦在單一責任,同時也只具有單一責任" --- 每一個物件只能有一個理由改變,假若汽車類別中有駕駛方法不是很奇怪嗎?駕駛應該是操作者的責任才對。 偉大軟體條件之一: "高內聚低耦合",但有些沒經驗的工程師可能會把類別分成太細,細到甚至螺絲釘都成了類別,請注意:做軟體該做的事,別吹毛求疵。
4. 替代原則 (LSP, Liskov Substitution Principle)
"子型別(sub type)必須能替代其基礎型別(base type)" --- 這關乎著良好的繼承關係,假如有一天你發現子類別不能夠取代父類別,那表示繼承關係出錯...
這樣可能很難懂,舉個例子: 有一個平面地圖類別,其中有方法 get(x,y),現在要寫另一個3D地圖,你想說要繼承平面地圖,好的,當調用方法時取出x,y軸...z呢??
這種時候絕對不能使用繼承,不用擔心,還有其他的方式讓你完成你該做的事。
委派 --- 在3D地圖類別中直接使用平面地圖的方法get(x,y),不改變它的結構,讓他幫你取代x,y軸,3D地圖類別中再自己規劃z軸設計。
之外再提兩個方式:
(1) 合成 --- 能夠使用一組其他類別的行為,並在執行時期隨意切換。 (2) 聚合 --- 一個類別可以是另一個類別的一部份,但仍然能夠存在於該類別之外。
以上為設計原則,了解之後對於物件設計將會事半功倍!!