精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

領(lǐng)域/驅(qū)動(dòng)設(shè)計(jì)對(duì)軟件復(fù)雜度的應(yīng)對(duì)

開(kāi)發(fā) 開(kāi)發(fā)工具
領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)關(guān)注的焦點(diǎn)在于領(lǐng)域和領(lǐng)域邏輯,因?yàn)檐浖到y(tǒng)的本質(zhì)其實(shí)是給客戶(hù)(用戶(hù))提供具有業(yè)務(wù)價(jià)值的領(lǐng)域功能。

不管是因?yàn)橐?guī)模與結(jié)構(gòu)制造的理解力障礙,還是因?yàn)樽兓瘞?lái)的預(yù)測(cè)能力問(wèn)題,最終的決定因素還是因?yàn)樾枨蟆ric Evans認(rèn)為“很多應(yīng)用程序最主要的復(fù)雜性并不在技術(shù)上,而是來(lái)自領(lǐng)域本身、用戶(hù)的活動(dòng)或業(yè)務(wù)”。因而,領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)關(guān)注的焦點(diǎn)在于領(lǐng)域和領(lǐng)域邏輯,因?yàn)檐浖到y(tǒng)的本質(zhì)其實(shí)是給客戶(hù)(用戶(hù))提供具有業(yè)務(wù)價(jià)值的領(lǐng)域功能。

軟件復(fù)雜度

一、需求引起的軟件復(fù)雜度

需求分為業(yè)務(wù)需求與質(zhì)量屬性需求,因而需求引起的復(fù)雜度可以分為兩個(gè)方面:技術(shù)復(fù)雜度與業(yè)務(wù)復(fù)雜度。

技術(shù)復(fù)雜度來(lái)自需求的質(zhì)量屬性,諸如安全、高性能、高并發(fā)、高可用性等需求,為軟件設(shè)計(jì)帶來(lái)了極大的挑戰(zhàn)。讓人難受的是這些因素彼此之間又可能互相矛盾互相影響。例如,系統(tǒng)安全性要求對(duì)訪問(wèn)進(jìn)行控制,無(wú)論是增加防火墻,還是對(duì)傳遞的消息進(jìn)行加密,又或者對(duì)訪問(wèn)請(qǐng)求進(jìn)行認(rèn)證和授權(quán),都需要為整個(gè)系統(tǒng)架構(gòu)添加額外的間接層。這不可避免會(huì)對(duì)訪問(wèn)的低延遲產(chǎn)生影響,拖慢了系統(tǒng)的整體性能。又例如為了滿(mǎn)足系統(tǒng)的高并發(fā)訪問(wèn),我們需要對(duì)應(yīng)用服務(wù)進(jìn)行物理分解,通過(guò)橫向增加更多的機(jī)器來(lái)分散訪問(wèn)負(fù)載;同時(shí),我們還可以將一個(gè)同步的訪問(wèn)請(qǐng)求拆分為多級(jí)步驟的異步請(qǐng)求,再通過(guò)引入消息中間件對(duì)這些請(qǐng)求進(jìn)行整合和分散處理。這種分離一方面增加了系統(tǒng)架構(gòu)的復(fù)雜性,另一方面也因?yàn)橐肓烁嗟馁Y源,使得系統(tǒng)的高可用面臨挑戰(zhàn),并增加了維護(hù)數(shù)據(jù)一致性的難度。

業(yè)務(wù)復(fù)雜度對(duì)應(yīng)了客戶(hù)的業(yè)務(wù)需求,因而這種復(fù)雜度往往會(huì)隨著需求規(guī)模的增大而增加。由于需求不可能做到完全獨(dú)立,一旦規(guī)模擴(kuò)大到一定程度,不僅產(chǎn)生了功能數(shù)量的增加,還會(huì)因?yàn)楣δ芑ハ嘀g的依賴(lài)與影響使得這種復(fù)雜度產(chǎn)生疊加,進(jìn)而影響到整個(gè)系統(tǒng)的質(zhì)量屬性,例如系統(tǒng)的可維護(hù)性與可擴(kuò)展性。在考慮系統(tǒng)的業(yè)務(wù)需求時(shí),還會(huì)因?yàn)闇贤ú粫场⒖蛻?hù)需求不清晰等多種局外因素帶來(lái)需求的變更和修改。如果不能很好地控制這種變更,就可能因?yàn)槎啻涡薷膶?dǎo)致業(yè)務(wù)邏輯糾纏不清,系統(tǒng)可能開(kāi)始慢慢腐爛,變得不可維護(hù),最終形成一種如Brian Foote和Joseph Yoder所說(shuō)的“大泥球”系統(tǒng)。

以電商系統(tǒng)的促銷(xiāo)規(guī)則為例。針對(duì)不同類(lèi)型的顧客與產(chǎn)品,商家會(huì)提供不同的促銷(xiāo)力度;促銷(xiāo)的形式多種多樣,包括贈(zèng)送積分、紅包、優(yōu)惠券、禮品;促銷(xiāo)的周期需要支持定制,既可以是特定的日期,例如雙十一促銷(xiāo),也可以是節(jié)假日的固定促銷(xiāo)模式。如果我們?cè)谠O(shè)計(jì)時(shí)沒(méi)有充分考慮促銷(xiāo)規(guī)則的復(fù)雜度,并處理好促銷(xiāo)規(guī)則與商品、顧客、賣(mài)家與支付乃至于物流、倉(cāng)儲(chǔ)之間的關(guān)系,開(kāi)發(fā)過(guò)程就會(huì)變得踉踉蹌蹌,舉步維艱。

技術(shù)復(fù)雜度與業(yè)務(wù)復(fù)雜度并非完全獨(dú)立,二者混合在一起產(chǎn)生的化合作用更讓系統(tǒng)的復(fù)雜度變得不可預(yù)期,難以掌控。同時(shí),技術(shù)的變化維度與業(yè)務(wù)的變化維度并不相同,產(chǎn)生變化的原因也不一致,倘若未能很好地界定二者之間的關(guān)系,系統(tǒng)架構(gòu)缺乏清晰邊界,會(huì)變得難以梳理。復(fù)雜度一旦增加,團(tuán)隊(duì)規(guī)模也將隨之?dāng)U大,再揉以嚴(yán)峻的交付周期、人員流動(dòng)等諸多因素,就好似將各種不穩(wěn)定的易燃易爆氣體混合在一個(gè)不可逃逸的密閉容器中一般,隨時(shí)都可能爆炸:

軟件復(fù)雜度

