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

從業(yè)務(wù)開發(fā)中學(xué)習(xí)和理解架構(gòu)設(shè)計(jì)

開發(fā) 架構(gòu) 新聞
架構(gòu)設(shè)計(jì)并不高端,它本身所產(chǎn)生的價(jià)值并不明顯,真正能夠產(chǎn)生價(jià)值的在于我們當(dāng)前正在走的路:如何理解我們的業(yè)務(wù)問題。

前言

在軟件開發(fā)領(lǐng)域經(jīng)常會(huì)接觸到架構(gòu)這個(gè)詞匯,在我最初的印象中,架構(gòu)是一個(gè)很高級(jí)的詞匯。它似乎代表了復(fù)雜的工程結(jié)構(gòu)、高層次的抽象設(shè)計(jì)、最新的開發(fā)語言特性等等。對(duì)于當(dāng)時(shí)只專注于寫業(yè)務(wù)邏輯的我來說,不免心生對(duì)架構(gòu)的敬畏。工作中對(duì)架構(gòu)的討論很少,出現(xiàn)則是一些高級(jí)晦澀的描述,但是從來沒有人清楚地解釋過架構(gòu)做了哪些事。所以,架構(gòu)到底是什么?架構(gòu)和業(yè)務(wù)之間是什么關(guān)系?

當(dāng)我們看一些關(guān)于架構(gòu)的書籍或者資料,不免會(huì)接觸到一些對(duì)架構(gòu)的定義或者描述。比如:約束、規(guī)則、邊界、實(shí)體關(guān)系、模型定義等等。但是懂得這些概念并不能幫助我們?cè)O(shè)計(jì)出來更好的架構(gòu),當(dāng)我們套用設(shè)計(jì)原則進(jìn)行架構(gòu)設(shè)計(jì)時(shí),不免會(huì)覺得空洞乏味,總覺得少了點(diǎn)什么。雖然我們?yōu)榧軜?gòu)設(shè)計(jì)做了很多事,但是似乎什么也沒做。因?yàn)橹会槍?duì)架構(gòu)設(shè)計(jì)本身來說,很難說清楚它所產(chǎn)生的價(jià)值。所以,好的架構(gòu)設(shè)計(jì)的出發(fā)點(diǎn)是什么?好的架構(gòu)應(yīng)該是什么樣的呢?  

去年我有一個(gè)任務(wù):將我們當(dāng)前工程的代碼進(jìn)行重新的拆分和組合,以厘清模塊間的關(guān)系,控制工程中模塊依賴的復(fù)雜度。這看起來是一個(gè)很簡單的工作,找到一個(gè)不同于當(dāng)前的且更合理的目錄劃分方案,就可以嘗試落地實(shí)施。但是這又是一個(gè)很困難的工作,因?yàn)槲覀兪紫纫卮鹩心男┠K、模塊間是什么依賴關(guān)系的問題。其實(shí),回到任務(wù)的本身,我們并不是只想對(duì)代碼文件進(jìn)行重新的組織和劃分,我們的目標(biāo)是業(yè)務(wù)模塊解耦合,定義并明確業(yè)務(wù)模塊間的依賴規(guī)則。面對(duì)這樣的目標(biāo),我們需要首先從業(yè)務(wù)視角更清晰地定義和劃分模塊,然后從工程結(jié)構(gòu)視角確定模塊間的關(guān)系。所以,代碼目錄調(diào)整實(shí)際上是一個(gè)對(duì)業(yè)務(wù)場(chǎng)景、工程結(jié)構(gòu)理解和設(shè)計(jì)的問題。代碼目錄的結(jié)構(gòu)代表了我們的工程結(jié)構(gòu),也是業(yè)務(wù)場(chǎng)景劃分的抽象描述,更是模塊定義以及模塊依賴關(guān)系的展現(xiàn)。

在設(shè)計(jì)代碼目錄劃分方案的過程中,看了一些工程結(jié)構(gòu)設(shè)計(jì)的資料,讀了一些關(guān)于架構(gòu)設(shè)計(jì)的書。對(duì)于架構(gòu)有了一些理解。本文是對(duì)這段學(xué)習(xí)和任務(wù)完成過程的思考和沉淀。我希望能夠回答上面提到的幾個(gè)問題:

1. 架構(gòu)到底是什么? 架構(gòu)和業(yè)務(wù)之間的關(guān)系

2. 好的架構(gòu)的設(shè)計(jì)出發(fā)點(diǎn)是什么? 好的架構(gòu)應(yīng)該是什么樣的

什么是架構(gòu)

架構(gòu)的定義

首先架構(gòu)是一個(gè)漢語詞匯。它的定義是:人們對(duì)一個(gè)結(jié)構(gòu)內(nèi)的元素及元素間關(guān)系的一種主觀映射的產(chǎn)物。從這個(gè)定義可以看出,傳統(tǒng)的架構(gòu)在描述一個(gè)系統(tǒng)中有什么元素,以及元素之間關(guān)系。在建筑領(lǐng)域,架構(gòu)也用于描述建筑物的結(jié)構(gòu)。    

作為一個(gè)計(jì)算機(jī)領(lǐng)域的詞匯,架構(gòu)的定義是:有關(guān)軟件整體結(jié)構(gòu)與組件的抽象描述,用于指導(dǎo)大型軟件系統(tǒng)各個(gè)方面的設(shè)計(jì)。實(shí)際上也在定義有什么以及關(guān)系的問題。  

從工程化解讀架構(gòu)設(shè)計(jì)的作用

無論是在建筑領(lǐng)域還是計(jì)算機(jī)領(lǐng)域,我們通常會(huì)用工程描述這類工作的項(xiàng)目。比如我所在的部門是工程技術(shù)中心,我是一個(gè)工程類的程序員等。我們可以稱之為工程的工作項(xiàng)目包括:建筑工程、軍事工程、水利工程、生物工程、軟件工程等。而我們?cè)谕瓿身?xiàng)目的過程中,進(jìn)行架構(gòu)設(shè)計(jì)實(shí)際上就是推進(jìn)實(shí)施工程化的一部分。那么進(jìn)行工程架構(gòu)設(shè)計(jì)會(huì)考慮哪些因素,它對(duì)實(shí)施工程化的作用是什么呢?

假設(shè),讀者你現(xiàn)在是一位建筑工程師,負(fù)責(zé)建造一棟房屋。

雖然我們沒有真正的蓋過房子,但是在進(jìn)行房屋的整體結(jié)構(gòu)設(shè)計(jì)時(shí),你一定會(huì)關(guān)心這些:

1. 房屋用途。 首先要明確這棟房子是干什么用的

2. 房屋層數(shù)。 和用途緊密相關(guān),不同用途的房子層數(shù)也是不一樣的

3. 房屋外觀。 定義這棟房屋應(yīng)該長什么樣

4. 房屋的布局。 定義這棟房屋應(yīng)該怎么更好地被使用

等等。我們稱上面這幾個(gè)屬性是房屋的基礎(chǔ)能力。 作為一個(gè)靠譜的建筑工程師,你一定還會(huì)著重地設(shè)計(jì)這些:

1. 水電走向。 這很重要。 保證房屋的安全性和使用的便捷

2. 承重和抗壓。 房屋的使用壽命很大程度上依賴于此

等等。我們稱上面的這幾個(gè)屬性是安全性和性能。

另外一方面,你大概不會(huì)關(guān)心房屋的裝修風(fēng)格、地板顏色、衣柜品牌等等因素。我們稱這些為應(yīng)用細(xì)節(jié)。

總結(jié)來說,進(jìn)行房屋的工程架構(gòu)設(shè)計(jì)時(shí)更多地關(guān)系底層設(shè)計(jì),而不在乎過多的技術(shù)細(xì)節(jié)。

所以,我們可以給架構(gòu)的作用下一個(gè)定義:在明確用途的基礎(chǔ)上定義使用的規(guī)則和約束,提供了基礎(chǔ)的支撐能力,并保障安全性、性能和使用周期。

軟件架構(gòu)設(shè)計(jì)的原則和要求

到目前為止,我們已經(jīng)明確了在做架構(gòu)設(shè)計(jì)時(shí)必須遵循的前提和原則:明確用途。此外也對(duì)架構(gòu)設(shè)計(jì)提出要求:提供基礎(chǔ)能力、保障安全性、性能等。

同樣的,引申到計(jì)算機(jī)領(lǐng)域。當(dāng)我們進(jìn)行軟件架構(gòu)設(shè)計(jì)時(shí)也必須遵循的原則有:

1. 架構(gòu)設(shè)計(jì)一定要從業(yè)務(wù)場(chǎng)景出發(fā)

這實(shí)際上就是明確用途的大前提。架構(gòu)設(shè)計(jì)一定是要從業(yè)務(wù)出發(fā)、面向業(yè)務(wù)變化的。只有在我們明確了我們的業(yè)務(wù)場(chǎng)景和業(yè)務(wù)目標(biāo)后,在此基礎(chǔ)上進(jìn)行的架構(gòu)設(shè)計(jì)才是能真正產(chǎn)生業(yè)務(wù)價(jià)值的。一個(gè)脫離了業(yè)務(wù)場(chǎng)景而設(shè)計(jì)的架構(gòu),無論多么新穎和高級(jí),也絕不是一個(gè)好的架構(gòu)。

2. 架構(gòu)設(shè)計(jì)一定要落到業(yè)務(wù)場(chǎng)景中去驗(yàn)證

我們不能只從基礎(chǔ)能力、安全性或者性能方面去評(píng)判一個(gè)架構(gòu)的好壞。架構(gòu)對(duì)業(yè)務(wù)開發(fā)的支持能力,面向業(yè)務(wù)變化時(shí)的靈活度以及持續(xù)演進(jìn)能力等都是評(píng)判的因素。

此外,我們要求軟件架構(gòu)必須是靈活的,能夠滿足未來業(yè)務(wù)持續(xù)發(fā)展的要求。

業(yè)務(wù)場(chǎng)景是不斷變化的,架構(gòu)也要具有跟隨業(yè)務(wù)形態(tài)不斷演進(jìn)的能力。架構(gòu)設(shè)計(jì)的核心是保證面向業(yè)務(wù)變化時(shí)有足夠靈活的響應(yīng)力,這要求架構(gòu)設(shè)計(jì)能夠識(shí)別到業(yè)務(wù)的核心領(lǐng)域。所以,無論是面向當(dāng)前還是面向未來,架構(gòu)設(shè)計(jì)都需要真正地識(shí)別和理解業(yè)務(wù)問題。

架構(gòu)設(shè)計(jì)的原則

本章節(jié)介紹幾個(gè)軟件架構(gòu)設(shè)計(jì)時(shí)可以遵循的原則,實(shí)際上在進(jìn)行功能模塊設(shè)計(jì)也可以參考這些設(shè)計(jì)原則。

SRP 單一職責(zé)原則

1. 一個(gè)函數(shù)只負(fù)責(zé)完成一個(gè)功能

2. 任何一個(gè)模塊只對(duì)某一類行為者負(fù)責(zé)

3. 一個(gè)類或者函數(shù)應(yīng)該有且僅有一個(gè)被改變的理由

在實(shí)際的編碼中,我們還是可以看到很多違反單一職責(zé)的例子的,比如超長的函數(shù)體。一個(gè)函數(shù)內(nèi)做了很多事,實(shí)際上就是負(fù)責(zé)了太多的功能,很多的變更都要修改這個(gè)函數(shù),這導(dǎo)致很難控制變更影響的范圍。

我們可以將大函數(shù)拆分成小函數(shù),小函數(shù)體負(fù)責(zé)的功能更加單一,相應(yīng)的也會(huì)更加靈活。所以我們建議大家多寫一些小的函數(shù)體。但是不要在函數(shù)拆分的過程中進(jìn)行過度的封裝和抽象。

OCP 開閉原則

1. 易于擴(kuò)展,抗拒修改

模塊要易于擴(kuò)展,控制修改。這是我們?cè)诔鯇W(xué)編程語言時(shí)就會(huì)被教育到的設(shè)計(jì)原則。開閉原則幫助我們?cè)O(shè)計(jì)更加靈活的模塊,同時(shí)還能控制模塊變更的影響范圍。

LSP 里氏替換原則

1. 所有引用父類的地方都可以替換成子類,而行為不發(fā)生改變

使用里氏替換原則可以保證父類的復(fù)用性。它主要是用來判斷抽象和繼承關(guān)系設(shè)計(jì)是否合理,即某個(gè)類是否應(yīng)該具有某個(gè)屬性,以及一個(gè)類到底是不是另外一個(gè)類的子類。

舉一個(gè)典型的例子,乘馬是乘馬,乘白馬也是乘馬,乘黑馬也是乘馬。那么白馬和黑馬就是馬的子類,是符合LSP的。

下面是兩個(gè)典型的違反LSP原則的例子。也是網(wǎng)上也特別常見的例子。

