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

阿里高級技術專家方法論:如何寫復雜業務代碼?

開發 項目管理
簡單的介紹下業務背景,零售通是給線下小店供貨的B2B模式,我們希望通過數字化重構傳統供應鏈渠道,提升供應鏈效率,為新零售助力。阿里在中間是一個平臺角色,提供的是Bsbc中的service的功能。

[[273698]]

張建飛是阿里巴巴高級技術專家,一直在致力于應用架構和代碼復雜度的治理。最近,他在看零售通商品域的代碼。面對零售通如此復雜的業務場景,如何在架構和代碼層面進行應對,是一個新課題。結合實際的業務場景,Frank 沉淀了一套“如何寫復雜業務代碼”的方法論,在此分享給大家,相信同樣的方法論可以復制到大部分復雜業務場景。

一個復雜業務的處理過程

業務背景

簡單的介紹下業務背景,零售通是給線下小店供貨的B2B模式,我們希望通過數字化重構傳統供應鏈渠道,提升供應鏈效率,為新零售助力。阿里在中間是一個平臺角色,提供的是Bsbc中的service的功能。

商品力是零售通的核心所在,一個商品在零售通的生命周期如下圖所示:

在上圖中紅框標識的是一個運營操作的“上架”動作,這是非常關鍵的業務操作。上架之后,商品就能在零售通上面對小店進行銷售了。因為上架操作非常關鍵,所以也是商品域中最復雜的業務之一,涉及很多的數據校驗和關聯操作。針對上架,一個簡化的業務流程如下所示:

過程分解

像這么復雜的業務,我想應該沒有人會寫在一個service方法中吧。一個類解決不了,那就分治吧。

說實話,能想到分而治之的工程師,已經做的不錯了,至少比沒有分治思維要好很多。我也見過復雜程度相當的業務,連分解都沒有,就是一堆方法和類的堆砌。

不過,這里存在一個問題:即很多同學過度的依賴工具或是輔助手段來實現分解。比如在我們的商品域中,類似的分解手段至少有3套以上,有自制的流程引擎,有依賴于數據庫配置的流程處理:

本質上來講,這些輔助手段做的都是一個pipeline的處理流程,沒有其它。因此,我建議此處最好保持KISS(Keep It Simple and Stupid),即最好是什么工具都不要用,次之是用一個極簡的Pipeline模式,最差是使用像流程引擎這樣的重方法。

除非你的應用有極強的流程可視化和編排的訴求,否則我非常不推薦使用流程引擎等工具。第一,它會引入額外的復雜度,特別是那些需要持久化狀態的流程引擎;第二,它會割裂代碼,導致閱讀代碼的不順暢。大膽斷言一下,全天下估計80%對流程引擎的使用都是得不償失的。

回到商品上架的問題,這里問題核心是工具嗎?是設計模式帶來的代碼靈活性嗎?顯然不是,問題的核心應該是如何分解問題和抽象問題,知道金字塔原理的應該知道,此處,我們可以使用結構化分解將問題解構成一個有層級的金字塔結構:

按照這種分解寫的代碼,就像一本書,目錄和內容清晰明了。