隨著業(yè)務(wù)需求的增加與變化,以及對(duì)質(zhì)量屬性的高標(biāo)準(zhǔn)要求,自然也引起了軟件系統(tǒng)規(guī)模的增大與結(jié)構(gòu)的繁雜,至于變化,則是軟件開(kāi)發(fā)繞不開(kāi)的話題。因此,當(dāng)我們面對(duì)一個(gè)相對(duì)復(fù)雜的軟件系統(tǒng)時(shí),通常面臨的問(wèn)題在于:

  • 問(wèn)題域過(guò)于龐大而復(fù)雜,使得從問(wèn)題域中尋求解決方案的挑戰(zhàn)增加。該問(wèn)題與軟件系統(tǒng)的規(guī)模有關(guān)。
  • 開(kāi)發(fā)人員將業(yè)務(wù)邏輯的復(fù)雜度與技術(shù)實(shí)現(xiàn)的復(fù)雜度混淆在一起。該問(wèn)題與軟件系統(tǒng)的結(jié)構(gòu)有關(guān)。
  • 隨著需求的增長(zhǎng)和變化,無(wú)法控制業(yè)務(wù)復(fù)雜度和技術(shù)復(fù)雜度。該問(wèn)題與軟件系統(tǒng)的變化有關(guān)。

針對(duì)這三個(gè)問(wèn)題,領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)都給出了自己的應(yīng)對(duì)措施。

二、領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)的應(yīng)對(duì)措施

1. 隔離業(yè)務(wù)復(fù)雜度與技術(shù)復(fù)雜度

要避免業(yè)務(wù)邏輯的復(fù)雜度與技術(shù)實(shí)現(xiàn)的復(fù)雜度混淆在一起,首要任務(wù)就是確定業(yè)務(wù)邏輯與技術(shù)實(shí)現(xiàn)的邊界,從而隔離各自的復(fù)雜度。這種隔離也是題中應(yīng)有之義,畢竟技術(shù)與業(yè)務(wù)的關(guān)注點(diǎn)完全不同。例如在電商的領(lǐng)域邏輯中,訂單業(yè)務(wù)關(guān)注的業(yè)務(wù)規(guī)則包括驗(yàn)證訂單有效性,計(jì)算訂單總額,提交和審核訂單的流程等;技術(shù)關(guān)注點(diǎn)則從實(shí)現(xiàn)層面保障這些業(yè)務(wù)能夠正確地完成,包括確保分布式系統(tǒng)之間的數(shù)據(jù)一致性,確保服務(wù)之間通信的正確性等。

業(yè)務(wù)邏輯并不關(guān)心技術(shù)是如何實(shí)現(xiàn)的。無(wú)論采用何種技術(shù),只要業(yè)務(wù)需求不變,業(yè)務(wù)規(guī)則就不會(huì)變化。換言之,理想狀態(tài)下,我們應(yīng)該保證業(yè)務(wù)規(guī)則與技術(shù)實(shí)現(xiàn)是正交的。

領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)通過(guò)分層架構(gòu)與六邊形架構(gòu)確保業(yè)務(wù)邏輯與技術(shù)實(shí)現(xiàn)的隔離。

(1) 分層架構(gòu)的關(guān)注點(diǎn)分離

分層架構(gòu)遵循了“關(guān)注點(diǎn)分離”原則,將屬于業(yè)務(wù)邏輯的關(guān)注點(diǎn)放到領(lǐng)域?qū)?Domain Layer)中,而將支撐業(yè)務(wù)邏輯的技術(shù)實(shí)現(xiàn)放到基礎(chǔ)設(shè)施層(Infrastructure Layer)中。同時(shí),領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)又頗具創(chuàng)見(jiàn)的引入了應(yīng)用層(Application Layer)。應(yīng)用層扮演了雙重角色。一方面它作為業(yè)務(wù)邏輯的外觀(Facade),暴露了能夠體現(xiàn)業(yè)務(wù)用例的應(yīng)用服務(wù)接口;另一方面它又是業(yè)務(wù)邏輯與技術(shù)實(shí)現(xiàn)的粘合劑,實(shí)現(xiàn)二者之間的協(xié)作。

下圖展現(xiàn)的就是一個(gè)典型的領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)分層架構(gòu)。藍(lán)色區(qū)域的內(nèi)容與業(yè)務(wù)邏輯有關(guān),灰色區(qū)域的內(nèi)容與技術(shù)實(shí)現(xiàn)有關(guān),二者涇渭分明,然后匯合在應(yīng)用層。應(yīng)用層確定了業(yè)務(wù)邏輯與技術(shù)實(shí)現(xiàn)的邊界,通過(guò)直接依賴(lài)或者依賴(lài)注入(DI,Dependency Injection)的方式將二者結(jié)合起來(lái):

(2) 六邊形架構(gòu)的內(nèi)外分離

由Cockburn提出的六邊形架構(gòu)則以“內(nèi)外分離”的方式,更加清晰地勾勒出業(yè)務(wù)邏輯與技術(shù)實(shí)現(xiàn)的邊界,且將業(yè)務(wù)邏輯放在了架構(gòu)的核心位置。這種架構(gòu)模式改變了我們觀察系統(tǒng)架構(gòu)的視角:

體現(xiàn)業(yè)務(wù)邏輯的應(yīng)用層與領(lǐng)域?qū)犹幱诹呅渭軜?gòu)的內(nèi)核,并通過(guò)內(nèi)部的六邊形邊界與基礎(chǔ)設(shè)施的模塊隔離開(kāi)。當(dāng)我們?cè)谶M(jìn)行軟件開(kāi)發(fā)時(shí),只要恪守架構(gòu)上的六邊形邊界,就不會(huì)讓技術(shù)實(shí)現(xiàn)的復(fù)雜度污染到業(yè)務(wù)邏輯,保證了領(lǐng)域的整潔。邊界還隔離了變化產(chǎn)生的影響。如果我們?cè)陬I(lǐng)域?qū)踊驊?yīng)用層抽象了技術(shù)實(shí)現(xiàn)的接口,再通過(guò)依賴(lài)注入將控制的方向倒轉(zhuǎn),業(yè)務(wù)內(nèi)核就會(huì)變得更加的穩(wěn)定,不會(huì)因?yàn)榧夹g(shù)選型或其他決策的變化而導(dǎo)致領(lǐng)域代碼的修改。

(3) 案例:隔離數(shù)據(jù)庫(kù)與緩存的訪問(wèn)