第一個(gè)是正方形不是矩形。

class Rectangle {
public:
int32_t getWidth() const {return width;}
int32_t getHeight() const {return height;}


virtual void setWidth(int32_t w) {
width = w;
}
virtual void setHeight(int32_t h) {
height = h;
}
private:
int32_t width = 0;
int32_t height = 0;


};
class Square : public Rectangle {
public:
void setWidth(int32_t w) override {
Rectangle::setWidth(w);
Rectangle::setHeight(w);
}
void setHeight(int32_t h) override {
// …
}
};


void reSize(Rectangle rect) {
while (rect.getHeight() <= rect.getWidth()){
rect.setHeight(rect.getWidth() + 1);
}
}

正方形類Square繼承自矩形類Rectangle,并且重寫了函數(shù)setWidth和setHeight。在函數(shù)reSize中,將父類Rectangle對(duì)象替換成子類Square后,將會(huì)出現(xiàn)死循環(huán),程序出現(xiàn)異常。不符合LSP原則。

所以正方形不是矩形。 第二個(gè)是鴕鳥不是鳥。

class Bird {
public:
int32_t getVelocity() const {return velocity;}
private:
int32_t velocity = 0; // 飛行速度
};


class Ostrich : public Bird {
};
void crossRiver(Bird bird) {
int32_t distance = 1000;
int32_t elapsed = distance / bird.getVelocity();
}

鳥類Brid具有飛行速度的屬性,鴕鳥類Ostrich繼承自類Brid,飛行速度默認(rèn)為0。在函數(shù)crossRiver中,將基類Brid對(duì)象替換成子類Ostrich對(duì)象后,獲取的飛行速度為0,出現(xiàn)了除0異常。不符合LSP原則。

所以鴕鳥不是鳥。

在這兩個(gè)例子中,結(jié)合里氏替換原則, 我們得出了兩個(gè)奇怪的結(jié)論,違背了幾何學(xué)和生物學(xué)的常識(shí)。其實(shí)問題在于我們對(duì)抽象和接口的設(shè)計(jì)上。比如前一個(gè)例子中reSize函數(shù),它的條件判斷是有問題的。對(duì)于一個(gè)矩形對(duì)象,寬高不一定非得相等,所以將寬高相等作為循環(huán)的條件是不合理的。

對(duì)于后一個(gè)例子,飛行并不是鳥類的統(tǒng)一特征,所以抽象的鳥類不應(yīng)該擁有飛行速度這個(gè)屬性,也不應(yīng)該具有飛行的接口。那么我們應(yīng)該怎么處理這個(gè)問題呢。準(zhǔn)確來說,鳥類可以具有是否可以飛行的接口,然后有一個(gè)速度屬性。可以飛行的鳥返回飛行速度,而鴕鳥返回行走速度。

所以,里氏替換原則用于驗(yàn)證我們的接口和抽象設(shè)計(jì)是否合理,同時(shí)也可以驗(yàn)證繼承關(guān)系是否合理。

ISP 接口隔離原則

1. 不依賴于自己不需要的東西

2. 使用接口類的方式細(xì)化功能模塊,每個(gè)接口類負(fù)責(zé)某一類明確的功能

指導(dǎo)我們進(jìn)行接口設(shè)計(jì)的原則。類似于單一職責(zé)原則,多個(gè)單一的接口負(fù)責(zé)的功能更簡單,更易于維護(hù),這比一個(gè)龐大的接口要好。在做接口設(shè)計(jì)時(shí)要盡量保證接口的小巧、簡潔和正交,這樣給業(yè)務(wù)層提供了更多的靈活性。一個(gè)大的接口可能會(huì)做業(yè)務(wù)層并不希望做的事,同時(shí)當(dāng)業(yè)務(wù)層需要擴(kuò)展功能時(shí)也會(huì)使變更影響的范圍過大。

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

1. 為了保證系統(tǒng)的靈活性(易于修改)和穩(wěn)定性(修改影響范圍小),在依賴關(guān)系中應(yīng)該避免引用具體的類

2. 接口比實(shí)現(xiàn)更穩(wěn)定,所以盡量避免修改函數(shù)實(shí)現(xiàn)時(shí)對(duì)依賴該接口的模塊的影響

3. 繼承關(guān)系是依賴關(guān)系中最強(qiáng)的,盡量避免繼承自有具體實(shí)現(xiàn)的類

這個(gè)原則目的在于降低使模塊間的耦合度,并且使底層模塊更易于被修改和替換。當(dāng)下層功能發(fā)生變化時(shí)可以控制對(duì)上層業(yè)務(wù)的影響范圍,使得整體系統(tǒng)更加穩(wěn)定和靈活。

DIP原則在后面章節(jié)介紹架構(gòu)設(shè)計(jì)方法時(shí)也會(huì)多次提到。

以上這五個(gè)設(shè)計(jì)原則統(tǒng)稱為SOLID原則。在《整潔架構(gòu)之道》中有比較詳細(xì)的介紹。

奧卡姆剃刀原則

奧卡姆剃刀原則不是在軟件開發(fā)領(lǐng)域提出的,而是在哲學(xué)領(lǐng)域提出的。奧卡姆剃刀原則對(duì)科學(xué)和哲學(xué)的發(fā)展都極為重要,因?yàn)樗嬖V人們理論應(yīng)該盡量簡潔,理論中一切不影響結(jié)論的多余部分都應(yīng)該被剔除掉。

正如奧卡姆剃刀原則的精髓一樣,它的描述非常簡潔有力:如非必要,勿增實(shí)體。

我們也可以稱它為簡單即為美原則。通俗的描述是:用盡量少的步驟完成一件事。或者,如果對(duì)于一個(gè)事物有兩種解釋,采用最簡單或能被證偽的那種。正是因?yàn)閵W卡姆剃刀原則,我們才更加相信哥白尼的日心說,更相信牛頓和愛因斯坦。否則,地球是宇宙中心的理論也沒錯(cuò),只是其他行星和恒星環(huán)繞地球的軌道公式也太復(fù)雜了,而且也容易被自然現(xiàn)象證偽。

在眾多的介紹軟件設(shè)計(jì)方法的書籍和資料中也多次提到過奧卡姆剃刀原則。應(yīng)用到軟件開發(fā)領(lǐng)域,它確實(shí)給了我們很大的啟示。設(shè)想一下我們是不是遇到過這樣的場(chǎng)景:

1. 費(fèi)力地向別人解釋某個(gè)模塊為什么那么設(shè)計(jì)

2. 為某段代碼加的注釋比代碼都多

