系統設計之初應該考慮到的問題

2021-06-22 10:05:05 字數 4012 閱讀 2791

乙個起碼合格的系統,在設計之初就應該考慮到各個方面,不求完備,起碼也要深思熟慮。當然,你也可以在接到任務的下一刻,就敲起了鍵盤,然後在不斷地迭代開發中發現問題,解決問題。但是,一些問題,真的是在設計之初就可以預見的。這裡只是以自己的經歷,提出自己的拙見,並且不斷提醒自己,這個問題下一次一定要考慮到。

1.日誌

日誌的存在絕對不是某些人嘴中的所謂軟體工程的條條框框的面子工程,而是乙個系統中最重要的、不可或缺的部分。日誌的存在除了記錄系統執行時的一些資料,更多也起到一種證據和資料追溯的作用。當系統複雜到一定程度後,往往會出現一些莫名其妙的錯誤,但是又十分難於復現或在短時間內通過閱讀**找到原因,這個時候,日誌就起到了重要的作用。通過日誌,記錄下每一步關鍵操作,業務流程是在哪 裡中斷的,這對於快速排查問題是十分重要的。另外,在一些與外部互動的api中,日誌也記錄了request和response,這為定位原因提供 了依據,不至於在出現問題時相互扯皮。簡訊沒傳送成功,誰的錯?使用者還是程式設計師,或者介面提供商,或者某團體又在開會了?郵件沒收到,又是誰的錯?當然,記錄日誌並不是為了真的去找誰的麻煩,而是為了定位問題,解決問題。

記錄日誌時,一定要做好歸類,分門別類記錄不同型別的日誌,當然,記錄的載體隨意,可以是文字檔案,也可以說資料庫。次重要的日誌記文字檔案,重要的記資料庫。

一般我是這麼對要記錄在文字的日誌分類的:

/**

* 日誌型別

* @desc:

* @author [email protected]

* @date:2013-09-12

*/public enum logtype

public string gettype()

}

對於系統中的一些模組,我採用的是request-response模式來設計。在父類中記錄日誌,然後子類繼承父類,呼叫父類的方法提交引數並獲得響應。這樣,所有子模組的引數都會被記錄下來,而在子模組中,這個日誌記錄的過程就像不存在一樣。這種方式記錄的都是重要的日誌,和業務結合比較緊密。可以簡化為下面的**:

public class yreq 

public hashmapdata()

public void submit()}

-- private string mobile;

private int userid;

super();

}/**

* 構造request引數

*/public void param()

}

2.測試

測試已經是乙個爛了又爛的話題,單元測試、效能壓測都屬於測試的範圍。我覺得比較重要,也需要特意強調的就是單元測試,尤其是單元測試的意義和存在的價值。有這麼乙個場景,某客戶反映我們的系統還款手續費有問題,而我只是乙個新來的程式設計師,並且我們的客戶很多 。這個時候一般的做法是這樣的:

(1)在客戶**註冊乙個賬號路人甲;

(2)發布一筆借款,發布借款時才發現需要實名認證;

(3)提交實名認證;

(4)後台審批實名認證;

(5)繼續發布借款,發現還需要申請信用額度;

(6)申請信用額度;

(7)後台審批信用額度申請

(8)終於好了,現在可以發布借款了。

(9)後台審批借款;

(10)註冊賬號路人乙;

(11)前台充值金額;

(12)後台審批充值請求;

(13)路人乙借款給路人甲

(14)後台管理員審批這筆借款;

(15)路人甲還款給路人乙;

(16)路人乙檢視收到的還款;

乙個小時後,老闆揹著手踱過來,站我背後問道「小x呀,客戶提到的bug改好了沒呀?」,我只能一邊諾諾地回答「我還在測試借款那一步。。額。。貌似有點小問題無法借款」,看著老闆搖著腦袋遠去的背影,只能暗罵「催!催!催!腦殼有包啊,啷個有額個快,bug我都還沒復現呢」。

問題就出在當流程複雜後,限制條件越來越多,每步流程都有很多先決條件,並且都是繁瑣而耗時的手工操作。由於沒有單元測試,出現問題時,我必須一步一步來,即使我在之前已經建好了測試賬號,也只能省略有限的幾步,還是不得不按部就班,花費大量的時間去復現bug 。有了單元測試後呢?簡單多了,我只要按照模組像搭積木一樣的拼裝各個環節,最後來個斷言,直接告訴我過了還是沒過。過了,我就可以

閒下來看看小電影,沒通過測試?那也不怕,分解開來,一步一步來。

又比如,我開發了乙個新模組,這個模組需要生成十多個新使用者進行多輪測試,怎麼辦?沒有單元測試之前,只能傻乎乎地手工註冊,1個 ,2個,3個...,後來發現有點傻啊,預先準備了一堆sql語句,做點修改,放到資料庫裡執行一下,獲取到了id主鍵,然後又去資金表裡,以這個主鍵為userid,再插入一條資料。這個節奏貌似有點不對勁啊,傻不傻呀,有單元測試為啥不用?寫個迴圈不就好了。

