如何設計一款優秀的軟體架構

2021-01-16 CSDN技術社區

「風語者客服+」是針對中小型企業推出的客服SaaS,節約了企業自建客服系統所需的巨大成本。為了給企業提供穩定可靠且優質的服務,我們在整體架構上費盡心思。雖然不盡完美,希望藉此拋磚引玉,互相切磋。

前言

」Look deep into nature,and then you will understand everything better.「 -- Albert Einstein

我國傳統文化上,要做成一件事,講究三個方面:明道,優術,取勢。在軟體架構設計方面而言,也是類似的道理:遵循自然規律以明確大的方向,使用優秀的實操戰術,再根據實際情況落地。

這是個快餐年代,幾乎所有人都只做一件事 -「取勢」。幾乎沒有多少人會去理解一個Servlet的工作原理,去理解一次HTTP請求的完整流程,因為有超多框架幫你屏蔽了這裡的細節。詢問一個人會什麼技術,回答也往往是我會Hibernate、Spring、Ibatis、會PullToRefresh組件、會使用SDWebimage。不過這些框架(Framework)其實並不是軟體架構。軟體架構是一所有生命力的房子,而這些框架只是大一點的板磚。

因為筆者水平有限,這裡只提一些普遍準則,也就是」正確的廢話「,以饗視聽。不會深入到實操戰術上,比如怎麼用Spring實施MVC架構,怎麼使用Maven管理依賴,Redis的常用操作,怎麼搭建一個負載均衡的集群,如何使用阿里巴巴的Dubbo框架進行服務化等等。如果大家有興趣,可以自行搜索,有很多優秀的文章可供參考。

不幸的「程序猿」和「程序媛」各有各的痛苦,幸福的程式設計師都是相似的。其實說幸福有點言過其實,下面就說說怎麼讓他們不那麼痛苦。

一. 很好的模塊化支持

「At the bottom of every person's dependency, thereis always pain, Discovering the pain and healing it is an essential step inending dependency.」 --Chris Prentiss

他們都在一個相對穩定的軟體架構裡編碼,自己的代碼不會依賴很多模塊,不會因為自己微小的改動造成全局的失敗。正如"1984"中的老大哥說的,Ignorance isstrength(」對外界的「無知就是一種力量).  任何一個模塊都不能有太強的存在感。

曾經在一個大型網際網路公司裡面,任何人只要用到一個核心模塊的功能,就必須依賴一個部署在某遠程伺服器的庫,而且還有IP限制,只能把代碼部署到指定網段才能運行起來。導致基本上沒法在本地進行單元測試或者簡單調試。這個核心庫的存在感太強,就成了開發的瓶頸,嚴重的降低了生產力和碼農的幸福程度。

在「風語者客服+」的架構中,每個碼農都可以很方便的在本地把服務啟動起來,一分鐘up and running,隨便做一些改動就可以立竿見影的看到效果。這裡要歸功於幾個東西:

1. Git代碼管理

在團隊作戰中,每個程式設計師可以取下來完整的最新代碼庫,也可以在本地分支上盡情揮毫潑墨,而不擔心影響別人的工作。也可以把本地修改先stash起來,review一下別人的代碼,再unstash恢復回來。要想提高團隊效率,代碼倉庫管理建議儘快遷移到Git上。

2. Maven、Gradle、Cocopods等依賴管理

Maven是一個管理依賴(Dependency)的工具,現在在Java社區應該是比較普及的,無法想像現在還有團隊直接拷貝jar包來管理依賴。雖然早期沒有Maven的時候,都是拷貝jar包這麼過來的,碰到的問題也是顯而易見的,依賴的jar包作者改了某個bug,沒能及時傳導到調用方。多個調用方使用不一致的jar包,導致各種奇異bug。對應的在安卓社區,使用gradle的比較多,iOS的Objective-C開發中,多採用CocoaPods。

二. 高內聚,低耦合

He should focus on his knitting, nottrying to do everything. Do one thing well.-- Steve Jobs

