顯示具有 Software Engineering 標籤的文章。 顯示所有文章
顯示具有 Software Engineering 標籤的文章。 顯示所有文章

星期四, 6月 02, 2016

[Coding Style] Train Wrecks

啥系Train Wrecks
字面上來看就是火車事故”  “火車殘骸
Train Wrecks

這裡是用來比喻以下的程式碥
滿常看到程式寫成這樣
這樣的程式很難理解,因為有4objects需理解(ctxt+3getXxx)
而這裡有三層,短短一行就得讀很久

那該怎麼寫呢

1.Split
閱讀者可以直接看到Class Type會比較容易閱讀些
不過也不是很好

2.寫成屬性呢
function好一些,畢竟function還有logic,而property就單純些
不過會expose internal structure
所以也不是很建議

3.Hybrids
省略看標題應該就懂了

4.Hiding Structure
最好的方式,就是不要讓人想,所以細節直接包起來最快
直接在ctxt寫個function,不用看細節(這招真好,不虧是Uncle Bob)
p.s. 這裡小小的跳過一段,程式最終的用意是要取file path,再寫file,所以直接回給OutputStream


總結
過去就一直覺得Train Wrecks的寫法很難閱讀
幸好被大師指正,有理由可以不這樣寫了

Reference
唔... 我忘了...

星期五, 5月 23, 2014

程式應易抽換,而非再利用

幾年前看到這句話「程式應易抽換,而非再利用」,一直看不懂這意思
過去觀念一直是程式應模組化,以便「重覆使用」
怎麼會這麼說呢

最近在學軟體架構,講師又提到這詞
沒說沒感覺,再回去review Design Patterns
還真的都在說易更換,而非重覆使用
為什麼呢

先看這句Prefer composition over inheritance (組合超越繼承)
這句話也讓我想了很久
物件的好處不就是要繼承嗎?
怎麼又要我們不要用繼承,那過去在學的是什麼

原因1:父類別的改變就會直接影響所有的子類別
原因2:因為程式只會對父類別操作,所以子類別需熟悉父類的實作(例如父類別的function實作二件事,而子類別只實無一件事)

因此用composition不會影響原結構而且易於抽換不同的物件
所以"Prefer composition over inheritance"
而這句就代表了「程式應易抽換,而非再利用」

真是太深奧了...

星期五, 8月 19, 2011

書: Clean Code

  1. What is clean code
    • "elegant and efficient" Bjarne Stroustrup, C++之父
      寫的真好...
    • "simple and direct" Grady Booch, OO大師
      幾個字就說出精要,大師就是大師

    為什麼會有bad code
    程式不斷修改,保持clean,混亂的程式碼才不會越滾越大
    導致沒辦法維護,記住童子軍的規則
    The Boy Scout Rule
    Leave the campground cleaner than you found it.

    5S
    • Sort 命名易辯識
    • Systematize 歸類(知道到哪找)
    • Cleaning 潔簡
    • Standardization 一致的coding style
    • Self-discipline 遵守規定
    總而言之就是Keep it clean
    Each function, each class, each module
    exposes a single-minded attitude

  2. Meaningful Names
    • Use Intention-Revealing Names
      透過命名就能知其意圖,如果還需要註解來解釋它,就代表不夠清楚
    • Use Pronounceable Names
      使用可發音的Name幫助溝通
    • Use Searchable Names
      方便search及取代
    • Use Problem Domain Names
      沒有適合使用的term,就使用domain的term,讓接手維護的人至少還可以問domain專家,這代表什麼
  3. Functions
    • Do One Thing(Small)
      只做命名的事細節,包給其他function
    • Function Arguments The Ideal number of arguments is 0 有參數,增加理解困難

  4. Comments
    Don’t comment bad code
    rewrite it 註解沒太多幫助,不如重寫重新整理

程式持續修改演化
不可能一次把程式寫好
First, Make It Work
Then Make It Right


References

星期五, 6月 03, 2011

軟體開發書單

初階
  1. 態度
    心態最重要... 一切從心開始...
    • 自慢 1
    • 自慢 4
    • 打不破的人生 30 個定律
    • 學徒模式 優秀軟體開發者的養成之路
  1. Programming 
    • 編程創藝:編寫出卓越的程式碼 Code Craft: The Practive of Writing Excellent Code
    • 重構:改善現有程式碼的設計 Refactoring: Improving the Design of Existing Code, Martin Fowler
    • 程式碼大全 Code Complete
    • 程式開發心理學 The Psychology of Computer Programming 
    • 程式師修煉之道 The Pragmatic Programmer
    • 程式設計實踐 The Practice of Programming
    • Woking Efficiency with Legacy Code
  2. Design Pattern
    • 設計模式:可重複用的物導向軟體的基礎 Design Patters: Elements of Reusable Object-Oriented Software 
    • Design Pattern於java語言上的實習應用, 結城浩
  3. Coding Sytle