3. 為了解決一個(gè)問題而引入一個(gè)新的模塊

當(dāng)我們費(fèi)力說明和解釋某個(gè)代碼設(shè)計(jì)時(shí),真正的問題并不在于我們解釋的不夠充分,或者聽眾不夠聰明理解不了,而在于代碼設(shè)計(jì)本身沒有很好地體現(xiàn)其業(yè)務(wù)語義。實(shí)際上過多的解釋和注釋都是多余的,是可以被奧卡姆剃刀砍掉的。

對(duì)于為了解決一個(gè)問題而引入一個(gè)模塊也是在工作中經(jīng)常遇到的問題。有很多原因?qū)е履承┠K變得腐化難以維護(hù),比如最初的設(shè)計(jì)沒有很好地貼合業(yè)務(wù)場(chǎng)景;編碼規(guī)范不夠好,后面的修改也沒有遵守規(guī)則;接手者沒有完全理解作者的意圖就著手修改等等。而程序員也經(jīng)常會(huì)有的一個(gè)想法是:當(dāng)一個(gè)模塊難以維護(hù)了,最好的方法是用一個(gè)新模塊替換掉它。實(shí)際上這種方法并沒有觸及問題的本質(zhì),在沒有找到導(dǎo)致模塊腐化的原因之前,在沒有制定規(guī)范的模塊設(shè)計(jì)方案之前,我們都不能保證新模塊不會(huì)有舊模塊一樣的問題。所以,想開發(fā)新模塊替換掉舊模塊很大程度上是在逃避對(duì)舊模塊問題的思考,新模塊也很有可能淪落到舊模塊一樣的地步。如果回答不了這個(gè)矛盾的問題,還是用奧卡姆剃刀把新模塊剔除掉吧,新模塊是多余的,并沒有解決真正的問題。

奧卡姆剃刀原則保證解決問題的方法是簡單有效的,同時(shí)也約束我們應(yīng)當(dāng)思考更根本的問題,不能浮于問題表象采用最省力的方法。

其他的設(shè)計(jì)原則概覽

DRY(Dont Repeat Yourself): 保證代碼的可復(fù)用性,避免代碼邏輯的重復(fù)

YAGNI(You Aint Gonna Need It): 代碼應(yīng)易于擴(kuò)展,但要避免過度設(shè)計(jì),不要編寫當(dāng)前用不到的代碼。

KISS(Keep It Simple, Stupid): 把事情想復(fù)雜,做簡單

POLA(Principle of Least Astonishment): 最小驚奇原則。 代碼應(yīng)合乎邏輯和規(guī)范,給閱讀者最少的驚嚇。 接口設(shè)計(jì)避免標(biāo)新立異。


常用的幾種架構(gòu)設(shè)計(jì)

分層架構(gòu)

分層架構(gòu)是指基于具體的業(yè)務(wù)模型按照功能模塊將代碼進(jìn)行分層組織。每一層代表了一組相關(guān)功能的集合。具體分為幾層沒有明確的規(guī)則,通常可以分為3-4層或者更多。在分層架構(gòu)中,依賴關(guān)系是由上往下,上層依賴于下層,不能反向依賴。越往下的層次越通用,偏向于基礎(chǔ)能力。越往上層次越動(dòng)態(tài),偏向于業(yè)務(wù)。

分層架構(gòu)設(shè)計(jì)按照依賴規(guī)則的嚴(yán)格程度分為嚴(yán)格型分層架構(gòu)和松散型分層架構(gòu)。嚴(yán)格型分層架構(gòu)要求每一層只能訪問其直接依賴的層,不能訪問其間接依賴的層。松散型分層架構(gòu)允許每一層訪問位于其下方的任意一層。嚴(yán)格型分層架構(gòu)使得各個(gè)層之間的耦合度降到最低,但是靈活性不足,當(dāng)上層需要訪問下面間接層的能力時(shí)必須從上往下層層穿透。松散型分層架構(gòu)在保證依賴規(guī)則的前提下提供了足夠的靈活性,所以大部分分層架構(gòu)都是松散型的。

分層架構(gòu)設(shè)計(jì)簡潔易懂。對(duì)抽象事物按照基礎(chǔ)特征進(jìn)行分類,符合我們的思維習(xí)慣,易于理解。分層架構(gòu)設(shè)計(jì)保證每一層內(nèi)部有較好的內(nèi)聚性,減少了層與層之間的耦合度,易于基礎(chǔ)能力的沉淀和復(fù)用,也易于控制變更帶來的風(fēng)險(xiǎn)。 ?

另外一方面,分層架構(gòu)設(shè)計(jì)雖然定義了多個(gè)層,但是層與層之間的邊界并不是特別清晰。對(duì)于新增的模塊有可能難以確定應(yīng)該放在哪一層。或者隨著業(yè)務(wù)邏輯的變化,未來可能需要調(diào)整模塊所屬的層次。分層架構(gòu)中,上層模塊對(duì)下層模塊有直接的依賴,下層模塊的實(shí)現(xiàn)直接向上層模塊暴露。在修改或者替換下層模塊時(shí)需要修改上層模塊,對(duì)上層業(yè)務(wù)的影響較大。業(yè)務(wù)實(shí)現(xiàn)與基礎(chǔ)能力沒有完全解耦合。

六邊形架構(gòu)

又稱為端口-適配器架構(gòu)。為了解決具體實(shí)現(xiàn)依賴于基礎(chǔ)能力的問題,采用依賴倒置設(shè)計(jì)方法將工程分為內(nèi)部和外部。內(nèi)部是具體的業(yè)務(wù)邏輯,外部是依賴的基礎(chǔ)能力。內(nèi)部業(yè)務(wù)邏輯不再直接依賴于外部基礎(chǔ)能力,而是都依賴于其抽象定義。使用依賴注入的方式將外部實(shí)現(xiàn)傳入內(nèi)部業(yè)務(wù)邏輯中。內(nèi)部和外部使用接口進(jìn)行交互,內(nèi)部業(yè)務(wù)邏輯訪問基礎(chǔ)能力時(shí)直接調(diào)用其抽象接口即可。

六邊形架構(gòu)解決了業(yè)務(wù)邏輯直接依賴外部模塊的問題,它們都依賴于抽象,不依賴于直接的實(shí)現(xiàn)和細(xì)節(jié)。它們直接通過定義好的接口進(jìn)行交互。因?yàn)闃I(yè)務(wù)邏輯和外部模塊沒有直接的依賴關(guān)系,在修改和替換外部模塊時(shí)只需要按照接口定義實(shí)現(xiàn)功能,不需要改動(dòng)業(yè)務(wù)邏輯。

