2006年11月30日 星期四

[重構]簡化函式呼叫

1.Rename Method : 取個更合適的函式名

2.Add Parameter : 增加參數

3.Remove Parameter : 減少參數

4.Separate Query from Modifier : 將會回傳與會修改物件內部狀態的函式分開

5.Parameterize Method : 讓函式帶參數

6.Replace Parameter with Explicit Method : 以明確函式取代參數

7.Preserve Whole Object : 保持物件的完整

8.Replace Parameter with Method : 以函式取代參數

9.Introduce Parameter Object : 使用參數物件

10.Remove Setting Method : 去除不希望改變值的field的設值函式

11.Hide Method : 把不被其它class使用的method設為private或移除

12.Replace Constructor with Factory Method : 以Create method取代建構式

13.Encapsulate Downcast : 封裝向下轉型

14.Replace Error Code with Exception : 以錯誤碼來表示某些錯誤(異常)

15.Replace Exception with Test : 以測試取代異常

2006年11月28日 星期二

[重構]條件式的重構

1.Decompose Conditional : 分解條件式

2.Consolidate Condition Expression : 合併條件式

3.Consolidate Duplicate Conditional Fragments : 合併重複的條件片段

4.Remove Control Flag : 移去控制用的變數

5.Replace Nested Conditional with Guard Clauses : 以衛述句取代巢狀條件式

6.Replace Conditional with Polymorphism : 以多型取代條件式

7.Introduce Null Object : 使用NULL物件

8.Introduce Assertion :  使用Assertion

2006年11月27日 星期一

[重構]物件內資料成員的重構

1.Self Encapsulate Field : 自我封裝欄位 (為field提供get/set moethod)

2.Replace Data Value with Object : 以物件取代資料

3.Change Value to Reference : 將實值物件改為參考物件

4.Change Reference to Value : 將參考物件改為實值物件

5.Replace Array with Object : 以物件取代陣列

6.Duplicate Observed Data : 將資料copy到domain object中,並以Observer pattern作同步控制

7.Change Unidirectionl Association to Bidirectionl : 將物件的單向關聯改為雙向關聯

8.Change Bidirectionl Association to Unidirectionl : 將物件的雙向關聯改為單向關聯

9.Replace Magic Number with Symbolic Constant : 以符號取代魔數

10.Encapsulate Field : 封裝欄位 (儘量不提供public field)

11.Encapsulate Collection : 封裝群集

12.Replace Recode with Data Class : 以資料類別取代記錄

13.Replace Type Code with Class : 以類別取代型別

14.Replace Type Code with Subclass :  以子類別取代型別

15.Replace Type Code with State/Strategy :  以State/Strategy取代型別

16.Replace Subclass with Field : 以欄位取代子類別

[重構]在物件之間的重構

1.Move Method : 將函式搬到它適合的位置
2.Move Field : 將資料搬到它適合的位置

3.Extract Class : 將一個功能太多的class,提練為多個class

4.Inline Class : 將功能過小的Class,合併為一個

5.Hide Delegate : 在server端建立client所需要的函式,用以隱藏delegation

6.Remove Middle Man : 移除過多的簡單 delegation

7.Introduce Foreign Method : 加入外來的函式

8.Introduce Local Extention : 加入區域性擴展

2006年11月22日 星期三

Serial port programming in Unix/Linux

最近有機會接觸了serial port programming(另外還有Video for Linux API,socket programming等等), 由於平台是Linux,所以有機會比較深入地去接觸kernel,發覺Linux真是個很漂亮的系統(當然不是指各套件預裝User Interface :P ),在欣賞這個精湛的設計時,也期許未來能夠參許這樣的藝術工作.

以下整理了一些serial programming常用的功能:

1.標頭檔,是在寫serial port programming時常用的,為了簡化版面,我就不細說每個標頭檔是那些函式會到了
#include <stdio.h> /* Standard input/output definitions */
#include <string.h> /* String function definitions */
#include <unistd.h> /* UNIX standard function definitions */
#include <fcntl.h> /* File control definitions */
#include <errno.h> /* Error number definitions */
#include <termios.h> /* POSIX terminal control definitions */

2.開啟/關閉serial port
int fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY);

if (fd == -1)
{
//Could not open the port.

}
else
fcntl(fd, F_SETFL, 0);

close(fd) ;

3.設定control options
struct termios options;
//Get the current options for the port...

tcgetattr(fd, &options);

//Set the baud rates to 19200...
cfsetispeed(&options, B19200);
cfsetospeed(&options, B19200);

//Enable the receiver and set local mode
options.c_cflag |= (CLOCAL | CREAD);

//Set the new options for the port
tcsetattr(fd, TCSANOW, &options);

4.常用的組合

  • No parity (8N1):


options.c_cflag &= ~PARENB ;
options.c_cflag &= ~CSTOPB ;
options.c_cflag &= ~CSIZE ;
options.c_cflag |= CS8 ;


  • Even parity (7E1):


options.c_cflag |= PARENB ;
options.c_cflag &= ~PARODD ;
options.c_cflag &= ~CSTOP ;
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS7;


  • Odd parity (7O1):


options.c_cflag |= PARENB ;
options.c_cflag |= PARODD ;
options.c_cflag &= ~CSTOPB ;
options.c_cflag &= ~CSIZE ;
options.c_cflag |= CS7;


  • Space parity is setup the same as no parity (7S1):


options.c_cflag &= ~PARENB ;
options.c_cflag &= ~CSTOPB ;
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8;

5.設定hardware flow control
options.c_cflag |= CNEW_RTSCTS; /* Also called CRTSCTS */
或是 options.c_cflag &= ~CNEW_RTSCTS;

6.讀寫
直接用 read() , write()就好了

2006年11月21日 星期二

[重構]函式(method)的重構

1.Extract Method:把一段程式碼獨立出來,另外成為一個函式

2.Inline Method:將函式展開其它函式(合併)

3.Inline Temp:對於只用一次的暫存變數,把所有引用此變數的動作,替換成對它賦值的運算式本身

4.Replace Temp with Query:把暫存變數所存放的運算式結果,提煉成一獨立函式

5.Introdce Explaining Variable:把複雜的運算式的結果放進一暫存變數,並以變數名解釋其用途

6.Split Temporary Variable:不將一個暫存區域變數,用於多個功能

7.Remove Assignments to Parameters:不更改參數值(以一暫存變數複製之)

8.Replace Method with Method Object:將函式放入一物件,區域變數為其data field

9.Substitute Algorithm:將某個演算法替換成另一個更清晰的演算法

2006年11月17日 星期五

[重構]bad smells in code

If it strikes,change it!

以下是一些需要被重構的code,若你的程式碼出現在下列的某幾種現象時,請改善它

1.Duplicated Code : 重覆的程式碼
2.Long Method : 太長的函式
3.Large Class : 過大的類別
4.Long Parameter List : 太長的參數列
5.Divergent Change : 發散式變化 (一個class受多種變化的影響)
6.Shotgun Surgery : 霰彈式修改 (一種變化會引發多個class的修改)
7.Feature Envy : 依戀情結 (函式對於某個class的存取,高過於自己的host class)
8.Data Clumps : 資料泥團 (某些資料總是綁在一起並,一起出現在多個地方)
9.Primitive Obsession : 基本型別偏執 (將幾個俱相關的基本型別合併成一個小物件)
10.Switch Statement : (少用switch句型)
11.Parallel Inheritance Hierarchies : 平行繼承體系 (不同繼承體系中存在著相同的class)
12.Lazy Class : 冗員類別 (除去沒有必要的class)
13.Speculative Generality : 非必要地談未來性 (除去非必要的hook)
14.Temporary Field : 暫存欄位 (除去class中,暫存用的欄位)
15.Message Chains : 過度耦合的訊息鏈 (連續向不同的函式要求不同的物件)
16.Middle Man : 中間人 (除去一些不做實事的函式)
17.Inappropriate : 狎暱關係 (兩個class花太多時間去用對方的private成員)
18.Alternative Classes with Different Interfaces : 異曲同工的類別 (兩個不同函式卻做一樣的事)
19.Incomplete Library Class : 不完備的函式庫 (想修改library部分功能時)
20.Data Class : 純稚的資料類別 (封裝好data class)
21.Refused Bequest : 被拒絕的遺贈 (當subclass 不希望或不需要得到superclass的功能)
22.Comments : 過多的註解 (試著讓註解變得多餘)