領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)建議我們?cè)陬I(lǐng)域?qū)咏①Y源庫(kù)(Repository)的抽象,它的實(shí)現(xiàn)則被放在基礎(chǔ)設(shè)施層,然后采用依賴(lài)注入在運(yùn)行時(shí)為業(yè)務(wù)邏輯注入具體的資源庫(kù)實(shí)現(xiàn)。那么,對(duì)于處于內(nèi)核之外的Repositories模塊而言,即使選擇從MyBatis遷移到Sprint Data,領(lǐng)域代碼都不會(huì)受到牽連:

  1. package practiceddd.ecommerce.ordercontext.application; 
  2.  
  3. @Transaction 
  4. public class OrderAppService { 
  5.    @Service 
  6.    private PlaceOrderService placeOrder; 
  7.     
  8.    public void placeOrder(Identity buyerId, List<OrderItem> items, ShippingAddress shipping, BillingAddress billing) { 
  9.        try { 
  10.            palceOrder.execute(buyerId, items, shipping, billing); 
  11.        } catch (OrderRepositoryException | InvalidOrderException | Exception ex) { 
  12.            ex.printStackTrace(); 
  13.            logger.error(ex.getMessage()); 
  14.        } 
  15.    } 
  16.  
  17. package practiceddd.ecommerce.ordercontext.domain; 
  18.  
  19. public interface OrderRepository { 
  20.    List<Order> forBuyerId(Identity buyerId); 
  21.    void add(Order order); 
  22. }  
  23.  
  24. public class PlaceOrderService { 
  25.    @Repository 
  26.    private OrderRepository orderRepository; 
  27.  
  28.    @Service 
  29.    private OrderValidator orderValidator;     
  30.  
  31.    public void execute(Identity buyerId, List<OrderItem> items, ShippingAddress shipping, BillingAddress billing) { 
  32.        Order order = Order.create(buyerId, items, shipping, billing); 
  33.        if (orderValidator.isValid(order)) { 
  34.            orderRepository.add(order); 
  35.        } else { 
  36.            throw new InvalidOrderException(String.format("the order which placed by buyer with %s is invalid.", buyerId)); 
  37.        } 
  38.    } 
  39.  
  40. package practiceddd.ecommerce.ordercontext.infrastructure.db; 
  41.  
  42. public class OrderMybatisRepository implements OrderRepository {} 
  43. public class OrderSprintDataRepository implements OrderRepository {} 

對(duì)緩存的處理可以如法炮制,但它與資源庫(kù)稍有不同之處。資源庫(kù)作為訪問(wèn)領(lǐng)域模型對(duì)象的入口,其本身提供的增刪改查功能,在抽象層面上是對(duì)領(lǐng)域資源的訪問(wèn)。因此在領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)中,我們通常將資源庫(kù)的抽象歸屬到領(lǐng)域?qū)印?duì)緩存的訪問(wèn)則不相同,它的邏輯就是對(duì)key和value的操作,與具體的領(lǐng)域無(wú)關(guān)。倘若要為緩存的訪問(wèn)方法定義抽象接口,在分層的歸屬上應(yīng)該屬于應(yīng)用層,至于實(shí)現(xiàn)則屬于技術(shù)范疇,應(yīng)該放在基礎(chǔ)設(shè)施層:

  1. package practiceddd.ecommerce.ordercontext.application; 
  2.  
  3. @Transaction 
  4. public class OrderAppService { 
  5.    @Repository 
  6.    private OrderRepository orderRepository; 
  7.  
  8.    @Service 
  9.    private CacheClient<List<Order>> cacheClient; 
  10.     
  11.    public List<Order> findBy(Identity buyerId) { 
  12.        Optional<List<Order>> cachedOrders = cacheClient.get(buyerId.value()); 
  13.        if (cachedOrders.isPresent()) { 
  14.            return orders.get(); 
  15.        }  
  16.        List<Order> orders = orderRepository.forBuyerId(buyerId); 
  17.        if (!orders.isEmpty()) { 
  18.            cacheClient.put(buyerId.value(), orders); 
  19.        } 
  20.        return orders; 
  21.    } 
  22.  
  23. package practiceddd.ecommerce.ordercontext.application.cache; 
  24.  
  25. public interface CacheClient<T> { 
  26.    Optional<T> get(String key); 
  27.    void put(String key, T value); 
  28.  
  29. package practiceddd.ecommerce.ordercontext.infrastructure.cache; 
  30.  
  31. public class RedisCacheClient<T> implements CacheClient<T> {} 

2. 限界上下文的分而治之

在前面分析緩存訪問(wèn)接口的歸屬時(shí),我們將接口放在了系統(tǒng)的應(yīng)用層。從層次的職責(zé)來(lái)看,這樣的設(shè)計(jì)是合理的,但它卻使得系統(tǒng)的應(yīng)用層變得更加臃腫,職責(zé)也變得不夠單一了。這是分層架構(gòu)與六邊形架構(gòu)的局限所在,因?yàn)檫@兩種架構(gòu)模式僅僅體現(xiàn)了一個(gè)軟件系統(tǒng)的邏輯劃分。倘若我們將一個(gè)軟件系統(tǒng)視為一個(gè)縱橫交錯(cuò)的魔方,前述的邏輯劃分僅僅是一種水平方向的劃分。至于垂直方向的劃分,則是面向垂直業(yè)務(wù)的切割。這種方式更利于控制軟件系統(tǒng)的規(guī)模,將一個(gè)龐大的軟件系統(tǒng)劃分為松散耦合的多個(gè)小系統(tǒng)的組合。

針對(duì)前述案例,我們可以將緩存視為一個(gè)獨(dú)立的子系統(tǒng)。它同樣擁有自己的業(yè)務(wù)邏輯和技術(shù)實(shí)現(xiàn),因而也可以為其建立屬于緩存領(lǐng)域的分層架構(gòu)。在架構(gòu)的宏觀視角,這個(gè)緩存子系統(tǒng)與訂單子系統(tǒng)處于同一個(gè)抽象層次,這一概念在領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)中,被稱(chēng)之為限界上下文(Bounded Context)。

