由Spring應(yīng)用的瑕疵談?wù)凞DD的概念與應(yīng)用(二)

上一篇文章中,通過Spring Web應(yīng)用的瑕疵引出改善的措施椎眯,我們講解了領(lǐng)域驅(qū)動開發(fā)的相關(guān)概念和設(shè)計策略挠将。本文主要講解領(lǐng)域模型的幾種類型和DDD的簡單實踐案例。

架構(gòu)風(fēng)格

在《實現(xiàn)領(lǐng)域驅(qū)動設(shè)計》一書中提到了幾種架構(gòu)風(fēng)格:六邊形架構(gòu)编整、REST架構(gòu)舔稀、CQRS 和事件驅(qū)動等。在實際使用中掌测,落地的架構(gòu)并非是純粹其中的一種内贮,而很有可能戶將上述幾種架構(gòu)風(fēng)格結(jié)合起來實現(xiàn)。

分層架構(gòu)

分層架構(gòu)的一個重要原則是每層只能與位于其下方的層發(fā)生耦合赏半。分層架構(gòu)可以簡單分為兩種贺归,即嚴格分層架構(gòu)和松散分層架構(gòu)。在嚴格分層架構(gòu)中断箫,某層只能與位于其直接下方的層發(fā)生耦合拂酣,而在松散分層架構(gòu)中,則允許某層與它的任意下方層發(fā)生耦合仲义。DDD分層架構(gòu)中比較經(jīng)典的三種模式:四層架構(gòu)婶熬、五層架構(gòu)和六邊形架構(gòu)。

四層架構(gòu)

Eric Evans在《領(lǐng)域驅(qū)動設(shè)計-軟件核心復(fù)雜性應(yīng)對之道》這本書中提出了傳統(tǒng)的四層架構(gòu)模式:

  • User Interface為用戶界面層(或表示層)埃撵,負責(zé)向用戶顯示信息和解釋用戶命令赵颅。這里指的用戶可以是另一個計算機系統(tǒng),不一定是使用用戶界面的人暂刘。
  • Application為應(yīng)用層饺谬,定義軟件要完成的任務(wù),并且指揮表達領(lǐng)域概念的對象來解決問題谣拣。這一層所負責(zé)的工作對業(yè)務(wù)來說意義重大募寨,也是與其它系統(tǒng)的應(yīng)用層進行交互的必要渠道。應(yīng)用層要盡量簡單森缠,不包含業(yè)務(wù)規(guī)則或者知識拔鹰,而只為下一層中的領(lǐng)域?qū)ο髤f(xié)調(diào)任務(wù),分配工作贵涵,使它們互相協(xié)作列肢。它沒有反映業(yè)務(wù)情況的狀態(tài)恰画,但是卻可以具有另外一種狀態(tài),為用戶或程序顯示某個任務(wù)的進度瓷马。
  • Domain為領(lǐng)域?qū)樱ɑ蚰P蛯樱┧┗梗撠?zé)表達業(yè)務(wù)概念,業(yè)務(wù)狀態(tài)信息以及業(yè)務(wù)規(guī)則欧聘。盡管保存業(yè)務(wù)狀態(tài)的技術(shù)細節(jié)是由基礎(chǔ)設(shè)施層實現(xiàn)的自沧,但是反映業(yè)務(wù)情況的狀態(tài)是由本層控制并且使用的。領(lǐng)域?qū)邮菢I(yè)務(wù)軟件的核心树瞭,領(lǐng)域模型位于這一層。
  • Infrastructure層為基礎(chǔ)實施層爱谁,向其他層提供通用的技術(shù)能力:為應(yīng)用層傳遞消息晒喷,為領(lǐng)域?qū)犹峁┏志没瘷C制,為用戶界面層繪制屏幕組件访敌,等等凉敲。基礎(chǔ)設(shè)施層還能夠通過架構(gòu)框架來支持四個層次間的交互模式寺旺。

傳統(tǒng)的四層架構(gòu)都是限定型松散分層架構(gòu)爷抓,即Infrastructure層的任意上層都可以訪問該層(“L”型),而其它層遵守嚴格分層架構(gòu)阻塑。