洋蔥圈架構(gòu)(整潔架構(gòu))

洋蔥圈架構(gòu)又稱為整潔架構(gòu),結(jié)合了分層架構(gòu)、六邊形架構(gòu)和領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)特點(diǎn)的架構(gòu)設(shè)計(jì)方法。洋蔥圈架構(gòu)是對(duì)六邊形架構(gòu)的進(jìn)一步擴(kuò)展,依賴關(guān)系依然是外部依賴內(nèi)部。參考領(lǐng)域驅(qū)動(dòng)設(shè)計(jì),將依賴層次劃分為3-4層甚至更多。從內(nèi)向外依次為:領(lǐng)域模型、業(yè)務(wù)邏輯、領(lǐng)域服務(wù)、基礎(chǔ)能力、外部模塊等。

洋蔥圈架構(gòu)具有六邊形架構(gòu)的優(yōu)點(diǎn),采用依賴倒置的原則使內(nèi)部業(yè)務(wù)模型不再直接依賴于外部基礎(chǔ)能力。外部模塊的變動(dòng)和替換不影響內(nèi)部業(yè)務(wù)邏輯。采用領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)的方法劃分實(shí)體和模型,利于業(yè)務(wù)規(guī)則的抽象和業(yè)務(wù)模型的建立,對(duì)未來業(yè)務(wù)迭代的支持較好。洋蔥圈架構(gòu)使業(yè)務(wù)實(shí)體、業(yè)務(wù)模型和業(yè)務(wù)實(shí)現(xiàn)處在里層,保證了業(yè)務(wù)模型和實(shí)現(xiàn)的穩(wěn)定,避免受到外部模塊變動(dòng)的影響。

例如,使三方SDK或者數(shù)據(jù)庫系統(tǒng)屬于最外層,使用依賴注入的方法將它們的實(shí)現(xiàn)傳入內(nèi)部邏輯。當(dāng)替換三方SDK或者數(shù)據(jù)庫系統(tǒng)時(shí),按照接口定義實(shí)現(xiàn)具體細(xì)節(jié)即可。不需要對(duì)內(nèi)部邏輯進(jìn)行改動(dòng)。

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

領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)簡稱為DDD(Domain-Driven Design)。準(zhǔn)確來說它不是一個(gè)架構(gòu)設(shè)計(jì)方法,而是一種以業(yè)務(wù)分析和劃分來驅(qū)動(dòng)系統(tǒng)架構(gòu)設(shè)計(jì)的軟件開發(fā)方法。它強(qiáng)調(diào)識(shí)別業(yè)務(wù)的核心問題域來確定問題邊界,同時(shí)將問題域進(jìn)行分解降低分析的復(fù)雜度。DDD強(qiáng)調(diào)通過關(guān)注業(yè)務(wù)核心提升業(yè)務(wù)價(jià)值。

下面是DDD的一些核心概念,我們做一些簡單的介紹。

1. 領(lǐng)域: 有確定的范圍和邊界的業(yè)務(wù)問題域。 實(shí)際上是我們要解決什么業(yè)務(wù)問題的抽象描述。 比如提供給用戶當(dāng)前位置、目的地位置且提供到達(dá)信息是高德地圖的問題域。

2. 子域: 將大的問題域根據(jù)業(yè)務(wù)規(guī)則的不同拆分成的小問題域。 比如高德地圖的問題域太大了,難以解決。 我們可以將問題域拆分成定位、POI搜索、路線規(guī)劃等子問題域。

3. 界限上下文: 領(lǐng)域之間的抽象邊界。 封裝了領(lǐng)域內(nèi)的概念、規(guī)則和模型。

4. 實(shí)體: 具有唯一標(biāo)識(shí)的、存在生命周期的對(duì)象。 比如展示給用戶可見的POI氣泡是一個(gè)實(shí)體,它有狀態(tài)和確定的生命周期。

5. 值對(duì)象: 沒有唯一標(biāo)識(shí)和生命周期的對(duì)象,依附于實(shí)體而存在。 比如POI信息是值對(duì)象,本身沒有狀態(tài),只能依附于POI氣泡這個(gè)實(shí)體而存在。

6. 聚合: 領(lǐng)域內(nèi)一組實(shí)體、值對(duì)象的集合。 封裝了集合與外界的交互

使用DDD對(duì)業(yè)務(wù)問題進(jìn)行分析和拆解后,可以采用任何一種架構(gòu)設(shè)計(jì)方法,無論是分層架構(gòu)、六邊形架構(gòu)或者整潔架構(gòu)等。但是DDD要求架構(gòu)設(shè)計(jì)從實(shí)際的業(yè)務(wù)場(chǎng)景出發(fā),理解業(yè)務(wù)的核心問題。架構(gòu)需要明確概念、規(guī)則的設(shè)計(jì),并且保證業(yè)務(wù)模型的穩(wěn)定性。使用分層架構(gòu)展現(xiàn)DDD的領(lǐng)域設(shè)計(jì)方法,將工程分為4層:基礎(chǔ)設(shè)施層、領(lǐng)域?qū)印?yīng)用層和用戶接口層。


我們所用的架構(gòu)方案

鷹巢

我所在的團(tuán)隊(duì)—— 鷹巢 業(yè)務(wù)組負(fù)責(zé)高德地圖規(guī)劃和導(dǎo)航的業(yè)務(wù)能力實(shí)現(xiàn)。它向下對(duì)接引擎層,包括定位引擎、導(dǎo)航引擎、渲染引擎等,向上對(duì)接前端JS層。除了承接功能龐大、邏輯復(fù)雜的導(dǎo)航業(yè)務(wù)外, 鷹巢 還負(fù)責(zé)引擎能力的封裝以及將這些封裝能力向上層JS透出。

在進(jìn)行代碼目錄劃分之前, 鷹巢 的功能實(shí)現(xiàn)也是按照模塊化進(jìn)行設(shè)計(jì)的,但是模塊之間并沒有明確的依賴關(guān)系。任何代碼都可以互相的引用,這也就導(dǎo)致了工程中各模塊之間有錯(cuò)綜復(fù)雜的調(diào)用關(guān)系,很難以說清楚某一個(gè)模塊應(yīng)該處于哪個(gè)位置,應(yīng)該如何被引用。雖然我們一直將工程代碼分為框架層和業(yè)務(wù)層,但是框架層和業(yè)務(wù)層之間的依賴關(guān)系并不明確。業(yè)務(wù)層依賴框架層,框架層也依賴了業(yè)務(wù)層,并不符合分層架構(gòu)的設(shè)計(jì)原則,所以鷹巢的工程架構(gòu)不屬于分層架構(gòu)。

