最近看到了一篇文章 Hyrum’s Law涌萤,覺(jué)得非常有意思淹遵,感覺(jué)應(yīng)該翻譯一下,也順帶夾雜點(diǎn)自己的理解负溪。
這篇文章主要是一位在底層架構(gòu)上面工作多年的一位資深工程師觀察到的一個(gè)現(xiàn)象透揣,簡(jiǎn)單來(lái)說(shuō),就是:
當(dāng)一個(gè) API 有足夠的用戶的時(shí)候川抡,在約定中你承諾的什么都無(wú)所謂辐真,所有在你系統(tǒng)里面被觀察到的行為都會(huì)被一些用戶直接依賴。
在詳細(xì)解釋這個(gè)之前崖堤,我們可以先來(lái)說(shuō)說(shuō)程序設(shè)計(jì)里面非常重要的兩個(gè)東西侍咱,接口和實(shí)現(xiàn)。通常在一個(gè)系統(tǒng)里面密幔,接口就是一個(gè)于系統(tǒng)交互的抽象楔脯,譬如汽車的方向盤和油門,剎車這些(我們通過(guò)這些來(lái)控制汽車胯甩,與汽車交互)淤年,而實(shí)現(xiàn)則是這個(gè)系統(tǒng)工作的一種方式,譬如汽車的輪子和引擎(汽車實(shí)際是通過(guò)這些來(lái)工作的)蜡豹。區(qū)分接口和實(shí)現(xiàn)的好處是非常明顯的麸粮,當(dāng)一個(gè)系統(tǒng)快速迭代,變得越來(lái)越復(fù)雜和難以理解的時(shí)候镜廉,抽象能非常好的幫助我們管理這些復(fù)雜性弄诲。
關(guān)于如何定義不同層級(jí)的抽象,可以參考其他的文章娇唯,譬如經(jīng)典的《人月神話》齐遵,這里我們可以假設(shè),如果一個(gè)抽象被定義好了塔插,那么它其實(shí)就是有形具體了梗摇。也就是說(shuō),一個(gè)接口在理論上面需要清晰的將系統(tǒng)的使用者和該系統(tǒng)的實(shí)現(xiàn)隔離開(kāi)想许。但現(xiàn)實(shí)往往是殘酷的伶授,當(dāng)這個(gè)系統(tǒng)開(kāi)始逐漸膨脹断序,一些用戶開(kāi)始依賴一些通過(guò)接口暴露出的內(nèi)部的實(shí)現(xiàn)細(xì)節(jié),這條理論就被打破了糜烹。
著名的 Joe 有一篇文章 Law of Leaky Abstractions违诗,里面就列舉了很多這樣的例子,一個(gè)就是我們常用的 SQL疮蹦。SQL 其實(shí)可以看做是一個(gè)對(duì)數(shù)據(jù)庫(kù)操作的抽象诸迟,我們只需要通過(guò) SQL 語(yǔ)句就能非常方便的查詢數(shù)據(jù),而不用去為數(shù)據(jù)庫(kù)寫特定的執(zhí)行步驟愕乎。但是阵苇,有時(shí)候,我們會(huì)發(fā)現(xiàn)感论,一些 SQL 語(yǔ)句明顯會(huì)比其他的運(yùn)行的要慢绅项,譬如 where a=b and b=c and a=c
可能就比 where a=b and b=c
要快不少,為了搞明白笛粘,我們就必須深入細(xì)節(jié)趁怔,去看相關(guān)的 query plan。這時(shí)候薪前,我們其實(shí)就已經(jīng)打破了 SQL 這層的抽象润努,因?yàn)槲覀儽仨氁チ私獾讓訉?shí)際的執(zhí)行方式了。
只要細(xì)致觀察示括,通常我們都會(huì)發(fā)現(xiàn)一個(gè)有趣的現(xiàn)象铺浇,原作者將其稱為 “The Law of Implicit Interfaces” ,也就是說(shuō)垛膝,只要一個(gè)系統(tǒng)有足夠的使用者鳍侣,那么就沒(méi)有啥私有實(shí)現(xiàn)這個(gè)說(shuō)法了,用戶會(huì)開(kāi)始依賴實(shí)現(xiàn)的任何方面吼拥,無(wú)論是內(nèi)部的還是外部的倚聚。這樣,實(shí)現(xiàn)的一些隨意變更也會(huì)被限制了凿可,因?yàn)楝F(xiàn)在我們不光要保證公開(kāi)的有文檔的接口惑折,同時(shí)也要考慮已經(jīng)被使用的內(nèi)部的隱示接口。原作者將這個(gè)現(xiàn)象稱為 “bug-for-bug compatibility”枯跑。
隱示接口的產(chǎn)生是一個(gè)緩慢的過(guò)程惨驶,以至于接口的使用者通常都不會(huì)注意到它已經(jīng)出現(xiàn)了。例如敛助,一個(gè)接口不保證任何性能粗卜,但使用者通過(guò)它的實(shí)現(xiàn),預(yù)期了它的性能能達(dá)到哪一個(gè)層級(jí)纳击。這個(gè)期望變成了系統(tǒng)的一個(gè)隱示接口续扔,后續(xù)改系統(tǒng)的任何改動(dòng)都需要保證這個(gè)接口的性能特性攻臀,從而能讓用戶正常工作。
隱示接口來(lái)自于大型系統(tǒng)的增長(zhǎng)测砂,當(dāng)然我們其實(shí)并不想讓這個(gè)問(wèn)題出現(xiàn)茵烈,這就要求我們?cè)跇?gòu)建和維護(hù)復(fù)雜系統(tǒng)的時(shí)候思考的更全面一點(diǎn)百匆。我們需要意識(shí)到砌些,隱示接口會(huì)限制我們系統(tǒng)的設(shè)計(jì)和發(fā)展,對(duì)于任何的流行系統(tǒng)加匈,接口的水比我們想的還深存璃。