當你感覺需要撰寫註解時,請先嘗試重構,試著所有註解都變成多餘的 :)

[重構]重構的時機

Don Robert所提出的準則: 事不過三,三則重構 (three strikes and you refactor)

這句話的意思是說,某件事第一次做時就直接去作,第二次做時也許會覺得很麻煩,第三次做的時候,就代表需要重構了.

其它重構的時機有

1.要加入新功能的時候

2.要修改bug的時候

3.在復審(review)程式碼的時候

而何時不該重構呢?就是你的code己經亂到幾乎要重寫的地步,那麼就不用浪貴那麼多的時間了. :)

trace程式碼的好工具 kscope

以往寫windows程式時,看程式碼都是用像是VisualC++這類的IDE,但是到了Linux底下,就一直找不到好用的工具,以前有試著用過anjuta跟eclipse,可是這些都不是好的trace工具,我覺得好的trace工具,一定要有對語法分析並標色的功能,對不同檔案用不同tag顯示,最好還能夠對變數能夠有快速參照並可以很快的找到定義的地方,這些kscope都滿足了!

http://kscope.sourceforge.net/

2006年11月16日 星期四

Refactoring 重構

「任何一個傻瓜都能寫出計算機可以理解的程式碼,唯有寫出人類容易理解的程式碼,才是優秀的程式員.」

這是兩年前吸引我去閱讀Refactoring(重構)的一句話,就名詞定義上而言,重構是一種對軟體內部的調整,在不改變外在行為的原則下,提高程式碼的可讀性,以及降低成本,提昇效能.

2006年11月14日 星期二

[ubuntu]製作iso檔

將光碟機的內容製成iso檔

$dd if=/dev/cdrom of=image.iso

將is掛載到檔案系統

$mkdir /mnt/iso

$mount -o loop,ro -t iso9660 ./image.iso /mnt/iso

2006年11月13日 星期一

新的blog

把blog從vega.cs.tku.edu.tw換到了實驗室網站了,雖然我很少在寫東西,不過wordpress感覺還不錯,最主要是我想要的功能都有,而且可以theme,真是太棒了!!

2006年11月10日 星期五

[note] socket programming中AF_INET與PF_INET的不同

在最初的定義上,AF_INET是Address Family的,而PF_INET是protocol family,兩者在網路架構上層級不同.其中protocol較為低層,像是TCP/IP,而Address較為高層,在TCP/IP中有IPv4與IPv6兩種不同的協定,因為現今的網路只使用IPv4,故兩者通常定為一樣的值,用久了,大家都混著用了,若程式只是要在IPv4上work的話,那麼使用兩種都可以,但若是要支援不同的Address Family的話,就必須使用PF_INET了.

[note]移除不必要的service

用 ps ax 可以知道目機有那些會使用I/O port的行程在跑,可以的話,盡量讓這些程式減少到一頁,同時也要注意inetd或xinetd有沒有代理那些service,

//檢查inetd中有那些service
$ grep -v "^#" /etc/inetd.conf

//關 service
#/etc/init.d/some_service stop

// 列出正在listen的程式
#netstat -lp