文檔驅(qū)動開發(fā)模式在 AIMS 中的應(yīng)用與實踐
有一個很老的梗: 我最討厭別人寫的代碼沒有文檔,我也最討厭自己需要寫文檔。
有這種想法的程序員應(yīng)該算是一個老鳥了,對于大多數(shù)程序員來說,對于他們來說: 文檔是什么。
對于大規(guī)模,超大規(guī)模的項目,并且歷時很長,需要大量人員協(xié)同開發(fā)的項目,沒有文檔簡直不可想象。但是由于時間緊,任務(wù)重,大多數(shù)的項目中的開發(fā)者都沒時間寫文檔,而且,文檔也不計入考核指標(biāo),導(dǎo)致開發(fā)者也沒有動機(jī)寫文檔。這就造成了很多項目都缺少規(guī)范化文檔,項目的交接和接口的對齊都是靠口口相傳,接口定義準(zhǔn)確度低,并且項目的整體開發(fā)效率低下。
作為一個文檔愛好者的筆者來說,平常很重要的一件事兒就是將自己的工作歸納總結(jié)并整理成文檔。即便如此,筆者也面臨著很多問題:
需求很快就變了,光是改代碼就已經(jīng)耗盡了我的精力了,哪有時間同步文檔。
要么先改代碼,要么先改文檔,總之文檔和代碼之間存在一個不一致錯位期。
除此之外,由于我們主要從事AI相關(guān)能力的研發(fā),所以在開發(fā)過程中還存在以下特殊的問題:
開發(fā)者不得不寫大量重復(fù)的網(wǎng)絡(luò)編程相關(guān)的業(yè)務(wù)代碼,這些代碼的質(zhì)量通常不高,并且在后期的反復(fù)修改中變得越來越臃腫,從而難以維護(hù)。
因為重復(fù)的業(yè)務(wù)代碼開發(fā)工作占比過大,嚴(yán)重壓縮智能化研發(fā)人員在AI方面的精力投入,這就導(dǎo)致了企業(yè)投入大量人力卻無法得到好的效果。
經(jīng)過不斷的摸索和實踐,AIMS項目組采取了一套文檔驅(qū)動的開發(fā)模式,可以有效地解決上述在項目中廣泛存在的問題。
1.??? AI接口開發(fā)的特點
不同于傳統(tǒng)API的CRUD接口的開發(fā),AI的開發(fā)模式通常包含了以下步驟:
數(shù)據(jù)清洗;
模型訓(xùn)練;
參數(shù)調(diào)優(yōu);
API上線。
前三項都是我們組的強(qiáng)項,也是我們的工作重點。但是在實際工作中,卻是API上線消耗了我們的大部分精力。AIMS項目組大都從事的是AI方向相關(guān)的工作,對于API的相關(guān)庫flask、tornado也不是很熟悉,這就導(dǎo)致開發(fā)人員需要花大量時間去了解網(wǎng)絡(luò)編程相關(guān)內(nèi)容,開發(fā)出來的程序質(zhì)量可能也不是很高。而且,在接口開發(fā)后,還需要準(zhǔn)備一份Swagger UI給前端的開發(fā)人員,這又是一項繁重的工作。為了解決如上所述的痛點問題,AI接口開發(fā)就需要滿足以下兩個特點和需求:
API的核心函數(shù)是現(xiàn)成的;
需要將API開發(fā)工作量降到最低。
2.?? 文檔驅(qū)動的開發(fā)模式
我們發(fā)現(xiàn)API的接口文檔中已經(jīng)包含了實現(xiàn)API接口的所有信息。也就是說,API接口文檔的信息熵和API接口代碼的信息熵是一樣的。因此,我們只需要完成代碼或者文檔中的一項即可,另外一項可以交給框架自動生成,這就避免了把同樣一件事情重復(fù)做兩遍的問題。考慮到文檔不論從可讀性、易寫性還是可維護(hù)性都勝過代碼,我們決定寫文檔,然后根據(jù)文檔生成對應(yīng)的代碼。
我們參考了OpenAPI Specification3.0.1標(biāo)準(zhǔn),以及JSON Schema定義了一套API描述語言,開發(fā)者基于這個API描述語言撰寫API文檔。當(dāng)完成文檔時,API的開發(fā)工作也隨之完成,大大節(jié)省了API接口的開發(fā)工作量。經(jīng)過初步估計,使用文檔驅(qū)動模式開發(fā)一個API接口,通常可以減少40%–70%的工作量。
3.?? AIMS框架介紹
為了實現(xiàn)文檔驅(qū)動的開發(fā)模式,AIMS基于tornado實現(xiàn)了一套Web后端框架,如下圖所示。
1.1.? Application Router組件
每一個API都會有一個路徑,即一個正則表達(dá)式[1]。一個微服務(wù)中的多個API的所有路徑會組成一個API路徑列表。
當(dāng)Application Router接收到請求時,會根據(jù)請求中的URI在路由表中查找。如果匹配到某一個Request Handler,路由模塊會將請求轉(zhuǎn)發(fā)給響應(yīng)的Request Handler。如果所有的路徑都不匹配,則返回404結(jié)果
[2]
。
1.2. Request Handler組件
Request Handler處理來自Application Router的響應(yīng),是AIMS架構(gòu)的核心,而Document則是Request Handler的核心。在AIMS架構(gòu)中,Document是指函數(shù)的文檔,即__doc__。Request Handler是在服務(wù)的啟動階段動態(tài)生成的。
事實上,在AIMS架構(gòu)圖中,只有Document是開發(fā)者必須寫的[3]。其它的組件都是由AIMS提供的,或者是由Document自動生成的,所以AIMS開發(fā)模式也被稱為文檔驅(qū)動型開發(fā)模式。開發(fā)者只需要維護(hù)Document即可,從而實現(xiàn)減少開發(fā)者工作量的目的。
1.1.? Watchman組件
Watchman組件可以通過設(shè)置來訂閱某些接口的異常,當(dāng)被訂閱接口出現(xiàn)任何異常時,Exception Handler便會觸發(fā)Watchman組件。
因為Recorder組件記錄了Arguments,Watchman甚至可以自動產(chǎn)生一個可以復(fù)現(xiàn)該問題的測試用例,方便開發(fā)人員定位問題。
1.2. Recorder組件
Recorder是一個采集器,可以采集每一次請求的所有細(xì)節(jié)信息,包括請求ID、請求參數(shù)、遠(yuǎn)程IP、被調(diào)用的接口、響應(yīng)時間、工作目錄和進(jìn)程號等各種信息。這些數(shù)據(jù)具有以下兩個作用:
系統(tǒng)的維護(hù)者可以利用Recorder中的數(shù)據(jù)快速定位,復(fù)現(xiàn)現(xiàn)網(wǎng)問題,可以看做是一個更強(qiáng)大的日志系統(tǒng)。
通過請求ID,訓(xùn)練數(shù)據(jù)收集系統(tǒng)可以將請求參數(shù)、響應(yīng)數(shù)據(jù)與用戶反饋數(shù)據(jù)關(guān)聯(lián)起來,這就相當(dāng)于是一條有標(biāo)記的數(shù)據(jù)。
1.3. Logger組件
Logger是AIMS封裝的日志模塊,用法和python自帶的logging.Logger使用方式一致,最大限度地降低開發(fā)者的學(xué)習(xí)成本。
1.4. 補(bǔ)充說明
我們注意到,在AIMS架構(gòu)圖中,Argument Parser、Schema Checker、Swagger UI和OpenAPI Specification是同源的,即都是來自Document。這就不會出現(xiàn)文檔(Swagger UI、OpenAPI Specification)與函數(shù)實現(xiàn)(Argument Parser、Schema Checker)不一致的情況。開發(fā)者也不需要同時維護(hù)Argument Parser、Schema Checker、Swagger UI和OpenAPI Specification相關(guān)代碼。
以上就是文檔驅(qū)動開發(fā)在AIMS框架中的優(yōu)勢,既降低了開發(fā)者的工作量,又解決了一致性的問題。事實證明,自動產(chǎn)生的組件質(zhì)量也是優(yōu)于開發(fā)者自行開發(fā)的代碼,并且不易出錯,從而提升整體服務(wù)的質(zhì)量以及穩(wěn)定性。
[1] 在AIMS開發(fā)中,這個字段是寫在__doc__中的api_path字段中。
[2] 事實上,路由模塊會將請求轉(zhuǎn)發(fā)給NotFoundRequestHandler,然后由NotFoundRequestHandler進(jìn)行響應(yīng)。
[3] 在AI相關(guān)微服務(wù)開發(fā)過程中,F(xiàn)unction,也就是核心功能函數(shù),是已經(jīng)準(zhǔn)備好的。
API 開發(fā)者
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。