五層架構(gòu)

五層架構(gòu)是根據(jù)《DCI架構(gòu):面向?qū)ο缶幊痰男聵?gòu)想》中提及的DCI架構(gòu)模式總結(jié)而成蓝撇。DCI架構(gòu)(Data碑幅、Context和Interactive三層架構(gòu)):

  • Data層描述系統(tǒng)有哪些領(lǐng)域概念及其之間的關(guān)系丝蹭,該層專注于領(lǐng)域?qū)ο蟮拇_立和這些對象的生命周期管理及關(guān)系,讓程序員站在對象的角度思考系統(tǒng)澈驼,從而讓“系統(tǒng)是什么”更容易被理解走搁。
  • Context層:是盡可能薄的一層独柑。Context往往被實現(xiàn)得無狀態(tài),只是找到合適的role私植,讓role交互起來完成業(yè)務(wù)邏輯即可忌栅。但是簡單并不代表不重要,顯示化context層正是為人去理解軟件業(yè)務(wù)流程提供切入點和主線曲稼。
  • Interactive層主要體現(xiàn)在對role的建模索绪,role是每個context中復(fù)雜的業(yè)務(wù)邏輯的真正執(zhí)行者,體現(xiàn)“系統(tǒng)做什么”躯肌。role所做的是對行為進行建模者春,它聯(lián)接了context和領(lǐng)域?qū)ο蟆S捎谙到y(tǒng)的行為是復(fù)雜且多變的清女,role使得系統(tǒng)將穩(wěn)定的領(lǐng)域模型層和多變的系統(tǒng)行為層進行了分離钱烟,由role專注于對系統(tǒng)行為進行建模。該層往往關(guān)注于系統(tǒng)的可擴展性,更加貼近于軟件工程實踐拴袭,在面向?qū)ο笾懈嗟氖且灶惖囊暯沁M行思考設(shè)計读第。

DCI目前廣泛被看作是對DDD的一種發(fā)展和補充,用在基于面向?qū)ο蟮念I(lǐng)域建模上拥刻。五層架構(gòu)的具體定義如下:

  • User Interface是用戶接口層怜瞒,主要用于處理用戶發(fā)送的Restful請求和解析用戶輸入的配置文件等,并將信息傳遞給Application層的接口般哼。
  • Application層是應(yīng)用層吴汪,負責(zé)多進程管理及調(diào)度、多線程管理及調(diào)度蒸眠、多協(xié)程調(diào)度和維護業(yè)務(wù)實例的狀態(tài)模型漾橙。當(dāng)調(diào)度層收到用戶接口層的請求后,委托Context層與本次業(yè)務(wù)相關(guān)的上下文進行處理楞卡。
  • Context是環(huán)境層霜运,以上下文為單位,將Domain層的領(lǐng)域?qū)ο骳ast成合適的role蒋腮,讓role交互起來完成業(yè)務(wù)邏輯淘捡。
  • Domain層是領(lǐng)域?qū)樱x領(lǐng)域模型池摧,不僅包括領(lǐng)域?qū)ο蠹捌渲g關(guān)系的建模焦除,還包括對象的角色role的顯式建模。
  • Infrastructure層是基礎(chǔ)實施層作彤,為其他層提供通用的技術(shù)能力:業(yè)務(wù)平臺踢京,編程框架,持久化機制宦棺,消息機制瓣距,第三方庫的封裝,通用算法代咸,等等蹈丸。
六邊形架構(gòu)

六邊形架構(gòu)(Hexagonal Architecture),又稱為端口和適配器風(fēng)格呐芥,最早由 Alistair Cockburn 提出逻杖。在 DDD 社區(qū)得到了發(fā)展和推廣,之所以是六變形是為了突顯這是個扁平的架構(gòu)思瘟,每個邊界的權(quán)重是相等的荸百。

