架構(gòu)權(quán)衡評(píng)估方法(ATAM):如何評(píng)估一個(gè)系統(tǒng)的質(zhì)量
JAVA前線?
歡迎大家關(guān)注公眾號(hào)「JAVA前線」查看更多精彩分享,主要內(nèi)容包括源碼分析、實(shí)際應(yīng)用、架構(gòu)思維、職場(chǎng)分享、產(chǎn)品思考等等,同時(shí)也非常歡迎大家加我微信「java_front」一起交流學(xué)習(xí)
1 質(zhì)量屬性
在系統(tǒng)設(shè)計(jì)和開發(fā)過程中,我們比較容易關(guān)注系統(tǒng)的功能維度,例如有沒有實(shí)現(xiàn)預(yù)期功能,輸入?yún)?shù)和輸出參數(shù)是否匹配等等,這是比較容易測(cè)試和衡量的。
但是我們不能就此止步,因?yàn)闈M足功能是系統(tǒng)的基本要求,還需要關(guān)注系統(tǒng)的非功能維度,例如系統(tǒng)性能是否優(yōu)秀,代碼可擴(kuò)展性如何,出現(xiàn)異常是否可以自動(dòng)降級(jí)等等,這些指標(biāo)決定了系統(tǒng)能否提供高質(zhì)量的服務(wù)。
在之前文章《結(jié)構(gòu)化思維如何指導(dǎo)技術(shù)系統(tǒng)優(yōu)化》提到了三個(gè)質(zhì)量屬性:高性能、高可用、高擴(kuò)展。本文我們充實(shí)為六個(gè)質(zhì)量屬性:性能、可用性、可修改性、可靠性、安全性、易用性:

1.1 性能
1.1.1 如何定義
性能有兩個(gè)定義維度,第一個(gè)維度是單位時(shí)間內(nèi)可以做多少事情,第二個(gè)維度是做完單位數(shù)量的事情需要多長時(shí)間,常用以下參數(shù)進(jìn)行量化:
QPS:每秒處理請(qǐng)求數(shù)
TPS:每秒處理事務(wù)數(shù)
并發(fā)數(shù):同一時(shí)刻處理請(qǐng)求數(shù)/事務(wù)數(shù)
響應(yīng)時(shí)間:系統(tǒng)對(duì)請(qǐng)求做出響應(yīng)的時(shí)間
并發(fā)數(shù) = QPS x RT
1.1.2 如何提升
提升性能可以從兩個(gè)維度思考,第一個(gè)維度是時(shí)間維度,從事前、事中、事后三個(gè)時(shí)間節(jié)點(diǎn)進(jìn)行優(yōu)化。事前是指在訪問最開始就拒絕無效流量。事中可以使用提高并發(fā)度(并發(fā)編程),增加資源(服務(wù)器、分布式緩存、讀寫分離,分庫分表),減少交互(批量請(qǐng)求)等方案。事后是指數(shù)據(jù)分析需求可以放到離線數(shù)據(jù)中心進(jìn)行,不要放在主應(yīng)用和主數(shù)據(jù)庫進(jìn)行。
第二個(gè)維度是層次維度,每一層都可以進(jìn)行優(yōu)化。系統(tǒng)架構(gòu)一般分為數(shù)據(jù)層、緩存層、服務(wù)層、網(wǎng)關(guān)層、客戶端、代理層,每一層都可以按照事前、事中、事后進(jìn)行優(yōu)化,而不是一提到優(yōu)化就是加緩存,應(yīng)該更加全面地思考。

1.2 可用性
1.2.1 如何定義
可用性是指系統(tǒng)正常運(yùn)行時(shí)間占總運(yùn)行時(shí)間比例,業(yè)界常用X個(gè)9指標(biāo)進(jìn)行量化,例如可用性達(dá)到5個(gè)9,那么全年系統(tǒng)不可用時(shí)間只有5分鐘:

1.2.2 如何提升
(1) 非線性
我們從另一個(gè)概念理解可用性:非線性,這個(gè)概念在生活中無處不在。
假設(shè)要趕早上8點(diǎn)鐘的火車,如果6:30出發(fā)可以在7:00到達(dá)車站,所以得到一個(gè)結(jié)論:只要30分鐘就可以到達(dá)車站。
如果早上睡晚一點(diǎn)7:15出發(fā),那么按照預(yù)期7:45可以到達(dá)車站。但是最可能的結(jié)果是錯(cuò)過這趟火車。因?yàn)檎糜錾显绺叻鍖?dǎo)致至少需要1個(gè)小時(shí)才能到達(dá)車站。
我們?cè)俜治鲆粋€(gè)互聯(lián)網(wǎng)秒殺場(chǎng)景。假設(shè)秒殺系統(tǒng)當(dāng)每秒30個(gè)請(qǐng)求時(shí),響應(yīng)時(shí)間是10毫秒。如果按照線性思維可以做出如下設(shè)計(jì):
每秒30個(gè)訪問量響應(yīng)時(shí)間10毫秒
每秒300個(gè)訪問量響應(yīng)時(shí)間100毫秒
每秒3000個(gè)訪問量響應(yīng)時(shí)間1000毫秒
如果按照這個(gè)思路做系統(tǒng)設(shè)計(jì)可能會(huì)發(fā)生重大的錯(cuò)誤。因?yàn)楫?dāng)每秒3000個(gè)訪問量發(fā)生時(shí),響應(yīng)時(shí)間可能不是1000毫秒,而是可能直接導(dǎo)致系統(tǒng)發(fā)生崩潰。
這就是非線性,事物不是簡單線性疊加關(guān)系,當(dāng)達(dá)到某個(gè)臨界值時(shí)會(huì)造成一種截然不同的結(jié)果。
(2) 提升策略
冗余 + 自動(dòng)故障轉(zhuǎn)移
最基本冗余策略就是主從模式。原理是準(zhǔn)備兩臺(tái)機(jī)器,部署了同一份代碼,在功能層面是相同的,都可以對(duì)外提供相同的服務(wù)。
一臺(tái)機(jī)器啟動(dòng)提供服務(wù),這就是主服務(wù)器。另一臺(tái)機(jī)器啟動(dòng)在一旁待命,不提供服務(wù),隨時(shí)監(jiān)聽主服務(wù)器的狀態(tài),這就是從服務(wù)器。當(dāng)發(fā)現(xiàn)主服務(wù)器出現(xiàn)故障時(shí),從服務(wù)器立刻替換主服務(wù)器,繼續(xù)為用戶提供服務(wù)。
自動(dòng)故障轉(zhuǎn)移策略是指當(dāng)主系統(tǒng)發(fā)生異常時(shí),應(yīng)該可以自動(dòng)探測(cè)到異常,并自動(dòng)切換為備用系統(tǒng)。不應(yīng)該只依靠人工去切換成,否則故障處理時(shí)間會(huì)顯著增加。
降級(jí)策略
當(dāng)系統(tǒng)遇到無法承受的壓力時(shí),選擇暫時(shí)關(guān)閉一些非關(guān)鍵的功能,或者延時(shí)提供一些功能,把此刻所有的資源都提供給現(xiàn)在最關(guān)鍵的服務(wù)。
在秒殺場(chǎng)景中下訂單就是最核心最關(guān)鍵的功能。當(dāng)系統(tǒng)壓力將要到達(dá)臨界值時(shí),可以暫時(shí)先關(guān)閉一些非核心功能如查詢功能。
還有一種降級(jí)策略,當(dāng)系統(tǒng)依賴的下游服務(wù)出現(xiàn)錯(cuò)誤,甚至已經(jīng)完全不可用了,那么此時(shí)就不能再調(diào)用這個(gè)下游服務(wù)了,否則可能導(dǎo)致雪崩。所以直接返回兜底方案,把下游服務(wù)直接降級(jí)。
延時(shí)策略
用戶下訂單成功后就需要進(jìn)行支付。假設(shè)秒殺系統(tǒng)下訂單每秒訪問量是3000,有沒有必要將每秒3000次訪問量壓力傳遞給支付服務(wù)器?
答案是沒有必要。因?yàn)橛脩裘霘⒊晒罂梢陨酝砀犊睿缈梢蕴D(zhuǎn)到一個(gè)支付頁面,提示用戶只要在10分鐘內(nèi)支付完成即可。
這樣流量就被分?jǐn)傊翈追昼姡行ПWo(hù)了系統(tǒng)。技術(shù)架構(gòu)還可以使用消息隊(duì)列做緩沖,讓下游系統(tǒng)根據(jù)處理能力拉取消息。
隔離策略
物理隔離:應(yīng)用分別部署在不同物理機(jī)、不同機(jī)房,資源之間不會(huì)互相影響。
線程隔離:不同類型的請(qǐng)求進(jìn)行分類,交給不同的線程池處理,當(dāng)一類請(qǐng)求出現(xiàn)高耗時(shí)和異常,不影響另一類請(qǐng)求訪問。
1.3 可修改性
1.3.1 如何定義
可修改性是指是否能夠以較高的性價(jià)比對(duì)系統(tǒng)進(jìn)行變更的能力,可以分為以下四種類型:
可擴(kuò)展性:系統(tǒng)擴(kuò)展新構(gòu)件時(shí)對(duì)其它構(gòu)件的影響程度
可維護(hù)性:系統(tǒng)修改舊構(gòu)件時(shí)對(duì)其它構(gòu)件的影響程度
結(jié)構(gòu)重組:重新組織構(gòu)件關(guān)系的難易程度
可移植性:在不同硬件平臺(tái)、編程語言、操作系統(tǒng)間移植的難易程度
1.3.2 如何提升
可修改性最終在解決牽一發(fā)而動(dòng)全身的復(fù)雜性問題,復(fù)雜業(yè)務(wù)之所以復(fù)雜,一個(gè)重要原因是涉及角色或者類型較多,如果平鋪直敘地進(jìn)行設(shè)計(jì)會(huì)出現(xiàn)if-else代碼塊,可讀性和可修改性都很低。
我們分析一個(gè)下單場(chǎng)景。當(dāng)前有ABC三種訂單類型:A訂單價(jià)格9折,物流最大重量不能超過9公斤,不支持退款。B訂單價(jià)格8折,物流最大重量不能超過8公斤,支持退款。C訂單價(jià)格7折,物流最大重量不能超過7公斤,支持退款。按照需求字面含義平鋪直敘地寫代碼也并不難:
public?class?OrderServiceImpl?implements?OrderService?{
????@Resource
????private?OrderMapper?orderMapper;
????@Override
????public?void?createOrder(OrderBO?orderBO)?{
????????if?(null?==?orderBO)?{
????????????throw?new?RuntimeException("參數(shù)異常");
????????}
????????if?(OrderTypeEnum.isNotValid(orderBO.getType()))?{
????????????throw?new?RuntimeException("參數(shù)異常");
????????}
????????//?A類型訂單
????????if?(OrderTypeEnum.A_TYPE.getCode().equals(orderBO.getType()))?{
????????????orderBO.setPrice(orderBO.getPrice()?*?0.9);
????????????if?(orderBO.getWeight()?>?9)?{
????????????????throw?new?RuntimeException("超過物流最大重量");
????????????}
????????????orderBO.setRefundSupport(Boolean.FALSE);
????????}
????????//?B類型訂單
????????else?if?(OrderTypeEnum.B_TYPE.getCode().equals(orderBO.getType()))?{
????????????orderBO.setPrice(orderBO.getPrice()?*?0.8);
????????????if?(orderBO.getWeight()?>?8)?{
????????????????throw?new?RuntimeException("超過物流最大重量");
????????????}
????????????orderBO.setRefundSupport(Boolean.TRUE);
????????}
????????//?C類型訂單
????????else?if?(OrderTypeEnum.C_TYPE.getCode().equals(orderBO.getType()))?{
????????????orderBO.setPrice(orderBO.getPrice()?*?0.7);
????????????if?(orderBO.getWeight()?>?7)?{
????????????????throw?new?RuntimeException("超過物流最大重量");
????????????}
????????????orderBO.setRefundSupport(Boolean.TRUE);
????????}
????????//?保存數(shù)據(jù)
????????OrderDO?orderDO?=?new?OrderDO();
????????BeanUtils.copyProperties(orderBO,?orderDO);
????????orderMapper.insert(orderDO);
????}
}
上述代碼從功能上完全可以實(shí)現(xiàn)業(yè)務(wù)需求,但是程序員不僅要滿足功能,還需要思考代碼的可維護(hù)性。如果新增一種訂單類型,或者新增一個(gè)訂單屬性處理邏輯,那么我們就要在上述邏輯中新增代碼,如果處理不慎就會(huì)影響原有邏輯。
為了避免牽一發(fā)而動(dòng)全身這種情況,設(shè)計(jì)模式中的開閉原則要求我們面向新增開放,面向修改關(guān)閉,我認(rèn)為這是設(shè)計(jì)模式中最重要的一條原則。
需求變化通過擴(kuò)展,而不是通過修改已有代碼實(shí)現(xiàn),這樣就保證代碼穩(wěn)定性。擴(kuò)展也不是隨意擴(kuò)展,因?yàn)槭孪榷x了算法,擴(kuò)展也是根據(jù)算法擴(kuò)展,用抽象構(gòu)建框架,用實(shí)現(xiàn)擴(kuò)展細(xì)節(jié)。標(biāo)準(zhǔn)意義的二十三種設(shè)計(jì)模式說到底最終都是在遵循開閉原則。
如何改變平鋪直敘的思考方式?這就要為問題分析加上縱向和橫向兩個(gè)維度,我選擇使用分析矩陣方法,其中縱向表示策略,橫向表示場(chǎng)景:

(1) 縱向做隔離
縱向維度表示策略,不同策略在邏輯上和業(yè)務(wù)上應(yīng)該是隔離的,本實(shí)例包括優(yōu)惠策略、物流策略和退款策略,策略作為抽象,不同訂單類型去擴(kuò)展這個(gè)抽象,策略模式非常適合這種場(chǎng)景。本文詳細(xì)分析優(yōu)惠策略,物流策略和退款策略同理。
//?優(yōu)惠策略
public?interface?DiscountStrategy?{
????public?void?discount(OrderBO?orderBO);
}
//?A類型優(yōu)惠策略
@Component
public?class?TypeADiscountStrategy?implements?DiscountStrategy?{
????@Override
????public?void?discount(OrderBO?orderBO)?{
????????orderBO.setPrice(orderBO.getPrice()?*?0.9);
????}
}
//?B類型優(yōu)惠策略
@Component
public?class?TypeBDiscountStrategy?implements?DiscountStrategy?{
????@Override
????public?void?discount(OrderBO?orderBO)?{
????????orderBO.setPrice(orderBO.getPrice()?*?0.8);
????}
}
//?C類型優(yōu)惠策略
@Component
public?class?TypeCDiscountStrategy?implements?DiscountStrategy?{
????@Override
????public?void?discount(OrderBO?orderBO)?{
????????orderBO.setPrice(orderBO.getPrice()?*?0.7);
????}
}
//?優(yōu)惠策略工廠
@Component
public?class?DiscountStrategyFactory?implements?InitializingBean?{
????private?Map?strategyMap?=?new?HashMap<>();
????@Resource
????private?TypeADiscountStrategy?typeADiscountStrategy;
????@Resource
????private?TypeBDiscountStrategy?typeBDiscountStrategy;
????@Resource
????private?TypeCDiscountStrategy?typeCDiscountStrategy;
????public?DiscountStrategy?getStrategy(String?type)?{
????????return?strategyMap.get(type);
????}
????@Override
????public?void?afterPropertiesSet()?throws?Exception?{
????????strategyMap.put(OrderTypeEnum.A_TYPE.getCode(),?typeADiscountStrategy);
????????strategyMap.put(OrderTypeEnum.B_TYPE.getCode(),?typeBDiscountStrategy);
????????strategyMap.put(OrderTypeEnum.C_TYPE.getCode(),?typeCDiscountStrategy);
????}
}
//?優(yōu)惠策略執(zhí)行
@Component
public?class?DiscountStrategyExecutor?{
????private?DiscountStrategyFactory?discountStrategyFactory;
????public?void?discount(OrderBO?orderBO)?{
????????DiscountStrategy?discountStrategy?=?discountStrategyFactory.getStrategy(orderBO.getType());
????????if?(null?==?discountStrategy)?{
????????????throw?new?RuntimeException("無優(yōu)惠策略");
????????}
????????discountStrategy.discount(orderBO);
????}
}
(2) 橫向做編排
橫向維度表示場(chǎng)景,一種訂單類型在廣義上可以認(rèn)為是一種業(yè)務(wù)場(chǎng)景,在場(chǎng)景中將獨(dú)立的策略進(jìn)行串聯(lián),模板方法設(shè)計(jì)模式適用于這種場(chǎng)景。
模板方法模式一般使用抽象類定義算法骨架,同時(shí)定義一些抽象方法,這些抽象方法延遲到子類實(shí)現(xiàn),這樣子類不僅遵守了算法骨架約定,也實(shí)現(xiàn)了自己的算法。既保證了規(guī)約也兼顧靈活性,這就是用抽象構(gòu)建框架,用實(shí)現(xiàn)擴(kuò)展細(xì)節(jié)。
//?創(chuàng)建訂單服務(wù)
public?interface?CreateOrderService?{
????public?void?createOrder(OrderBO?orderBO);
}
//?抽象創(chuàng)建訂單流程
public?abstract?class?AbstractCreateOrderFlow?{
????@Resource
????private?OrderMapper?orderMapper;
????public?void?createOrder(OrderBO?orderBO)?{
????????//?參數(shù)校驗(yàn)
????????if?(null?==?orderBO)?{
????????????throw?new?RuntimeException("參數(shù)異常");
????????}
????????if?(OrderTypeEnum.isNotValid(orderBO.getType()))?{
????????????throw?new?RuntimeException("參數(shù)異常");
????????}
????????//?計(jì)算優(yōu)惠
????????discount(orderBO);
????????//?計(jì)算重量
????????weighing(orderBO);
????????//?退款支持
????????supportRefund(orderBO);
????????//?保存數(shù)據(jù)
????????OrderDO?orderDO?=?new?OrderDO();
????????BeanUtils.copyProperties(orderBO,?orderDO);
????????orderMapper.insert(orderDO);
????}
????public?abstract?void?discount(OrderBO?orderBO);
????public?abstract?void?weighing(OrderBO?orderBO);
????public?abstract?void?supportRefund(OrderBO?orderBO);
}
//?實(shí)現(xiàn)創(chuàng)建訂單流程
@Service
public?class?CreateOrderFlow?extends?AbstractCreateOrderFlow?{
????@Resource
????private?DiscountStrategyExecutor?discountStrategyExecutor;
????@Resource
????private?ExpressStrategyExecutor?expressStrategyExecutor;
????@Resource
????private?RefundStrategyExecutor?refundStrategyExecutor;
????@Override
????public?void?discount(OrderBO?orderBO)?{
????????discountStrategyExecutor.discount(orderBO);
????}
????@Override
????public?void?weighing(OrderBO?orderBO)?{
????????expressStrategyExecutor.weighing(orderBO);
????}
????@Override
????public?void?supportRefund(OrderBO?orderBO)?{
????????refundStrategyExecutor.supportRefund(orderBO);
????}
}
1.4 可靠性
1.4.1 如何定義
可靠性包括容錯(cuò)性和健壯性,系統(tǒng)面對(duì)錯(cuò)誤輸入仍能保證正確輸出的能力,可以分為兩種類型:系統(tǒng)可靠性和業(yè)務(wù)可靠性。
系統(tǒng)可靠性是指面對(duì)出現(xiàn)基本錯(cuò)誤的輸入,系統(tǒng)能夠識(shí)別和攔截,而不是任由其在構(gòu)件中傳遞,造成錯(cuò)誤數(shù)據(jù)或者引發(fā)系統(tǒng)異常。例如空值引發(fā)的空指針異常,不應(yīng)該出現(xiàn)在系統(tǒng)中。
業(yè)務(wù)可靠性是指輸入?yún)?shù)在基本校驗(yàn)通過的情況下,系統(tǒng)能夠進(jìn)行業(yè)務(wù)校驗(yàn),不會(huì)引發(fā)超出業(yè)務(wù)預(yù)期的輸出結(jié)果。例如電商系統(tǒng)中的超賣現(xiàn)象,重復(fù)創(chuàng)建訂單現(xiàn)象都是業(yè)務(wù)可靠性較低的表現(xiàn)。
1.4.2 如何提升
(1) 攔截
提升可靠性的關(guān)鍵是應(yīng)該盡早在上層識(shí)別并攔截異常數(shù)據(jù),阻止其在構(gòu)件中流動(dòng),避免產(chǎn)生系統(tǒng)異常和錯(cuò)誤數(shù)據(jù),尤其當(dāng)產(chǎn)生錯(cuò)誤數(shù)據(jù)后,數(shù)據(jù)修復(fù)難度大。
提升系統(tǒng)可靠性可以在服務(wù)入口增加判空校驗(yàn)、參數(shù)類型校驗(yàn)、范圍校驗(yàn)、合法枚舉值校驗(yàn)等基本校驗(yàn),一旦發(fā)現(xiàn)異常直接拒絕。
提升業(yè)務(wù)可靠性可以增強(qiáng)業(yè)務(wù)校驗(yàn),例如庫存預(yù)扣減,活動(dòng)有效期校驗(yàn),參與活動(dòng)次數(shù)校驗(yàn),扣減庫存校驗(yàn),分布式鎖控制并發(fā)等方案,如果校驗(yàn)規(guī)則復(fù)雜可以引入規(guī)則引擎進(jìn)行條件組合,不滿足業(yè)務(wù)條件直接拒絕請(qǐng)求。
(2) 告警
如果第一階段沒有將異常輸入攔截成功,那么就要在發(fā)生異常時(shí)及時(shí)感知,異常分為系統(tǒng)異常和業(yè)務(wù)異常。
系統(tǒng)異常是不允許出現(xiàn)的異常,例如空指針,操作數(shù)據(jù)庫失敗等異常,一旦出現(xiàn)就要立即告警。
業(yè)務(wù)異常可以分為以下類型:
業(yè)務(wù)告警:單位時(shí)間出現(xiàn)X次需要告警
延時(shí)告警:某指標(biāo)單位時(shí)間內(nèi)是否變化
數(shù)據(jù)告警:單位時(shí)間數(shù)據(jù)指標(biāo)是否正常
1.5 安全性與易用性
安全性是指系統(tǒng)防止非法用戶訪問的能力,易用性是指系統(tǒng)使用的難易程度,本文不展開論述,下一個(gè)章節(jié)會(huì)通過實(shí)例提到。
2 架構(gòu)評(píng)估方法
2.1 三種評(píng)估方法
因?yàn)樯婕暗奖姸嘧兞亢蛨?chǎng)景,所以評(píng)估一個(gè)復(fù)雜技術(shù)系統(tǒng)的質(zhì)量并不是一件容易的事情。業(yè)界有以下三種評(píng)估方法:
第一是基于問卷的方式,通過問卷調(diào)查對(duì)系統(tǒng)比較熟悉的相關(guān)人員,這種方式主觀性很強(qiáng)。
第二是基于度量的方式,對(duì)系統(tǒng)指標(biāo)完全量化,基于量化指標(biāo)評(píng)價(jià)系統(tǒng),這種方式需要評(píng)估者對(duì)系統(tǒng)非常熟悉。
第三種是基于場(chǎng)景的方式,篩選出系統(tǒng)的關(guān)鍵場(chǎng)景,根據(jù)系統(tǒng)在不同場(chǎng)景中的表現(xiàn)進(jìn)行評(píng)估,這種方式具有一定的主觀性,需要評(píng)估者對(duì)系統(tǒng)比較熟悉,這也是目前較為流行的架構(gòu)評(píng)估方法。
架構(gòu)權(quán)衡評(píng)估方法(ATAM)的英文全稱是:Architecture Tradeoff Analysis Method,由卡梅隆大學(xué)軟件工程協(xié)會(huì)提出,是一種基于場(chǎng)景的架構(gòu)評(píng)估方法,核心是結(jié)合質(zhì)量屬性效用樹對(duì)系統(tǒng)進(jìn)行評(píng)價(jià),確定風(fēng)險(xiǎn)點(diǎn)、敏感點(diǎn)、權(quán)衡點(diǎn),并對(duì)系統(tǒng)架構(gòu)做出決策和折中。
ATAM分為以下步驟,其中1、2、3為描述和介紹階段,4、5、6為調(diào)查和分析階段,7、8為測(cè)試階段,9為報(bào)告階段。

