馬不停蹄的做了兩周的Android開發(fā).好久沒做了,連最基本的內(nèi)容基本上都已經(jīng)忘記了.
在做Android開發(fā)的過程中,給我們的后臺服務(wù)提交了大量的issue,這迫使我思考到底怎樣才能寫出健壯的代碼.

在這片文章中,我將會介紹,我想到的方法.
TDD(測試驅(qū)動開發(fā))
盡管這個在業(yè)界似乎還不是很流行,但是它對于保證代碼的健壯性很重要.我們開發(fā)人員中的很多人,在開發(fā)完成后,不會寫測試用例來對代碼進行完整的測試.比如說,對于一個修改用戶信息的功能,可能只會測試正確的輸入.而對于那些異常情況,比如,我們知道,修改用戶信息的接口,一定是需要傳一個用戶的uuid來識別是修改的哪位用戶的信息,而用戶(這里我們稱前臺開發(fā)人員為用戶)在調(diào)用的時候,可能并沒有傳用戶的uuid的情況,并不會測試到.對于這種情況,不夠健壯的代碼會給出500,服務(wù)器錯誤,而健壯的代碼會給你一個錯誤信息,告訴你缺少了必要的參數(shù).在我們的服務(wù)中,格式為:
{
"code": "error_code",
"data": "error_message"
}
但是如果我們在開發(fā)之前,確定下來我們的模塊需要擁有的接口,以及接口需要的參數(shù),進一步確定可能會有什么錯誤發(fā)生,并提前寫好相應(yīng)的測試腳本.在開發(fā)完成后,執(zhí)行一下測試腳本,便能發(fā)現(xiàn)代碼中的錯誤,代碼還會不健壯嗎?
還是上面那個例子,修改用戶的信息的接口,假設(shè)我們允許修改的用戶信息有:
- 用戶昵稱(長度最長為20個字節(jié),即最長20個英文單詞,10個漢字)(必須傳入)
- 用戶性別(1代表男,2代表女)(必須傳入)
- 用戶出生日期(格式為YYYY-MM-DD)(必須傳入)
- 用戶簡介(長度最長為40個字節(jié),即最長40個英文單詞,20個漢字)(必須傳入)
我們可以確定可能有下面的異常情況:
- 用戶沒有傳入表明用戶身份的uuid
- 用戶傳入了一個錯誤的uuid,即不存在的用戶
- 用戶沒有傳入必要的參數(shù),比如缺少用戶昵稱,用戶性別等
- 用戶傳了不合法的參數(shù),比如傳入了用戶的密碼
- 傳入的用戶昵稱為null
- 傳入的用戶昵稱為""(即空字符串)
- 傳入的用戶昵稱長度大于20字節(jié)
- 傳入的用戶昵稱為不支持的字符編碼
- 傳入的用戶性別格式不正確,比如傳入'woman'
- 傳入的用戶性別的取值不正確,比如傳入了'3'
- 傳入的用戶出生日期格式不正確,比如傳入的格式為'YYYY-MM-DD hh:mm:ss'
- 傳入的用戶出生日期取值不正確,比如現(xiàn)在是2017年,他傳入的用戶年份是2018或者1800,傳入的月份是13,等
- 傳入的用戶簡介為null
- 傳入的用戶簡介為""(即空字符串)
- 傳入的用戶簡介長度大于40字節(jié)
- 傳入的用戶簡介為不支持的字符編碼
- 用戶傳入了正確的數(shù)據(jù)但是返回的結(jié)果不正確
我們根據(jù)上面可能的異常情況以及正確輸入寫一個測試腳本,在Java中,對于Restful接口,我們使用Rest Assured庫.開發(fā)完成之后,只需執(zhí)行一下測試腳本,就能發(fā)現(xiàn)程序中存在哪些錯誤.
做回歸測試
我們在修復(fù)一個issue,或者增加新的接口的時候,并不能確保我們的修改對其他接口沒有影響.所以,我們還需要做回歸測試.如果上面寫了TDD的測試腳本,那這里我們只需要在這個腳本中新增新接口的測試用例,再執(zhí)行一遍測試就Ok了.如果沒有上面的那個腳本,這里你也很可能就會因為嫌麻煩而不做.
我們項目組中的成員,很多次就是因為沒有執(zhí)行回歸測試,而導(dǎo)致新接口能用而舊接口失效的問題.
將生產(chǎn)環(huán)境下數(shù)據(jù)庫需要的約束同樣加在開發(fā)環(huán)境下
數(shù)據(jù)庫約束其實也是提高我們的代碼健壯性的一個好幫手.比如,在新增用戶的粉絲接口中(用戶和粉絲的關(guān)系在一張單獨的表中),我們需要用戶傳入的粉絲id是一個存在的用戶的uuid.如果不用約束,我們需要在代碼中先遍歷數(shù)據(jù)庫來查詢用戶是否存在,而如果我們直接使用外鍵約束,讓粉絲id是用戶id的外鍵,那么我們只需要查看數(shù)據(jù)庫是否返回違反外鍵約束的錯誤就能確定用戶是否存在了.
在修改用戶信息的那個例子中,如果你沒有先寫測試腳本,忘了判斷用戶昵稱是否為空,而你數(shù)據(jù)庫中,用戶昵稱字段有非空約束.通過傳入空昵稱時這個非空約束報的錯誤,你就能知道需要先判斷用戶昵稱是否為空.
永遠不要認為你依賴的東西會正常工作
作為一個后臺微服務(wù),我們一定會用到數(shù)據(jù)庫,會用到緩存.如果你假設(shè)數(shù)據(jù)庫不會宕機,并沒有處理數(shù)據(jù)庫宕機的代碼,那你的代碼永遠都不夠健壯.一旦數(shù)據(jù)庫宕機,前臺就會返回大量的500,有心人就會有可乘之機了.
做壓力測試
有的錯誤,如果你不做壓力測試,是察覺不到的.比如,不正確的并發(fā)處理,死鎖等問題.對于一個點贊接口來說,如果你用postman來進行測試,點一次結(jié)果正確,點兩次結(jié)果正確,但是你并發(fā)的點一萬次,結(jié)果可能就會因為并發(fā)處理不對而是9990了.
如果你沒用數(shù)據(jù)庫連接池,網(wǎng)絡(luò)帶寬足夠大,并發(fā)執(zhí)行十萬次數(shù)據(jù)庫寫操作,數(shù)據(jù)庫可能就會因此宕機(至少會有明顯的網(wǎng)路延時),這時候如果你的微服務(wù)如果對外提供正確的錯誤信息,那恭喜,你的代碼足夠健壯了.