淺談業務系統設計哲學

{"type":"doc","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"作者:易振強"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#25b7c4","name":"user"}}],"text":"1.  背景"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"size","attrs":{"size":10}}],"text":"設計和開發業務系統是一個很“神奇”的工作,我已經在軟件行業工作多年,遇見過各種類型的業務研發工程師,幹我們這行的人都知道,軟件開發入門門檻沒像外行人所認爲的那樣高,當然,這個行業也絕對不乏“高手”。再回到之前說的,爲啥我會認爲設計和開發業務系統是一個很“神奇”的工作?因爲“開發工程師”這職位應該是軟件行業人數最多的羣體,我們如今在PC或者手機上用到的各式各樣的軟件都離不開他們,在這一職位上,我們能結識各式各樣的人,所謂歷經人生百態。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"size","attrs":{"size":10}}],"text":"可能有很大一部分工程師認爲開發業務系統很簡單,所以對這一日常工作內容不那麼感冒,他們常常用自己“六七分”實力來做設計、寫代碼,所以也容易導致工作七八年,寫過“一麻袋”的業務系統,但自身能力提升較慢,最後自我埋汰到:“寫了這麼多年業務系統代碼,都把自己都寫廢了”。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"size","attrs":{"size":10}}],"text":"我們當然不希望自己是這樣的結局。"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#25b7c4","name":"user"}}],"text":"2.  業務系統的設計哲學"}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"2.1 可維護性是根本"}]},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"size","attrs":{"size":10}}],"text":"系統也需要人來“保養”"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"size","attrs":{"size":10}}],"text":"代碼可讀性很關鍵"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"size","attrs":{"size":10}}],"text":"打造可擴展系統"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"size","attrs":{"size":10}}],"text":"把這個放第一條,有些人會感到意外,如何理解這裏的“可維護性”?簡單來說就是我們的業務系統——"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"size","attrs":{"size":10}}],"text":"1.能否在當前組織模式下滿足業務的發展而進行快速迭代;"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"size","attrs":{"size":10}}],"text":"2.能否爲了承接增長的流量而橫向快速擴容;"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"size","attrs":{"size":10}}],"text":"3.能否支持團隊內多人協作維護;"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"size","attrs":{"size":10}}],"text":"4.能否支持快速對線上問題進行定位和止損;"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"size","attrs":{"size":10}}],"text":"5.運維成本能否可控。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"size","attrs":{"size":10}}],"text":"可維護性和系統的架構設計和編碼實現高度相關,這裏很有必要說下設計的實現部分——編碼,編碼是開發階段很重要的一環,其實很多一線研發工程師的能力,在寫代碼時就能“高下立判”。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"size","attrs":{"size":10}}],"text":"那麼業務系統編碼階段最重要的是什麼?這個問題很多人會有不同的答案,但我這邊的答案只有一個:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"size","attrs":{"size":10}}],"text":"即——在正確實現功能的前提下讓代碼具備較高的可讀性。我在進行CR時,會非常看重這一點。代碼可讀性並不等同於你的代碼一定要寫的很短或很精煉(但是短代碼或格式規整的代碼確實能降低閱讀者負擔,讓閱讀者賞心悅目),而是說一定得說明這段代碼爲什麼這麼做(加註釋也好,代碼能自說明也好),特別是某些“特殊邏輯”!"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"size","attrs":{"size":10}}],"text":"之所以在這裏特別強調這一點,是因爲業務系統總在隨着業務不斷在迭代,“鐵打的代碼流水的猿”,只要業務活得夠久,你永遠不知道下一個維護這套系統的人是誰、是哪個團隊,而系統的可維護性、可擴展性、穩定性、重構等,強依賴的是後續繼承者能看懂你寫的代碼,千萬不能造成:我很懂業務,但我看不懂你代碼爲什麼這樣寫,尷尬的是我又不敢改。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"size","attrs":{"size":10}}],"text":"特別怕一些“天賦異稟”的開發者,用“很巧妙”的思路將業務系統實現的只有他自己能懂,而其他人“望而生畏”,導致後續遭人詬病,所以我們需要記住,只有學習成本低,系統才能談可維護性。"}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"2.2 穩定性是底線"}]},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"size","attrs":{"size":10}}],"text":"充分拆解背後的非功能性訴求"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"size","attrs":{"size":10}}],"text":"核心資源和非核心資源需要隔離"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"size","attrs":{"size":10}}],"text":"儘可能做到自動降級"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"size","attrs":{"size":10}}],"text":"實現異常出口"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"size","attrs":{"size":10}}],"text":"任何業務系統不能只滿足基本的業務功能需求,很多非功能性需求產品和業務方同學不一定會直接展現在PRD上,需要我們研發工程師或架構師來“拿捏”,常見的非功能性需求比如系統穩定性、吞吐量、性能、響應時間、時效性、數據安全性、數據一致性等。這其中,系統穩定性是最常見的非功能性需求,也是很多大型互聯網公司業務方能直接感知到產研的一面,一旦系統故障被用戶投訴,業務方第一直覺就是技術那邊出了問題。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"size","attrs":{"size":10}}],"text":"系統穩定性建設的抓手很多(參見:穩定性全系列文章),一線研發同學在設計和實現時,一定得有自己的原則和意識,比如核心接口和非核心接口的資源隔離(例如線程池、部署隔離等);弱依賴做到真正的弱依賴,出問題不能影響核心鏈路(設置合理的超時時間,能做到自動降級或熔斷最好);關鍵資源一定得受保護(比如藉助SDS、Sentinel、Hystrix等)和監控;異常情況得可看、可感知(配置合適並且有效的告警策略和大盤)。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"size","attrs":{"size":10}}],"text":"系統穩定性猶如工程師的底子,不能隨便拿出來到處說,但需要花精力花功夫不斷去維護和鞏固,一旦沒做好,鬼知道別人背後咋說你。"}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"2.3 多參考業界的成功模式"}]},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"size","attrs":{"size":10}}],"text":"GoF的23種設計模式"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"size","attrs":{"size":10}}],"text":"面向對象的X大設計原則"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"size","attrs":{"size":10}}],"text":"學習業界的成功或失敗案例"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"size","attrs":{"size":10}}],"text":"合理利用設計模式,遵循面向對象的設計原則,有了這些大家熟知的模式,會降低整個業務系統的學習成本,無形中也優化了系統的內部結構,提升了系統的可擴展性。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"size","attrs":{"size":10}}],"text":"研發工程師或架構師得有自己的獨立思考能力和創造力,但創新這東西我們不能強求,很多成功的設計或方案,都是在前人的成功或失敗經驗加上自己的一些因地制宜的“變化”而“長”出來的,我們在做業務系統架構設計時應該多看看行業標杆如何做,他們這樣做的效果是什麼?目前他們遇到的問題是什麼?他們的方案有哪部分是不適合我們的?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"size","attrs":{"size":10}}],"text":"有了這些,哪怕是“管中窺豹”,根據以往經驗,我們也能看出個所以然來。"}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"2.4 選擇恰當的設計方案"}]},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"size","attrs":{"size":10}}],"text":"中間件的設計方式不一定適合業務系統"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"size","attrs":{"size":10}}],"text":"方案選型要考慮團隊的技能水位"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"size","attrs":{"size":10}}],"text":"方案要符合項目當前的發展階段"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"size","attrs":{"size":10}}],"text":"重點評估方案的維護成本"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"size","attrs":{"size":10}}],"text":"從多套方案中選擇最合適的方案"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"size","attrs":{"size":10}}],"text":"一個系統的架構是客觀存在的,在業務系統進行架構設計時,一定要結合業務形態、非功能性訴求、當前組織架構、團隊技能水位、現有基礎設施、運維資源等。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"業務形態"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"size","attrs":{"size":10}}],"text":"要考慮如下問題:服務的可靠性和準確性是否會影響用戶的生命財產安全?服務的用戶人羣是什麼?服務是否有早晚高峯期?服務是否要存儲大量數據?服務流量如何?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"非功能性訴求"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"size","attrs":{"size":10}}],"text":"即非功能性需求,架構設計時一定要充分挖掘隱藏在業務背後的一些需求,比如給心跳起搏機開發軟件系統,其他的可以不提,但一定要絕對的安全和可靠。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"當前組織結構"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"size","attrs":{"size":10}}],"text":"我們當然應該避免多個團隊去維護一個系統,所以系統拆分力度一定要和組織結構相當或細於組織,這本質上和\"康威定律\"也有些關係。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"團隊技能水位"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"size","attrs":{"size":10}}],"text":"這是一個很殘酷的現實,團隊應該去維護和發展符合自己能力的系統,如果某個框架或某項技術是該系統架構設計的關鍵,而這個框架或技術是團隊短時間內無法有效承載的,那這就不是合適的架構設計。我們不能把屠龍刀才能砍的架構設計,去丟給手裏只有菜刀的程序猿來實現。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"現有基礎設施"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"size","attrs":{"size":10}}],"text":"底層設施決定上層建築,我們需要有效的利用周邊的基礎設施,如果沒有MQ的使用經驗,但我們的架構設計卻強依賴MQ,除非你希望借這個業務系統的實現來“培養”一些MQ專家出來,那麼我們架構設計時最好將MQ換成另一個“現成”技術套件。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"運維資源"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"size","attrs":{"size":10}}],"text":"這也是一個殘酷的現實,我們很多架構設計需要考慮運維團隊,甚至很多架構師在設計系統時,會主動去和運維同學溝通,參考他們的建議,這樣做沒錯,有好的運維團隊支持,你的系統成功了一半。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"size","attrs":{"size":10}}],"text":"業務系統和中間件系統的設計和實現思路有差別,中間件系統可以“無止境”的去打磨系統的性能和擴展性,很多技術大牛在給中間件添磚加瓦時怎麼巧妙怎麼來,所以有時候中間件代碼的可讀性並不高(當然,不排除某些中間件產品在這方面做的很好),往往中間件系統關注的點和業務系統的關注點大相徑庭,儘量不要以中間件的思路去寫業務系統,否則容易走極端。業務系統的設計和開發一定得帶着理解業務的思路去做。避免過度設計或過於前瞻性設計(如果真有必要,這些可以放到二期、三期去做),不然會給系統實現增加負擔,得不償失。如果拿捏不準,可以先給出多套設計方案,然後再仔細分析,權衡利弊來做選擇。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"size","attrs":{"size":10}}],"text":"這裏有個遺留問題,就是怎樣的系統架構設計纔是合格的設計?我認爲,只有能抓住現階段業務成敗關鍵點的設計纔是合格的架構設計方案(就好比只有準確抓住社會主義初級階段社會的主要矛盾,纔對黨和國家工作重點的轉移、推動社會生產力的發展和社會全面進步,具有重大的理論意義和實踐意義)。所以,這也從側面驗證了,架構設計可以“扣”細節,只要這些細節會影響系統建設的成敗,那麼架構設計就應該包含它。"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#25b7c4","name":"user"}}],"text":"3.  總結"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"size","attrs":{"size":10}}],"text":"好的設計方案一定要被大多數人所接受和理解的,那些只有少數一兩個人能看懂的方案,要不另闢蹊徑(風險高),要不其實是過度設計(性價比低),當然,我們說的是一般情況,在某些業務領域,確實是存在一些“最佳方案”。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#25b7c4","name":"user"}}],"text":"更多精彩文章,請掃碼或長按下方二維碼閱讀原文"}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/6d/6d9b7c5733e93d94193655ec96b98d39.png","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":"center","origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章