3.資料指標與監控

伺服器的運**況如何?記憶體占用和cpu消耗如何?優化的效果如何?這些都需要資料來說話。話說有一天專案經理安排新來的程式設計師甲優化 一台伺服器,過了半個小時,甲興沖沖地地跑去對經理說「我優化好了!」,

經理問「你都改了啥?」

甲:「啪啪啪啪。。。」

經理:「效能提公升了多少?cpu占用降低了麼?相比之前的qps增加到多少了?」,

甲:「啊?啥?」,

經理:「那我們現在的使用者數是多少?」,

甲:「什麼??」

經理:「出去!」。

好了,不言而喻,沒有資料的優化都是耍流氓。資料是評判優化的標準,也是優化的方向。轉眼三天過去了,專案經理急匆匆地跑來問甲:"***的**突然打不開了,咋搞的!?",甲愣住了,趕緊回憶最近做了啥改動,想想最近也 沒乾啥啊,好在甲也是受過專業訓練的,一點也不慌張,立馬想到第二步,看日誌。開啟apache日誌一看,有個mysql的錯誤,說是什麼什 麼不能寫入資料。立馬明白了,磁碟空間滿了!都怪自己,平時不注意監控資料。磁碟用了多少也沒注意,日誌生成了一堆又一堆也不管,三個月前的備份都還在。又回到了第乙個問題,日誌寫入是否可控?是否可能寫滿磁碟?是否有定期清理機制?

4.重發機制

回到第乙個問題,簡訊傳送不出去咋辦?難道就放著嗎?顯然不行,有時候傳送不了可能是網路的問題,也有可能是資料的問題,而這些問題都是可以解決的。比如我遇到的問題,乙個簡訊傳送前需要登陸。但是由於這個介面被多個客戶使用,某個客戶b手賤,**中呼叫了之前遺留的退出操作。而新的流程中並不需要這個退出,而且退出了就不能發簡訊了。而我們又改不了b的**,a很鬱悶,b還不知道。怎麼 辦?很簡單,在a的**中send函式加入login函式,一旦a傳送失敗,根據返回碼判斷,如果是登入狀態不對,就給他重新登入,重發一次試試。

public function sendsms($arr) 

return $ret;

}

當然,這個重發也可以是一直重試直到成功,但是不要犯下和這裡類似的錯誤。

5.多和少的問題

系統是否設計過度?還是估計不足?按照500qps標準設計的**,在第三個月後,隨著業務的擴大,還能滿足需求不?效能優化和擴充套件容易不?是否留有快取介面?有的話,有沒有考慮快取節點故障的可能性?有沒有考慮到雪崩的可能性?還是快取只是個裝飾?問題的起因是這樣的,我曾經面對這樣的乙個**,他的設計是典型的mv架構,對,是mv,不是mvc。少了controll層。他的做法是直接在模板中使用list和module,並且帶入引數,從m層獲取資料,繞開了c層。這樣一來,系統變得極其簡單,一點不懂程式設計的人也能通過在v層裡大量用list和迴圈來顯示資料,根本不需要寫c層**,只需要懂html和簡單的模板語法。問題就在這,幾個月後,系統規模擴大了,伺服器已經扛不住了,我需要給這個系統加入快取,遇到問題了,由於沒有c層,我很難對快取進行細粒度控制,v層顯然不合適而且也麻煩,m 層也是類似問題,因為我無法保證和統一其它地方的v呼叫這個m也是這個快取機制。結果就是m層變得很凌亂,系統體驗變得很呆滯。

類似的問題還出現在很多地方,系統設計之初太短見,導致後期擴充套件困哪。好的系統設計,5年後還能輕鬆應對新需求,爛的設計,半年後就很吃力了。那設計過度呢?額,設計過度的系統,我還是願意設計過度一點也不短視。

乙個合格的系統,還有很多很多需要去考慮,這裡就先說這麼多吧。

營銷型後台系統開發應該考慮到的

今日需處理事務 待發貨訂單 未處理的提現申請 商品庫存報警 多日業務對比 成交訂單數 成功付款訂單總額 銷售利潤 之間的對比 平台資訊 會員總數,今日註冊 員會等級分配情況 商品總數量 已下架的商品 本月提現總額等 會員的基本資訊上 業務推薦人 可用提現資金 以下資金聯接乙個變動明細,如變動時間 變...

考慮到記憶體覆蓋的strcpy實現

已知strcpy函式的原型是 char strcpy char dst,const char src 實現strcpy函式 解釋為什麼要返回char 假如考慮dst和src記憶體重疊的情況,strcpy該怎麼實現 char strcpy char dst,const char src 1 1 con...

乙個金融系統考慮到的

1.為了安全起見,所有的寫操作都要計入audit表中 2.考慮效率 reconciliation settlement 引入影子表 這是乙個實表,非虛表 影子表是對多個業務相關表的資料冗餘。3.資料庫表設計時留了一些字段,並不表示任何業務意義,僅僅是為了以後擴充。雖醜陋但實用,能解決部分問題。4.表...