"Do one thing well"其實不算是老喬的專利,UNIX哲學和Google哲學都提倡這一點。這句話本身不完全對,比如對於一個商人,如果只會Do onething well,那他無法在市場中存活,但是在工程師中卻是萬般推崇的哲學。

我們可以期望一個人具備一百種技能,然而對一個工具只期望它把一個需求解決好解決徹底,對於實現工具的一個類,一個方法,更是如此。但是,實際經驗中,我們經常看到一個5000行以上代碼的類,活像一個巨人版的瑞士軍刀,什麼都能做,但是什麼都做不好。這就是」Separation of Duty"沒有做好的典範。

在風語者」客服+「對外提供的SDK和API中,我們也提倡同樣的思想,力爭把App使用」客服+「SDK的門檻降到最低,每個API都能自言其一,而且API直接沒有時序上的依賴關係。內部各個模塊的開發,也秉承同樣的責任分割原則。責任分割原則的落實,沒有什麼好的框架或者工具來支持。只能通過老鳥經常去做Code Review,找出存在的問題,提出重構方案,並督促菜鳥改進。

個人一般採用的重構思路,僅作為參考,照搬後被老闆批評乃至造成工傷概不負責:

把一個大的工具類,根據主題不同,拆分成若干個互不幹擾的高內聚工具類;舉個例子,一個萬能的NetworkUtils可能可以拆成HttpUtils, FTPUtils,TelnetUtils等;對於一個被頻繁調用的類,仔細觀察調用情況,如果有一些方法的被調用頻率遠遠低於其他方法,那麼需要考慮這個方法是不是應該放在這個類中;存在A,B兩個類之間的相互依賴,或者更多類的混亂依賴,那麼就更要抽絲剝繭,通過合理安排類的功能來去除環形依賴;嘗試一句話說清楚一個類的功能,不要使用「和」,「以及」,「或者」等連接詞;如果出現了這些連接詞,就需要引起重視;

三. 用進化擁抱變化

「It is not the strongest or the most intelligentwho will survive but those who can best manage change.」 ― Leon C. Megginson

前段時間,朋友圈瘋傳一篇文章 -——「架構腐化之謎」,大家都深表同感,紛紛表示對自己架構的未來的擔憂。然而,說句不合時宜的話, 90%的擔憂是杞人憂天,因為以現在產品更新換代的速度,90%的項目面市即意味著死亡,沒等到架構腐朽,產品已經入土了。

剩下10%裡面,也許有9%會一直堅持活下去,但是不會蓬勃發展,也就是說,只要保證不出現內存洩露之類的問題,代碼就會一直在幾臺小伺服器上運行下去,哪怕後面沒有人維護也沒關係。只有1%的產品,會日新月異的更新迭代,最終成長為巨無霸,或者巨無霸的生態下的一個環節。這個言論看似悲觀,卻是對現實最好的妥協。

謬用一下泰戈爾的名言:「不是槌的打擊,而是水的載歌載舞,使鵝卵石臻於完美」, 不是閉門造車的架構,而是不斷擁抱變化的需求,才使得架構臻於完美。

假如在早期就糾結於架構的完美性,而延遲產品的交付,是非常得不償失的。只有生存下來,才有機會。再根據市場變化,不斷優化架構,從而延長軟體的生命周期。那麼,假如撞大運,真的成了這1%,怎樣做才能算是擁抱變化?

首先,請參考本文第一點和第二點。如果這兩點基本功沒有練好,那麼談架構的進化就和還沒有通關十八羅漢的新手就想練成九陰真經是一個道理。

在設計之初,初步考慮系統的Scalability(可伸縮性)

下面在第四點會詳細闡述。

內部的各個模塊儘量做到可插拔

一方面是接口和實現的分離,可以隨著需求的變化更換實現;另一方面,儘量把功能服務化,成為微服務,並且可以監控到服務的互相調用情況,當某個服務老化,可以逐步廢棄或使用新的服務取代之。這一點上,阿里巴巴的Dubbo框架是一個不錯的選擇。