進階
  1. 物件觀念
    • Streamlined Object Modeling
    • Object Modes: Strategies, Patterns, and Applications (2/e) - by Peter Coad
    • Java Modeling in Color with UML: Enterprise Components and Process - by Peter Coad, Eric Lefebvre, Jeff De Luca
  2. Software Architecture
    1. Expert One-on-One J2EE Design and Development
      Spring Framework的創始人Rod Johnson對於J2EE 2.x的反思
    2. Expert One-on-One J2EE Development without EJB
  3. Software Development
  4. 專案管理
    • 人月神話 (The Mythical Ma0Month)
    • 溫伯格的軟體管理學, 溫伯格
    • 與熊共舞:軟體專案的風險管理
    • UML Distilled, Martin Fowler
    • 讓事情發生--專案管理之美學
    • 人件 (Peopleware:Productive Projects and Teams)
    • 深入淺出軟體開發 
    • Ship it
References

星期六, 10月 02, 2010

Coding Style

一直以來都是自己開發系統
也還沒跟別人合作過
快把自己的coding style好好補一下

Mr.Days建議閱讀的文章

讀了幾篇
coding style就是要讓別人可以看的懂,能很快的看出結構
以這個為出發點 本身的coding style就不會太差了
其他的技巧及convention就多讀一點囉...
  • Naming Rule
    最近聽人介紹一本書Clean Code, 感覺也挺不錯的
    看別人寫好的心得最快,以下截出幾句...
    • Use Intention-Revealing Names 
      一個命名,還需要註解來解釋它,就代表他還不夠清楚表示意思
    • Make Meaningful Distinctions
      獨自開發時容易因為一時的方便,只為了建置或開發方便,而隨手使用了不具意義或暫時的命名,往往之後帶來相當多潛在的問題
    • Use Pronounceable Names
      幫助溝通,而且不會顯得這麼愚蠢
    • Use Searchable Names 
      太容易重複出現,就會導致不容易搜尋與定位
  • Version control
    時常自己獨立完成一支程式,想想個人做Version control頂多是backup吧... 不... backup都至少是上個星期的事情了...
    fcamel的文章「養成寫程式的好習慣」,提到即便是一個人 做Version control也是有幫助的
    原本還沒想到有什麼好處
    看完後,發現自己還滿常發生facmel的說的狀況
    • 寫程式較不怕被中斷,只要 hg diff 就知道剛才改了什麼。commit 前也能清楚明白這次做了那些修改,去掉忘了除掉的 debug code。
    • 可以放心地修改,改到昏頭就 hg up -C 清掉剛才不知所云的修改,不用花費力氣將程式弄回正常的版本。
    • 寫到一半發覺要先完成另一個功能,hg shelve 暫存目前的修改,接著將另一個功能做完並 commit,再 hg unshelve 回頭做原本的事,可以輕鬆地切換目標,隨時專注在目前的目標上。
    • 若發覺某個功能忽然不能運作,hg up 切回舊的版本,做個 binary search (或用 hg bisect) 立即找到改出問題的 commit。由於每個 commit 都很精簡,看一下就會找到改爛的原因。

說到差的conding style...
我最受不了沒縮排的...
真不知道他們怎麼coding的...
哦..還有還有... 把所有東西都寫在同一個class裡的那種...

References:

星期日, 4月 18, 2010

Code Complete 2

作者:Steve McConnell

Ch6 工作類別

類別基礎:抽象資料型別(ADT)
將字型大小變更為12點,即16個像素高
//易混淆
currentFont.size = 16; //不知是pixel還是點

//較具意義
currentFont.size = PointsToPixels(12); 
currentFont.bold = true;
currentFont.setBoldOn();

Ch7 高品質常式

從常式名稱中可猜出其作用
單一且明確定義的目的
參數不易超過7個,造成閱讀不易
具備抵禦錯誤資料,不會造成當機

良好的常式名稱
  • 描述常式的所有工作
  • 避免無意義、模糊式空泛的動詞命令
  • FormatAndPrintOut()會比HandleOutput()更加的清楚
  • 勿僅用數字后別常式名稱
  • part1(),part2()
  • 用回傳值述命名函式
  • printer.isReady(),user.next()