針對(duì)龐大而復(fù)雜的問(wèn)題域,限界上下文采用了“分而治之”的思想對(duì)問(wèn)題域進(jìn)行了分解,有效地控制了問(wèn)題域的規(guī)模,進(jìn)而控制了整個(gè)系統(tǒng)的規(guī)模。一旦規(guī)模減小,無(wú)論業(yè)務(wù)復(fù)雜度還是技術(shù)復(fù)雜度,都會(huì)得到顯著的降低,在對(duì)領(lǐng)域進(jìn)行分析以及建模時(shí),也能變得更容易。如果說(shuō)分層架構(gòu)與六邊形架構(gòu)確保了業(yè)務(wù)邏輯與技術(shù)實(shí)現(xiàn)的隔離,則限界上下文對(duì)整個(gè)系統(tǒng)進(jìn)行了劃分,將一個(gè)大系統(tǒng)拆分為一個(gè)個(gè)小系統(tǒng)后,我們?cè)倮梅謱蛹軜?gòu)與六邊形架構(gòu)思想對(duì)其進(jìn)行邏輯分層,設(shè)計(jì)會(huì)變得更易于把控,系統(tǒng)的架構(gòu)也會(huì)變得更加的清晰。

案例:限界上下文幫助架構(gòu)的演進(jìn)

國(guó)際報(bào)稅系統(tǒng)是為跨國(guó)公司的駐外出差雇員(系統(tǒng)中被稱(chēng)之為Assignee)提供方便一體化的稅收信息填報(bào)平臺(tái)。客戶(hù)是一家會(huì)計(jì)師事務(wù)所,該事務(wù)所的專(zhuān)員(Admin)通過(guò)該平臺(tái)可以收集雇員提交的報(bào)稅信息,然后對(duì)這些信息進(jìn)行稅務(wù)評(píng)審。如果Admin評(píng)審出信息有問(wèn)題,則返回給Assignee重新修改和填報(bào)。一旦信息確認(rèn)無(wú)誤,則進(jìn)行稅收分析和計(jì)算,并獲得最終的稅務(wù)報(bào)告提交給當(dāng)?shù)卣约肮蛦T本人。

系統(tǒng)主要涉及的功能包括:

  • 駐外出差雇員的薪酬與福利
  • 稅收計(jì)劃與合規(guī)評(píng)審
  • 對(duì)稅收評(píng)審的分配管理
  • 稅收策略設(shè)計(jì)與評(píng)審
  • 對(duì)駐外出差雇員的稅收合規(guī)評(píng)審
  • 全球的Visa服務(wù)

主要涉及的用戶(hù)角色包括:

  • Assignee:駐外出差雇員
  • Admin:稅務(wù)專(zhuān)員
  • Client:出差雇員的雇主

在早期的架構(gòu)設(shè)計(jì)時(shí),架構(gòu)師并沒(méi)有對(duì)整個(gè)系統(tǒng)的問(wèn)題域進(jìn)行拆分,而是基于用戶(hù)角色對(duì)系統(tǒng)進(jìn)行了簡(jiǎn)單粗暴的劃分,分為兩個(gè)相對(duì)獨(dú)立的子系統(tǒng):Frond End與Office End。這兩個(gè)子系統(tǒng)單獨(dú)部署,分別面向Assignee與Admin。系統(tǒng)之間的集成則通過(guò)消息和Web Service進(jìn)行通信。兩個(gè)子系統(tǒng)的開(kāi)發(fā)分屬不同的團(tuán)隊(duì),F(xiàn)rond End由美國(guó)的團(tuán)隊(duì)負(fù)責(zé)開(kāi)發(fā)與維護(hù),而Office End則由印度的團(tuán)隊(duì)負(fù)責(zé)。整個(gè)架構(gòu)如下圖所示:

采用這種架構(gòu)面臨如下問(wèn)題:

  • 龐大的代碼庫(kù):整個(gè)Front End和Office End都沒(méi)有做物理分解,隨著需求的增多,代碼庫(kù)變得格外龐大
  • 分散的邏輯:系統(tǒng)分解的邊界是不合理的,沒(méi)有按照業(yè)務(wù)分解,而是按照用戶(hù)的角色進(jìn)行分解,導(dǎo)致大量相似的邏輯分散在兩個(gè)不同的子系統(tǒng)中
  • 重復(fù)的數(shù)據(jù):兩個(gè)子系統(tǒng)中存在業(yè)務(wù)重疊,因而也導(dǎo)致了部分?jǐn)?shù)據(jù)的重復(fù)
  • 復(fù)雜的集成:Front End與Office End因?yàn)槟承┫嚓P(guān)的業(yè)務(wù)需要彼此通信,這種集成關(guān)系是雙向的,且由兩個(gè)不同的團(tuán)隊(duì)開(kāi)發(fā),導(dǎo)致集成的接口混亂,消息協(xié)議多樣化
  • 知識(shí)未形成共享:兩個(gè)團(tuán)隊(duì)完全獨(dú)立開(kāi)發(fā),沒(méi)有掌握端對(duì)端的整體流程,團(tuán)隊(duì)之間沒(méi)有形成知識(shí)的共享
  • 無(wú)法應(yīng)對(duì)需求變化: 新增需求包括對(duì)國(guó)際旅游、Visa的支持,現(xiàn)有系統(tǒng)的架構(gòu)無(wú)法很好地支持這些變化

采用領(lǐng)域驅(qū)動(dòng)設(shè)計(jì),我們將架構(gòu)的主要關(guān)注點(diǎn)放在了“領(lǐng)域”,與客戶(hù)進(jìn)行了充分的需求溝通和交流。通過(guò)分析已有系統(tǒng)的問(wèn)題域,結(jié)合客戶(hù)提出的新需求,對(duì)整個(gè)問(wèn)題域進(jìn)行了梳理,并利用限界上下文對(duì)問(wèn)題域進(jìn)行了分解,獲得了如下限界上下文:

  • Account Management:管理用戶(hù)的身份與配置信息
  • Calendar Management:管理用戶(hù)的日程與旅行足跡

之后,客戶(hù)希望能改進(jìn)需求,做到全球范圍內(nèi)的工作指派與管理,目的在于提高公司的運(yùn)營(yíng)效率。通過(guò)對(duì)領(lǐng)域的分析,我們又識(shí)別出兩個(gè)限界上下文。在原有的系統(tǒng)架構(gòu)中,這兩個(gè)限界上下文同時(shí)處于Front End與Office End之中,屬于重復(fù)開(kāi)發(fā)的業(yè)務(wù)邏輯:

  • Work Record Management:實(shí)現(xiàn)工作的分配與任務(wù)的跟蹤
  • File Sharing:目的是實(shí)現(xiàn)客戶(hù)與會(huì)計(jì)師事務(wù)所之間的文件交換