儘量採用優秀的框架,站在巨人的肩膀上

例如在Web層面,我們使用Twitter的Bootstrap前端框架來實現響應式Web編程,提高生產效率的同時減少了為解決各種設備適配問題的投入。當然,這就需要設計師配合,按照Bootstrap規範來設計頁面,減少一些個性化設計。

最後,考慮系統的Resilience(彈性,也叫耐受性)

俗一點說,就是變成一隻打不死的小強,代碼中儘量提前預判可能遇到的各種情形。經常看到代碼裡面有一堆的if(){}判斷語句,我就問作者,「你考慮過else{}嗎?」一般回答都是,「這絕對只有if,不會有else的」,可如果真的遇到else怎麼辦?千年蟲問題就是這麼誕生的。可能很多新同學還不知道什麼是千年蟲問題,簡單地說,就是當年的碼農,為了省一點內存空間,只用了2位數來表達年份,比如int year = 98; 表達1998年。我猜碼農當時的心態也是,「就我這代碼,還能活到2000年,搞笑吧?」

程式設計師們平時可以多擴大自己的腦洞,想想有哪些else情況自己沒有處理,而且可以輕易處理的。比如伺服器掛了,那麼App端是不是也要跟著crash,還是給出友好一點的提示,或者更友好一點,使用本地緩存。

四. 設計可擴展,但不要過度設計

it's better to have infinite scalability and not need it, than to needinfinite scalability and not have it--@littleidea 網友

無限的擴展能力是一種奢望,但是起碼不能讓擴展能力成為0。試想一下,你辛辛苦苦為老闆開發了一個網站,過了一個月,網站超負荷了,老闆說,「小A啊,之前2臺伺服器花了我5萬塊,預計流量馬上要翻倍了,再給你5萬塊,幫我扛過去啊。」結果你發現,問題不是線性增加伺服器就能解決的,原來的程序沒有做分層(Web,Business Logic, Data Access等),導致加伺服器也只能把所有層的代碼全搬到新的伺服器,雖然只是Business Logic的計算有壓力,卻要浪費老闆很多伺服器。更糟糕的是,因為程序裡面用到了文件系統和作業系統命令,不好做負載均衡。

這裡有一些準則供參考:

代碼分層是必須的,層次明朗以後,當哪個層次的負載較重,想辦法對該層次進行優化或者擴容即可;保持核心服務是無狀態的,所謂無狀態就是沒有和請求相關的數據依賴;儘可能的選用已被驗證的廣泛採用的成熟基礎架構;充分利用Zookeeper等集群管理工具,來對服務進行管理;

風語者「客服+」中,把業務相關的代碼內部組裝為風語者ServiceBox,使用阿里巴巴的Dubbo服務進行註冊管理。當負載增加時,可以迅速在運維層面增加服務節點,以提供更高的服務能力,從而保證客戶的優質體驗。


作者簡介:

黃耀華

具有11年的計算機軟體研發及大型網際網路產品研發經驗,曾在IBM,百度,人人網等業內頂級企業任職,特別對企業級軟體,大規模數據處理,搜尋引擎,移動App開發等領域的原理和實現有著全面且深入的認識。(編輯/魏偉)

更多SaaS技術文章,請掃描下方二維碼關注我們


