作者:Scott Meyers
“設計”這項工作包括很多東西,不過當然最重要的方面之一是介面規範。介面決定了一個組件的哪些方面對哪些人是可以查閱的;它們因此決定了封裝。 介面指名什麼功能(資料,屬性,方法等)對客戶來說是可用的。介面反映了一個系統是怎樣被分解成它所定製的組件的。
介面遍地都是。它們是GUI和API中的"I",但是它們比那個更加無孔不入。類和結構都有介面;函數和方法有介面;模版和名稱空間有介面;子系統和模組有介面;庫和應用程式有介面。不論你在軟體系統開發中扮演什麼角色,都會或多或少設計一些介面的設計,所以,瞭解一些啟發學習法,它們暗示什麼時候你做的不錯,什麼時候你做的糟糕,這樣對你是有協助的。隨著時間的推移,我總結了一些最重要的通用介面設計指導原則如下:
使介面容易被正確地使用並且難於被錯誤地使用。
這條準則導致一個結論就是有些開發人員覺得不安。
介面設計者必須負責
讓我們做一個合理的假設,你的客戶-使用你的介面的人-正試圖完成一個好的項目。他們聰明,很熱情,並且有責任心。他們願意閱讀一些有助於理解正在使用的系統的文檔。他們想讓一切都正確的工作。
既然如此,如果他們使用你的介面時犯了一個錯誤,那這就是你的錯誤。我們假設他們盡全力而為-他們想要獲得成功。如果他們失敗了,原因在於你。因此,如果某個人錯誤地使用你的介面,不管他們是很努力地去做(很少這樣)還是你的介面允許他們去做一些簡單但不正確(經常是這樣)的事情。這就像把鞋穿在並不合適的腳上:這意味著介面使用錯誤的責任在於介面設計者,而不是介面使用者。
在一個完美的世界中,堅持這條原則將保證程式正確地執行。在這樣的世界中,做一些不正確的事情的程式將不會被編譯,而通過編譯的程式幾乎做的都是正確的事情。在人機介面層,錯誤的命令將被拒絕,而被接受的命令則幾乎當然執行做正確的事情,但是在大多數軟體系統中使用的介面只要稍作努力就能得倒顯著的改善。
改善你的介面
考慮一個表示日期的(C++)類,它的建構函式可能像這樣聲明:
class Date {
public:
explicit Date(int month, int day, int year);
};
這是一個介面容易被錯誤使用的經典例子。因為3個參數都是一個類型的,調用者很容易將順序搞混。按照作者的意思我們應該這樣做(不過這似乎有點麻煩,沒辦法,老美就是牛,聽他的吧):
#include <iostream>
struct Day { // thin wrapper for Day
explicit Day(int day): d(day) {}
int d;
};
struct Year { // thin wrapper for Year
explicit Year(int year): y(year) {}
int y;
};
class Month {
public:
static const Month Jan; // a fixed set of immutable
static const Month Feb; // Month objects
//...
static const Month Dec;
int number() const { return m; }
private:
explicit Month(int month): m(month) {}
int m;
};
const Month Month::Jan(1);
const Month Month::Feb(2);
//...
const Month Month::Dec(12);
class Date {
public:
explicit Date(Month m, Day d, Year y); // revised (safer,
explicit Date(Year y, Month m, Day d); // more flexible)
explicit Date(Day d, Month m, Year y) // interface
: dNum(d.d), mNum(m.number()), yNum(y.y)
{
std::cout << "D.M.Y = "
<< dNum << '.' << mNum << '.' << yNum << '/n';
}
private:
int dNum, mNum, yNum;
};
int main()
{
Date today(Day(10), Month::Jan, Year(2005));
}
接下來幹什嗎?不翻譯了,發現這翻譯文章還真是挺麻煩的,以後就自己看看就行了,也沒那麼多的時間啊。