隨著我們對(duì)領(lǐng)域知識(shí)的逐漸深入理解與分析,又隨之識(shí)別出如下限界上下文:

  • Consent:管理合法的遵守法規(guī)的狀態(tài)
  • Notification:管理系統(tǒng)與客戶(hù)之間的交流
  • Questionnaire:對(duì)問(wèn)卷調(diào)查的數(shù)據(jù)收集

這個(gè)領(lǐng)域分析的過(guò)程實(shí)際上就是通過(guò)對(duì)領(lǐng)域的分析,引入限界上下文對(duì)問(wèn)題域進(jìn)行分解,通過(guò)降低規(guī)模的方式降低問(wèn)題域的復(fù)雜度;同時(shí),通過(guò)為模型確定清晰的邊界,使得系統(tǒng)的結(jié)構(gòu)變得更加的清晰,保證了領(lǐng)域邏輯的一致性。一旦確定了清晰的領(lǐng)域模型,就能夠幫助我們更加容易地發(fā)現(xiàn)系統(tǒng)的可重用點(diǎn)與可擴(kuò)展點(diǎn),并遵循“高內(nèi)聚松耦合”原則對(duì)系統(tǒng)職責(zé)進(jìn)行合理分配,再輔以分層架構(gòu)劃分邏輯邊界,如下圖所示:

我們將識(shí)別出來(lái)的限界上下文定義為微服務(wù),并對(duì)外公開(kāi)REST服務(wù)接口。UI Applications是一個(gè)薄薄的展現(xiàn)層,它會(huì)調(diào)用后端的RESTful服務(wù),也使得服務(wù)在保證接口不變的前提下能夠單獨(dú)演化。每個(gè)服務(wù)都是獨(dú)立的,可以單獨(dú)部署,因而可以針對(duì)服務(wù)建立單獨(dú)的代碼庫(kù)和對(duì)應(yīng)的特性團(tuán)隊(duì)(Feature Team)。服務(wù)的重用性和可擴(kuò)展性也有了更好的保障,服務(wù)與UI之間的集成變得更簡(jiǎn)單,整個(gè)架構(gòu)更加清晰了。

3. 領(lǐng)域模型對(duì)領(lǐng)域知識(shí)的抽象

領(lǐng)域模型是對(duì)業(yè)務(wù)需求的一種抽象,表達(dá)了領(lǐng)域概念、領(lǐng)域規(guī)則以及領(lǐng)域概念之間的關(guān)系。一個(gè)好的領(lǐng)域模型是對(duì)統(tǒng)一語(yǔ)言的可視化表示,通過(guò)它可以減少需求溝通可能出現(xiàn)的歧義;通過(guò)提煉領(lǐng)域知識(shí),并運(yùn)用抽象的領(lǐng)域模型去表達(dá),就可以達(dá)到對(duì)領(lǐng)域邏輯的化繁為簡(jiǎn)。模型是封裝,實(shí)現(xiàn)了對(duì)業(yè)務(wù)細(xì)節(jié)的隱藏;模型是抽象,提取了領(lǐng)域知識(shí)的共同特征,保留了面對(duì)變化時(shí)能夠良好擴(kuò)展的可能性。

案例:項(xiàng)目管理系統(tǒng)的領(lǐng)域模型

我們開(kāi)發(fā)的項(xiàng)目管理系統(tǒng)需要支持多種軟件項(xiàng)目管理流程,例如瀑布、RUP、XP或者Scrum。這些項(xiàng)目管理流程是迥然不同的,如果需要各自提供不同的解決方案,就會(huì)使得系統(tǒng)的模型變得非常復(fù)雜,也可能引入許多不必要的重復(fù)。通過(guò)領(lǐng)域建模,我們可以對(duì)項(xiàng)目管理領(lǐng)域的知識(shí)進(jìn)行抽象,尋找具有共同特征的領(lǐng)域概念。這就需要分析各種項(xiàng)目管理流程的主要特征與表現(xiàn),才能從中提煉出領(lǐng)域模型。

瀑布式軟件開(kāi)發(fā)由需求、分析、設(shè)計(jì)、編碼、測(cè)試、驗(yàn)收六個(gè)階段構(gòu)成,每個(gè)階段都由不同的活動(dòng)構(gòu)成,這些活動(dòng)可能是設(shè)計(jì)或開(kāi)發(fā)任務(wù),也可能是召開(kāi)評(píng)審會(huì)。流程如下圖所示:

RUP清晰地劃分了四個(gè)階段:先啟階段、細(xì)化階段、構(gòu)造階段與交付階段。每個(gè)階段可以包含一到多個(gè)迭代,每個(gè)迭代有不同的工作,例如業(yè)務(wù)建模、分析設(shè)計(jì)、配置與變更管理等。RUP的流程如下圖所示:

XP作為一種敏捷方法,采用了迭代的增量式開(kāi)發(fā),提倡為客戶(hù)交付具有業(yè)務(wù)價(jià)值的可運(yùn)行軟件。在執(zhí)行交付計(jì)劃之前,XP要求團(tuán)隊(duì)對(duì)系統(tǒng)的架構(gòu)做一次預(yù)研(Architectual Spike,又被譯為架構(gòu)穿刺)。當(dāng)架構(gòu)的初始方案確定后,就可以進(jìn)入每次小版本的交付。每個(gè)小版本交付又被劃分為多個(gè)周期相同的迭代。在迭代過(guò)程中,要求執(zhí)行一些必須的活動(dòng),如編寫(xiě)用戶(hù)故事、故事點(diǎn)估算、驗(yàn)收測(cè)試等。XP的流程如下圖所示:

Scrum同樣是迭代的增量開(kāi)發(fā)過(guò)程。項(xiàng)目在開(kāi)始之初,需要在準(zhǔn)備階段確定系統(tǒng)愿景、梳理業(yè)務(wù)用例、確定產(chǎn)品待辦項(xiàng)(product backlog)、制定發(fā)布計(jì)劃以及組建團(tuán)隊(duì)。一旦在確定了產(chǎn)品待辦項(xiàng)以及發(fā)布計(jì)劃之后,就進(jìn)入sprint迭代階段。sprint迭代過(guò)程是一個(gè)固定時(shí)長(zhǎng)的項(xiàng)目過(guò)程,在這個(gè)過(guò)程中,整個(gè)團(tuán)隊(duì)需要召開(kāi)計(jì)劃會(huì)議、每日站會(huì)、評(píng)審會(huì)議和回顧會(huì)議。Scrum的流程如下圖所示:

不同的項(xiàng)目管理流程具有不同的業(yè)務(wù)概念。例如瀑布式開(kāi)發(fā)分為了六個(gè)階段,但卻沒(méi)有發(fā)布和迭代的概念。RUP沒(méi)有發(fā)布的概念,而Scrum又為迭代引入了sprint的概念。

不同的項(xiàng)目管理流程具有不同的業(yè)務(wù)規(guī)則。例如RUP的四個(gè)階段會(huì)包含多個(gè)迭代周期,每個(gè)迭代周期都需要完成對(duì)應(yīng)的工作,只是不同的工作在不同階段所占的比重不同。XP需要在進(jìn)入發(fā)布階段之前,進(jìn)行架構(gòu)預(yù)研,而在每次小版本發(fā)布之前,都需要進(jìn)行驗(yàn)收測(cè)試和客戶(hù)驗(yàn)收。Scrum的sprint是一個(gè)基本固定的流程,每個(gè)迭代召開(kāi)的四會(huì)(計(jì)劃會(huì)議、評(píng)審會(huì)議、回顧會(huì)議與每日站會(huì))都有明確的目標(biāo)。

領(lǐng)域建模就是要從這些紛繁復(fù)雜的領(lǐng)域邏輯中尋找到能夠表示項(xiàng)目管理領(lǐng)域的概念,并利用面向?qū)ο蠼7妒交蚱渌妒綄?duì)概念進(jìn)行抽象,并確定它們之間的關(guān)系。經(jīng)過(guò)對(duì)這些項(xiàng)目管理流程的分析,我們雖然發(fā)現(xiàn)在業(yè)務(wù)概念和規(guī)則上確有不同之處,但由于它們都?xì)w屬于軟件開(kāi)發(fā)領(lǐng)域,我們自然也能尋找到某些共同特征的蛛絲馬跡。

首先,從項(xiàng)目管理系統(tǒng)的角度看,無(wú)論針對(duì)何種項(xiàng)目管理流程,我們的主題需求是不變的,就是要為這些管理流程制定軟件開(kāi)發(fā)計(jì)劃(Plan)。不同之處在于,計(jì)劃可以由多個(gè)階段(Phase)組成,也可以由多個(gè)發(fā)布(Release)組成。一些項(xiàng)目管理流程沒(méi)有發(fā)布的概念,我們可以認(rèn)為是一個(gè)發(fā)布。那么,到底是發(fā)布包含了多個(gè)階段,還是階段包含了多個(gè)發(fā)布呢?我們發(fā)現(xiàn)在XP中,明顯地劃分了兩個(gè)階段:Architecture Spike與Release Planning,而發(fā)布只屬于Release Planning階段。因而從概念內(nèi)涵上,我們可以認(rèn)為是階段(Phase)包含了發(fā)布(Release)。每個(gè)發(fā)布又包含了一到多個(gè)迭代(Iteration),至于Scrum的sprint概念其實(shí)可以看做是迭代的一種特例。每個(gè)迭代可以開(kāi)展多種不同的活動(dòng)(Activity),這些活動(dòng)可以是整個(gè)團(tuán)隊(duì)參與的會(huì)議,也可以是部分成員或特定角色執(zhí)行的實(shí)踐。對(duì)于計(jì)劃而言,我們還需要跟蹤任務(wù)(Task)。與活動(dòng)不同,任務(wù)具有明確的計(jì)劃起止時(shí)間、實(shí)際起止時(shí)間、工作量、優(yōu)先級(jí)與承擔(dān)人。

于是,我們提煉出如下的統(tǒng)一領(lǐng)域模型:

為了項(xiàng)目管理者更加方便地制定項(xiàng)目計(jì)劃,產(chǎn)品經(jīng)理提出了計(jì)劃模板功能。當(dāng)管理者選擇對(duì)應(yīng)的項(xiàng)目管理生命周期類(lèi)型后,系統(tǒng)會(huì)自動(dòng)創(chuàng)建滿(mǎn)足其規(guī)則的初始計(jì)劃。基于該需求,我們更新了之前的領(lǐng)域模型:

在增加的領(lǐng)域模型中,LifeCycleSpecification是一個(gè)隱含的概念,遵循領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)提出的規(guī)格(Specification)模式,封裝了項(xiàng)目開(kāi)發(fā)生命周期的約束規(guī)則。

領(lǐng)域模型以可視化的方式清晰地表達(dá)了業(yè)務(wù)含義,我們可以根據(jù)這個(gè)模型來(lái)指導(dǎo)后面的程序設(shè)計(jì)與編碼實(shí)現(xiàn)。當(dāng)增加新的需求或者需求發(fā)生變化時(shí),我們能夠敏銳地捕捉到現(xiàn)有模型的不匹配之處,并對(duì)其進(jìn)行更新。領(lǐng)域模型傳遞了知識(shí),可以作為交流的載體,符合人們的心智模型,有利于讓開(kāi)發(fā)人員從紛繁復(fù)雜的業(yè)務(wù)中解脫出來(lái)。這是領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)對(duì)于前述第三個(gè)問(wèn)題——控制業(yè)務(wù)復(fù)雜度的解答。

【本文為51CTO專(zhuān)欄作者“張逸”原創(chuàng)稿件,轉(zhuǎn)載請(qǐng)聯(lián)系原作者】

戳這里,看該作者更多好文

責(zé)任編輯:趙寧寧 來(lái)源: 51CTO專(zhuān)欄
相關(guān)推薦

2018-12-18 10:11:37

軟件復(fù)雜度軟件系統(tǒng)軟件開(kāi)發(fā)

2024-04-25 08:33:25

算法時(shí)間復(fù)雜度空間復(fù)雜度

2021-09-17 10:44:50

算法復(fù)雜度空間

2024-04-16 08:19:40

架構(gòu)高可用消息隊(duì)列

2020-12-30 09:20:27

代碼

2015-10-13 09:43:43

復(fù)雜度核心

2017-12-02 18:53:27

滴滴出行業(yè)務(wù)中臺(tái)對(duì)策

2020-08-24 08:15:29

軟件互聯(lián)網(wǎng)分布式

2021-01-05 10:41:42

算法時(shí)間空間

2014-09-11 15:05:40

驅(qū)動(dòng)設(shè)計(jì)驅(qū)動(dòng)開(kāi)發(fā)

2017-07-14 10:55:05

2014-09-26 10:00:25

驅(qū)動(dòng)設(shè)計(jì)DDD領(lǐng)域

2009-07-09 10:45:16

C#基本概念復(fù)雜度遞歸與接口

2019-11-18 12:41:35