我們知道,經(jīng)典分層架構(gòu)分為三層(展現(xiàn)層滨攻、應(yīng)用層够话、數(shù)據(jù)訪問層)蓝翰,而對于六邊形架構(gòu),可以分成另外的三層:

  • 領(lǐng)域?qū)樱―omain Layer):最里面女嘲,純粹的核心業(yè)務(wù)邏輯畜份,一般不包含任何技術(shù)實現(xiàn)或引用。
  • 端口層(Ports Layer):領(lǐng)域?qū)又庑滥幔撠?zé)接收與用例相關(guān)的所有請求爆雹,這些請求負責(zé)在領(lǐng)域?qū)又袇f(xié)調(diào)工作。端口層在端口內(nèi)部作為領(lǐng)域?qū)拥倪吔玢倒模诙丝谕獠縿t扮演了外部實體的角色钙态。
  • 適配器層(Adapters Layer):端口層之外,負責(zé)以某種格式接收輸入菇晃、及產(chǎn)生輸出驯绎。比如,對于 HTTP 用戶請求谋旦,適配器會將轉(zhuǎn)換為對領(lǐng)域?qū)拥恼{(diào)用,并將領(lǐng)域?qū)觽骰氐捻憫?yīng)進行封送屈尼,通過 HTTP 傳回調(diào)用客戶端册着。在適配器層不存在領(lǐng)域邏輯,它的唯一職責(zé)就是在外部世界與領(lǐng)域?qū)又g進行技術(shù)性的轉(zhuǎn)換脾歧。適配器能夠與端口的某個協(xié)議相關(guān)聯(lián)并使用該端口甲捏,多個適配器可以使用同一個端口,在切換到某種新的用戶界面時鞭执,可以讓新界面與老界面同時使用相同的端口司顿。
圖片轉(zhuǎn)自網(wǎng)絡(luò)

這樣做的好處是將使業(yè)務(wù)邊界更加清晰,從而獲得更好的擴展性兄纺,除此之外大溜,業(yè)務(wù)復(fù)雜度和技術(shù)復(fù)雜度分離,是 DDD 的重要基礎(chǔ)估脆,核心的領(lǐng)域?qū)涌梢詫W⒃跇I(yè)務(wù)邏輯而不用理會技術(shù)依賴钦奋,外部接口在被消費者調(diào)用的時候也不用去關(guān)心業(yè)務(wù)內(nèi)部是如何實現(xiàn)。

REST架構(gòu)

RESTful風(fēng)格的架構(gòu)將 資源 放在第一位疙赠,每個 資源 都有一個 URI 與之對應(yīng)付材,可以將 資源 看著是 DDD 中的實體;RESTful 采用具有自描述功能的消息實現(xiàn)無狀態(tài)通信圃阳,提高系統(tǒng)的可用性厌衔;至于 資源 的哪些屬性可以公開出去,針對 資源的操作捍岳,RESTful使用HTTP協(xié)議的已有方法來實現(xiàn):GET富寿、PUT睬隶、POST和DELETE。

在 DDD 的實現(xiàn)中作喘,我們可以將對外的服務(wù)設(shè)計為 RESTful 風(fēng)格的服務(wù)理疙,將實體/值對象/領(lǐng)域服務(wù)作為資源對外提供增刪改查服務(wù)。但是并不建議直接將實體暴露在外泞坦,一來實體的某些隱私屬性并不能對外暴露窖贤,二來某些資源獲取場景并不是一個實體就能滿足。因此我們在實際實踐過程中贰锁,在領(lǐng)域模型上增加了 DTO 這樣一個角色赃梧,DTO 可以組合多個實體/值對象的資源對外暴露。

CQRS

CQRS 就是平常大家在講的讀寫分離豌熄,通常讀寫分離的目的是為了提高查詢性能授嘀,同時達到讀/寫的解耦。讓 DDD 和 CQRS 結(jié)合锣险,我們可以分別對讀和寫建模蹄皱,查詢模型通常是一種非規(guī)范化數(shù)據(jù)模型,它并不反映領(lǐng)域行為芯肤,只是用于數(shù)據(jù)顯示巷折;命令模型執(zhí)行領(lǐng)域行為,且在領(lǐng)域行為執(zhí)行完成后崖咨,想辦法通知到查詢模型锻拘。

