「軟件分析」與「軟件設(shè)計(jì)」這樣的詞眼經(jīng)常聽到,然而要真正理解「軟件分析」和「軟件設(shè)計(jì)」的本質(zhì)是比較難的,本文帶你了解軟件分析與設(shè)計(jì)的「邏輯性」到底是什么。
一、系統(tǒng)分析與設(shè)計(jì)的邏輯性框架
在日常的工作中,「軟件分析」與「軟件設(shè)計(jì)」這樣的詞眼經(jīng)常聽到,然而要真正理解「軟件分析」和「軟件設(shè)計(jì)」的本質(zhì)是比較難的,它依賴極強(qiáng)的工作經(jīng)驗(yàn),又加上軟件分析與設(shè)計(jì)沒有標(biāo)準(zhǔn)的程式化步驟,導(dǎo)致不同的人有自己不同的方法,也就造成了很多人認(rèn)為軟件分析與設(shè)計(jì)是非?!缚斩础梗€不如寫具體的代碼實(shí)在,而大部分的人寫的是業(yè)務(wù)型代碼,被嘲弄寫CRUD的代碼沒成就感。 軟件分析與設(shè)計(jì)如其它行業(yè)一樣,具有很強(qiáng)的邏輯性,沒有邏輯性支撐,很難做好事。比如寫作,有「謀篇布局」、「起承轉(zhuǎn)合」、「遣詞造句」等這些「原則」和「方法」,沒有洞悉到這些底層邏輯,一個(gè)高手寫的文章和一個(gè)普通人寫的文章,效果是天差地別。因此,首先要講清楚的是軟件分析與設(shè)計(jì)的「邏輯性」到底是什么,下圖是軟件分析與設(shè)計(jì)的邏輯全景圖。
?
1.1 方法
1.1.1 分析階段
軟件分析與設(shè)計(jì)并沒有那么神秘,本質(zhì)來講還是為了解決現(xiàn)實(shí)的問題,和「醫(yī)生看病」、「工人修車」、「廚師做菜」一樣的,都需要方法作為指導(dǎo),否則沒有任何頭緒,只能抓瞎。方法是具有普適性,只是不同的行業(yè)有各自的特性,具體落地上有差異。?
既然是要解決問題,那么總得知道問題是什么吧,就好比醫(yī)生看病,做各種檢查、化驗(yàn),都是為了全面地了解疾病,所以第一步是需要定義好問題,然而當(dāng)下很多人都忽略了這一步,直接上來想我要用哪種中間件、哪個(gè)框架,連問題都沒有定義好,直接想實(shí)現(xiàn)無疑是本末倒置。
問題是理想與實(shí)現(xiàn)差距的矛盾,現(xiàn)實(shí)是不滿足理想的訴求,因此,首先需要了解用戶的訴求是什么,想解決怎樣的問題,這也即為是需求。需求分析最大的挑戰(zhàn)是什么是真正想要的,就好比一個(gè)病人說了一大堆的癥狀,他所說的癥狀表現(xiàn)與書本上的描述有時(shí)是有出入的,定義出真正的需求至關(guān)重要,接下來就要思考通過怎樣的方法去梳理清楚用戶需求。?
用例是表達(dá)用戶使用系統(tǒng)實(shí)現(xiàn)某些目標(biāo)文本化的情節(jié)描述,它強(qiáng)調(diào)的是用戶目標(biāo)、觀點(diǎn)。我們應(yīng)該從用戶目標(biāo)的角度出發(fā)思考,也有的人稱之為利益相關(guān)者的關(guān)注點(diǎn),道理很簡(jiǎn)單,我們做出來的軟件是為了服務(wù)于用戶的,不是用戶想要的,就算用了多高科技的的技術(shù)也是失敗的。
用例只是一個(gè)概括的描述,因此還需要細(xì)化,一個(gè)用例包括一個(gè)或多個(gè)場(chǎng)景,場(chǎng)景是參與者與系統(tǒng)之間的活動(dòng)和交互,比如用戶下單,有下單成功,有下單失敗兩個(gè)場(chǎng)景。因此到這里還只是分析階段,分析的目的是了解現(xiàn)狀和目標(biāo),以及系統(tǒng)要素組成,它不關(guān)心如何實(shí)現(xiàn)做、如何實(shí)現(xiàn)。分析不僅限于軟件行業(yè),其它的行業(yè)也是如此,只是在分析過程的程式化步驟、方法不一樣而已。
1.1.2 設(shè)計(jì)階段
當(dāng)我們清楚地知道要做什么之后,接下來要思考如何去實(shí)現(xiàn),實(shí)現(xiàn)的途徑有很多種,如同一百個(gè)廚師做同樣的菜,做出來的效果不一樣。設(shè)計(jì)階段有兩點(diǎn)需要考慮的:一是如何將功能細(xì)化實(shí)現(xiàn);另一點(diǎn)是如何更好地實(shí)現(xiàn)。第一點(diǎn)不管用什么方法都可以實(shí)現(xiàn),難的是第二點(diǎn),更好地實(shí)現(xiàn)是需要遵循一些章法,也需要評(píng)判體系,要不然你怎么知道好與不好呢,常見的定量評(píng)判指標(biāo)有:成本、性能、可靠性、效率等,還有一類是定性的評(píng)判指標(biāo)有:開放性、體驗(yàn)性等。?
度量的指標(biāo)相對(duì)容易,就像醫(yī)生看病,看療效、看成本,軟件設(shè)計(jì)也是一樣,歸根到底是「多快好省」。然而軟件設(shè)計(jì)的章法就復(fù)雜得多,它具有很強(qiáng)的藝術(shù)性,正所謂「文無第一,武無第二」,比武一定可以比出個(gè)高下,誰打贏了就是勝利一方,然而比文就難了,不能說你寫的就一定比我寫的好,只是不同人的喜好不一樣而已,當(dāng)然這里指的旗鼓相當(dāng)?shù)貙?duì)比,不同層次的對(duì)比一眼還是能看得出來的。
在設(shè)計(jì)階段最為關(guān)鍵的是定義出「關(guān)鍵的技術(shù)問題」,一般分類兩類:一是站在用戶視角的設(shè)計(jì),它重點(diǎn)考量的是「便捷性」和「易理解」;另一個(gè)是站在系統(tǒng)層面,重點(diǎn)考量的是「復(fù)用性」、「擴(kuò)展性」和「穩(wěn)定性」。貼近用戶的設(shè)計(jì),讓用戶用最少的理解就能使用它,用戶無須感知底層復(fù)雜的設(shè)計(jì),核心是回答用戶最樸素的原始訴求。系統(tǒng)層面的設(shè)計(jì)要靈活,多用組合正交設(shè)計(jì)提升系統(tǒng)的復(fù)用性和擴(kuò)展性,在具體方案設(shè)計(jì)中要考慮到穩(wěn)定性因素,比如寫日志會(huì)帶來性能問題,這個(gè)在方案設(shè)計(jì)中就要考慮到。洞察到關(guān)鍵技術(shù)問題,并非一朝一夕就能練就成,需要在工作中大量地實(shí)踐,總結(jié)經(jīng)驗(yàn),保持技術(shù)的敏感度才行,在第二節(jié)中通過實(shí)際的案例方便大家加深理解。
1.2 工具
有了方法,接下來要有工具來幫我們更好地做事,與方法對(duì)應(yīng)的,我們軟件設(shè)計(jì)的工具是UML,接下來介紹UML中常用的圖。
1.2.1 活動(dòng)圖
軟件從本質(zhì)上是在模擬現(xiàn)實(shí)業(yè)務(wù)運(yùn)行的過程,是由一個(gè)個(gè)交互活動(dòng)組成的,因此,在分析階段需要梳理出業(yè)務(wù)的活動(dòng)是怎樣的,通過圖形的方式記錄下來。
活動(dòng)圖要體現(xiàn)出「參與者」、「活動(dòng)起點(diǎn)」、「活動(dòng)關(guān)鍵路徑」、「活動(dòng)終點(diǎn)」,比如用戶下單,有「瀏覽」、「加購」、「支付」等活動(dòng)。通過活動(dòng)圖可以看出業(yè)務(wù)的生命周期是怎樣的,能夠抓住業(yè)務(wù)的關(guān)鍵流程。
1.2.2 用例圖
用例圖是強(qiáng)調(diào)用戶的目標(biāo)和觀點(diǎn),是文本化的情節(jié)描述,用例從本質(zhì)上講并不是圖,它是文本,用圖形是簡(jiǎn)化了表達(dá)形式,它核心有三點(diǎn):「參與者」、「要做什么」、「結(jié)果是怎樣的」。用例圖是對(duì)活動(dòng)圖的細(xì)化,對(duì)其中的一個(gè)活動(dòng)定義出要實(shí)現(xiàn)怎樣的目標(biāo)。場(chǎng)景又是對(duì)用例圖的細(xì)化,你會(huì)發(fā)現(xiàn),從目標(biāo)到實(shí)現(xiàn),一步一步地細(xì)化下來,細(xì)化是對(duì)擴(kuò)大對(duì)認(rèn)識(shí)的理解,不在認(rèn)識(shí)范圍內(nèi),也就不會(huì)去做。
1.2.3 順序圖
將場(chǎng)景通過順序圖表達(dá)出來,它核心強(qiáng)調(diào)的是系統(tǒng)應(yīng)該提供怎樣的能力,注意順序圖與時(shí)序圖的區(qū)別,順序圖是人與系統(tǒng)的交互,它想表達(dá)的是系統(tǒng)應(yīng)該提供怎樣的能力滿足用戶的訴求,而時(shí)序圖系統(tǒng)內(nèi)部實(shí)現(xiàn),強(qiáng)調(diào)的是如何實(shí)現(xiàn)這種能力。?
其實(shí)到順序圖這一步,基本上系統(tǒng)要提供的能力就清楚了,當(dāng)然,這里是知道系統(tǒng)要做什么,至于要怎么實(shí)現(xiàn)它并不關(guān)心。以上我認(rèn)為它是分析階段,把用戶想實(shí)現(xiàn)的內(nèi)容清楚地定義出來,接下來就是思考怎么實(shí)現(xiàn)。
1.2.4 時(shí)序圖
時(shí)序圖有兩種作用:一是表達(dá)功能是如何實(shí)現(xiàn)的;另一個(gè)是看責(zé)任分配是否合理。第一點(diǎn)比較好理解,一個(gè)功能實(shí)現(xiàn)是由多個(gè)不同的對(duì)象組合來實(shí)現(xiàn),對(duì)象間有交互依賴。第二點(diǎn)是評(píng)判對(duì)象設(shè)計(jì)是否合理,如何兩個(gè)對(duì)象頻繁交互,是不是可以合并在一起,如何一對(duì)象中的操作過多,是不是可以拆解。
1.2.5 類圖
類圖的作用也有兩種:一是表達(dá)屬性和職責(zé);另一個(gè)是層次結(jié)構(gòu)。類中的屬性和職責(zé)是一個(gè)統(tǒng)一體,屬性體現(xiàn)的是認(rèn)知能力,職責(zé)體現(xiàn)的是行為能力,擁有怎樣的認(rèn)識(shí),就會(huì)產(chǎn)生怎樣的行為。類不是一個(gè)孤零零的個(gè)體,它與其它的類之間有依賴、協(xié)作關(guān)系,因此,類圖中體現(xiàn)繼承、依賴、泛化、包含等關(guān)系。
1.3 原則篇
軟件設(shè)計(jì)原則汗牛充棟,簡(jiǎn)化下來就三點(diǎn):「復(fù)用」、「變化」、「認(rèn)知復(fù)雜度」,好的設(shè)計(jì)處處體現(xiàn)設(shè)計(jì)原則,把這些原則刻畫到骨子里,而不是刻意體現(xiàn),如同「沒有規(guī)矩不成方圓」一樣,重點(diǎn)是要理解為什么要這些原則,從本質(zhì)上講是為了軟件能夠「多快好省」地完成。
利潤 = 收入 - 成本,從這個(gè)公式中,很明顯我們想要實(shí)現(xiàn)利潤最大化,怎么辦呢,有兩個(gè)方法:一是收入變多,最好地方式是實(shí)現(xiàn)規(guī)?;欢浅杀窘档停恍枰蛘吆苌偻度氤杀?。從這兩點(diǎn)中,引申出「復(fù)用」和「變化」兩個(gè)原則,復(fù)用是不投入或者少投入實(shí)現(xiàn)功能,相比從頭做是不是要節(jié)省成本呢,我們的產(chǎn)品不可能一成不變的,那么變化是在所難免的,如果能支撐靈活地?cái)U(kuò)展是不是也能節(jié)省成本呢。
1.3.1 復(fù)用
從上面的分析看,「復(fù)用性」的重要程度不言而喻,比起煙囪式開發(fā),復(fù)用的成本要低得多,所以產(chǎn)生出了xx平臺(tái)、xx中臺(tái),它們的本質(zhì)目的還是為了復(fù)用,減少重復(fù)開發(fā)成本。實(shí)現(xiàn)復(fù)用的手段有很多,復(fù)用的程度也不一樣,這個(gè)就要靠平時(shí)的積累,就像醫(yī)生積累「藥」和「藥方」一樣,這些都是我們解決問題的「工具」。先要有復(fù)用的思維,否則只有工具也是無用的,不知道要怎么用、在哪里用。?
不同的場(chǎng)景,復(fù)用采用的設(shè)計(jì)方法是不一樣的,舉幾個(gè)例子方便大家理解。
完全復(fù)用
最簡(jiǎn)單的復(fù)用是100%的復(fù)用,比如加法計(jì)算操作,它肯定是100%復(fù)用的,只用傳輸不同的數(shù)字進(jìn)去,就可以計(jì)算出結(jié)果。一般完全復(fù)用的是工具型的能力,它與具體的業(yè)務(wù)語義無關(guān)。?
配置化復(fù)用
這一類的復(fù)用程度接近100%,只用配置一些與業(yè)務(wù)相關(guān)的具體的參數(shù)即可,比如對(duì)賬場(chǎng)景,配置兩個(gè)不同的數(shù)據(jù)源表,再配置對(duì)賬規(guī)則即可完成對(duì)賬。這一類場(chǎng)景適用于業(yè)務(wù)比較固定,流程是通用的,并且差異變化是可枚舉的。
部分復(fù)用
然而,在實(shí)現(xiàn)世界中,沒有太多像完全復(fù)用的事情,如果變化還不能通過配置化來實(shí)現(xiàn),可以使用「模板方法」或「策略模式」,將變化延遲到子類中去實(shí)現(xiàn),這種方法在大家日常工作很常見,也有的使用SPI擴(kuò)展點(diǎn)實(shí)現(xiàn)。這一類復(fù)用場(chǎng)景是有明確的「主流程」,只有少量的變化隨業(yè)務(wù)變化,變化也是可枚舉的,那么就可以抽象出擴(kuò)展點(diǎn)。?
還有一類變化是很難枚舉的,不知道會(huì)有怎樣的變化,此時(shí)最好的方法是通過「事件」解耦,主流程完成之后,發(fā)一個(gè)事件消息出來,誰關(guān)注就去實(shí)現(xiàn)該功能,本質(zhì)上講Spring中Aware機(jī)制也屬于事件的處理方法。
完全不能復(fù)用
還有一類完全不能復(fù)用,但要抽象出標(biāo)準(zhǔn)的接口,比如常用的數(shù)據(jù)庫操作,Connection、Statement就是標(biāo)準(zhǔn)的接口,不同的數(shù)據(jù)庫廠商實(shí)現(xiàn)具體的數(shù)據(jù)庫操作。不要覺得這種沒有意義,它從更高的層面定義了規(guī)范,使用者是面向抽象使用,可以不關(guān)注具體的實(shí)現(xiàn)是怎樣的。
1.3.2 變化
復(fù)用和變化是一起出來的,軟件唯一不變的是變化,怎么支撐未來更好地?cái)U(kuò)展是我們要思考的,如果一個(gè)功能千年不變,怎么簡(jiǎn)單就怎么實(shí)現(xiàn),而如果有變化的話,那就需要好好地設(shè)計(jì),用最少的成本去支撐未來的變化。比較難的是要洞察出什么在變化,這個(gè)還真不是那么好想到的,需要有行業(yè)經(jīng)驗(yàn)積累,看多了、實(shí)踐多了,會(huì)發(fā)現(xiàn)里面的一些門道。?
舉一個(gè)應(yīng)對(duì)變化的例子,稅務(wù)在計(jì)稅時(shí),不同的業(yè)務(wù)計(jì)稅規(guī)則不一樣,有的金本位要計(jì)稅,有的不需要計(jì)稅,有的非金本位要計(jì)稅,有的不需要。如果放在一個(gè)大的擴(kuò)展點(diǎn)中實(shí)現(xiàn),那么這就是典型的面向過程的設(shè)計(jì)思維,我們抽象出了「計(jì)稅表達(dá)式」這個(gè)實(shí)體來應(yīng)對(duì)變化,「計(jì)稅項(xiàng)」要不要計(jì)稅、計(jì)稅口徑是怎樣的,新業(yè)務(wù)接入通過「配置化」來解決。
1.3.3 認(rèn)識(shí)復(fù)雜度
認(rèn)識(shí)是分層次的,最高層越簡(jiǎn)單,最低層越復(fù)雜,對(duì)于使用者來講,他希望看到的是簡(jiǎn)單的內(nèi)容,如果太復(fù)雜,很難上手,比如命令行式的操作系統(tǒng)和桌面式的操作系統(tǒng),明顯桌面式的操作系統(tǒng)更受大眾的歡迎,這也是微軟在目前依然在操作系統(tǒng)市場(chǎng)占用份額上還是大頭的原因。軟件分層的目的不僅是讓關(guān)注點(diǎn)分離,還有另外一個(gè)目的是降低認(rèn)識(shí)復(fù)雜度,從簡(jiǎn)單到復(fù)雜,這和我們軟件分析一樣的,從粗到細(xì)。?
類的設(shè)計(jì)也是一樣的,舉一個(gè)例子,稅務(wù)在開發(fā)票時(shí),開票這個(gè)模型結(jié)構(gòu)需要調(diào)用者感知嗎,肯定不需要,因?yàn)榘l(fā)票中有很多的領(lǐng)域概念,如開票主體、發(fā)票行等,用戶的目的就是開一張發(fā)票,他只用告訴你他知道的信息,不關(guān)心你內(nèi)部要怎么實(shí)現(xiàn),基于這個(gè)思考,我們抽象出了「開票申請(qǐng)」這個(gè)實(shí)體出來,它本質(zhì)是貼近業(yè)務(wù)場(chǎng)景的實(shí)體,所包含的信息也是有限的,極大地降低了認(rèn)知復(fù)雜度。
二、系統(tǒng)分析與設(shè)計(jì)的2個(gè)案例
2.1 日志框架
2.1.1 日志框架分析
打印日志在我們?nèi)粘9ぷ鲙缀跏侨巳硕紩?huì)接觸到,日志的核心作用是記錄關(guān)鍵有效的信息,幫助我們快速地排查、定位問題,否則沒有日志信息兩眼一抓瞎。根據(jù)我們的經(jīng)驗(yàn),希望日志中包含時(shí)間、類、方法、代碼行、關(guān)鍵日志信息,用了這些信息就能方便我們排查問題。?
根據(jù)上面的分析,我們很快可以畫出日志的概念模型,如下圖所示。從本質(zhì)上講,我們是將日志信息存儲(chǔ)到指定的地方,如存儲(chǔ)文件中,輸出到控制臺(tái)上,另外還有日志存儲(chǔ)的格式可以有多種,比如普通的格式,還有XML、HTML的格式等。?
從概念模型上看,設(shè)計(jì)一個(gè)日志框架并不復(fù)雜,但在設(shè)計(jì)階段中,還需要挖掘更多的信息,我們輸入的信息更多,設(shè)計(jì)時(shí)考慮的因素也就越全,更能滿足用戶的訴求。
2.1.1 日志框架設(shè)計(jì)
2.1.1.1 貼近用戶的設(shè)計(jì)
站在用戶的視角,他關(guān)注的是信息以怎樣的格式存儲(chǔ)在哪里,因此,有兩個(gè)概念用戶是要關(guān)注的,一個(gè)是「存儲(chǔ)目的地」,另一個(gè)是「存儲(chǔ)樣式」,這兩個(gè)是可以根據(jù)用戶的喜好配置的,將這兩個(gè)概念抽象下,「存儲(chǔ)目的地」抽象成「Appender」,「存儲(chǔ)樣式」抽象成「LayoutPattern」。除了配置外,用戶在使用時(shí)需要一個(gè)接口類,將其抽象成「Logger」門面類,只用簡(jiǎn)單的調(diào)用日志打印接口即可。
2.1.1.1 系統(tǒng)視角的設(shè)計(jì)
站在系統(tǒng)視角上,用戶在日志打印時(shí),他關(guān)注的是日志信息,如時(shí)間、類名、方法名等信息他不會(huì)顯示去寫,因此還需要抽象一個(gè)概念出來表達(dá)日志信息的概念,抽象成「LogRecord」,這樣概念類圖如下圖所示。?
按照這個(gè)設(shè)計(jì),很快可以設(shè)計(jì)出一個(gè)簡(jiǎn)易的日志框架,代碼結(jié)構(gòu)如下所示。
Appender類如下所示,它定義的是一個(gè)模板方法,先調(diào)用LayoutPattern獲取格式化的日志數(shù)據(jù),然后再輸出到目標(biāo)存儲(chǔ)上,Appender和LayoutPattern是可以獨(dú)立變化的,同時(shí)將寫操作延遲到子類中實(shí)現(xiàn)。
再細(xì)細(xì)想一下,日志本身是為了方便排查問題,但額外日志的存儲(chǔ)是有性能開銷的,這個(gè)在設(shè)計(jì)時(shí)就要著重考慮了。如何減少寫日志帶來的性能開銷呢,從三個(gè)方面考慮:
大文件變小文件:打開一個(gè)1G的文件和打開1M的文件肯定是不一樣的,復(fù)雜問題的治理也是同樣的思路,拆分成小問題處理,因此在寫文件時(shí)可以按照「時(shí)間」、「容量大小」切分成小的文件。
內(nèi)存映射寫文件:傳統(tǒng)的IO寫數(shù)據(jù),操作系統(tǒng)需要從用戶態(tài)切換到內(nèi)核態(tài),性能開銷會(huì)很大,可以使用內(nèi)存映射的方式寫文件,提升IO性能。
同步變異步寫文件:同步寫文件是需要等文件寫好了后再往下執(zhí)行業(yè)務(wù)代碼,而異步就不一樣,它將日志記錄存儲(chǔ)在一個(gè)隊(duì)列中,開戶另一個(gè)線程慢慢寫到文件中,不阻塞業(yè)務(wù)邏輯執(zhí)行。?
通過上面的分析,一個(gè)簡(jiǎn)單的日志框架隨著對(duì)它的理解加深,設(shè)計(jì)方案也在變化,核心是要能看到關(guān)鍵的技術(shù)問題有哪些,能提供哪些增量價(jià)值或差異化的價(jià)值。?
2.2 定時(shí)任務(wù)框架
2.2.1 定時(shí)任務(wù)框架分析
定時(shí)任務(wù)在我們平時(shí)的工作中也經(jīng)常使用,如每天定時(shí)發(fā)送郵件、定時(shí)做數(shù)據(jù)檢查等,完成定時(shí)任務(wù)的訴求也比較簡(jiǎn)單,就是在指定的時(shí)間執(zhí)行指定的任務(wù),從這個(gè)角度看,業(yè)務(wù)模型并不復(fù)雜,如下圖所示。調(diào)度任務(wù)和調(diào)度時(shí)間是兩個(gè)獨(dú)立的變化維度。為了讓任務(wù)能夠調(diào)度起來,還有一個(gè)「調(diào)度器」的概念并沒有在業(yè)務(wù)模型上體現(xiàn)出來,將要執(zhí)行的任務(wù),以及調(diào)度時(shí)間告知給調(diào)度器,調(diào)度器就能根據(jù)要求調(diào)度任務(wù)。
?
2.2.2 定時(shí)任務(wù)框架設(shè)計(jì)
2.2.2.1 貼近用戶的設(shè)計(jì)
站在用戶視角,他關(guān)心的有三點(diǎn):
任務(wù)要按照怎樣的規(guī)范去編寫,因此需要一個(gè)概念「Job」去表達(dá),它定義了一個(gè)execute()接口。
調(diào)度時(shí)間如何去表達(dá),抽象出「Trigger」這個(gè)概念,表示到時(shí)就觸發(fā)任務(wù)執(zhí)行。
任務(wù)如何提交,需要一個(gè)門面類「Scheduler」去表達(dá),接受用戶提交的任務(wù)。
2.2.2.2 系統(tǒng)視角的設(shè)計(jì)
站在系統(tǒng)的視角,很快能想到解決方法,用戶提交任務(wù)后要保存至一個(gè)隊(duì)列中「JobQueue」,「JobQueue」中存儲(chǔ)的是「JobDetail」,「JobQueue」包含了「Job」和「Trigger」兩部分信息,然后有一個(gè)調(diào)度線程「SchedulerThread」不斷掃描「JobQueue」,判斷當(dāng)前任務(wù)是否要被執(zhí)行,如果需要執(zhí)行就調(diào)用「Job」的execute()方法,類的概念模型如下圖所示。
按照這個(gè)設(shè)計(jì),很快可以設(shè)計(jì)出一個(gè)簡(jiǎn)易的任務(wù)調(diào)度框架,代碼結(jié)構(gòu)如下所示。?
?
定時(shí)任務(wù)最關(guān)鍵的技術(shù)挑戰(zhàn)是查找要調(diào)度執(zhí)行的任務(wù),很容易想到對(duì)「JobQueue」中的「JobDetail」排序,發(fā)現(xiàn)Job的executeTime快到了就執(zhí)行,然而排序是消耗CPU資源的,不同的排序算法時(shí)間復(fù)雜度也不一樣。怎么降低排序算法的時(shí)間復(fù)雜度呢,最簡(jiǎn)單的用最小堆排序算法,每次從堆頂獲取任務(wù)執(zhí)行,而每次添加任務(wù),又涉及到堆的調(diào)整,這個(gè)過程也是消耗CPU資源的。有沒有更快的算法呢,有人提出了時(shí)間輪的解決方法,類似鐘一樣,如一分鐘是60格,類似將任務(wù)的時(shí)間計(jì)算好,放到對(duì)應(yīng)的格中,如果有多個(gè)相同的任務(wù),就有一個(gè)鏈表鏈起來,xxl-job就用了時(shí)間輪的方法,將未來周期性需要 調(diào)度執(zhí)行的任務(wù)放在時(shí)間輪中,時(shí)間輪的數(shù)據(jù)結(jié)構(gòu)是一個(gè)Map。
這還是一個(gè)簡(jiǎn)單的任務(wù)調(diào)度框架,還有很多問題沒有考慮到,比如任務(wù)分片、分布式定時(shí)任務(wù)等,還是回到需求分析上,我們要做的功能邊界是什么,目標(biāo)是什么,再去設(shè)計(jì)對(duì)應(yīng)的解決方案。?
三、總結(jié)
在日常技術(shù)方案設(shè)計(jì)時(shí),最為關(guān)鍵的是要能定義出關(guān)鍵的技術(shù)問題,有兩類問題是我們要著重考慮的:一是貼近用戶視角的便捷性設(shè)計(jì),主要是對(duì)業(yè)務(wù)概念的抽象,用戶以最小的知識(shí)感知系統(tǒng);另一個(gè)是系統(tǒng)的視角設(shè)計(jì),除了完成功能外,還要定義出關(guān)鍵的技術(shù)問題以及度量的方法,如打印日志帶來的系統(tǒng)開銷,怎么做到對(duì)系統(tǒng)產(chǎn)生最小的影響;定時(shí)任務(wù)調(diào)度的調(diào)度算法設(shè)計(jì),選用不同的數(shù)據(jù)結(jié)構(gòu)的效果是不一樣的,普通的排序算法沒有堆排序算法好,但堆排序同樣涉及到性能開銷,這就讓我們不斷想更好地方案去解決。
編輯:黃飛
-
cpu
+關(guān)注
關(guān)注
68文章
10854瀏覽量
211574 -
軟件設(shè)計(jì)
+關(guān)注
關(guān)注
3文章
58瀏覽量
17770 -
線程
+關(guān)注
關(guān)注
0文章
504瀏覽量
19675 -
調(diào)度器
+關(guān)注
關(guān)注
0文章
98瀏覽量
5245
原文標(biāo)題:一文探究系統(tǒng)分析與設(shè)計(jì)的邏輯性
文章出處:【微信號(hào):OSC開源社區(qū),微信公眾號(hào):OSC開源社區(qū)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論