API設(shè)計(jì)原則
一致、易于掌握和強(qiáng)大的API是Qt最著名的優(yōu)點(diǎn)之一。此文總結(jié)了我們?cè)谠O(shè)計(jì)Qt風(fēng)格API的過程中所積累的訣竅(know-how)。其中許多是通用準(zhǔn)則;而其他的則更偏向于約定,遵循這些約定主要是為了與已有的API保持一致。
雖然這些準(zhǔn)則主要用于對(duì)外的API(public API),但在設(shè)計(jì)對(duì)內(nèi)的API(private API)時(shí)也推薦遵循相同的技巧(techniques),作為開發(fā)者之間協(xié)作的禮儀(courtesy)。
如有興趣也可以讀一下Jasmin Blanchette的Little Manual of API Design (PDF)或是本文的前身Matthias Ettrich的Designing Qt-Style C++ APIs。
1. 好API的6個(gè)特質(zhì)
API之于程序員就如同圖形界面之于普通用戶(end-user)。API中的『P』實(shí)際上指的是『程序員』(Programmer),而不是『程序』(Program),強(qiáng)調(diào)的是API是給程序員使用的這一事實(shí)。
在第13期Qt季刊,Matthias的關(guān)于API設(shè)計(jì)的文章中提出了觀點(diǎn):API應(yīng)該極簡(jiǎn)(minimal)且完備(complete)、語義清晰簡(jiǎn)單(have clear and simple semantics)、符合直覺(be intuitive)、易于記憶(be easy to memorize)和引導(dǎo)API使用者寫出可讀代碼(lead to readable code)。
1.1 極簡(jiǎn)
極簡(jiǎn)的API是指每個(gè)class的public成員盡可能少,public的class也盡可能少。這樣的API更易理解、記憶、調(diào)試和變更。
1.2 完備
完備的API是指期望有的功能都包含了。這點(diǎn)會(huì)和保持API極簡(jiǎn)有些沖突。如果一個(gè)成員函數(shù)放在錯(cuò)誤的類中,那么這個(gè)函數(shù)的潛在用戶就會(huì)找不到,這也是違反完備性的。
1.3 語義清晰簡(jiǎn)單
就像其他的設(shè)計(jì)一樣,我們應(yīng)該遵守最少意外原則(the principle of least surprise)。好的API應(yīng)該可以讓常見的事完成的更簡(jiǎn)單,并有可以完成不常見的事的可能性,但是卻不會(huì)關(guān)注于那些不常見的事。解決的是具體問題;當(dāng)沒有需求時(shí)不要過度通用化解決方案。(舉個(gè)例子,在Qt 3中,QMimeSourceFactory不應(yīng)命名成QImageLoader并有不一樣的API。)
1.4 符合直覺
就像計(jì)算機(jī)里的其他事物一樣,API應(yīng)該符合直覺。對(duì)于什么是符合直覺的什么不符合,不同經(jīng)驗(yàn)和背景的人會(huì)有不同的看法。API符合直覺的測(cè)試方法:經(jīng)驗(yàn)不很豐富的用戶不用閱讀API文檔就能搞懂API,而且程序員不用了解API就能看明白使用API的代碼。
1.5 易于記憶
為使API易于記憶,API的命名約定應(yīng)該具有一致性和精確性。使用易于識(shí)別的模式和概念,并且避免用縮寫。
1.6 引導(dǎo)API使用者寫出可讀代碼
代碼只寫一次,卻要多次的閱讀(還有調(diào)試和修改)。寫出可讀性好的代碼有時(shí)候要花費(fèi)更多的時(shí)間,但對(duì)于產(chǎn)品的整個(gè)生命周期來說是節(jié)省了時(shí)間的。
最后,要記住的是,不同的用戶會(huì)使用API的不同部分。盡管簡(jiǎn)單使用單個(gè)Qt類的實(shí)例應(yīng)該符合直覺,但如果是要繼承一個(gè)類,讓用戶事先看好文檔是個(gè)合理的要求。
2. 靜態(tài)多態(tài)
相似的類應(yīng)該有相似的API。在繼承(inheritance)合適時(shí)可以用繼承達(dá)到這個(gè)效果,即運(yùn)行時(shí)多態(tài)。然而多態(tài)也發(fā)生在設(shè)計(jì)階段。例如,如果你用QProgressBar替換QSlider,或是用QString替換QByteArray,你會(huì)發(fā)現(xiàn)API的相似性使的替換很容易。這即是所謂的『靜態(tài)多態(tài)』(static polymorphism)。
靜態(tài)多態(tài)也使記憶API和編程模式更加容易。因此,一組相關(guān)的類有相似的API有時(shí)候比每個(gè)類都有各自的一套API更好。
一般來說,在Qt中,如果沒有足夠的理由要使用繼承,我們更傾向于用靜態(tài)多態(tài)。這樣可以減少Q(mào)tpublic類的個(gè)數(shù),也使剛學(xué)習(xí)Qt的用戶在翻看文檔時(shí)更有方向感。
2.1 好的案例
QDialogButtonBox與QMessageBox,在處理按鈕(addButton()、setStandardButtons()等等)上有相似的API,不需要繼承某個(gè)QAbstractButtonBox類。
2.2 差的案例
QTcpSocket與QUdpSocket都繼承了QAbstractSocket,這兩個(gè)類的交互行為的模式(mode of interaction)非常不同。似乎沒有什么人以通用和有意義的方式用過QAbstractSocket指針(或者能以通用和有意義的方式使用QAbstractSocket指針)。
2.3 值得斟酌的案例
QBoxLayout是QHBoxLayout與QVBoxLayout的父類。好處:可以在工具欄上使用QBoxLayout,調(diào)用setOrientation()使其變?yōu)樗?垂直。壞處:要多一個(gè)類,并且有可能導(dǎo)致用戶寫出這樣沒什么意義的代碼,((QBoxLayout *)hbox)->setOrientation(Qt::Vertical)。
-
API
+關(guān)注
關(guān)注
2文章
1620瀏覽量
64043
原文標(biāo)題:API設(shè)計(jì)原則
文章出處:【微信號(hào):C_Expert,微信公眾號(hào):C語言專家集中營(yíng)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
評(píng)論