那么命令模型如何通知到查詢模型呢? 如果查詢模型和領(lǐng)域模型共享數(shù)據(jù)源击蹲,則可以省卻這一步署拟;如果沒有共用數(shù)據(jù)源,則可以借助于 消息模式(Messaging Patterns)通知到查詢模型歌豺,從而達到最終一致性(Eventual Consistency)推穷。

Martin 在 blog 中指出:CQRS 適用于極少數(shù)復(fù)雜的業(yè)務(wù)領(lǐng)域,如果不是很適合反而會增加復(fù)雜度类咧;另一個適用場景為獲取高性能的服務(wù)缨恒。

領(lǐng)域模型

在上面小節(jié)講解了領(lǐng)域驅(qū)動設(shè)計的幾種架構(gòu)風(fēng)格,下面我們具體結(jié)合簡單的實例來看其中的領(lǐng)域模型劃分轮听,初步分為4大類:

  1. 失血模型
  2. 貧血模型
  3. 充血模型
  4. 脹血模型

我們看看這些領(lǐng)域模型的具體內(nèi)容骗露,以及他們的優(yōu)缺點。

失血模型

失血模型簡單來說血巍,就是domain object只有屬性的getter/setter方法的純數(shù)據(jù)類萧锉,所有的業(yè)務(wù)邏輯完全由business object來完成(又稱TransactionScript),這種模型下的domain object被Martin Fowler稱之為“貧血的domain object”述寡。如下:

  • 一個實體類叫做Item

    public class Item implements Serializable {   
     private Long id = null;   
     private int version;   
     private String name;   
     private User seller;   
     // ...  
     //   getter/setter方法省略不寫柿隙,避免篇幅太長   
    

}
```

  • 一個DAO接口類叫做ItemDao

    public interface ItemDao {   
     public Item getItemById(Long id);   
     public Collection findAll();   
     public void updateItem(Item item);   
    

}
```

  • 一個DAO接口實現(xiàn)類叫做ItemDaoHibernateImpl

    public class ItemDaoImpl implements ItemDao extends DaoSupport {   
     public Item getItemById(Long id) {   
         return (Item) getHibernateTemplate().load(Item.class, id);   
     }   
     public Collection findAll() {   
         return (List) getHibernateTemplate().find("from Item");   
     }   
     public void updateItem(Item item) {   
         getHibernateTemplate().update(item);   
     }   
    

}
```

  • 一個業(yè)務(wù)邏輯類叫做ItemManager(或者叫做ItemService)

public class ItemManager {
private ItemDao itemDao;
public void setItemDao(ItemDao itemDao) { this.itemDao = itemDao;}
public Bid loadItemById(Long id) {
itemDao.loadItemById(id);
}
public Collection listAllItems() {
return itemDao.findAll();
}
public Bid placeBid(Item item, User bidder, MonetaryAmount bidAmount,
Bid currentMaxBid, Bid currentMinBid) throws BusinessException {
if (currentMaxBid != null && currentMaxBid.getAmount().compareTo(bidAmount) > 0) {
throw new BusinessException("Bid too low.");
}

  // ...  

}
```

以上是一個完整的失血模型的示例代碼叶洞。在這個示例中,loadItemById禀崖、findAll 等等業(yè)務(wù)邏輯統(tǒng)統(tǒng)放在 ItemManager 中實現(xiàn)衩辟,而 Item 只有 getter/setter 方法。

貧血模型

簡單來說波附,就是 domain ojbect 包含了不依賴于持久化的領(lǐng)域邏輯艺晴,而那些依賴持久化的領(lǐng)域邏輯被分離到 Service 層。

Service(業(yè)務(wù)邏輯掸屡,事務(wù)封裝) --> DAO ---> domain object


image

這也就是 Martin Fowler 指的 rich domain object:

  • 一個帶有業(yè)務(wù)邏輯的實體類封寞,即domain object是Item
  • 一個DAO接口ItemDao
  • 一個DAO實現(xiàn)ItemDaoHibernateImpl
  • 一個業(yè)務(wù)邏輯對象ItemManager

這種模型的優(yōu)點:

  1. 各層單向依賴,結(jié)構(gòu)清楚仅财,易于實現(xiàn)和維護
  2. 設(shè)計簡單易行狈究,底層模型非常穩(wěn)定

