函式設計的兩個原則(單一出口、一專多能)和例項
阿新 • • 發佈:2019-01-07
函式設計應該像模組設計一樣,講究介面和封裝。函式的命名應該讓使用函式的程式設計師見名知意,函式應該封裝成簡單易用的形式,而且當函式內部實現演算法變化時,函式還能夠保持介面的穩定性。
下面的例子來源於浙江大學翁愷老師的《C語言程式設計進階》中的線性搜尋演算法。
首先看這樣一個搜尋演算法,實現的功能是在一個數組中找出需要的數字,並且返回該數字在陣列中的位置;找不到,則返回-1。
int search(int key,int a[],int len) { int ret=-1; //這個是函式的輸出介面,返回-1則表示沒有找到;返回非-1的陣列則表示對應元素的下標 for(int i=0;i<len;i++){ //int i寫在for語句中是C99的寫法,編譯器如果不支援C99,則需要寫在for外面 if(key==a[i]){ ret=i; break; } } return ret; }
這裡,ret就是程式的輸出介面,無論內部函式演算法如何變化,始終保證介面的易用性,對使用該函式的程式設計師封裝其內部複雜性。這個函式是比較好的。
然後有人提出這樣一種函式的寫法:
int search(int key,int a[],int len)
{
int ret=-1; //這個是函式的輸出介面,返回-1則表示沒有找到;返回非-1的陣列則表示對應元素的下標
for(int i=0;i<len;i++){
if(key==a[i]){
return i;
}
}
return -1;
}
當找到對應元素時,直接返回位置i;找不到,返回-1.
這裡違反了函式或者模組設計的原則:單一出口原則
還有一種寫法如下:
int search(int key,int a[],int len)
{
int ret=-1; //這個是函式的輸出介面,返回-1則表示沒有找到;返回非-1的陣列則表示對應元素的下標
for(int i=0;i<len;i++){
if(key==a[i]){
break;
}
}
if(i==len)
{
return -1;
}
else{
return i;
}
}
思路是首先看能否找到搜尋的元素,找不到,則i=len,返回-1;找到的話,則會直接在第一個if語句進行break,然後轉入下面的else語句,返回找到的位置。這個函式看起來好像也沒有問題,但是違反了函式設計的另一個原則:不要一專多能。變數i承擔了兩個功能,不僅用來遍歷,還用來表示到底有沒有找到搜尋元素。所以,一專多能是不好的程式碼。
這樣回頭來看,往往在函式裡面可以單獨設定函式的輸出介面。