如何使用常式參數
  • 文件化有關參數的介面假設
  • 不要回頭再寫註解,數字參考單位,預期值的範圍、永不應出現的特定值
  • 考慮輸入、修改和輸出參數的命名慣例
  • input_,modify_,output_

Ch8 防禦性程式設計

用判斷提示證明和驗證前置條件及後置條件
又稱為design by contract (Meyer 1997)
function velocity(float latitude, float longitude,float elevation){
//Preconditions
Debug.Asert ( -90 <= latitude && latitude <= 90); 
Debug.Assert ( 0 <= longitude && longitude<= 360); 
Debug.Assert ( -500 <= elevation && elevation <= 75000); ... 

//Postcondition 
Debug.Assert()0 <= returnVelocity && returnVelocity <= 600);  
//return value 
return returnVelocity ; 
}

對於錯誤的條件,常式通常會用判斷提示直接處理錯誤的程式碼
判斷提示
Debug.Assert()0 <= returnVelocity && returnVelocity <= 600); 

直接處理錯誤的程式碼
...
//cloest legal value
if(latitude <-90) latitude = -90; else if (latitude > -90)
latitude = 90;
...

8.3 處理錯誤的技巧
傳回中性值
有時對錯誤資料的最佳反應就是持續操作,回傳預設值。數字計算=>0,文字操作=>空字串
關鍵情況下,就回傳錯誤,不要回傳錯誤的資料。
以下一個有效資料取代
處理資料串流時
傳回與上一次相同的回答
考慮建立集中的例外況報告程式
確保例外狀況處理一致性,也能提供中央儲存機制九
function reportException(string className, Exception ex){
string caption="Exception";
string message = 
"Exception: " + ex.Message + Enviroment.NewLine +
"Class: " + className + Enviroment.NewLine +
"Routine: " + ex.TargetSite.Name;

MessageBox.Show(message,caption);
}

//example
try{
...
}catch(Exception ex){
reportException(CLASSNAME,ex);
}

8.5 建立路障,避免程式內含錯誤造成的損毀
撰寫驗證類別,在所有介面運算資料前,透過驗證類別確保資料有效

Ch14 組織直線
14.1.須依特定順序排列的陳述式
1.連續呼叫相依的methods
//計算年營收前,得先計算季營收,而計算季營收前,要先計算月營收
revenue.ComputeMonthly(); //
revenue.ComputeQuarterly();
revenue.ComputeAnnual();
相依性不明顯,將來順序對換,會造成錯誤, 要讓程式碼可看出其相依關係
 2.初始化
//求各部門支出前,要先利用ComputeMarketingExpense()初始化
ComputeMarketingExpense(); //
ComputeSalesExpense();
ComputeTravelExpense();
無法在第一時間看出計算前要先初始化,將來順序對換會錯誤

使常式參數使相依性明顯 
//利用初始化及輸出值,提示相依性
expenseData = InitializeExpenseData(expenseData);

expenseData = ComputeMonthly(expenseData);
expenseData = ComputeQuarterly();
expenseData = ComputeAnnual();  

Ch15 使用條件式
15.1 if
指導方針
  • 先寫pass判斷的正常路徑;再寫異常案例後,避免模糊掉執行邏輯
  • 將正常的case置於if block, 而非else後方
OpenFile(inputFile, status); 
if( status = Status_Success )  //pass
    ReadFile( inputFile, fileData, status); //名目案例
    if(status = Status_Success)
    { 
        end(); 
        errorType= ErrorType_None;
    }
    else
        errorType = ErrorType_FileReadError; //錯誤案例
else
    errorType = FileOpenError; //錯誤案例
重點在讀取主要流程,而非費力專研例外案例
Ch26. 程式碼微調技巧
26.2 迴圈
決策外置(Unswitching)
如果if判斷不會在迴圈執行時變更,就把if搬到迴圈外

合併
將兩個相同集合項目的迴圈合併,一次就把兩次事做完
for(i=0;i<n;i++)
  a++;
for(i=0;i < n;i++)
  b++;
------------------------合併成------------------------
for(i=0;i < n;i++){
  a++;
  b++;
}

減少迴圈內的工作
要使迴圈有效率,其中的關鍵在減少迴圈內部的工作。
如果可在外部運算部份或全部的陳述式,只讓結果進入迴圈內,就可提升效率