缺點為:

  1. domain object的部分比較緊密依賴的持久化 domain logic 被分離到Service層,顯得不夠 OO
  2. Service 層過于厚重

具體代碼較為簡單盏求,不再展示抖锥。

充血模型

充血模型和第二種模型差不多,所不同的就是如何劃分業(yè)務(wù)邏輯碎罚,即認為磅废,絕大多業(yè)務(wù)邏輯都應(yīng)該被放在domain object里面(包括持久化邏輯),而Service層應(yīng)該是很薄的一層魂莫,僅僅封裝事務(wù)和少量邏輯,不和DAO層打交道爹耗。

Service(事務(wù)封裝) ---> domain object <---> DAO

[圖片上傳失敗...(image-5fe4c2-1555327562177)]

這種模型就是把第二種模型的 domain object 和 business object 合二為一了耙考。所以 ItemManager 就不需要了,在這種模型下面潭兽,只有三個類倦始,他們分別是:

  • Item:包含了實體類信息,也包含了所有的業(yè)務(wù)邏輯
  • ItemDao:持久化DAO接口類
  • ItemDaoHibernateImpl:DAO接口的實現(xiàn)類

在這種模型中山卦,所有的業(yè)務(wù)邏輯全部都在Item中鞋邑,事務(wù)管理也在Item中實現(xiàn)。
這種模型的優(yōu)點:

  1. 更加符合OO的原則
  2. Service層很薄账蓉,只充當(dāng)Facade的角色枚碗,不和DAO打交道。

這種模型的缺點:

  1. DAO和domain object形成了雙向依賴铸本,復(fù)雜的雙向依賴會導(dǎo)致很多潛在的問題肮雨。
  2. 如何劃分Service層邏輯和domain層邏輯是非常含混的,在實際項目中箱玷,由于設(shè)計和開發(fā)人員的水平差異怨规,可能導(dǎo)致整個結(jié)構(gòu)的混亂無序陌宿。
  3. 考慮到Service層的事務(wù)封裝特性,Service層必須對所有的domain object的邏輯提供相應(yīng)的事務(wù)封裝方法波丰,其結(jié)果就是Service完全重定義一遍所有的domain logic壳坪,非常煩瑣,而且 Service 的事務(wù)化封裝其意義就等于把 OO 的domain logic 轉(zhuǎn)換為過程的 Service TransactionScript掰烟。

脹血模型

基于充血模型的第三個缺點爽蝴,有同學(xué)提出,干脆取消Service層媚赖,只剩下domain object和DAO兩層霜瘪,在domain object的domain logic上面封裝事務(wù)。

domain object(事務(wù)封裝惧磺,業(yè)務(wù)邏輯) <---> DAO

似乎ruby on rails就是這種模型颖对,他甚至把 domain object 和 DAO 都合并了。

該模型優(yōu)點:

  1. 簡化了分層
  2. 也算符合OO

該模型缺點:

  1. 很多不是domain logic的 service 邏輯也被強行放入 domain object磨隘,引起了domain ojbect模型的不穩(wěn)定
  2. domain object 暴露給web層過多的信息缤底,可能引起意想不到的副作用。

小結(jié)

在這四種模型當(dāng)中番捂,失血模型和脹血模型應(yīng)該是不被提倡的个唧。而貧血模型和充血模型從技術(shù)上來說,都已經(jīng)是可行的了设预。貧血模型和充血模型哪個更加好一些徙歼?人們針對這個問題進行了曠日持久的爭論,最后仍然沒有什么結(jié)果鳖枕。雙方爭論的焦點主要在我上面加粗的兩句話上魄梯,就是領(lǐng)域模型是否要依賴持久層,因為依賴持久層就意味著單元測試的展開要更加困難(無法脫離框架進行測試宾符,原文的討論中這里專指Hibernate)酿秸,領(lǐng)域?qū)泳透y獨立,將來也更難從應(yīng)用程序中剝離出來魏烫,當(dāng)然好處是業(yè)務(wù)邏輯不必混放在不同的層中辣苏,使得單一職責(zé)性體現(xiàn)的更好。而支持者(充血模型)認為哄褒,只要將持久層抽象出來稀蟋,即可減少測試的困難性,同時適用充血模型畢竟帶來了不少開發(fā)上的便利性呐赡,除了依賴持久層這一點糊治,擁有更多好處的充血模型仍然值得選擇。最后罚舱,誰也沒能說服誰井辜,關(guān)于貧血模型和充血模型的選擇绎谦,更多的要靠具體的業(yè)務(wù)場景來決定,并不能說哪一種更比哪一種好粥脚。設(shè)計模式這種東西不是向來都沒有什么定論么窃肠。