相關焦點

  • 15 年架構設計經驗:我眼中的那些優秀架構師
    後來,在和他進一步溝通的過程中,我發出了這樣的感慨:一個工程師,如果不能從架構師的角度思考問題,帶領團隊,整體完成一個系統的架構設計與開發,就永遠也不會了解如何做一個架構師。而如果他不去做一個架構師,又永遠沒有機會帶領一個團隊,完成一個系統的架構設計與開發。 這裡似乎形成一個死循環。能否解開呢?
  • SWE.2軟體架構設計
    ,識別哪些軟體需求應該分配給軟體的哪些要素,並根據已定義的標準評估軟體架構設計。 過程結果:為了成功地執行了這一過程: 1)定義了識別軟體要素的軟體架構設計; 2)軟體需求被分配到軟體的組成部分; 3)定義了各軟體要素的接口; 4)定義了軟體要素的動態行為和資源消耗目標; 5)在軟體需求和軟體架構設計之間建立一致性和雙向可追溯性
  • SWE.2的軟體架構設計
    SWE.2的軟體架構設計 汽車電子硬體設計 發表於 2021-01-11 10:36:40 過程ID:SWE.2 過程名稱:軟體架構設計 過程目的:軟體架構設計過程目的是建立一個架構設計
  • 軟體項目實訓及課程設計指導——如何實現面向對象的系統架構設計
    軟體項目實訓及課程設計指導——如何實現面向對象的系統架構設計1、什麼是面向對象的軟體應用系統的架構設計從軟體應用系統的架構設計師的角度來看,所謂的軟體應用系統的系統架構就是一套構建軟體應用系統的整體結構的各種設計準則
  • 軟體項目實訓及課程設計指導——如何實現面向服務的系統架構設計
    軟體項目實訓及課程設計指導——如何實現面向服務的系統架構設計1、什麼是基於SOA的軟體系統架構(1)什麼是面向服務的軟體系統體系架構所謂的SOA(Service-Oriented Architecture,面向服務的軟體系統體系架構
  • 軟體項目實訓及課程設計指導——系統設計中的系統架構設計示例
    軟體項目實訓及課程設計指導——軟體系統設計中的系統架構設計示例1、軟體系統概要設計中所涉及的主要設計內容和工作過程(1)在軟體應用系統項目的系統概要設計工作中,首先是要完成軟體系統的總體架構設計及系統的分層設計,然後再利用UML包視圖體現出軟體系統架構設計的最終結果
  • 軟體項目實訓及課程設計指導——軟體系統設計中的系統架構設計示例
    軟體項目實訓及課程設計指導——軟體系統設計中的系統架構設計示例 1、軟體系統概要設計中所涉及的主要設計內容和工作過程 (1)在軟體應用系統項目的系統概要設計工作中,首先是要完成軟體系統的總體架構設計及系統的分層設計,然後再利用
  • 如何保證軟體應用系統架構設計結果的可擴展性和可重用性(上篇)
    軟體項目實訓及課程設計指導——如何保證軟體應用系統架構設計結果的可擴展性和可重用性(上篇)1、良好的可重用性軟體系統架構設計結果的主要體現可重用性的軟體應用系統的系統架構設計結果主要體現在如下兩個方面——本項目的系統架構設計的結果是可重用的和在本項目的系統架構設計中重用成熟的系統架構設計方案
  • 2020年的13個優秀企業架構工具
    人們需要了解有關這些優秀企業架構(EA)工具的更多信息,以及它們是否為組織提供了合適的解決方案。13個優秀企業架構工具1.組織可以看到每個應用程式的每個組件如何與組織中的其他資產進行交互以創建規則,發出警報並啟用對這些資產的治理。其功能包括報告和分析、部署管理、代碼重構、應用程式組合管理、架構治理和轉換路線圖。5.
  • 架構設計:企業總體架構要如何做?小白也能快速領悟的設計思想
    企業總體架構是什麼,有什麼用,怎麼做,如何落地,這些東西聽起來非常抽象,做起來也是非常抽象。軟體工程從開始到結束一般會經歷需求、分析、編碼、測試、部署、維護6個階段,每個階段都會固定的輸出物,例如剛開始的產品需求文檔(PRD),後面的架構設計文檔等。
  • 如何畫架構圖?
    一、架構圖的定義及作用 什麼是架構圖?不過我們可以進行拆分理解: 架構圖=架構+圖 這樣問題就轉化成,什麼是架構,以及什麼是圖? 關於架構,百度百科上是這樣定義的: 架構,又名軟體架構,是有關軟體整體結構與組件的抽象描述,於指導型軟體系統各個方面的設計。
  • 如何在系統架構設計中應用面向切面的設計思想分離橫切關注點
    軟體項目實訓及課程設計指導——如何在系統架構設計中應用面向切面的設計思想分離橫切關注點1、什麼是面向切面編程AOP(Aspect Oriented Programming)技術軟體應用系統中的「橫切問題」( 切面問題)主要是指如何實現對軟體應用系統中的如下典型問題的技術實現:事務、安全、日誌、並發鎖等橫切關注。因為,當軟體應用系統變得越來越複雜,其中的這些橫切關注點等方面的技術問題如何有效地得以解決,並成為一個比較棘手的問題時,面向切面編程AOP的相關技術就可以很輕鬆地解決軟體應用系統中橫切關注點這些棘手問題。
  • 【科普】 Alias:一款優秀的造型軟體
    在製作賽車外型的時候我們需要一款設計造型的軟體。相信犀牛憑藉著其擁有中文界面和較為容易上手獲得大家的青睞。但是,犀牛並非是最強大的,它有它自身難以彌補的缺陷。所以,在造型設計領域有一款軟體因為其極強的自由度和先進性受到眾多設計師的追捧。這款讓許許多多的設計師為之瘋狂,讓學生為之落淚。
  • 構建優秀產品信息架構的三要素
    當一個網站需要幫助其用戶更好地從大量數據中獲取信息時,就需要考慮信息架構了。越是以信息查詢、獲取、消費、生產等為核心業務的網站,信息架構越顯得重要。所以,現今大部分的內容型網站、社區、電子商務網站,等等,都需要考慮到信息架構的問題。「情境、內容與用戶」這3個簡單的詞語,不僅完美地濃縮了Web信息架構設計的理念精華,也道出了從事網際網路產品設計時需要關注的三大點。
  • 如何升級架構設計思維
    打開APP 如何升級架構設計思維 Linux愛好者 發表於 2021-01-11 10:39:44 孫玄,江湖人稱「玄姐」,前58
  • 五大常用軟體架構分析方案
    一、分層架構 分層架構(layered architecture)是最常見的軟體架構,也是事實上的標準架構。如果你不知道要用什麼架構,那就用它。
  • 平面設計一定要會的幾款軟體
    隨著人們生活水平的提高,平面設計在我們的日常生活中顯得越來越重要,無論是淘寶店鋪裝修,還是企業產品包裝、形象宣傳,甚至是我們日常穿的衣服、住的房子都離不開平面設計的參與,近幾年來平面設計從業人員在逐年遞增,各大學校平面設計專業尤為火爆,作為一名平面設計工作從業者,下面金老師就來為你介紹一下平面設計一定要會的幾款軟體。
  • 如何基於用戶洞察,設計2B產品的業務架構?
    、產品架構與業務架構」解析, 我們大概釐清了產品在進入正式研發階段的三個關鍵設計成果:業務架構、產品架構和信息架構。3、基於對社會關係的影響嚴格來說,用戶的行為受社會關係的「支配」,而不僅僅是「影響」,我們接受一款產品,替換一款產品,是因為「關係」帶來我們的吸引和約束,比如微信之所以難以被取代,一個因素之一就是社會關係的捆綁。
  • EEA2019: 解密下一代新能源汽車電子電氣架構設計
    基於公共信息和基準數據,車輛EEA會以某些模式演變並遵循一些共同趨勢;為具備安全性,可修改性,可測性的架構設計BMS軟體架構直接影響質量,成本,開發進度,這是滿足功能要求和質量屬性的必要條件。但是,處理質量屬性會使架構產生差異。如何使車輛EE系統更加靈活和可升級,是新能源汽車行業的熱門話題。
  • 阿里P8聯合多位業界大佬整合的架構寶典,真正的漲薪秘籍
    第2篇:面向架構的架構(微服務)第二部分將介紹微服務的各個細節,包括架構設計的技術選型、架構模式與實踐、數據一致性保證、微服務與DevOps 的關係,以及如何設計雲微服務架構。通過這一部分的學習,大家將了解微服務建設涉及的方方面面內容。