算法Python計(jì)算復(fù)雜性理論

2021-10-15 09:43:12

希爾排序復(fù)雜度

2022-08-16 09:04:23

代碼圈圈復(fù)雜度節(jié)點(diǎn)

2019-12-24 09:46:00

Linux設(shè)置密碼

2022-02-22 10:11:01

系統(tǒng)軟件架構(gòu)

2020-02-06 13:59:48

javascript算法復(fù)雜度

2012-06-21 09:24:05

軟件定義網(wǎng)絡(luò)SDN
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

亚洲国产专区| 亚洲欧美在线综合| 久久奇米777| 国产成人中文字幕| 亚洲二区在线播放| 久久香蕉精品香蕉| 欧美主播一区二区三区| 公共露出暴露狂另类av| 日本激情一区二区三区| 日产欧产美韩系列久久99| 成年人精品视频| 久久丫精品国产亚洲av不卡| 国产亚洲欧美日韩精品一区二区三区| 亚洲精品欧美专区| 欧美激情国产日韩| 亚洲av无码国产精品永久一区| 久久精品盗摄| 久久777国产线看观看精品| 久久精品老司机| 亚洲2区在线| 欧美日韩在线三区| 国产女大学生av| caoporn免费在线视频| 91香蕉视频污| 99久久精品免费看国产一区二区三区| 亚洲精品男人的天堂| 午夜精品视频| 日韩视频亚洲视频| 性欧美精品中出| 麻豆一区一区三区四区| 欧美一级淫片007| 天天插天天操天天射| 阿v视频在线观看| 亚洲精品国产视频| 中文字幕人成一区| 91caoporn在线| 91免费观看国产| 国产精品免费一区二区| 国产欧美熟妇另类久久久| 日韩成人av影视| 日韩免费观看视频| 中文字幕免费在线观看视频| 亚洲精品黄色| 亚州欧美日韩中文视频| 青春草免费视频| 亚洲色图插插| 久久手机免费视频| www深夜成人a√在线| 欧美wwwww| 日韩中文av在线| 在线观看日本黄色| 日韩av在线播放网址| 永久免费精品影视网站| 免费视频91蜜桃| 成人激情免费视频| 日韩中文在线观看| 国产suv一区二区三区| 欧美一区二区| 欧美激情综合亚洲一二区| 黄色在线观看免费| 亚洲精品资源| 欧洲s码亚洲m码精品一区| 日韩色图在线观看| 视频一区中文字幕国产| 国产精品日韩在线一区| 一二三四区在线| 国产一区二区在线观看视频| 91成人伦理在线电影| 日韩专区第一页| 91麻豆国产自产在线观看| 日本一区二区三区视频免费看| 国产午夜在线视频| 中文字幕一区二区三区在线不卡 | 男人日女人下面视频| 色老头视频在线观看| 国产精品国产三级国产三级人妇| 日韩最新中文字幕| 2018av在线| 色一情一乱一乱一91av| 欧美婷婷精品激情| 亚洲欧美日本国产| 亚洲欧美激情在线视频| 黄色激情小视频| 欧美日本久久| 欧洲成人在线观看| 国产一区二区在线视频聊天| 高清不卡在线观看| 欧美日韩亚洲一区二区三区四区| 岛国在线大片| 亚洲精品免费电影| 超碰97人人射妻| 白嫩亚洲一区二区三区| 亚洲国产精品中文| 亚洲欧美色图视频| 天天做天天爱天天爽综合网| 久久久伊人日本| 久久中文字幕免费| 国产精品白丝jk黑袜喷水| 久久久久久欧美精品色一二三四 | 久久久久久久久久久久久夜| 国产高清免费在线| 中国色在线日|韩| 91麻豆精品91久久久久久清纯 | 中文字幕成人av| 黄网站色视频免费观看| 亚洲成人人体| 亚洲成人xxx| 女同久久另类69精品国产| 99精品热视频只有精品10| 国产免费一区二区三区香蕉精| 天天干天天插天天操| 国产精品久久久一本精品| 欧美精品自拍视频| 国产精品日韩精品在线播放| 亚洲美女久久久| 精品少妇一二三区| 六月丁香综合在线视频| 蜜桃传媒视频第一区入口在线看| 91一区二区三区在线| 欧美中文字幕一二三区视频| 在线视频 日韩| 欧美精品18| 91美女片黄在线观| 91ph在线| 欧美三级一区二区| 谁有免费的黄色网址| 中文日韩在线| 国产精品久久久久久久久久久久午夜片 | 9999在线精品视频| 国产一级揄自揄精品视频| 精品在线播放视频| 成人精品免费视频| 4444亚洲人成无码网在线观看| 久久影视精品| 亚洲欧洲日本专区| 国产精品第5页| 26uuu亚洲婷婷狠狠天堂| 欧美亚洲黄色片| 亚洲三级av| 欧美激情2020午夜免费观看| 亚洲av无码一区二区乱子伦| 亚洲久草在线视频| 一本之道在线视频| 中文字幕一区二区精品区| 91系列在线观看| 超碰电影在线播放| 欧美一级在线视频| 免费又黄又爽又色的视频| 国产精一品亚洲二区在线视频| 国产高清精品软男同| 婷婷丁香久久| 久久99国产精品久久久久久久久| av免费观看在线| 亚洲激情中文1区| 中文字幕永久免费| 99精品国产福利在线观看免费 | 亚洲成a人v欧美综合天堂麻豆| 在线这里只有精品| 99久久99久久精品免费看小说.| 日韩高清在线一区| 亚洲午夜精品久久久中文影院av| 婷婷久久免费视频| 另类图片亚洲另类| 亚洲精品国产av| 激情懂色av一区av二区av| 成人手机在线免费视频| 午夜亚洲视频| 亚洲mv在线看| 久久久国产精品入口麻豆| 欧美激情xxxxx| 日本亚洲一区| 欧美麻豆精品久久久久久| 国产黄色小视频网站| 成人性生交大片免费看中文| 免费无码毛片一区二三区| 亚洲系列另类av| 国产欧美精品一区二区三区介绍| 动漫一区在线| 日韩美女av在线| 亚洲天堂狠狠干| 亚洲一卡二卡三卡四卡无卡久久| 波多野结衣先锋影音| 日本欧美一区二区三区乱码| 综合操久久久| 女一区二区三区| 国产精品自拍网| 超碰成人av| 日韩视频免费看| 四虎在线观看| 欧美一区二区三区免费在线看 | 久草中文综合在线| 97超碰人人澡| 天堂网在线观看国产精品| 精品在线视频一区二区| 日韩精品第二页| 欧美有码在线观看视频| 成人影院在线观看| 亚洲午夜激情免费视频| 亚洲国产精品一| 精品视频一区三区九区| 国产精品自拍视频一区| 国产精品美女久久久久高潮 | 中文字幕av在线一区二区三区| 制服.丝袜.亚洲.中文.综合懂| 久久性色av| 男人添女荫道口图片| 欧美成人自拍| 日本午夜一区二区三区| 精品久久ai| 亚洲最大的免费| 最新日韩一区| 欧美性做爰毛片| 日韩三级免费| 日韩视频免费大全中文字幕| 九色蝌蚪在线| 亚洲国产精品女人久久久| 国产色在线视频| 欧洲精品一区二区三区在线观看| 精品成人久久久| 亚洲综合无码一区二区| 国产一区二区三区在线视频观看| 国产婷婷一区二区| av在线网站观看| 成人免费av网站| 免费黄色av网址| 国精产品一区一区三区mba视频 | 亚洲人成电影在线观看天堂色| 日本黄色一区二区三区| 欧美激情在线免费| 日本欧美爱爱爱| 黄色软件视频在线观看| 欧美黑人又粗大| 神马午夜伦理不卡| 久99久在线视频| 香蕉成人app免费看片| 久久福利视频网| 怡红院在线播放| 欧美成人久久久| 91麻豆免费在线视频| 久久香蕉国产线看观看av| 黄色网页在线播放| 久久精品人人爽| 顶级网黄在线播放| 欧美插天视频在线播放| a在线免费观看| 欧美富婆性猛交| 男女在线观看视频| 久久久久久久久网站| heyzo高清在线| 欧美亚洲第一页| 户外露出一区二区三区| 国产精品亚洲自拍| 电影91久久久| 岛国视频一区免费观看| 久久精品凹凸全集| 欧美人xxxxx| 成人羞羞网站入口免费| 亚洲乱码一区二区三区三上悠亚| 久久一区91| 亚洲一区 在线播放| 国内综合精品午夜久久资源| 国内精品在线观看视频| 美女视频一区免费观看| 麻豆一区二区三区视频| 国产一区二区三区免费看| 久久人妻少妇嫩草av蜜桃| 99精品视频在线观看免费| 成人乱码一区二区三区av| 国产精品福利一区| 久久久一区二区三区四区| 欧美日韩国产精品| 中文在线最新版天堂| 欧美一区二区大片| 人妻精品无码一区二区| 亚洲欧美日韩视频一区| 日本www在线| 欧美激情第三页| 涩涩涩视频在线观看| 国产精品视频yy9099| 国产日韩在线观看视频| 狠狠色综合网站久久久久久久| 美女毛片一区二区三区四区| 影音先锋在线亚洲| 精品成人一区| 向日葵污视频在线观看| 懂色av一区二区在线播放| 天天躁日日躁aaaa视频| 亚洲一区二区三区免费视频| 久久精品无码av| 欧美美女激情18p| 亚洲欧美日韩成人在线| 久久精品最新地址| 天堂av在线网| 91在线视频精品| 亚洲小说图片| 日韩国产成人无码av毛片| 日本欧美韩国一区三区| 人妻av一区二区| 国产精品久久久久aaaa樱花| 亚洲精品77777| 欧美精品欧美精品系列| 青青国产在线| 欧美黑人一区二区三区| 香蕉久久一区| 人偷久久久久久久偷女厕| 欧美日韩网站| 可以看污的网站| 久久精品一区二区三区不卡牛牛| 五月天丁香激情| 精品视频在线免费观看| 亚洲人成色777777老人头| 欧美成人一区二区三区电影| 影视一区二区三区| 久久久久久久久四区三区| 亚洲性感美女99在线| 亚洲一区二区三区三州| 国产精品无圣光一区二区| 国产区一区二区三| 欧美精品一区二区三区四区| 一区二区三区伦理| 成人午夜小视频| 久久影院一区| 爱情岛论坛vip永久入口| 久久综合久久综合久久综合| 国产一级片网址| 精品国产麻豆免费人成网站| av免费在线网站| 亚洲一区二区三区xxx视频| 久久一区二区三区电影| 国产野外作爱视频播放| 国产午夜精品久久久久久免费视 | 欧美日韩免费看片| 国外成人在线视频| 亚洲精品v亚洲精品v日韩精品| 亚洲一区二区三区午夜| 日本sm残虐另类| 99精品全国免费观看| 欧美午夜一区二区三区| 成人影院免费观看| 国产成人一区二区| 欧美久久综合网| 性欧美videossex精品| 国产日产欧美一区| 亚洲av人无码激艳猛片服务器| 亚洲桃花岛网站| 成人做爰视频www| 亚洲欧洲精品在线观看| 九九**精品视频免费播放| 日韩欧美国产成人精品免费| 制服.丝袜.亚洲.另类.中文| 成码无人av片在线观看网站| 亚洲字幕在线观看| 激情亚洲成人| 国产激情在线免费观看| 色噜噜狠狠色综合中国| av福利在线播放| 91老司机精品视频| 在线日韩av| 97超碰在线免费观看| 在线国产电影不卡| 毛片在线看网站| 动漫美女被爆操久久久| 99综合在线| 成人在线观看免费高清| 91精品国产综合久久精品app| 婷婷在线播放| 乱一区二区三区在线播放| 日韩高清一区二区| 免费国产羞羞网站美图| 欧美精品一区二区三区蜜桃视频| 国产欧美一区二区三区精品酒店| 日韩欧美在线观看强乱免费| 国产在线精品免费| 日本中文字幕在线免费观看| 国产亚洲精品久久久久久777| 婷婷精品久久久久久久久久不卡| 国产精品久久久久9999爆乳| 久久天堂av综合合色蜜桃网| 伊人网中文字幕| 久久久久久久av| 精品久久影视| 26uuu国产| 在线观看91精品国产入口| 91在线中字| 日本一区二区在线视频观看| 国产一区二区在线看| 欧美特黄aaaaaa| 久久天堂电影网| 亚洲激情77| japan高清日本乱xxxxx| 福利视频一区二区| 高潮毛片在线观看| 蜜桃av噜噜一区二区三| 国产剧情一区二区| 无码人妻av免费一区二区三区| 美女精品久久久| 成人高清电影网站| 亚洲 欧美 日韩在线| 777a∨成人精品桃花网| 成人性生活视频|