這個套系統算是非常完整的,由我自己全程設計構建的系統。其他幾套系統多多少少是與同事合作之類的,並沒有那么完整的經驗。
不算大的一套東西,但是卻的確學到很多,主要是關於數據庫設計、設計api、代碼結構設計、項目推進、項目時間和難度的預估、測試預估。
項目從拿到需求到積分系統的完成(包括對接現有支付模塊,編寫測試之類)其實耗時不多,大概在16個天,對賬系統包括測試做了4天總工作日大概在20天。但是這個看似正常的時間,跟最開始估計的時間相差甚遠。我在前期有很多加班包括周末加班的情況下才勉強能照着現在這個進度完成,實際上最初估沒有對賬系統的完成時間只有12天,中間差了4個工作日,算上加班的時間可能差了7個工作日。可能這就是不經常預估項目時間的人容易犯下的錯誤吧,對自己的編碼效率莫名自信,殊不知里面其實有大量不可控因素影響進度。其中很大影響比重在於修改前面人寫的支付模塊的代碼上,不僅需要大量時間閱讀前面的人寫的代碼和思路,還需要把自己的邏輯加進去,這極花時間。所以估時間的時候一定要預留充足的時間,這個后面再提一下。
(一) 還是按順序來吧,先說數據庫設計,設計API,設計代碼結構
花了大概兩天時間設計了數據庫,一共涉及到11張表。弄好了之后拉着leader和主管開了一個短會,我闡述了我的設計思路,然后拉着他們幫我看看設計是否存在問題,或者有沒有地方有漏洞是我沒有辦法考慮到的。這里我其實設計了兩張流水表,每當有一筆收入或者支出的積分,都會在支出和收入的流水表里面增加一條記錄,但是最開始的時候,因為某些原因我可能需要update流水表里面的字段,但是leader告訴我流水表最好不要有update的操作,這樣可能比較容易出錯,流水表只往內記錄,不更新,這樣不會出問題。這點使得我開始從表穩定性去思考這個問題,覺得還是有一定道理。因為流水表最終在結算的時候可能用於對賬,一旦這個表因為更新字段出現問題,那么對賬就會出錯,電商系統的對賬出錯的話。。。。。
找前輩幫忙看因為他們比我更熟悉系統,所以一定要拉他們幫自己看看,否則有些坑,或者以前弄的hack可能會影響到新的系統進行某些操作。做了一些改動,然后我們一致同意了一個決定,就是如果全部做好一起上線代碼量超大最少2k行,可能完全沒有辦法review。畢竟要花時間去看一個2k行代碼的項目,還是需要花費不少的時間。所以決定將項目拆成兩塊分批上線。由於構件積分的查詢存儲使用之類的東西是完全不會影響到現有系統的,所以可以單獨上線,然后將接入現在的支付退款系統作為另外一部分進行上線。這樣就拆開了現在邏輯和新構件系統的耦合,看代碼上面也會變得稍微方便一些。
當時討論完之后,leader讓我最好當天的下午,或者第二天的早上將這套東西要提供給app的api定出來,大概需要哪些api。api定下來之后,寫東西就可以按照api來依次實現功能了。
這個步驟真的是讓我大受啟發,在數據庫設計完成之后,就設計到底要提供哪些功能出來,就能完成初步的api設計。這樣想就可以安好想提供的功能依次編寫代碼了,也不容易漏掉什么東西。其實這里面最難的部分,就是將思路理清楚,能讓自己知道究竟有哪些工作完成,什么先完成,什么可以后完成比較好。在設計完api和數據庫之后我可能需要畫一些圖,和做一些筆記來輔助我思考這些問題才可以讓我自己的思路變得更清晰。我自己的畫拿了幾張a4紙在上面大概畫了寫了一下有哪些api,名字大概叫什么,提供什么樣的功能,可能會設計到的表之類。
最后這個chapter里面關於代碼結構:

dao里面存放了各新建表的模型,由於使用orm所以使用到這些模型。
model里面存放了各種中間邏輯,包括調用dao里面的方法創建更新刪除數據,拼接各類數據。
外面api提供了各功能的api函數,api層我只處理了入參,保證各入參的類型合法然后傳給model對應的函數進行進一步的邏輯處理。
const里面存放了各種可能會使用到的常量。在設計常量存放的時候這次踩了一個坑,最好把有哪幾個可能出現的常量類型分別建立一個類,在類下面寫,而且最好提前分配好他們所屬的數字區域。打個比方,我們可能有支出和收入不同的常量需求,千萬不要寫成這種:
class IncomeConst(object): INCOME_NORMAL_REVIEW = 1 # 正常評價獲得積分 INCOME_REVIEW_BONUS = 2 # 好評獲得的額外積分 INCOME_UNLOCK_ORDER = 5 # 訂單積分解除鎖定 INCOME_REFUND_ORDER = 7 # 退款退積分 class ExpenditureConst(object): EXPENDITURE_FRESH_MEMBER = 3 # 愛嘗鮮購買 EXPENDITURE_LOCK_ORDER = 4 # 訂單積分消費鎖定 EXPENDITURE_OFFSET_CASH = 6 # 積分抵現
應該首先確定income里面占用的是1000-1999的數字 那么expenditure就可以占用2000-2999的數字 這樣能保證同樣類型的const是連貫的就像這樣:
class IncomeConst(object): INCOME_NORMAL_REVIEW = 1000 # 正常評價獲得積分 INCOME_REVIEW_BONUS = 1001 # 好評獲得的額外積分 INCOME_UNLOCK_ORDER = 1002 # 訂單積分解除鎖定 INCOME_REFUND_ORDER = 1003 # 退款退積分 class ExpenditureConst(object): EXPENDITURE_FRESH_MEMBER = 2001 # 愛嘗鮮購買 EXPENDITURE_LOCK_ORDER = 2002 # 訂單積分消費鎖定 EXPENDITURE_OFFSET_CASH = 2003 # 積分抵現
不要把自己搞得像個精神分裂一樣,遇到了就往里加一項數字上漲一個。。。。簡直不忍直視= =。
exception里面存放了各種可能會拋出的錯誤,統一繼承自Excepition類
(二) 項目推進
項目推進的過程中,無非是按照前面設計好的東西按部就班的一個模塊一個模塊的寫。其實中間也沒有碰到什么特別坑爹的事情,只是把原先的兩個上線步驟拆成了三個,因為發現前面其實雖然沒有構建整套積分支付的東西,但是卻有記錄用戶積分的東西,在用戶評論商品之后會給用戶記錄積分的,這就造成了前面多多少少寫了一些積分的東西,我需要把這些原有的東西分好類重新放回到積分新設計的積分模塊里面去。這一步其實我在估時間的時候沒有想到的,由於前面寫的代碼比較隨便,導致我遷移起來很費勁,有非常多的依賴滿天飛,多花了很多時間,而且是影響線上的東西不得不小心翼翼,測了又測。總結了一個經驗,先從依賴最少的地方開始拆,拆完一塊就測一塊。這樣一步一步的弄幾乎不會出錯。千萬不要一連遷好幾塊的東西,最后再來一起測,那個時候要是再測出了問題,我相信改起來的難度非常大。你要依次去排查是前面哪個改動導致了這個問題,這幾乎的是不可行的。
遷移的理想狀態是,所有東西都有單元測試,如果沒對的情況下,跑單元測試都會報錯,你就能及時發現並切改動。現實是(好殘酷的樣子),如果沒有單元測試,你可能需要穩健的一步一步來。當你把簡單的東西都遷走之后,你會發現之前那些難以遷移的東西也變成容易遷的東西了。
(三) 項目進度預估,對項目時間包括測試部分的預估
就像第一部分談到的,其實如果時間非常充足和從容,你可能有大把時間來按照我上面說的流程對關鍵部分進行仔細測試,甚至給每個地方都帶上單元測試。現實是如果你自己估的項目時間過短,你可能沒有時間來完善測試方面的事情。前提是你的公司里面沒有專職QA,測試幾乎需要你自己完成,這個時候,將測試時間估算進你項目進度顯得非常重要。我這次的測試時間大概占完成項目時間的30%,這個結果很大部分取決於我還用了不少業余時間完成項目或進行測試,以及依賴一些以前同事編寫的支付部分的測試,如果全部自己來的話我估計時間至少需要估完成項目時間的50%時間用於測試或者編寫單元測試。也就是說如果你估計這個項目你15天可以寫完,你可能大概需要額外的7天時間用於測試和修復測試出來的bug,以及自己對代碼二次review。這樣的進度才能保證你代碼的質量,以及在上線之后不用提心吊膽是否會被客戶端或者web端的同事找麻煩。
對時間方面的估算,沒有幾個項目的經歷是肯定估不准的,在你發現在deadline之前完成不了項目的時候,一定要向自己的leader說明項目延期,以及因為什么原因導致了項目延期,並且盡快完成項目。所以對項目推進節奏的把控,可能嚴重影響項目質量,既不可以完全沒有壓力和時間上的deadline隨意完成項目,也不可把項目時間卡得過於緊,因為中間除了我上面分析得問題,還又可能出現諸如你需要請假有事,中途任務的插入。
以上。