26.3 資料轉換
使用整數而非浮點數
盡量不要使用陣列維度
減少陣列參考
利用變數存陣列值,就可避免在迴圈內讀取陣列值
for(...)
  rate[level] *= discount[type]; //discount[type]可抽出來
---------------------用變數取代---------------------------------
discounttype =  discount[type];
for(...)
  rate[level] *=  discounttype;

26.4 運算式
利用代數恆等式
not a and not b = not (a or b)
後者會比前者快上將近1份的時間
使用強度降代
  • 用加法取代乘法
  • 用乘法取代乘冪
  • 用三角恆等式取代三角常式
  • 整數運算會比浮點數快
  • 使用位移運算取代整數乘除

星期一, 12月 07, 2009

Refactoring: Impoving The Design of Existing Code

中譯:重構-改善既有程式的設計

前言

古老的工程諺語:「如果它還能執行,就不要動它」
 但專案功能不斷修改程碼,使原先系統結構逐漸衺弱,程式碼也更加複雜,無法除錯,也無法獲得可被接受的性能/效率
最後重新編寫整個系統,作者指出堅持以持續不斷的重構行為是成功專案的重要角色

重構:「在不改變程式碼外在行為的前提下,對程式碼做出修改,以改進程式的內部結構」

軟體會慢慢腐爛
 重構的步驟只要把某欄位(field)從一個class移到另一個class,把某段程式碼從method拉出成另一個method,或是在class hierarchy中把某些程式碼推上推下就行了,聚沙成塔,小小的修改累積就可以改善設計品質,這和「軟體會慢慢腐爛」的觀點恰恰相反

Ch1 Refactoring, a First Example

分解並重組method
案例中的錄影帶出租statement()做太多事,程式碼太長,可以其目的拆成至不同的class
每個method的程式碼越少越容易維護,且拆成 更多的method更容易reuse(copy-paste相同的程式碼,常發生改了a method忘了改相同容內的b method)
重構技術係以微小的步伐修改程式。改錯時,很容易發現它

更改變數是值得的行為嗎?(p.15)
好的程式碼應清楚表達自己的功能,變數名稱是程式碼清晰的關鍵
任何一個傻瓜都能寫出計算機可以理解的程式碼。唯有寫出人類容易理解的程式碼,才是優秀的程式員


Replace Temp with Query(p.21)
int thisAmount => each.getCharge()
儘量除去暫時變數,暫時變數會導致大量參數被傳來傳去。也很容易失去蹤跡=>相對要付出效率上的代價,但可由最佳化來調整(細節p.69)

運用多型取代與價格相關的條件邏輯(p.34)
=>引用State pattern
在父類別宣告abstract int getPriceCode(),讓子類別實作其條件,使其有自己的計費法
*另外邏輯判斷也該在物件本身的class(指switch(getMovie().getPriceCode())=>應在class movie裡寫switch (getPriceCode())
當有傳入值有可能有變化時,選擇可能變化小的,折起的side effect也較小
=>引用State pattern的重點在「修改與價格有關的行為」,或「新增定價標準」會較容易

Ch2 Principles in Refactoring

為何重構
-改進軟體設計=>消除duplicate code
-使軟體更易被理解
-助找到bugs=>程式碼易於理解,而不是從一個500行的method找

何時重構 The Rule of Three (p.58)
1.反感,第三次又做類似的事就該重構
2.添加功能時
3.修補錯誤時
4.code review時

Ch3 Bad smells in Code

何時重構、何時停止及重構的機制
1.Duplicated Code p.76
2.Long Method p.76
3.Large Class p.78
class太大,instance變數就會多,Duplicated Code也接腫而至
4.Long Parameter List p.78
5.Divergent Change(發散式變化) p.79
隨外界變化而有所修改,找出原因運幅Extract Clss提煉到另一個class
6.Shotgun Surgery(霰彈式修改) p.80
每遇修改就得在不同的classes內做小修改
7.Feature Envy(依戀情結)
某method內呼叫該class幾乎半打的getting method
8.Data Clumps
每次都會同時出現的幾個field
9.Primitive Obsession
日期年月日,3個int不如定義成object
原則
應放在一起的fields =>Extract Class
參數列中有基本型資料=>Introduce Parameter Object
從array挑資料 =>Replace Array with Object
10.Switch Statements

星期五, 11月 27, 2009

軟體工程

物件導向

物件導向程式的九個體操練習
by ihower
遵守九條規則,改善OO實作能力

測試
為什麼要寫 unit test?為什麼要先寫測試?
TDD 推廣:背景知識和簡介

看來還有很多東西要學習...加油...