在我們?nèi)ツ甑拇a目錄劃分的工作中,我們最終參考領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)的方法對(duì)代碼目錄進(jìn)行了重新的組織和劃分。將工程代碼整體上分為4層:基礎(chǔ)能力、業(yè)務(wù)層、工具層和接入層。以下是整體結(jié)構(gòu)圖:

適配層與以下的4層不在同一個(gè)倉庫,它包含了與前端JS交互的必要能力封裝。按照模塊的劃分規(guī)則,我們可以說,鷹巢的工程架構(gòu)屬于結(jié)合領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)的松散型分層架構(gòu)。它的特點(diǎn)是:

1. 按照領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)對(duì)工程代碼進(jìn)行組織和劃分,在業(yè)務(wù)層按照不同業(yè)務(wù)領(lǐng)域劃分代碼模塊

2. 采用分層架構(gòu)設(shè)計(jì)將工程分為多層,上層依賴于下層,下層不能依賴于上層

3. 上層任意模塊都可以調(diào)用下層任意模塊,屬于松散型架構(gòu)。 更加靈活

工程技術(shù)中心C++能力層(包括地圖引擎層)

在工程技術(shù)中心的語言能力框架中,從鷹巢、地圖引擎到基礎(chǔ)庫都是C++語言實(shí)現(xiàn)。使用統(tǒng)一的流程管控它們的開發(fā)、構(gòu)建、集成。在 引擎架構(gòu)升級(jí) 之前的相當(dāng)長的一段時(shí)間內(nèi),它們都屬于松散型分層架構(gòu),以下是簡化版的結(jié)構(gòu)圖: ??

? ?

實(shí)際上,包括引擎庫在內(nèi)的C++層有幾十上百個(gè)代碼倉庫,層次眾多,且從上層到下層的依賴關(guān)系復(fù)雜。如果將所有的依賴關(guān)系繪制出來,將是一個(gè)復(fù)雜的網(wǎng)狀。雖然整體架構(gòu)依然遵守了分層架構(gòu)的設(shè)計(jì)原則:只能上層依賴下層。但是因?yàn)橐蕾噷哟魏完P(guān)系的復(fù)雜,導(dǎo)致下層代碼的改動(dòng)對(duì)上層的影響很大,在構(gòu)建時(shí)也經(jīng)常出現(xiàn)庫版本不匹配的沖突。這使得上層業(yè)務(wù)層經(jīng)常處于不穩(wěn)定狀態(tài),不利于上層業(yè)務(wù)的快速迭代。并且下層能力升級(jí)也必然需要上層業(yè)務(wù)層做大工作量的適配。

在去年的 引擎架構(gòu)升級(jí) 中,抽離出抽象層,使得各個(gè)倉庫都依賴于抽象接口,不再依賴于具體的實(shí)現(xiàn)。抽象出來的抽象層包括:InterfaceApp、InterfaceAR、InterfaceARWalk、InterfaceHorus、InterfaceMap、InterfaceVMap、InterfaceTBT、InterfacePosEngine等。比如鷹巢和TBT都依賴于InterfaceTBT抽象層,使用依賴倒置的原則在App初始化時(shí)將TBT的實(shí)例化對(duì)象設(shè)置給鷹巢。鷹巢通過調(diào)用實(shí)例化對(duì)象的抽象接口訪問TBT的能力。同理,鷹巢和渲染都依賴于InterfaceMap抽象層。這種方式使得上層的業(yè)務(wù)層比較穩(wěn)定,只要保證抽象層接口的穩(wěn)定性,業(yè)務(wù)層基本上就不會(huì)受到下層改動(dòng)的影響。而且,當(dāng)下層進(jìn)行能力升級(jí)時(shí),只要按照抽象接口定義實(shí)現(xiàn)對(duì)應(yīng)能力即可,不需要業(yè)務(wù)層做適配。

從這方面來講,在引擎架構(gòu)升級(jí)后,引擎具有整潔架構(gòu)的特征。但是并不能完全稱為整潔架構(gòu),因?yàn)閺母蟮囊暯莵砜矗▽⒒A(chǔ)庫和Native層包括進(jìn)去),依然是松散型的分層架構(gòu)。所以,我們可以稱之為具有整潔架構(gòu)特征的松散型分層架構(gòu)。

總結(jié)

對(duì)于架構(gòu)設(shè)計(jì)的學(xué)習(xí)和理解,我認(rèn)為很難的一點(diǎn)是:即使懂得很多道理還是很難把事情做好。眾多的設(shè)計(jì)原則都是在不同業(yè)務(wù)場(chǎng)景下提出的,有些原則之間本身就是矛盾的。無論是架構(gòu)設(shè)計(jì)方法還是設(shè)計(jì)原則,它們不是金科玉律,更不可能放之四海而皆準(zhǔn)。它們的價(jià)值在于告訴我們應(yīng)該摒棄什么,應(yīng)該遵守什么。我們不用那些技術(shù)官僚的詞匯,用更接地氣的描述來說,設(shè)計(jì)原則也只是要求我們做到簡潔、規(guī)范和易于理解而已。架構(gòu)設(shè)計(jì)并不高端,它本身所產(chǎn)生的價(jià)值并不明顯,真正能夠產(chǎn)生價(jià)值的在于我們當(dāng)前正在走的路:如何理解我們的業(yè)務(wù)問題。

責(zé)任編輯:張燕妮 來源: 阿里開發(fā)者
相關(guān)推薦

2022-07-26 12:33:38

架構(gòu)設(shè)計(jì)場(chǎng)景

2019-03-20 09:30:31

2012-06-07 10:45:12

軟件架構(gòu)設(shè)計(jì)原則

2012-05-30 09:43:45

業(yè)務(wù)邏輯層

2012-06-07 10:35:40

架構(gòu)設(shè)計(jì)業(yè)務(wù)邏輯Java

2023-06-08 09:05:55

2023-12-13 08:31:23

2012-04-16 10:45:17

三層架構(gòu)

2011-04-08 17:03:19

Java架構(gòu)

2012-06-07 10:25:35

架構(gòu)設(shè)計(jì)服務(wù)層軟件設(shè)計(jì)

2009-07-06 10:36:41

敏捷開發(fā)

2017-02-20 09:02:31

Impala架構(gòu)設(shè)計(jì)

2023-07-17 18:39:27