以商品上架為例,程序的入口是一個上架命令(OnSaleCommand), 它由三個階段(Phase)組成。

  1. @Command 
  2. public class OnSaleNormalItemCmdExe { 
  3.  
  4.     @Resource 
  5.     private OnSaleContextInitPhase onSaleContextInitPhase; 
  6.     @Resource 
  7.     private OnSaleDataCheckPhase onSaleDataCheckPhase; 
  8.     @Resource 
  9.     private OnSaleProcessPhase onSaleProcessPhase; 
  10.  
  11.     @Override 
  12.     public Response execute(OnSaleNormalItemCmd cmd) { 
  13.  
  14.         OnSaleContext onSaleContext = init(cmd); 
  15.  
  16.         checkData(onSaleContext); 
  17.  
  18.         process(onSaleContext); 
  19.  
  20.         return Response.buildSuccess(); 
  21.     } 
  22.  
  23.     private OnSaleContext init(OnSaleNormalItemCmd cmd) { 
  24.         return onSaleContextInitPhase.init(cmd); 
  25.     } 
  26.  
  27.     private void checkData(OnSaleContext onSaleContext) { 
  28.         onSaleDataCheckPhase.check(onSaleContext); 
  29.     } 
  30.  
  31.     private void process(OnSaleContext onSaleContext) { 
  32.         onSaleProcessPhase.process(onSaleContext); 
  33.     } 

每個Phase又可以拆解成多個步驟(Step),以OnSaleProcessPhase為例,它是由一系列Step組成的:

  1. @Phase 
  2. public class OnSaleProcessPhase { 
  3.  
  4.     @Resource 
  5.     private PublishOfferStep publishOfferStep; 
  6.     @Resource 
  7.     private BackOfferBindStep backOfferBindStep; 
  8.     //省略其它step 
  9.  
  10.     public void process(OnSaleContext onSaleContext){ 
  11.         SupplierItem supplierItem = onSaleContext.getSupplierItem(); 
  12.  
  13.         // 生成OfferGroupNo 
  14.         generateOfferGroupNo(supplierItem); 
  15.  
  16.        // 發布商品 
  17.         publishOffer(supplierItem); 
  18.  
  19.         // 前后端庫存綁定 backoffer域 
  20.         bindBackOfferStock(supplierItem); 
  21.  
  22.         // 同步庫存路由 backoffer域 
  23.         syncStockRoute(supplierItem); 
  24.  
  25.         // 設置虛擬商品拓展字段 
  26.         setVirtualProductExtension(supplierItem); 
  27.  
  28.         // 發貨保障打標 offer域 
  29.         markSendProtection(supplierItem); 
  30.  
  31.         // 記錄變更內容ChangeDetail 
  32.         recordChangeDetail(supplierItem); 
  33.  
  34.         // 同步供貨價到BackOffer 
  35.         syncSupplyPriceToBackOffer(supplierItem); 
  36.  
  37.         // 如果是組合商品打標,寫擴展信息 
  38.         setCombineProductExtension(supplierItem); 
  39.  
  40.         // 去售罄標 
  41.         removeSellOutTag(offerId); 
  42.  
  43.         // 發送領域事件 
  44.         fireDomainEvent(supplierItem); 
  45.  
  46.         // 關閉關聯的待辦事項 
  47.         closeIssues(supplierItem); 
  48.     } 

看到了嗎,這就是商品上架這個復雜業務的業務流程。需要流程引擎嗎?不需要,需要設計模式支撐嗎?也不需要。對于這種業務流程的表達,簡單樸素的組合方法模式(Composed Method)是再合適不過的了。

因此,在做過程分解的時候,我建議工程師不要把太多精力放在工具上,放在設計模式帶來的靈活性上。而是應該多花時間在對問題分析,結構化分解,最后通過合理的抽象,形成合適的階段(Phase)和步驟(Step)上。

過程分解后的兩個問題

的確,使用過程分解之后的代碼,已經比以前的代碼更清晰、更容易維護了。不過,還有兩個問題值得我們去關注一下:

  • 領域知識被割裂肢解

什么叫被肢解?因為我們到目前為止做的都是過程化拆解,導致沒有一個聚合領域知識的地方。每個Use Case的代碼只關心自己的處理流程,知識沒有沉淀。

相同的業務邏輯會在多個Use Case中被重復實現,導致代碼重復度高,即使有復用,最多也就是抽取一個util,代碼對業務語義的表達能力很弱,從而影響代碼的可讀性和可理解性。

  • 代碼的業務表達能力缺失

試想下,在過程式的代碼中,所做的事情無外乎就是取數據--做計算--存數據,在這種情況下,要如何通過代碼顯性化的表達我們的業務呢?說實話,很難做到,因為我們缺失了模型,以及模型之間的關系。脫離模型的業務表達,是缺少韻律和靈魂的。

舉個例子,在上架過程中,有一個校驗是檢查庫存的,其中對于組合品(CombineBackOffer)其庫存的處理會和普通品不一樣。原來的代碼是這么寫的:

  1. boolean isCombineProduct = supplierItem.getSign().isCombProductQuote(); 
  2.  
  3. // supplier.usc warehouse needn't check 
  4. if (WarehouseTypeEnum.isAliWarehouse(supplierItem.getWarehouseType())) { 
  5. // quote warehosue check 
  6. if (CollectionUtil.isEmpty(supplierItem.getWarehouseIdList()) && !isCombineProduct) { 
  7.     throw ExceptionFactory.makeFault(ServiceExceptionCode.SYSTEM_ERROR, "親,不能發布Offer,請聯系倉配運營人員,建立品倉關系!"); 
  8. // inventory amount check 
  9. Long sellableAmount = 0L; 
  10. if (!isCombineProduct) { 
  11.     sellableAmount = normalBiz.acquireSellableAmount(supplierItem.getBackOfferId(), supplierItem.getWarehouseIdList()); 
  12. else { 
  13.     //組套商品 
  14.     OfferModel backOffer = backOfferQueryService.getBackOffer(supplierItem.getBackOfferId()); 
  15.     if (backOffer != null) { 
  16.         sellableAmount = backOffer.getOffer().getTradeModel().getTradeCondition().getAmountOnSale(); 
  17.     } 
  18. if (sellableAmount < 1) { 
  19.     throw ExceptionFactory.makeFault(ServiceExceptionCode.SYSTEM_ERROR, "親,實倉庫存必須大于0才能發布,請確認已補貨.\r[id:" + supplierItem.getId() + "]"); 

然而,如果我們在系統中引入領域模型之后,其代碼會簡化為如下:

  1. if(backOffer.isCloudWarehouse()){ 
  2.     return
  3.  
  4. if (backOffer.isNonInWarehouse()){ 
  5.     throw new BizException("親,不能發布Offer,請聯系倉配運營人員,建立品倉關系!"); 
  6.  
  7. if (backOffer.getStockAmount() < 1){ 
  8.     throw new BizException("親,實倉庫存必須大于0才能發布,請確認已補貨.\r[id:" + backOffer.getSupplierItem().getCspuCode() + "]"); 

有沒有發現,使用模型的表達要清晰易懂很多,而且也不需要做關于組合品的判斷了,因為我們在系統中引入了更加貼近現實的對象模型(CombineBackOffer繼承BackOffer),通過對象的多態可以消除我們代碼中的大部分的if-else。

過程分解+對象模型

通過上面的案例,我們可以看到有過程分解要好于沒有分解,過程分解+對象模型要好于僅僅是過程分解。對于商品上架這個case,如果采用過程分解+對象模型的方式,最終我們會得到一個如下的系統結構:

寫復雜業務的方法論

通過上面案例的講解,我想說,我已經交代了復雜業務代碼要怎么寫:即自上而下的結構化分解+自下而上的面向對象分析。

接下來,讓我們把上面的案例進行進一步的提煉,形成一個可落地的方法論,從而可以泛化到更多的復雜業務場景。

上下結合

所謂上下結合,是指我們要結合自上而下的過程分解和自下而上的對象建模,螺旋式的構建我們的應用系統。這是一個動態的過程,兩個步驟可以交替進行、也可以同時進行。

這兩個步驟是相輔相成的,上面的分析可以幫助我們更好的理清模型之間的關系,而下面的模型表達可以提升我們代碼的復用度和業務語義表達能力。

其過程如下圖所示:

使用這種上下結合的方式,我們就有可能在面對任何復雜的業務場景,都能寫出干凈整潔、易維護的代碼。

能力下沉

一般來說實踐DDD有兩個過程:

  • 套概念階段:了解了一些DDD的概念,然后在代碼中“使用”Aggregation Root,Bounded Context,Repository等等這些概念。更進一步,也會使用一定的分層策略。然而這種做法一般對復雜度的治理并沒有多大作用。
  • 融會貫通階段:術語已經不再重要,理解DDD的本質是統一語言、邊界劃分和面向對象分析的方法。

大體上而言,我大概是在1.7的階段,因為有一個問題一直在困擾我,就是哪些能力應該放在Domain層,是不是按照傳統的做法,將所有的業務都收攏到Domain上,這樣做合理嗎?說實話,這個問題我一直沒有想清楚。

因為在現實業務中,很多的功能都是用例特有的(Use case specific)的,如果“盲目”的使用Domain收攏業務并不見得能帶來多大的益處。相反,這種收攏會導致Domain層的膨脹過厚,不夠純粹,反而會影響復用性和表達能力。

鑒于此,我最近的思考是我們應該采用能力下沉的策略。

所謂的能力下沉,是指我們不強求一次就能設計出Domain的能力,也不需要強制要求把所有的業務功能都放到Domain層,而是采用實用主義的態度,即只對那些需要在多個場景中需要被復用的能力進行抽象下沉,而不需要復用的,就暫時放在App層的Use Case里就好了。

注:Use Case是《架構整潔之道》里面的術語,簡單理解就是響應一個Request的處理過程。

通過實踐,我發現這種循序漸進的能力下沉策略,應該是一種更符合實際、更敏捷的方法。因為我們承認模型不是一次性設計出來的,而是迭代演化出來的。

下沉的過程如下圖所示,假設兩個use case中,我們發現uc1的step3和uc2的step1有類似的功能,我們就可以考慮讓其下沉到Domain層,從而增加代碼的復用性。

指導下沉有兩個關鍵指標:

  • 復用性
  • 內聚性

復用性是告訴我們When(什么時候該下沉了),即有重復代碼的時候。內聚性是告訴我們How(要下沉到哪里),功能有沒有內聚到恰當的實體上,有沒有放到合適的層次上(因為Domain層的能力也是有兩個層次的,一個是Domain Service這是相對比較粗的粒度,另一個是Domain的Model這個是最細粒度的復用)。

比如,在我們的商品域,經常需要判斷一個商品是不是最小單位,是不是中包商品。像這種能力就非常有必要直接掛載在Model上。

  1. public class CSPU { 
  2.     private String code; 
  3.     private String baseCode; 
  4.     //省略其它屬性 
  5.  
  6.     /** 
  7.      * 單品是否為最小單位。 
  8.      * 
  9.      */ 
  10.     public boolean isMinimumUnit(){ 
  11.         return StringUtils.equals(code, baseCode); 
  12.     } 
  13.  
  14.     /** 
  15.      * 針對中包的特殊處理 
  16.      * 
  17.      */ 
  18.     public boolean isMidPackage(){ 
  19.         return StringUtils.equals(code, midPackageCode); 
  20.     } 

之前,因為老系統中沒有領域模型,沒有CSPU這個實體。你會發現像判斷單品是否為最小單位的邏輯是以StringUtils.equals(code, baseCode)的形式散落在代碼的各個角落。這種代碼的可理解性是可想而知的,至少我在第一眼看到這個代碼的時候,是完全不知道什么意思。

業務技術要怎么做

寫到這里,我想順便回答一下很多業務技術同學的困惑,也是我之前的困惑:即業務技術到底是在做業務,還是做技術?業務技術的技術性體現在哪里?

通過上面的案例,我們可以看到業務所面臨的復雜性并不亞于底層技術,要想寫好業務代碼也不是一件容易的事情。業務技術和底層技術人員唯一的區別是他們所面臨的問題域不一樣。

業務技術面對的問題域變化更多、面對的人更加龐雜。而底層技術面對的問題域更加穩定、但對技術的要求更加深。比如,如果你需要去開發Pandora,你就要對Classloader有更加深入的了解才行。

但是,不管是業務技術還是底層技術人員,有一些思維和能力都是共通的。比如,分解問題的能力,抽象思維,結構化思維等等。

用我的話說就是:“做不好業務開發的,也做不好技術底層開發,反之亦然。業務開發一點都不簡單,只是我們很多人把它做“簡單”了。

因此,如果從變化的角度來看,業務技術的難度一點不遜色于底層技術,其面臨的挑戰甚至更大。因此,我想對廣大的從事業務技術開發的同學說:沉下心來,夯實自己的基礎技術能力、OO能力、建模能力... 不斷提升抽象思維、結構化思維、思辨思維... 持續學習精進,寫好代碼。我們可以在業務技術崗做的很”技術“!。

后記

這篇文章是我最近思考的一些總結,大部分思想是繼承自我原來寫的COLA架構,該架構已經開源,目前在集團內外都有比較廣泛的使用。

這一篇主要是在COLA的基礎上,針對復雜業務場景,做了進一步的架構落地。個人感覺可以作為COLA的最佳實踐來使用。

另外,本文討論的問題之大和篇幅之短是不成正比的。原因是我假定你已經了解了一些DDD和應用架構的基礎知識。如果覺得在理解上有困難,我建議可以先看下《領域驅動設計》和《架構整潔之道》這兩本書。

如果沒有那么多時間,也可以快速瀏覽下我之前的兩篇文章應用架構之道 和 領域建模去知曉一下我之前的思想脈絡。

責任編輯:武曉燕 來源: 阿里技術
相關推薦

2020-10-12 07:57:42

技術架構制圖

2020-09-27 14:24:58

if-else cod業務

2023-05-30 07:56:23

代碼軟件開發

2013-12-25 09:50:27

華為馬悅企業業務

2022-06-27 08:47:29

BEM修飾符元素

2022-07-04 19:02:06

系統業務思考

2018-04-12 09:46:12

DevOps運維建設

2021-11-05 08:28:27

內存泄漏調試

2014-12-15 17:36:51

2014-09-11 15:05:40

驅動設計驅動開發

2018-10-08 09:00:58

考核技術人KPI

2017-06-05 15:08:14

容量全鏈路流量

2020-02-28 11:13:35

辦公阿里周報

2023-07-17 18:39:27

業務系統架構

2022-03-14 22:22:56

工程設計論代碼

2010-01-04 10:07:03

程序員

2022-04-07 17:30:31

Flutter攜程火車票渲染

2017-04-21 07:41:37

iOS自動化測試容器

2020-04-13 13:13:20

NLPAI語音

2019-10-14 10:21:47

代碼通用架構
點贊
收藏

51CTO技術棧公眾號

五月天婷婷社区| 卡通动漫亚洲综合| 户外露出一区二区三区| 国产精品伦一区二区三级视频| 91网站在线看| 日本免费观看视| 色狮一区二区三区四区视频| 精品国产麻豆免费人成网站| 毛葺葺老太做受视频| 国产素人视频在线观看| 99精品在线免费| 国产主播欧美精品| 青青青国产在线| 亚洲国产日韩欧美在线| 日韩大片免费观看视频播放| 精品久久久99| 欧美va在线| 亚洲国产va精品久久久不卡综合| 亚洲成人网上| 神马精品久久| 国产99久久久久| 成人黄色生活片| 亚洲国产精品无码久久久| 欧美日本久久| 久久精品青青大伊人av| 亚洲一区二区三区蜜桃| 一区二区三区在线资源| 欧美日韩国产高清一区二区| 免费毛片网站在线观看| 顶级网黄在线播放| 国产精品卡一卡二卡三| 日韩av大全| 四虎精品在永久在线观看| 粉嫩一区二区三区在线看| 国产日本欧美一区二区三区在线| 日本一区二区免费电影| 欧美日韩18| 久久精品人人爽| 日韩在线视频免费看| 国产精品一在线观看| 日韩激情在线视频| 午夜男人的天堂| 一区二区亚洲视频| 91精品国产欧美日韩| 国产欧美激情视频| 国产情侣一区二区三区| 欧美艳星brazzers| 成人亚洲视频在线观看| 色婷婷综合久久久中字幕精品久久| 亚洲成国产人片在线观看| 国产av熟女一区二区三区| caoporm免费视频在线| 亚洲视频精选在线| 一本二本三本亚洲码| av中文字幕在线观看| 亚洲天堂成人网| 精品国产三级a∨在线| av片在线观看永久免费| 亚洲三级在线观看| 三级在线免费观看| 怡红院红怡院欧美aⅴ怡春院| 一区二区中文字幕在线| 日韩第一页在线观看| 国产一二区在线| 亚洲观看高清完整版在线观看| 国产在线视频在线| 川上优av中文字幕一区二区| 精品福利在线观看| 男女啪啪网站视频| 欧美成人免费全部网站| 911国产精品| 粗大的内捧猛烈进出视频| 凹凸成人在线| 亚洲乱码av中文一区二区| 亚洲码无人客一区二区三区| 黑人操亚洲人| 日韩一区二区精品视频| 免费看一级大片| 在线国产欧美| 日韩av片电影专区| 国产乱码精品一区二区三区精东| 国产精品一区久久久久| 久99久视频| 91在线观看| 亚洲国产精品麻豆| 国产日韩成人内射视频| 自拍偷拍欧美日韩| 精品国产一区a| 人妻少妇无码精品视频区| 欧美wwwww| 亚州成人av在线| 中文字字幕在线中文乱码| 国产精品99久| 国产无套精品一区二区| 不卡在线视频| 亚洲一区二区三区四区五区中文 | 免费的黄网站在线观看| 亚洲综合色噜噜狠狠| 免费大片在线观看| 美国十次综合久久| 亚洲男人天堂手机在线| 91香蕉一区二区三区在线观看| 在线综合欧美| 成人激情免费在线| 你懂的视频在线| 亚洲男同性恋视频| 日本爱爱免费视频| av日韩在线播放| 丝袜亚洲另类欧美重口| 日韩欧美性视频| 韩国av一区二区| 日本午夜一区二区三区| 免费电影视频在线看| 欧美性猛交xxxxxxxx| 中文字幕人妻熟女在线| 成人影视亚洲图片在线| 97在线视频国产| 国产一区二区三区四区视频 | 欧美福利第一页| 国产精品第十页| 成人黄色免费网站在线观看| 国产在线黄色| 五月婷婷激情综合| 人妻少妇偷人精品久久久任期| 精品国产一区探花在线观看| 9.1国产丝袜在线观看| 国产普通话bbwbbwbbw| 国产日本一区二区| 99热自拍偷拍| youjizz亚洲| 欧美成人合集magnet| 一起草av在线| 欧美国产国产综合| av网址在线观看免费| 卡通动漫精品一区二区三区| 欧美国产日韩在线| www日本在线| 亚洲免费高清视频在线| www.久久av.com| 久久国产电影| 国产精品美女网站| 91美女视频在线| 欧美专区亚洲专区| 日韩福利在线视频| 日本vs亚洲vs韩国一区三区 | 麻豆视频在线免费观看| 欧美日韩在线观看一区二区| 精品无码在线观看| 久久久久久久性潮| 日韩成人在线观看| 国产手机在线视频| av一区二区三区| 欧美啪啪免费视频| 日本国产精品| 26uuu国产精品视频| 三级av在线播放| 色综合天天视频在线观看| 人妻aⅴ无码一区二区三区| 久热国产精品| 青青成人在线| 欧美黄页免费| 另类视频在线观看| 亚洲第九十九页| 亚洲va欧美va人人爽午夜| 中文字幕在线播放视频| 久久精品官网| 亚洲乱码一区二区三区| 日韩一级视频| 欧美区在线播放| 色婷婷在线视频| 欧美性jizz18性欧美| 免费看黄色的视频| 捆绑紧缚一区二区三区视频| 国产手机视频在线观看| 国产精品白丝一区二区三区| 欧洲亚洲免费视频| 日本美女在线中文版| 欧美一区二区黄| 日韩精品视频播放| 国产欧美一二三区| 欧美国产在线一区| 香蕉久久国产| 在线观看成人av电影| 精品丝袜久久| 国产精品视频专区| 手机电影在线观看| 亚洲欧美日韩一区二区在线| 国产精品爽爽久久| 狠狠躁夜夜躁久久躁别揉| a资源在线观看| 国产69精品久久99不卡| 国产激情在线观看视频| 亚洲九九视频| 免费精品视频一区二区三区| 精品国产一区二区三区2021| 欧美在线影院在线视频| 国产丝袜在线| 国产一区二区三区中文| 狠狠躁日日躁夜夜躁av| 欧美日韩一区二区三区免费看| 国产大片中文字幕在线观看| 亚洲国产精品高清| 中国黄色片视频| 久久99国产精品免费| 久久久999免费视频| 91精品国产乱码久久久久久久| 精品日产一区2区三区黄免费 | 精品视频在线视频| 国产精品 欧美 日韩| 国产精品久久久久桃色tv| 日韩av手机在线播放| 国产一区999| 中文字幕第21页| 亚洲少妇一区| 蜜桃视频一区二区在线观看| 日韩中文在线电影| 欧美精品一区二区三区在线看午夜| 日韩精品一区二区三区中文字幕| 国产精品久久久久久av下载红粉 | 亚洲最大免费视频| 激情图区综合网| 久久久久久三级| 一本综合久久| 国产欧美日韩小视频| 亚洲最大黄网| 麻豆中文字幕在线观看| 成人女性视频| 日本欧美精品久久久| 久久99国产精品久久99大师 | 51久久精品夜色国产麻豆| a视频在线免费看| 色婷婷综合久久久久| 韩日视频在线| 亚洲天堂免费观看| 欧美高清电影在线| 日韩精品免费一线在线观看| 全国男人的天堂网| 精品处破学生在线二十三| 精品人妻一区二区三区换脸明星| 欧美日韩国产一级| 久草热在线观看| 欧美性受xxxx黑人xyx| 无码人妻av一区二区三区波多野 | 亚洲欧美激情在线观看| 日韩视频免费观看高清完整版 | 香蕉视频免费版| 天天综合精品| 精品91一区二区三区| 久久麻豆精品| 国产av不卡一区二区| 欧美国产先锋| 亚洲国产精品成人天堂| 亚洲欧洲综合| 成人黄色片视频| 肉肉av福利一精品导航| 中文久久久久久| 精品中文字幕一区二区小辣椒| 亚洲怡红院在线| 国产精品资源在线观看| 国产清纯白嫩初高中在线观看性色| 国产91精品一区二区麻豆网站| 影音先锋资源av| 99免费精品在线观看| 亚洲 小说 欧美 激情 另类| 国产精品乱码人人做人人爱| 男女性高潮免费网站| 亚洲精品国产一区二区精华液| 精品肉丝脚一区二区三区| 图片区小说区国产精品视频| 久久精品无码av| 51精品秘密在线观看| 精品久久国产视频| 亚洲精品成人久久久| 岛国在线大片| 欧美成人精品在线观看| 美女网站在线看| 国产精品一区电影| 日韩精品中文字幕一区二区| 裸体丰满少妇做受久久99精品| 日韩黄色大片| 欧美久久在线观看| 日本在线观看不卡视频| 一级做a爱视频| 91免费国产在线| 国产成人在线网址| 亚洲国产乱码最新视频| 国产一卡二卡三卡| 91麻豆精品91久久久久同性| 韩国av永久免费| 一本色道久久综合亚洲精品小说 | 亚洲色图丝袜| 黄频视频在线观看| 国产农村妇女精品一区二区| 亚洲第一色av| 久久综合色一综合色88| 熟女少妇内射日韩亚洲| 亚洲国产wwwccc36天堂| 亚洲视频一区二区三区四区| 亚洲国产一区自拍| 欧美性天天影视| 欧美在线视频播放| 国产一区一区| 日韩欧美三级一区二区| 激情视频一区| 天天干天天操天天玩| 99免费精品视频| 免费一级片视频| 欧美日韩精品一区二区| 青青操视频在线| 欧美高清性猛交| 97精品资源在线观看| 欧美主播一区二区三区美女 久久精品人| 欧美一区高清| 玖玖爱视频在线| 国产天堂亚洲国产碰碰| 男女啊啊啊视频| 欧美www视频| www.欧美日本韩国| 国产欧美精品日韩精品| 九九视频免费观看视频精品| 免费看黄在线看| 成人国产一区二区三区精品| 777777国产7777777| 欧美日韩一级大片网址| 精品久久久久一区二区三区| 69视频在线免费观看| 综合激情久久| 日韩不卡一二区| 精品一区二区三区视频| 黄色av免费播放| 91黄视频在线观看| 黄色片视频在线观看| 18久久久久久| 欧美丝袜美腿| 久艹视频在线免费观看| 成人福利在线看| 国产无码精品在线播放| 精品福利一区二区三区免费视频| 性欧美高清come| 亚洲最大成人在线| 欧美一区91| 亚洲AV无码久久精品国产一区| 亚洲天堂网中文字| 精品人妻av一区二区三区| 久久精品视频中文字幕| 爱情电影网av一区二区| 最新黄色av网站| 国产一区二区三区香蕉| 日韩黄色免费观看| 日韩欧美一二区| 青春草视频在线| 国内精品久久国产| 亚洲综合丁香| 免费看91的网站| 欧美乱妇15p| a在线免费观看| 国产亚洲精品自在久久| 亚洲美女黄色| 草草影院第一页| 91久久精品国产91性色tv| 999国产在线视频| 91精品啪在线观看麻豆免费| 欧美在线三级| 中文字幕精品久久久| 日韩欧美aaa| 香蕉视频国产在线观看| 91免费国产视频| 亚洲国产一区二区精品专区| 女尊高h男高潮呻吟| 欧美亚洲高清一区| 米奇777四色精品人人爽| 99久久99久久| 久久av最新网址| 亚洲a∨无码无在线观看| 日韩欧美你懂的| 亚洲美女尤物影院| 亚洲日本欧美在线| 成人精品在线视频观看| 国产免费一区二区三区四区五区| 精品国产一区av| 盗摄系列偷拍视频精品tp| 欧美精品成人网| 亚洲男人都懂的| 男人久久精品| 亚洲va欧美va国产综合剧情| 99精品视频网| 国产午夜精品理论片在线| 日韩av在线影院| 亚洲日本免费电影| 国产免费黄色av| 亚洲欧美综合网| 三区在线视频| 亚洲自拍偷拍区| 久久人人精品| 久久精品女人毛片国产| 伊是香蕉大人久久| 欧美黑人做爰爽爽爽| 国产精品嫩草影院8vv8 | 欧美成人一区在线| 九九热线有精品视频99|