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

一個 UT Failed 引出的思考

開發(fā) 項(xiàng)目管理
前幾天某個服務(wù) ut 失敗,導(dǎo)致別人無法構(gòu)建。查看下源代碼以及 ut case, 發(fā)現(xiàn)槽點(diǎn)蠻多,分享下如何修復(fù),寫單測要注意的一些點(diǎn),由此引出設(shè)計模式中的概念依賴反轉(zhuǎn)、依賴注入、控制反轉(zhuǎn)。

[[420832]]

本文轉(zhuǎn)載自微信公眾號「董澤潤的技術(shù)筆記」,作者董澤潤。轉(zhuǎn)載本文請聯(lián)系董澤潤的技術(shù)筆記公眾號。

前幾天某個服務(wù) ut 失敗,導(dǎo)致別人無法構(gòu)建。查看下源代碼以及 ut case, 發(fā)現(xiàn)槽點(diǎn)蠻多,分享下如何修復(fù),寫單測要注意的一些點(diǎn),由此引出設(shè)計模式中的概念依賴反轉(zhuǎn)、依賴注入、控制反轉(zhuǎn)

失敗 case

  1. func toSeconds(in int64) int64 { 
  2.  if in > time.Now().Unix() { 
  3.   nanosecondSource := time.Unix(0, in
  4.   if dateIsSane(nanosecondSource) { 
  5.    return nanosecondSource.Unix() 
  6.   } 
  7.  
  8.   millisecondSource := time.Unix(0, in*int64(time.Millisecond)) 
  9.   if dateIsSane(millisecondSource) { 
  10.    return millisecondSource.Unix() 
  11.   } 
  12.  
  13.   // default to now rather than sending something stupid 
  14.   return time.Now().Unix() 
  15.  } 
  16.  return in 
  17.  
  18. func dateIsSane(in time.Time) bool { 
  19.  return (in.Year() >= (time.Now().Year()-1) && 
  20.   in.Year() <= (time.Now().Year()+1)) 

函數(shù) toSeconds 接收一個時間參數(shù),可能是秒、毫秒和其它時間,經(jīng)過判斷后返回秒值

  1. ...... 
  2.   { 
  3.  desc:   "less than now"
  4.  args:   1459101327, 
  5.  expect: 1459101327, 
  6. }, 
  7.  desc:   "great than year"
  8.  args:   now.UnixNano()/6000*6000 + 7.55424e+17, 
  9.  expect: now.Unix(), 
  10. }, 
  11. ...... 

上面是 test case table, 最后報錯 great than year 斷言失敗了。簡單的看下實(shí)現(xiàn)邏輯就能發(fā)現(xiàn),函數(shù)是想修正到秒值,但假如剛好 go gc STW 100ms, 就會導(dǎo)致 expect 與實(shí)際結(jié)果不符

如何從根本上修復(fù)問題呢?要么修改函數(shù)簽名,外層傳入 time.Now()

  1. func toSeconds(in int64, now time.Time) int64 { 
  2.   ...... 

要么將 time.Now 函數(shù)定義成當(dāng)前包內(nèi)變量,寫單測時修改 now 變量

  1. var now = time.Now 
  2.  
  3. func toSeconds(in int64) int64 { 
  4.  if in > now().Unix() { 
  5.   ...... 

以上兩種方式都比較常見,本質(zhì)在于單測 ut 不應(yīng)該依賴于當(dāng)前系統(tǒng)環(huán)境,比如 mysql, redis, 時間等等,應(yīng)該僅依賴于輸入?yún)?shù),同時函數(shù)執(zhí)行多次結(jié)果應(yīng)該一致。去年遇到過 CI 機(jī)器換了,新機(jī)器沒有 redis/mysql, 導(dǎo)致一堆 ut failed, 這就是不合格的寫法

如果依賴環(huán)境的資源,那么就變成了集成測試。如果進(jìn)一步再依賴業(yè)務(wù)的狀態(tài)機(jī),那么就變成了回歸測試,可以說是層層遞進(jìn)的關(guān)系。只有做好代碼的單測,才能進(jìn)一步確保其它測試正常。同時也不要神話單測,過份追求 100% 覆蓋

依賴注入

剛才我們非常自然的引入了設(shè)計模式中,非常重要的 依賴注入 Dependenccy injection 概念

  1. func toSeconds(in int64, now time.Time) int64  

簡單的講,toSeconds 函數(shù)調(diào)用系統(tǒng)時間 time.Now, 我們把依賴以參數(shù)的形式傳給 toSeconds 就是注入依賴,定義就這么簡單

關(guān)注 DI, 設(shè)計模式中抽像出來四個角色:

  • service 我們所被依賴的對像
  • client 依賴 service 的角色
  • interface 定義 client 如何使用 service 的接口
  • injector 注入器角色,用于構(gòu)造 service, 并將之傳給 client

我們來看一下面像對像的例子,Hero 需要有武器,NewHero 是英雄的構(gòu)造方法

  1. type Hero struct { 
  2.  name   string 
  3.  weapon Weapon 
  4.  
  5. func NewHero(name string) *Hero { 
  6.  return &sHero{ 
  7.   name:   name
  8.   weapon: NewGun(), 
  9.  } 

這里面問題很多,比如換個武器 AK 可不可以呢?當(dāng)然行。但是 NewHero 構(gòu)造時依賴了 NewGun, 我們需要把武器在外層初始化好,然后傳入

  1. type Hero struct { 
  2.  name   string 
  3.  weapon Weapon 
  4.  
  5. func NewHero(name string, wea Weapon) *Hero { 
  6.  return &Hero{ 
  7.   name:   name
  8.   weapon: wea, 
  9.  } 
  10.  
  11. func main(){ 
  12.  wea:= NewGun(); 
  13.  myhero = NewHero("killer47", wea) 

在這個 case 里面,Hero 就是上面提到的 client 角色,Weapon 就是 service 角色,injector 是誰呢?是 main 函數(shù),其實(shí)也是碼農(nóng)

這個例子還有問題,原因在于武器不應(yīng)該是具體實(shí)例,而應(yīng)該是接口,即上面提到的 interface 角色

  1. type Weapon interface { 
  2.  Attack(damage int

也就是說我們的武器要設(shè)計成接口 Weapon, 方法只有一個 Attack 攻擊并附帶傷害。但是到現(xiàn)在還不是理想的,比如說我沒有武器的時候,就不能攻擊人了嘛?當(dāng)然能,還有雙手啊,所以有時我們要用 Option 實(shí)現(xiàn)默認(rèn)依賴

  1. type Weapon interface { 
  2.  Attack(damage int
  3.  
  4. type Hero struct { 
  5.  name   string 
  6.  weapon Weapon 
  7.  
  8. func NewHero(name string, opts ...Option) *Hero { 
  9.  h := &Hero{ 
  10.   namename
  11.  } 
  12.  
  13.  for _, option := range options { 
  14.   option(i) 
  15.  } 
  16.  
  17.  if h.weapon == nil { 
  18.   h.weapon = NewFist() 
  19.  } 
  20.  return h 
  21.  
  22. type Option func(*Hero) 
  23.  
  24. func WithWeapon(w Weapon) Option { 
  25.  return func(i *Hero) { 
  26.   i.weapon = w 
  27.  } 
  28.  
  29. func main() { 
  30.  wea := NewGun() 
  31.  myhero = NewHero("killer47", WithWeapon(wea)) 

上面就是一個生產(chǎn)環(huán)境中,比較理想的方案,看不明白的可以運(yùn)行代碼試著理解下

第三方框架

剛才提到的例子比較簡單,injector 由碼農(nóng)自己搞就行了。但是很多時候,依賴的對像不只一個,可能很多,還有交叉依賴,這時候就需要第三方框架來支持了

  1.  <?xml version="1.0" encoding="UTF-8"?> 
  2.  <beans xmlns="http://www.springframework.org/schema/beans" 
  3.   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  4.   xsi:schemaLocation="http://www.springframework.org/schema/beans 
  5.   http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> 
  6.  
  7.     <bean id="service" class="ExampleService"
  8.     </bean> 
  9.  
  10.     <bean id="client" class="Client"
  11.         <constructor-arg value="service" />         
  12.     </bean> 
  13. </beans> 

 

 

 

Java 黨寫配置文件,用注解來實(shí)現(xiàn)。對于 go 來講,可以使用 wire, https://github.com/google/wire

  1. // +build wireinject 
  2.  
  3. package main 
  4.  
  5. import ( 
  6.     "github.com/google/wire" 
  7.     "wire-example2/internal/config" 
  8.     "wire-example2/internal/db" 
  9.  
  10. func InitApp() (*App, error) { 
  11.     panic(wire.Build(config.Provider, db.Provider, NewApp)) // 調(diào)用wire.Build方法傳入所有的依賴對象以及構(gòu)建最終對象的函數(shù)得到目標(biāo)對象 

類似上面一樣,定義 wire.go 文件,然后寫上 +build wireinject 注釋,調(diào)用 wire 后會自動生成 injector 代碼

  1. //go:generate go run github.com/google/wire/cmd/wire 
  2. //+build !wireinject 
  3.  
  4. package main 
  5.  
  6. import ( 
  7.     "wire-example2/internal/config" 
  8.     "wire-example2/internal/db" 
  9.  
  10. // Injectors from wire.go: 
  11.  
  12. func InitApp() (*App, error) { 
  13.     configConfig, err := config.New() 
  14.     if err != nil { 
  15.         return nil, err 
  16.     } 
  17.     sqlDB, err := db.New(configConfig) 
  18.     if err != nil { 
  19.         return nil, err 
  20.     } 
  21.     app := NewApp(sqlDB) 
  22.     return app, nil 

我司有項(xiàng)目在用,感興趣的可以看看官方文檔,對于構(gòu)建大型項(xiàng)目很有幫助

依賴反轉(zhuǎn) DIP 原則

我們還經(jīng)常聽說一個概念,就是依賴反轉(zhuǎn) dependency inversion principle, 他有兩個最重要的原則:

  • High-level modules should not depend on low-level modules. Both should depend on abstractions (e.g., interfaces).
  • Abstractions should not depend on details. Details (concrete implementations) should depend on abstractions.

高層模塊不應(yīng)該依賴低層模塊,需要用接口進(jìn)行抽像。抽像不應(yīng)該依賴于具體實(shí)現(xiàn),具體實(shí)現(xiàn)應(yīng)該依賴于抽像,結(jié)合上面的 Hero&Weapon 案例應(yīng)該很清楚了

那我們學(xué)習(xí) DI、DIP 這些設(shè)計模式目的是什么呢?使我們程序各個模塊之間變得松耦合,底層實(shí)現(xiàn)改動不影響頂層模塊代碼實(shí)現(xiàn),提高模塊化程度,增加括展性

但是也要有個度,服務(wù)每個都做個 interface 抽像一個模塊是否可行呢?當(dāng)然不,基于這么多年的工程實(shí)踐,我這里面有個準(zhǔn)則分享給大家:易變的模塊需要做出抽像、跨 rpc 調(diào)用的需要做出抽像

控制反轉(zhuǎn) IOC 思想

本質(zhì)上依賴注入是控制反轉(zhuǎn) IOC 的具體一個實(shí)現(xiàn)。在傳統(tǒng)編程中,表達(dá)程序目的的代碼調(diào)用庫來處理通用任務(wù),但在控制反轉(zhuǎn)中,是框架調(diào)用了自定義或特定任務(wù)的代碼,Java 黨玩的比較多

推薦大家看一下 coolshell 分享的 undo 例子。比如我們有一個 set 想實(shí)現(xiàn) undo 撤回功能

  1. type IntSet struct { 
  2.     data map[int]bool 
  3. func NewIntSet() IntSet { 
  4.     return IntSet{make(map[int]bool)} 
  5. func (set *IntSet) Add(x int) { 
  6.     set.data[x] = true 
  7. func (set *IntSet) Delete(x int) { 
  8.     delete(set.data, x) 
  9. func (set *IntSet) Contains(x int) bool { 
  10.     return set.data[x] 

這是一個 IntSet 集合,擁有三個函數(shù) Add, Delete, Contains, 現(xiàn)在需要添加 undo 功能

  1. type UndoableIntSet struct { // Poor style 
  2.     IntSet    // Embedding (delegation) 
  3.     functions []func() 
  4.   
  5. func NewUndoableIntSet() UndoableIntSet { 
  6.     return UndoableIntSet{NewIntSet(), nil} 
  7.   
  8. func (set *UndoableIntSet) Add(x int) { // Override 
  9.     if !set.Contains(x) { 
  10.         set.data[x] = true 
  11.         set.functions = append(set.functions, func() { set.Delete(x) }) 
  12.     } else { 
  13.         set.functions = append(set.functions, nil) 
  14.     } 
  15. func (set *UndoableIntSet) Delete(x int) { // Override 
  16.     if set.Contains(x) { 
  17.         delete(set.data, x) 
  18.         set.functions = append(set.functions, func() { set.Add(x) }) 
  19.     } else { 
  20.         set.functions = append(set.functions, nil) 
  21.     } 
  22. func (set *UndoableIntSet) Undo() error { 
  23.     if len(set.functions) == 0 { 
  24.         return errors.New("No functions to undo"
  25.     } 
  26.     index := len(set.functions) - 1 
  27.     if function := set.functions[index]; function != nil { 
  28.         function() 
  29.         set.functions[index] = nil // For garbage collection 
  30.     } 
  31.     set.functions = set.functions[:index
  32.     return nil 

上面是具體的實(shí)現(xiàn),有什么問題嘛?有的,undo 理論上只是控制邏輯,但是這里和業(yè)務(wù)邏輯 IntSet 的具體實(shí)現(xiàn)耦合在一起了

  1. type Undo []func() 
  2.  
  3. func (undo *Undo) Add(function func()) { 
  4.   *undo = append(*undo, function
  5. func (undo *Undo) Undo() error { 
  6.   functions := *undo 
  7.   if len(functions) == 0 { 
  8.     return errors.New("No functions to undo"
  9.   } 
  10.   index := len(functions) - 1 
  11.   if function := functions[index]; function != nil { 
  12.     function() 
  13.     functions[index] = nil // For garbage collection 
  14.   } 
  15.   *undo = functions[:index
  16.   return nil 

上面就是我們 Undo 的實(shí)現(xiàn),跟本不用關(guān)心業(yè)務(wù)具體的邏輯

  1. type IntSet struct { 
  2.     data map[int]bool 
  3.     undo Undo 
  4.   
  5. func NewIntSet() IntSet { 
  6.     return IntSet{data: make(map[int]bool)} 
  7.  
  8. func (set *IntSet) Undo() error { 
  9.     return set.undo.Undo() 
  10.   
  11. func (set *IntSet) Contains(x int) bool { 
  12.     return set.data[x] 
  13.  
  14. func (set *IntSet) Add(x int) { 
  15.     if !set.Contains(x) { 
  16.         set.data[x] = true 
  17.         set.undo.Add(func() { set.Delete(x) }) 
  18.     } else { 
  19.         set.undo.Add(nil) 
  20.     } 
  21.   
  22. func (set *IntSet) Delete(x int) { 
  23.     if set.Contains(x) { 
  24.         delete(set.data, x) 
  25.         set.undo.Add(func() { set.Add(x) }) 
  26.     } else { 
  27.         set.undo.Add(nil) 
  28.     } 

這個就是控制反轉(zhuǎn),不再由控制邏輯 Undo 來依賴業(yè)務(wù)邏輯 IntSet, 而是由業(yè)務(wù)邏輯 IntSet 來依賴 Undo. 想看更多的細(xì)節(jié)可以看 coolshell 的博客

再舉兩個例子,我們有 lbs 服務(wù),定時更新司機(jī)的坐標(biāo)流,中間需要處理很多業(yè)務(wù)流程,我們埋了很多 hook 點(diǎn),業(yè)務(wù)邏輯只需要對相應(yīng)的點(diǎn)注冊就可以了,新增加業(yè)務(wù)邏輯無需改動主流程的代碼

 

很多公司在做中臺,比如阿里做的大中臺,原來各個業(yè)務(wù)線有自己的業(yè)務(wù)處理邏輯,每條業(yè)務(wù)線都有工程師只寫各自業(yè)務(wù)相關(guān)的代碼。中臺化會抽像出共有的流程,每個新的業(yè)務(wù)只需要配置文件自定義需要的哪些模塊即可,這其實(shí)也是一種控制反轉(zhuǎn)的思想

 

責(zé)任編輯:武曉燕 來源: 董澤潤的技術(shù)筆記
相關(guān)推薦

2020-06-09 08:06:31

RocketMQ消息耗時

2022-11-13 10:07:22

SpringSpringBoot

2013-12-19 09:58:36

移動應(yīng)用產(chǎn)品市場

2020-07-10 09:55:15

程序員技能開發(fā)者

2011-08-25 09:03:40

2012-11-12 10:46:37

2021-06-06 16:15:57

地區(qū)接口項(xiàng)目

2019-07-01 09:58:05

鴻蒙系統(tǒng)華為

2014-05-13 13:42:54

工程師流程管理

2010-08-06 14:05:56

WPF

2020-01-06 13:11:30

技術(shù)工具

2013-03-26 14:17:21

架構(gòu)架構(gòu)設(shè)計事件驅(qū)動

2024-05-08 10:20:00

Redis分布式

2012-12-17 10:50:27

程序員

2012-07-10 16:09:54

App盈利

2022-01-04 09:01:10

開源項(xiàng)目開源技術(shù)

2024-03-14 09:07:05

刷數(shù)任務(wù)維度后端

2022-04-19 08:26:20

WebAPI架構(gòu)

2012-10-22 14:17:42

函數(shù)式程序員

2016-09-26 17:26:20

點(diǎn)贊
收藏

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

亚洲高清在线一区| 成人午夜在线影视| 天堂一区二区在线免费观看| 中文字幕日韩在线视频| 在线播放黄色av| av资源在线| 国产精品女同一区二区三区| 亚洲自拍偷拍网址| 五月婷婷视频在线| 91tv官网精品成人亚洲| 日韩精品一二三四区| 国产精品自拍视频在线| 不卡的av影片| 亚洲国产成人私人影院tom| 91在线中文字幕| 久久一区二区三区视频| 婷婷综合社区| 精品视频在线播放| 深爱五月综合网| 中老年在线免费视频| 亚洲少妇中出一区| 日本日本精品二区免费| 精品欧美一区二区精品少妇| 免费在线日韩av| 欧美成人午夜激情| 51妺嘿嘿午夜福利| 国产精品毛片视频| 欧美一区午夜精品| 人妻丰满熟妇av无码区app| 99福利在线| 欧美高清一级片在线观看| 国产精品对白一区二区三区| 中文字幕在线观看高清| 中国女人久久久| 欧美肥臀大乳一区二区免费视频| 国产成人免费观看网站| 亚洲免费专区| 亚洲第一男人av| 色姑娘综合天天| 精品国产黄a∨片高清在线| 午夜精品免费在线观看| 久久久天堂国产精品| 国产对白叫床清晰在线播放| www.亚洲精品| 古典武侠综合av第一页| 国产免费黄色片| 麻豆精品在线视频| 国产精品久久久久久影视| 日本一本高清视频| 亚洲五月婷婷| 欧美黄色成人网| 欧美三级 欧美一级| 91视频久久| 中文字幕视频在线免费欧美日韩综合在线看 | 亚洲精品久久久久久动漫器材一区 | 国产精品第6页| 久久一区二区三区超碰国产精品| 26uuu另类亚洲欧美日本一| 国产在线一二区| 亚洲无线一线二线三线区别av| 欧美国产日韩二区| 久久精品99国产精| 亚洲黄色大片| 2019中文字幕全在线观看| 国产欧美日韩另类| 国产日韩欧美三级| 8090成年在线看片午夜| 国产精品suv一区| 天堂成人国产精品一区| 国产精品扒开腿做| 亚洲专区第一页| 韩国毛片一区二区三区| 97netav| 日本精品999| 91免费精品国自产拍在线不卡| 久久99精品久久久久久久久久 | 欧美a一级片| 在线不卡中文字幕播放| 麻豆传媒在线看| 久久国产精品免费精品3p| 日韩不卡在线观看| 日本一卡二卡在线播放| 91高清一区| 欧美精品激情在线观看| 99re这里只有精品在线| 久久电影网电视剧免费观看| 99国产视频| 涩爱av在线播放一区二区| 国产视频亚洲色图| 成人在线免费观看网址| 精精国产xxxx视频在线野外| 在线亚洲一区观看| 999热精品视频| 天堂99x99es久久精品免费| 一区三区二区视频| 免费一级特黄特色大片| 天堂成人免费av电影一区| 成人午夜在线观看| 偷拍自拍在线| 亚洲日本一区二区三区| 久久精品视频16| 日韩午夜电影免费看| 精品国产乱码久久久久久浪潮 | www.五月激情| 久久久777精品电影网影网 | 男人和女人做事情在线视频网站免费观看| 亚洲精品一二三区| 欧美私人情侣网站| 久久久精品区| 国产亚洲一级高清| 日韩欧美大片在线观看| 狠狠狠色丁香婷婷综合久久五月| 国产精品亚洲综合| 免费在线观看av网站| 高跟丝袜欧美一区| 日本黄色www| 日韩免费av| 91国产视频在线| 99久久精品国产一区二区成人| 久久久一区二区三区| 国产免费一区二区视频| 午夜不卡一区| 国产一区二区三区毛片| 五月天婷婷综合网| 国产成人精品免费看| 亚洲精品影院| 九九热线视频只有这里最精品| 日本中文字幕在线视频观看| 久久久综合久久久| 蜜臀久久久99精品久久久久久| 国产精品二区三区| 黄色动漫在线观看| 欧美色爱综合网| 免费观看一级一片| 在线成人h网| 91亚洲精品在线观看| 91在线导航| 91精品1区2区| 色婷婷av777| 影音先锋亚洲精品| 99www免费人成精品| 快射av在线播放一区| 欧美日韩亚洲综合在线 | 亚洲片在线资源| 羞羞影院体验区| 99综合电影在线视频| 免费视频爱爱太爽了| 亚洲一区 二区| 九九精品在线观看| www.国产.com| 亚洲一区二区三区精品在线| 国产大学生av| 欧美高清日韩| 国产精品精品软件视频| 黑人精品视频| 亚洲国产精品va在线观看黑人| 日本三级中文字幕| 99精品桃花视频在线观看| 男人添女人下面高潮视频| 神马日本精品| 国产91在线播放精品91| 超碰97在线免费观看| 欧美色电影在线| 色欲一区二区三区精品a片| 激情丁香综合五月| 日韩视频一二三| 涩爱av色老久久精品偷偷鲁| 色综合久久久久久中文网| 成人福利小视频| 亚洲成av人片一区二区三区| 在线黄色免费网站| 日韩中文字幕一区二区三区| 一区二区免费在线观看| 国产精品一区免费在线| 欧美日韩国产二区| 色哟哟在线观看| 欧美亚洲高清一区| 日韩女优一区二区| 99久久精品情趣| www.xxx亚洲| 中文字幕亚洲综合久久五月天色无吗''| **亚洲第一综合导航网站| а√在线中文在线新版| 一二美女精品欧洲| 国产乱子伦精品无码码专区| 亚洲午夜日本在线观看| 欧美图片第一页| 国产综合久久久久久鬼色| 少妇久久久久久被弄到高潮| 亚洲人成网亚洲欧洲无码| 国产欧美韩国高清| av中文字幕在线看| 有码中文亚洲精品| 亚洲av永久纯肉无码精品动漫| 欧美日韩激情小视频| 国产jizz18女人高潮| 成人av免费观看| 日本高清久久久| 国产亚洲成人一区| 中文字幕99| 天堂在线精品| 91福利入口| 中文字幕日本一区| 亚洲国产精品精华液ab| 亚洲一级片av| 国产日韩1区| 青青草原国产免费| 你懂的在线观看一区二区| 国产欧美日韩精品丝袜高跟鞋| 在线中文字幕视频观看| 亚洲人成电影网站色xx| 精品人妻一区二区三区浪潮在线 | 亚洲精品720p| 亚洲一区二区三区网站| 精品国产999| 欧美人禽zoz0强交| 国产欧美日韩精品一区| 日本50路肥熟bbw| 国产最新精品免费| 黄色一级二级三级| 亚洲黄色免费| 日韩a级黄色片| 水蜜桃久久夜色精品一区| 六月婷婷久久| 福利片一区二区| 成人h视频在线观看播放| 高清av不卡| 国产最新精品视频| 中文字幕伦理免费在线视频 | 国产精品20p| 成人免费毛片嘿嘿连载视频| 亚洲欧美手机在线| 日本不卡一区二区| 国产91对白刺激露脸在线观看| 午夜精品999| 天天综合五月天| 日韩一区亚洲二区| 相泽南亚洲一区二区在线播放| 性欧美lx╳lx╳| 久久99久久精品国产| 都市激情亚洲欧美| 成人在线免费观看一区| 一区二区三区在线资源| 3d动漫啪啪精品一区二区免费 | 国产精品对白刺激久久久| 91嫩草国产线观看亚洲一区二区| 国产精品天天狠天天看| 国产成人精品一区二三区在线观看 | 久久精品国产美女| 看全色黄大色大片免费久久久| 91在线播放视频| ccyy激情综合| 国产一区二区三区四区五区在线| 国产精品任我爽爆在线播放| av免费观看久久| av男人一区| 久久久久久亚洲精品不卡4k岛国| 婷婷亚洲成人| 青娱乐一区二区| 日韩精品一区二区久久| 中文字幕剧情在线观看一区| 一区二区三区在线电影| 国产 欧美 日韩 一区| 最新国产拍偷乱拍精品| 亚洲国产精品久久久久婷蜜芽| 免费一区视频| 亚洲免费黄色网| 国产激情一区二区三区桃花岛亚洲| 美女流白浆视频| 久久综合色婷婷| 色欲AV无码精品一区二区久久| 国产精品的网站| 国产十六处破外女视频| 婷婷久久综合九色综合绿巨人| 香蕉影院在线观看| 欧洲av在线精品| 99久久精品国产成人一区二区| 亚洲国产成人久久综合| 国产三级在线| 久久成人一区二区| av毛片午夜不卡高**水| 国产91网红主播在线观看| 亚洲精品乱码日韩| 国产富婆一区二区三区 | 亚洲国产一区二区三区在线| 亚洲国产一成人久久精品| 日韩网站在线免费观看| 天堂精品中文字幕在线| 中文字幕久久久久久久| 91麻豆精品一区二区三区| 娇小11一12╳yⅹ╳毛片| 亚洲国产乱码最新视频 | 在线观看免费小视频| 亚洲精品视频一区| 亚洲一区欧美在线| 555夜色666亚洲国产免| 婷婷在线免费观看| 综合av色偷偷网| 国产精品vvv| 成人在线小视频| 首页亚洲中字| 成人在线免费观看网址| 天堂va蜜桃一区二区三区漫画版 | 26uuu色噜噜精品一区| 日韩国产第一页| 精品成人在线视频| 99热精品在线播放| 国产亚洲精品综合一区91| 国内高清免费在线视频| 国产精品亚洲片夜色在线| 精品按摩偷拍| 日本一道在线观看| 蜜臀a∨国产成人精品| 熟女人妻在线视频| 亚洲精品中文字幕乱码三区| 国产精品露脸视频| 日韩成人高清在线| 18网站在线观看| 国产欧美欧洲在线观看| 国产免费av一区二区三区| 日本熟妇人妻xxxx| 国产毛片精品视频| 黑人狂躁日本娇小| 在线观看av不卡| 蜜桃视频在线观看网站| 久久久亚洲国产| 欧美一级大片在线视频| 亚洲日本欧美在线| 日韩精品视频网站| 免费在线观看你懂的| 天天亚洲美女在线视频| 亚洲国产精品久久久久爰性色| 麻豆成人在线看| 农村妇女一区二区| 亚洲三区在线| 蜜芽一区二区三区| 91香蕉国产视频| 欧美在线三级电影| 成人免费一区二区三区视频网站| 欧美在线观看日本一区| 激情亚洲另类图片区小说区| 大西瓜av在线| 盗摄精品av一区二区三区| 久久久精品国产sm调教网站| 欧美一卡二卡三卡四卡| 成人免费看片| 亚洲最大av网站| 综合久久久久| 免费在线观看日韩av| 亚洲一二三区在线观看| 亚洲精品一区二区口爆| 久久久久久久久久久网站| 国产成人精品亚洲线观看| 免费无码毛片一区二三区| www.成人在线| 国产精品国产三级国产专区52| 亚洲免费小视频| 欧美日韩尤物久久| 亚洲自拍偷拍二区| 国产一区二区精品在线观看| 男人操女人的视频网站| 日韩欧美二区三区| xxxx成人| 欧美二级三级| 蜜臀av一区二区在线免费观看 | 精品国产一区二区三区久久久蜜臀| 91最新在线观看| 中文字幕中文字幕在线一区| 国产麻豆一精品一男同| 久久久久成人网| 日韩欧美在线精品| 冲田杏梨av在线| 亚洲欧美电影院| 日本人妻熟妇久久久久久| 欧美一区二区影院| 99免费精品| 国产在线不卡av| 欧美伊人久久久久久久久影院| 日本在线看片免费人成视1000| 亚洲综合中文字幕68页| 国产日韩1区| 国产一区二区精彩视频| 亚洲第一男人av| 国产经典一区| 今天免费高清在线观看国语| 99久精品国产| 国产女优在线播放| 欧美风情在线观看| 在线观看欧美理论a影院| av中文字幕网址| 午夜视频久久久久久| 淫片在线观看| 精品乱码一区二区三区| 麻豆国产精品官网| 国产精品a成v人在线播放| 少妇激情综合网| 色愁久久久久久| 91蝌蚪视频在线| 色天使色偷偷av一区二区| av免费网站在线观看|