后端開發:如何寫出可靠的接口

后端開發:如何寫出可靠的接口

畢業進入現在的公司已近一年,完整參與了部門新項目兩期的開發上線過程,作為一名后端開發,覺得最痛苦的是上線前和上線后的改 bug 階段,面對各種突如其來、莫名其妙的bug,頭昏腦漲、手忙腳亂、越改越懵,經常導致實驗式改 bug、改一個 bug 又出現倆 bug 的之類的慘劇,我就忍不住想,為什么每次上線前都會有這么多bug呢?

前幾天還讀到一篇豆瓣文章,沒有總結的就不是經驗,只是經歷。程序員也不能業務來了就寫代碼,有bug了就改bug,這樣技術很難提升,也就難怪每次都會有那么多bug了。有的開發人員工作多年,接口還是時不時500,前期忙著寫代碼,后期忙著改bug,心累。

我從一期熟悉業務、框架,寫一寫邊緣接口,到二期負責一個小模塊,嘗試數據庫、程序的設計,中間磕磕絆絆,昨天也順利上線,模模糊糊也感覺到了一些經驗,于是努力總結下,雖然簡單,也許能給自己和讀者一些啟發。(本文只針對初級水平,簡單的bug,不涉及高并發、海量數據等復雜問題)

一. 接口為什么出bug?

辛辛苦苦寫的接口,自己測的時候好好的,怎么別人一調就出錯了呢??(此處應有表情包,請自行腦補)當然可能是運行環境的問題,不過程序統一部署在服務器上,這一般是架構師或者運維負責的工作,至于編程語言或者操作系統的問題,也通通不在今天考慮范圍內,今天,我們只考慮自己寫出的bug。

事實上,運行中的程序所涉及的,無非三樣:資源(cpu、內存等)+ 算法(程序運行流程)+ 數據(用戶輸入、數據庫、第三方接口等)。通常我們認為資源是可靠的,出現bug主要是由于算法的不可靠或者數據的異常。

更進一步,機器嚴格按照0/1執行指令,算法上一次執行正常,為什么這一次會失敗?本質上還是因為數據變了,而算法沒能覆蓋此情況,因此,要想保證接口的穩定,主要從兩方面考慮:保證數據的可靠性、算法的健壯性,而算法的健壯性也就是考慮到數據的各種情況,兩者密不可分。

二. 如何寫出bug更少的接口?

如前分析,數據的變化是接口bug最常見、本質的原因。而其中,用戶輸入又是數據變化最主要的原因。而程序必然要有用戶輸入,否則毫無意義。

編程界有句名言:永遠不要相信用戶輸入。你永遠不知道,用戶會在一個期待姓名的輸入框里都輸入些什么。不要因為前端做了過濾你就放心,一方面是用戶可能會使用爬蟲等手段直接訪問你的接口,另一方面,前端也是你的用戶,溝通也存在誤差,前端可能會使用錯誤的方式調用你的接口,而這種錯誤可能會更加隱蔽。

第一條建議:嚴格校驗用戶的輸入,包括格式、內容。

我知道很多人都懶得去逐條檢驗用戶輸入,覺得只要功能正常就ok了,但是,這經常會導致后期改bug時投入更多的經歷。經常測試提了bug,你查來查去,發現是前端傳錯了參數,或者沒有合理限制用戶輸入,當然你可以很剛,讓前端去改,但這個過程已經浪費了你大量的時間精力,還不如一開始自己做好檢驗,返回合適的錯誤消息,會為你后期節省大量的精力。

對于php等動態語言,尤其如此,例如我們使用laravel框架,我會在所有接口入口處,首先使用$request->validate()檢驗所有輸入數據的格式,如有必要,還會寫代碼進一步校驗輸入內容,比如時間范圍、請求數據是否有效等等。

第二條建議:考慮用戶的騷操作,重復提交、延時提交

重復提交應該是大多數后端都能想到的情況,也就是接口的冪等性,有些資源只能操作一次,必須進行校驗,其實不僅是重復提交,還包括同一事件被兩人重復處理的情況。

而對于延時提交,其實是測試給我提bug后我才意識到的問題模式。例如我們通過get接口返回給用戶某種資源,用戶可以通過post接口回傳資源id并提交修改,由于是自己的get接口返回的,我們可能想著只驗證id合法就行了,看似形成嚴格閉環,但如果用戶停留在此頁面延時提交,則可能在此期間資源過期,或者資源已被他人修改,而改用戶也成功修改的bug。其實進一步思考,你會發現,這跟高并發情景下的資源失效有異曲同工之處。

第三條建議:檢驗數據庫、第三方接口的返回數據

除了用戶輸入,常見的數據來源還有數據庫、第三方接口。相對而言,這些數據接口會可靠的多,而且內容格式也更規范。不過為了接口的穩定性,最好也做一些檢驗。如常見的數據為空的情況,就要及時中止程序執行并拋出合適的信息。

對了,對于數據庫,我還遇到過bug,就是主從延遲導致的數據更新問題,由于經驗尚淺,這類問題不很擅長,就不再寫。

第四條建議:程序算法盡可能覆蓋異常情況

這條實際上是對前三條的補充,有些不合法的用戶輸入你可以直接中止程序并返回錯誤信息,但有些情況可能需要程序繼續運行,進行特殊處理,這些情況你在程序設計之初應該盡量考慮周全,后期bug會少很多,也更容易維護。

三. 如何寫出更高效的接口

最后,再寫一點點關于關于接口效率、代碼質量的思考。

1. 影響接口效率的主要是數據庫操作
以我有限的經歷來看,接口耗時長基本都是因為數據庫操作不合理,我們大多數的業務代碼并不會有性能問題。我見過不少在for循環里查詢數據庫的代碼,一定要避免,我們可以先一次性取出所有數據,然后逐個去處理。例如我們會在框架層記錄所有數據庫操作,調試接口時即可看到所有數據庫操作以及相應耗時,該合并的查詢要合并,該優化的耗時查詢相應去優化。

2. 合理使用Exception,日志

這條主要針對php語言,由于歷史原因,我看到不少代碼靠return中止程序并傳遞錯誤信息,這樣在代碼復雜、調用層次深了以后極難維護,遠沒有Exception機制直觀方便。還有,重要信息一定要寫日志,便于后期發現問題及調試,也可用來自證清白。

3. 代碼要合理劃分、抽象

不要復制粘貼代碼,重復的功能要獨立出來;設計時要合理考慮需求變更、擴展;寫小而專注的函數,不要把復雜功能一坨實現;這樣寫的代碼才易于修改、測試以及擴展。這塊我做的也不好,上線后看自己的代碼都是一坨一坨,難以維護,接下來還要多思考,多實踐。

四. 結束語

祝大家寫的代碼都沒有bug!

更多Laravel相關技術文章,請訪問Laravel教程欄目進行學習!

? 版權聲明
THE END
喜歡就支持一下吧
點贊7 分享