業(yè)務(wù)系統(tǒng)架構(gòu)

2017-07-06 00:27:17

虛擬訂單中心京東數(shù)據(jù)

2024-02-26 00:00:00

Nginx服務(wù)器HTTP

2013-05-27 10:58:28

Tumblr架構(gòu)設(shè)計(jì)雅虎收購

2022-11-11 10:48:55

AQS源碼架構(gòu)

2017-03-13 08:58:46

Spring Clou概覽架構(gòu)

2023-05-12 07:52:13

架構(gòu)設(shè)計(jì)設(shè)計(jì)原則

2016-02-18 10:09:23

12306核心思路架構(gòu)
點(diǎn)贊
收藏

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

欧美色图亚洲激情| 国产一线二线三线女| 中文字幕在线播放日韩| 你懂的亚洲视频| 精品国产露脸精彩对白 | 日韩欧美在线中字| 欧美不卡高清| 欧美第一区第二区| 不要播放器的av网站| 欧美一区二区三区| 99在线精品观看| 精品96久久久久久中文字幕无| 欧美成人乱码一区二区三区| 亚洲国产精品久久久久婷蜜芽| av每日在线更新| 国产白丝网站精品污在线入口 | 蜜桃视频网站在线观看| 岛国av在线一区| 国产精品三级久久久久久电影| 青青草原国产视频| 青青草成人影院| 亚洲高清福利视频| 久久精品久久99| 国产成人精品一区二三区在线观看 | 欧美bbbbb性bbbbb视频| 国产精品亚洲四区在线观看| 狠狠躁夜夜躁人人爽超碰91| 欧美 国产 精品| 国产免费av在线| 成人av在线一区二区三区| 国产在线观看一区二区三区| 中文字幕精品无码一区二区| 欧美日韩少妇| 久久精品一本久久99精品| 极品人妻一区二区三区| 成人免费直播在线| 日韩一区国产二区欧美三区| 亚欧激情乱码久久久久久久久| 中文字幕高清在线播放| 亚洲成人久久影院| 欧美性潮喷xxxxx免费视频看| 永久av在线| 中文字幕乱码一区二区免费| 欧美极品日韩| 免费国产在线观看| 久久免费午夜影院| 久久久一本精品99久久精品| www.亚洲欧美| 国产成人综合亚洲91猫咪| 成人精品久久一区二区三区| 自拍偷拍色综合| 日本欧美在线看| 国产精品av电影| 国产高清中文字幕| 亚洲在线日韩| 日本成人免费在线| 亚洲国产成人无码av在线| 99视频一区| 欧美一级片在线播放| www.av麻豆| 性色一区二区| 国产mv免费观看入口亚洲| 成年人av网站| 久久精品国产亚洲高清剧情介绍| 国产欧美韩国高清| 夜夜狠狠擅视频| 国产一区欧美日韩| 北条麻妃高清一区| 天天色棕合合合合合合合| 91免费看视频| 欧美少妇一区| 日本在线观看免费| 亚洲欧美偷拍卡通变态| 国产成a人亚洲精v品在线观看| 天堂亚洲精品| 香蕉av福利精品导航 | 日本中文字幕一区| 国产在线视频2019最新视频| 国产美女精品视频国产| 国产成人精品影视| 国产欧美综合精品一区二区| 青青免费在线视频| 国产精品国产a| 国产一级不卡视频| 僵尸再翻生在线观看| 91久久精品一区二区二区| 国产福利在线免费| 国产精品videossex| 亚洲人成自拍网站| www.毛片com| 性色一区二区| 亚洲综合av影视| 蜜桃视频在线播放| 亚洲免费在线电影| 青青青在线播放| 欧美国产中文高清| 亚洲女人天堂成人av在线| 日韩av片在线免费观看| 9国产精品视频| 国产精品一区久久久| 亚洲春色一区二区三区| 国产午夜精品在线观看| 白白操在线视频| 日韩电影av| 欧美一区二区三区男人的天堂| 欲求不满的岳中文字幕| 久久久久久影院| 午夜精品久久久久久久99热浪潮 | 5566中文字幕一区二区电影| 成人免费毛片日本片视频| 欧美成人激情| 日本欧美爱爱爱| 丰满大乳国产精品| 中文字幕色av一区二区三区| 国产青青在线视频| 久久9999免费视频| 色婷婷av一区二区三区久久| 日韩精品1区2区| 国产激情91久久精品导航| 天堂精品视频| 在线免费日韩片| 亚洲第一精品福利| 色婷婷在线视频观看| 免费在线观看不卡| 欧美激情一区二区三区在线视频| 丁香影院在线| 日韩欧美一区电影| 日本成人免费在线观看| 日韩精品一级中文字幕精品视频免费观看| 成人精品一二区| 成人在线直播| 欧美精品18+| xxxxx99| 日本中文在线一区| 欧美性xxxx69| av不卡一区二区三区| 国产日韩欧美在线观看| 户外极限露出调教在线视频| 午夜国产精品影院在线观看| 久久久国产精品久久久| 婷婷综合激情| 国产日韩在线看片| a视频网址在线观看| 一本大道久久精品懂色aⅴ | 四虎影视国产精品| 一区二区三区无码高清视频| 欧美在线观看不卡| 久久综合久久综合亚洲| 国产午夜大地久久| 国产一区二区三区亚洲| 久久人91精品久久久久久不卡| 性少妇videosexfreexxx片| 亚洲免费av在线| 91大神免费观看| 欧美激情五月| 国产v亚洲v天堂无码| 欧美日韩经典丝袜| 精品国产一区二区亚洲人成毛片| 免费日韩在线视频| 成人av网站在线| 黄色av网址在线播放| 国产伦精品一区二区三区在线播放| 欧美精品久久久久久久久久| 人妻一区二区三区四区| 欧美日韩亚洲视频| 久久久久久亚洲中文字幕无码| 老司机久久99久久精品播放免费 | 综合精品一区| 国产精品二区二区三区| 91在线三级| 国产视频亚洲精品| 怡红院成永久免费人全部视频| 国产精品乱人伦| 男人操女人下面视频| 精品69视频一区二区三区Q| 久久www免费人成精品| 欧美日韩视频免费观看| 啊v视频在线一区二区三区| 国产av一区二区三区| 亚洲大片精品永久免费| 人妻体内射精一区二区| 久久99久久久久| 黄色三级中文字幕| 国产免费av一区二区三区| 国产精品永久在线| 国产偷倩在线播放| 国产午夜精品一区二区三区| 国产黄色一区二区| 欧美性生交大片免网| 久久精品日韩无码| 成人av网址在线| 女人高潮一级片| 国产精品嫩草99av在线| 一区二区精品国产| 噜噜噜狠狠夜夜躁精品仙踪林| 国产美女高潮久久白浆| 波多野结衣中文字幕久久| 伊人精品在线观看| 丰满肉嫩西川结衣av| 欧美色欧美亚洲另类二区| 精品一区在线视频| 国产精品国产三级国产普通话99 | www.久久久久久| 色香色香欲天天天影视综合网| 在线观看成人毛片| 国产欧美日本一区视频| 国产综合内射日韩久| 毛片av中文字幕一区二区| 亚洲 欧美 日韩 国产综合 在线| 亚洲a在线视频| 日韩欧美亚洲在线| 久久97久久97精品免视看秋霞| 国产这里只有精品| 日韩电影免费观看高清完整版| 久久久久久久久久久av| 免费高清完整在线观看| 亚洲系列中文字幕| 婷婷丁香花五月天| 91精品国产入口在线| 狠狠躁夜夜躁人人爽视频| 精品久久在线播放| 久久久久97国产| 亚洲欧美二区三区| 色婷婷粉嫩av| 欧美极品aⅴ影院| 老鸭窝一区二区| www.亚洲人| 国产51自产区| 成人精品视频一区二区三区| 天堂在线一区二区三区| 六月丁香婷婷色狠狠久久| 欧美成人黑人猛交| 香蕉国产精品偷在线观看不卡| 成人性生活视频免费看| 欧美在线国产| 亚洲小说欧美另类激情| 久久免费精品视频在这里| 日本中文不卡| 精品久久久亚洲| 日韩福利一区二区三区| 国产亚洲一卡2卡3卡4卡新区| 久久国产精品久久精品国产| 日韩a级大片| 久久久一本精品99久久精品| 天堂在线精品| 欧美一区二区在线| 国产亚洲电影| 亚洲不卡1区| 国产一区二区三区四区大秀| 欧美日韩国产免费一区二区三区 | 777久久精品一区二区三区无码| 久久亚洲影视| 91成人在线视频观看| 亚洲一级淫片| 97免费视频观看| 亚洲欧美视频| 性刺激的欧美三级视频| 精品一区二区三区免费观看| 国产亚洲色婷婷久久| 东方欧美亚洲色图在线| 88av在线播放| 久久久不卡影院| 天美传媒免费在线观看| 亚洲丝袜制服诱惑| 一区二区三区免费高清视频| 亚洲高清一区二区三区| 欧美激情亚洲综合| 在线视频国内一区二区| 国产又粗又猛又爽又黄视频| 欧美一区二区二区| 天天操天天干天天爽| 亚洲人成啪啪网站| 黄色网页在线看| 性欧美激情精品| 一区在线影院| 97免费资源站| 欧美日韩爱爱| 欧美日韩一级在线| 在线一区视频| www.这里只有精品| 成人一级片网址| 手机免费看av| 一区二区三区欧美在线观看| 国偷自拍第113页| 欧美日韩一二三| 日韩中文字幕观看| 在线观看国产精品91| 青青草原av在线| 国产99视频在线观看| 日韩区欧美区| 日韩av一区二区三区在线观看| 亚洲先锋影音| 少妇性l交大片| 大胆亚洲人体视频| 99久久久无码国产精品不卡| 亚洲综合一二三区| 中文字幕在线网址| 亚洲国产欧美久久| 美女免费久久| 4p变态网欧美系列| 日本综合精品一区| 亚洲v国产v在线观看| 99精品国产在热久久下载| 四虎1515hh.com| 国产欧美一区二区精品秋霞影院 | 在线观看国产一区二区| 亚洲精品国产精品乱码不卡| 伊人一区二区三区久久精品| 成人超碰在线| 亚洲va欧美va国产综合剧情| 国语产色综合| 欧美啪啪免费视频| 国产精品一级片在线观看| 天天操天天干天天操天天干| 天天综合天天综合色| www.好吊色| 久久精品电影网| 巨胸喷奶水www久久久免费动漫| 精品免费视频123区| 欧美日韩三级| 日韩av影视大全| 国产精品久久三区| 手机av免费观看| 亚洲精品一区中文字幕乱码| 91www在线| 国产福利一区二区三区在线观看| 欧美ab在线视频| 天天干天天操天天做| 国产色爱av资源综合区| 中文字幕视频网站| 日韩成人中文字幕| 九色porny自拍视频在线播放| 国产成人精品日本亚洲11 | 国产麻豆免费视频| 色婷婷综合久久久久中文字幕1| 亚洲精品一级二级| 茄子视频成人在线观看| 亚洲综合丁香| av女人的天堂| 91久久久免费一区二区| 韩国精品视频| 国产精品久久久久久久9999| 亚洲影院天堂中文av色| 熟女人妇 成熟妇女系列视频| 91视频国产观看| 好看的av在线| 亚洲乱码一区二区| 日韩电影免费观看高清完整版| 欧美一区二区三区四区在线观看地址| 亚洲影院一区| 97人妻人人揉人人躁人人| 日本精品视频一区二区| 国产区视频在线播放| 国产日韩欧美视频在线| 欧美成人一品| 欧产日产国产精品98| 黑人狂躁日本妞一区二区三区 | 久久亚洲国产精品| 国产一区 二区| 亚洲国产精品无码av| 91偷拍与自偷拍精品| 亚洲永久精品一区| 久久精品国产69国产精品亚洲| 久久99成人| 国产午夜大地久久| 国产精品无圣光一区二区| 国产精品女人久久久| 欧美激情奇米色| 曰本一区二区三区视频| 天天色综合社区| 亚洲美女视频在线| 亚洲 小说区 图片区 都市| 国产经典一区二区| 91精品国产视频| 欧美激情 亚洲| 欧洲中文字幕精品| 尤物视频在线看| 久久青青草综合| 麻豆精品新av中文字幕| 久久久国产精品人人片| 亚洲免费av网址| 国产精品亚洲综合在线观看 | 日本一区二区视频| 精品一区二区在线免费观看| 久久久久99精品成人片毛片| 亚洲欧美中文字幕| 国产激情综合| 免费在线观看毛片网站| 日韩一区欧美小说| 性xxxxbbbb| 亚洲xxxx3d| 视频一区在线播放| 久久久久久久九九九九| 国产亚洲欧洲高清一区| 1769国产精品视频| 男人的天堂最新网址| 天天色 色综合| h网站久久久| 日本精品一区二区三区视频| 福利一区二区在线观看|