我個人則傾向使用充血模型,因為充血模型更加像一個設(shè)計完善的系統(tǒng)架構(gòu)刷允,好在計算機世界里有很多的 IOC 和 DI 框架冤留,唯一的缺陷依賴持久層可以通過各種變通的方法繞過,隨著技術(shù)的進步树灶,一些缺陷也會被慢慢解決纤怒。我的思路是這樣的:先將持久層抽象為接口,然后通過服務(wù)層將持久層注入到領(lǐng)域模型中天通,這樣領(lǐng)域模型僅僅會依賴于持久層的接口泊窘。而這個接口,可以利用現(xiàn)有框架的技術(shù)進行抽象像寒。

訂閱最新文章烘豹,歡迎關(guān)注我的公眾號

微信公眾號

參考

  1. 【DDD】業(yè)務(wù)建模實踐 —— 刪除帖子
  2. 貧血,充血模型的解釋以及一些經(jīng)驗
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末诺祸,一起剝皮案震驚了整個濱河市携悯,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌筷笨,老刑警劉巖憔鬼,帶你破解...
    沈念sama閱讀 211,348評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異胃夏,居然都是意外死亡轴或,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,122評論 2 385
  • 文/潘曉璐 我一進店門构订,熙熙樓的掌柜王于貴愁眉苦臉地迎上來侮叮,“玉大人避矢,你說我怎么就攤上這事悼瘾。” “怎么了审胸?”我有些...
    開封第一講書人閱讀 156,936評論 0 347
  • 文/不壞的土叔 我叫張陵亥宿,是天一觀的道長。 經(jīng)常有香客問我砂沛,道長烫扼,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,427評論 1 283
  • 正文 為了忘掉前任碍庵,我火速辦了婚禮映企,結(jié)果婚禮上悟狱,老公的妹妹穿的比我還像新娘。我一直安慰自己堰氓,他們只是感情好挤渐,可當(dāng)我...
    茶點故事閱讀 65,467評論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著双絮,像睡著了一般浴麻。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上囤攀,一...
    開封第一講書人閱讀 49,785評論 1 290
  • 那天软免,我揣著相機與錄音,去河邊找鬼焚挠。 笑死膏萧,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的宣蔚。 我是一名探鬼主播向抢,決...
    沈念sama閱讀 38,931評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼胚委!你這毒婦竟也來了挟鸠?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,696評論 0 266
  • 序言:老撾萬榮一對情侶失蹤亩冬,失蹤者是張志新(化名)和其女友劉穎艘希,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體硅急,經(jīng)...
    沈念sama閱讀 44,141評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡覆享,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,483評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了营袜。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片撒顿。...
    茶點故事閱讀 38,625評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖荚板,靈堂內(nèi)的尸體忽然破棺而出凤壁,到底是詐尸還是另有隱情,我是刑警寧澤跪另,帶...
    沈念sama閱讀 34,291評論 4 329
  • 正文 年R本政府宣布拧抖,位于F島的核電站,受9級特大地震影響免绿,放射性物質(zhì)發(fā)生泄漏唧席。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,892評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望淌哟。 院中可真熱鬧迹卢,春花似錦、人聲如沸徒仓。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蓬衡。三九已至喻杈,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間狰晚,已是汗流浹背筒饰。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留壁晒,地道東北人瓷们。 一個月前我還...
    沈念sama閱讀 46,324評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像秒咐,于是被迫代替她去往敵國和親谬晕。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,492評論 2 348

推薦閱讀更多精彩內(nèi)容