2.2 ATAM
本章節(jié)以之前文章《結(jié)合DDD講清楚編寫技術(shù)方案的七大維度》足球運(yùn)動(dòng)員信息管理系統(tǒng)為例看一看ATAM如何實(shí)際應(yīng)用。
第一階段是描述和介紹階段,首先由架構(gòu)師向大家介紹什么是ATAM方法,其次由產(chǎn)品經(jīng)理介紹開發(fā)足球運(yùn)動(dòng)員信息管理系統(tǒng)商業(yè)動(dòng)機(jī),最后由架構(gòu)師介紹系統(tǒng)整體架構(gòu),例如怎樣劃分領(lǐng)域,系統(tǒng)分為持久層、緩存層、中間件、業(yè)務(wù)中臺(tái)、服務(wù)層、網(wǎng)關(guān)層、客戶端和代理層等等。
第二階段是調(diào)查和分析階段,不同需求方均提出了相關(guān)需求,所涉及質(zhì)量場(chǎng)景如下:
(1) 系統(tǒng)在100毫秒內(nèi)響應(yīng)用戶請(qǐng)求
(2) 當(dāng)主數(shù)據(jù)庫發(fā)生故障后,10秒內(nèi)自動(dòng)切換至從數(shù)據(jù)庫
(3) 當(dāng)主機(jī)房發(fā)生故障后,5分鐘內(nèi)請(qǐng)求重定向至災(zāi)備機(jī)房
(4) 新增球員比賽和訓(xùn)練指標(biāo),開發(fā)工作在5人日內(nèi)完成
(5) 使用包含SSL數(shù)字證書的HTTPS訪問協(xié)議
(6) 球員信息管理界面要求簡單易用
(7) 出現(xiàn)異常引導(dǎo)用戶至錯(cuò)誤頁面,不能展示異常棧信息
(8) 對(duì)于球員信息配置功能的靈活度尚未達(dá)成共識(shí),影響了系統(tǒng)可修改性
(9) 對(duì)于球員比賽指標(biāo)實(shí)時(shí)收集響應(yīng)時(shí)間的要求,影響了數(shù)據(jù)存儲(chǔ)設(shè)計(jì)
(10) 主教練提出了訓(xùn)練指標(biāo)新模式,影響了系統(tǒng)性能和可修改性
根據(jù)上述場(chǎng)景生成質(zhì)量屬性效用樹,(1)屬于性能,(2)(3)屬性可用性,(4)屬于可修改性,(5)屬于安全性,(6)屬于易用性,(7)屬于可靠性:

再根據(jù)這些場(chǎng)景分析系統(tǒng)的風(fēng)險(xiǎn)點(diǎn)、敏感點(diǎn)、權(quán)衡點(diǎn)。風(fēng)險(xiǎn)點(diǎn)是指某些操作會(huì)給系統(tǒng)帶來隱患和風(fēng)險(xiǎn),(8)屬于風(fēng)險(xiǎn)點(diǎn)。敏感點(diǎn)是指為了實(shí)現(xiàn)某個(gè)特定質(zhì)量屬性,一個(gè)或多個(gè)系統(tǒng)組件所具有的特性,(9)屬于敏感點(diǎn)。權(quán)衡點(diǎn)是指某些操作會(huì)影響系統(tǒng)的多個(gè)質(zhì)量屬性,(10)屬于權(quán)衡點(diǎn)。
第三個(gè)階段是測(cè)試階段,根據(jù)足球運(yùn)動(dòng)員信息管理系統(tǒng)特性,我們首先確定場(chǎng)景優(yōu)先級(jí),由高到低分別是:性能、可靠性、可用性、可修改性、安全性、易用性。
架構(gòu)權(quán)衡分析方法所謂權(quán)衡在此得到了體現(xiàn),質(zhì)量屬性每個(gè)都很重要,但是根據(jù)系統(tǒng)特點(diǎn)需要對(duì)質(zhì)量屬性有優(yōu)先級(jí)排序,架構(gòu)設(shè)計(jì)時(shí)需要所有權(quán)衡和折中。
確定了優(yōu)先級(jí)之后,我們需要具體闡述針對(duì)每個(gè)質(zhì)量屬性采取了哪些方案,例如提升性能使用了緩存,提升可修改性使用了策略模式,提升可靠性使用了統(tǒng)一異常處理框架等等,具體方案可以參考本文第一章節(jié)。
第四個(gè)階段是報(bào)告階段,我們將評(píng)估過程和結(jié)果都匯總整理成文檔,其中包括質(zhì)量屬性效用樹、風(fēng)險(xiǎn)點(diǎn)、敏感點(diǎn)、權(quán)衡點(diǎn)、每次評(píng)估會(huì)議紀(jì)要以及最終架構(gòu)決策。
3 文章總結(jié)
第一系統(tǒng)滿足功能性需求是最基本的要求,作為架構(gòu)師不能就此止步,不僅應(yīng)該關(guān)注功能性需求,還應(yīng)該關(guān)注非功能性需求,質(zhì)量屬性就是衡量非功能性需求的重要指標(biāo)。
第二架構(gòu)評(píng)估方法分為基于問卷、基于度量、基于場(chǎng)景三種方式,目前業(yè)內(nèi)較為流行的是基于場(chǎng)景的評(píng)估方法,ATAM是一種優(yōu)秀的基于場(chǎng)景評(píng)估方法。
第三ATAM以質(zhì)量屬性效用樹為核心,幫助架構(gòu)師識(shí)別項(xiàng)目風(fēng)險(xiǎn)點(diǎn)、敏感點(diǎn)、權(quán)衡點(diǎn),指導(dǎo)架構(gòu)師做出合理架構(gòu)決策。
4 延伸閱讀
JAVA前線?
歡迎大家關(guān)注公眾號(hào)「JAVA前線」查看更多精彩分享,主要內(nèi)容包括源碼分析、實(shí)際應(yīng)用、架構(gòu)思維、職場(chǎng)分享、產(chǎn)品思考等等,同時(shí)也非常歡迎大家加我微信「java_front」一起交流學(xué)習(xí)
