識(shí)別代碼中的壞味道(二)

01.png

在上一篇文章中经伙,介紹了通過名字就能理解的 8 個(gè)壞味道瞭郑,感興趣可以查看識(shí)別代碼中的壞味道(一)胳徽。本篇文章將識(shí)別代碼中的另外 10 個(gè)代碼壞味道:10個(gè)晦澀但是通過簡單的即可識(shí)別的壞味道。

02.png

如上圖灭美,這 10 個(gè)代碼壞味道是:

  1. 發(fā)散式變化
  2. 霰彈式修改
  3. 依戀情結(jié)
  4. 數(shù)據(jù)泥球
  5. 基本類型偏執(zhí)
  6. 平行繼承體系
  7. 冗贅類
  8. 過度耦合信息鏈
  9. 異曲同工的類
  10. 純數(shù)據(jù)類

01 發(fā)散式變化

簡而言之就是一個(gè)類總是因?yàn)椴煌愋偷脑虬l(fā)生變化推溃。例如:需要修改數(shù)據(jù)源時(shí)要修改該類,需要修改緩存時(shí)還需要修改這個(gè)類届腐,甚至當(dāng)修改某個(gè)策略的計(jì)算公式時(shí)還會(huì)牽連到這個(gè)類铁坎。這種總是/經(jīng)常因?yàn)椴煌愋驮驅(qū)е乱粋€(gè)類發(fā)生變化的代碼就是指的發(fā)散式變化。

為什么發(fā)散式變化是代碼壞味道犁苏?

由于總是不同的原因?qū)е乱粋€(gè)類發(fā)生變化硬萍,意味著一個(gè)類中存在多種類型的行為(例如即操作訂單,又操作合同围详,還操作零件信息等)朴乖,大而全的類會(huì)導(dǎo)致下面兩方面的問題:

  1. 降低了代碼可讀性,存在不同上下問題的切換助赞;
  2. 很可能導(dǎo)致無法快速響應(yīng)變化买羞。大而復(fù)雜類,在修改和維護(hù)的時(shí)候雹食,并不容易做出決策畜普,同時(shí)單個(gè)原因的修改很可能導(dǎo)致一個(gè)原因修改導(dǎo)致和非相關(guān)的業(yè)務(wù)代碼發(fā)生變動(dòng)。
  3. 隨著代碼的增加群叶,代碼的復(fù)雜性肯定是增加的吃挑,而發(fā)散式變化如果不被關(guān)注钝荡,很容易導(dǎo)致后續(xù)代碼修改時(shí)類變成難以修改的大泥球。

發(fā)散式變化很容易導(dǎo)致另外一個(gè)壞味道出現(xiàn)儒鹿,就是“過大的類”化撕。

如何解決發(fā)散式變化這種壞味道?

單一職責(zé)原則可以用來解決發(fā)散式變化约炎、過大的類的壞味道的指導(dǎo)原則:一個(gè)類只有一個(gè)引起其變化的原因植阴。既然由于一個(gè)類存在過類行為,可以通過 Extract Class 來將不同的方法提煉到不同職責(zé)的類中圾浅。

發(fā)散式變化雖然很簡單掠手,但是卻是很容易遇到的一種壞味道。因?yàn)閯傞_始添加的代碼的很可能體會(huì)不到一個(gè)存在多類行為的壞處狸捕。只有當(dāng)類發(fā)生變化或者修改的時(shí)候才會(huì)逐漸這種大而全的實(shí)現(xiàn)的缺點(diǎn)喷鸽。

02 霰彈式修改

當(dāng)一個(gè)類進(jìn)行了修改會(huì)導(dǎo)致很多其他類也需要相應(yīng)進(jìn)行修改,我們稱為“霰彈式修改”灸拍。

為什么霰彈式修改是一種壞味道做祝?

  1. 當(dāng)出現(xiàn)霰彈式修改的時(shí)候,容易造成修改上的遺漏鸡岗,因此需要多次編譯混槐、運(yùn)行測試、測試功能才有可能完全修改轩性,雖然有的問題編譯的時(shí)候就可以發(fā)現(xiàn)已經(jīng)很快了声登,但是反復(fù)的編譯本來也是不斷花費(fèi)時(shí)間的,久而久之也是一種重復(fù)低效的揣苏。
  2. 不難發(fā)現(xiàn)一個(gè)類的變化導(dǎo)致其他類相應(yīng)的變化悯嗓,這是一種強(qiáng)耦合的表現(xiàn)。

如何解決霰彈式修改這種壞味道卸察?

既然霰彈式修改是一種耦合性的表現(xiàn)脯厨,我們可以將相關(guān)的代碼通過 Move Field (移動(dòng)屬性)和 Move Method (移動(dòng)方法)兩種重構(gòu)手段將代碼移動(dòng)到一個(gè)類中。這樣做的好處是讓變化的內(nèi)容聚集到了坑质,有助于簡化后續(xù)的修改俄认。

如果因?yàn)樯厦娴牟僮黝愔刑砑恿四承┓椒▽?dǎo)致一個(gè)類有了多個(gè)職責(zé),那么可以在進(jìn)一步通過 Extract Method(提煉函數(shù))來拆分職責(zé)洪乍。

也可以創(chuàng)建代理類或者方法重載來來解決特定的霰彈式修改導(dǎo)致的問題眯杏。

03 平行繼承體系(Parallel Inheritance Hierarchies)

平行繼承體系指:當(dāng)一個(gè)類增加 1 個(gè)子類的時(shí)候,另外一個(gè)類也需要增加被迫增加一個(gè)子類壳澳。

例如:

03.png

當(dāng)添加 XXXVIPTaskService 的時(shí)候就會(huì)需要新增出新的 XXXVIPScoreService 岂贩。

為什么平行繼承體系是一種代碼壞味道?

  1. 顯而易見雖然沒有直接關(guān)聯(lián),但是兩者是同時(shí)產(chǎn)生并存的萎津,但是兩者的關(guān)聯(lián)性并不顯性的呈現(xiàn)卸伞,而是在 GradeService 中才體現(xiàn)出來。

  2. 這樣的實(shí)現(xiàn)容易導(dǎo)致在 GradeService 中 Switch 語句的產(chǎn)生锉屈,switch 語句本身就是一種重復(fù)的體現(xiàn)荤傲。關(guān)于Switch 語句的問題可以參考:識(shí)別代碼中的壞味道(一)

如何解決平行繼承體系這種代碼壞味道?

圍繞上面說的原因可以做出如下兩步重構(gòu):

  1. 建立直接引用颈渊。即 SVIPTaskService 直接引用 SVIPScoreService遂黍。
  2. 參考《Java有限狀態(tài)機(jī)的4種實(shí)現(xiàn)對(duì)比》 消除繼承體系,這里過程可以使用Move Field 和 Move Method 等重構(gòu)手法俊嗽。

通過上面的重構(gòu)雾家,隱形的關(guān)聯(lián)變成直接引用。另外避免了 Switch 語句的問題绍豁。

04 依戀情結(jié)

剛開始接觸代碼中的壞味道時(shí)芯咧,乍一看你可能會(huì)覺得有些費(fèi)解。其實(shí)它描述的問題卻是很簡單的竹揍,就是:一個(gè)類多次調(diào)用另外一個(gè)類的方法來獲取最終的結(jié)果敬飒。如下

public class OrderService {

        public List<Order> findAllOrders() {
                ...
        }
        
        public Order findLatestOrder(List<Order> orders) {
                ...
        }
        
        public Order addProduct(Order order, Product product) {
                ...
        }

}

public class CartService {
    ...
      
    public void addProduct(Product product) {
        ...
        List<Orders> orders = orderService.findAllOrders();
        Order order = orderService.findLatestOrder(orders);
        order = orderService.addProduct(product);
        ...
    }
}

再是不用考慮上面這段的代碼業(yè)務(wù)上的合理性。代碼中 CartService 中多次調(diào)用 OrderService 的方法芬位,其目的就是執(zhí)行最后的 addProduct() 方法无拗,這就是一種依戀情結(jié)的代碼。

為什么依戀情結(jié)是代碼壞味道晶衷?

  1. 仔細(xì)觀察 CartService.addProduct() 方法不難發(fā)現(xiàn)那三行的代碼的意圖就是將 product 添加到最新的 order 中,如何實(shí)現(xiàn)將 product 添加到 product 這個(gè)目的阴孟,上面帶代碼顯然展示了一種策略的具體實(shí)現(xiàn)晌纫。顯然這種實(shí)現(xiàn)使得方法的職責(zé)不再單一。
  2. 另外一個(gè)問題是永丝,當(dāng) OrderService中的 findAllOrders()锹漱、findLatestOrder()、addProduct() 方法因?yàn)樾枨蟀l(fā)生變動(dòng)的時(shí)候慕嚷,都有可能會(huì)牽連到 CartService 中的代碼發(fā)生變化哥牍。因此上面中代碼通過強(qiáng)耦合性雖然實(shí)現(xiàn)了功能,但是應(yīng)對(duì)變化的能力也隨之降低喝检。代碼是不斷演進(jìn)的嗅辣,忽略了這種壞味道,會(huì)導(dǎo)致后續(xù)變化付出相應(yīng)的代價(jià)挠说。

如何解決依戀情結(jié)這種代碼壞味道澡谭?

如果你看過上一篇內(nèi)容或者看過上面前兩個(gè)壞味道,那么應(yīng)該也有一些思路了损俭,如果一類在一個(gè)方法中多次依賴另外一個(gè)類蛙奖,我們可以立即為有可能是職責(zé)沒有劃分劃分明確的原因潘酗,可以通過一下手段進(jìn)行重構(gòu):

  1. 將多次產(chǎn)生調(diào)用的幾行代碼使用 Extract Method(提煉函數(shù))提煉為一個(gè)新的函數(shù),并通過名稱來解釋這幾個(gè)行代碼所要表達(dá)的意思雁仲。
  2. 接下來可以使用 Move Method (搬移函數(shù))將剛剛提煉的函數(shù)放置到一個(gè)更合適的類中仔夺,可以是剛剛被調(diào)用的類中,也可以創(chuàng)建新的類攒砖。

通過上面簡單兩步缸兔,我們可以將后續(xù)變化影響的范圍變小,OrderService 內(nèi)的變化將不再容易牽連到 CartService祭衩。

05 數(shù)據(jù)泥球

數(shù)據(jù)泥球指的是:多個(gè)類/方法參數(shù)中都有相同的屬性灶体,且這些相同的屬性的業(yè)務(wù)意義也是相同的。

為什么數(shù)據(jù)泥球是代碼壞味道掐暮?

很顯然這是一種重復(fù)的表現(xiàn)蝎抽。數(shù)據(jù)泥球容易造成如下問題:

  1. 涉及到屬性的調(diào)整,容易造成遺漏路克,需要多次調(diào)整樟结。
  2. 降低閱讀代碼的效率,因?yàn)槊看味夹枰獜念愔凶R(shí)別出有幾個(gè)屬性是相關(guān)的在表達(dá)一個(gè)意思精算。
  3. 隨著代碼的增加容易導(dǎo)致多大的類瓢宦、長函數(shù)等多種壞味道。

如何解決數(shù)據(jù)泥球這種代碼壞味道灰羽?

  1. 如果類中的字段出現(xiàn)了數(shù)據(jù)泥球驮履,對(duì)于這些重復(fù)的字段可以使用 Extract Class( 提煉類) 將關(guān)聯(lián)幾個(gè)屬性提煉到一個(gè)類中,賦予它一個(gè)業(yè)務(wù)的概念廉嚼。
  2. 如果是多個(gè)方法參數(shù)中出現(xiàn)了多個(gè)重復(fù)的多個(gè)參數(shù)玫镐,可以通過 Introduce Parameter Object(引入?yún)?shù)對(duì)象)將多個(gè)參數(shù)使用對(duì)象來代替,從而有效的減少重復(fù)和參數(shù)個(gè)數(shù)怠噪。
  3. 其中 2 的另外一種情況恐似,如何調(diào)用者先通過一些邏輯生成幾個(gè)變量,再將這幾個(gè)變量通過參數(shù)傳遞給調(diào)用的方法傍念,那么可以使用 Presere Whole Object(保持對(duì)象完整)矫夷,將變量生成提煉到一個(gè)函數(shù)中,并并取消參數(shù)的傳遞憋槐,而是在被調(diào)用的方法中直接調(diào)用原本要傳遞的參數(shù)双藕。

06 基本類型偏執(zhí)

描述的是這樣一種代碼實(shí)現(xiàn)方式:經(jīng)常使用基本數(shù)據(jù)類型,而不愿意使用對(duì)象將這些基本數(shù)據(jù)類型和其行為進(jìn)行封裝阳仔。

為什么基本類型偏執(zhí)是代碼壞味道蔓彩?

首先基本類型有其作用。問題出現(xiàn)在不做場景區(qū)分場景,所有場景都是用基本數(shù)據(jù)類型去搭建業(yè)務(wù)邏輯赤嚼。

問題往往出現(xiàn)在這種場景:

幾個(gè)基本數(shù)據(jù)類型共同表達(dá)意思概念旷赖,但是實(shí)現(xiàn)方式卻是像搭積木一樣,將邏輯一步步的拼接搭建起來更卒,最終得到期望的結(jié)果等孵。

這種實(shí)現(xiàn)的方式的問題就在于日后閱讀代碼的時(shí)候每次閱讀都需要從頭到位梳理一遍,才能清楚的其表達(dá)的意思蹂空,時(shí)間消耗有的是幾秒鐘俯萌,有的是幾分鐘,但是堆積讀幾次將會(huì)累積消耗更多的閱讀時(shí)間上枕。問題就出現(xiàn)在不夠直白的揭示意圖咐熙。

使用幾個(gè)基本數(shù)據(jù)類型表示不同的類型,即所謂的 Type Code辨萍。

這種代碼也是存在可讀性的問題棋恼,而且非常容易導(dǎo)致 switch 語句的壞味道。

因此锈玉,并不是不能使用基本數(shù)據(jù)類型爪飘,而是應(yīng)該在揭示某個(gè)業(yè)務(wù)意圖的時(shí)候適當(dāng)?shù)氖褂梅庋b类咧,將多個(gè)基本數(shù)據(jù)類型封裝到一個(gè)類中燃辖。從而通過對(duì)象直白的表達(dá)意圖。

如何解決基本類型偏執(zhí)這種代碼壞味道汇歹?

  1. 通過 Extract Method (提煉函數(shù))將幾個(gè)基本數(shù)據(jù)類型拼接的邏輯提煉為一個(gè)方法椅棺,比通過方法名來解釋意圖犁罩。
  2. 如果按照1做了,發(fā)現(xiàn)類中出現(xiàn)不應(yīng)該出現(xiàn)的職責(zé)两疚,那么就可以將幾個(gè)相關(guān)的基本數(shù)據(jù)類型通過 Extract Class(提煉類)將幾個(gè)基本數(shù)據(jù)類型提煉為一個(gè)類來表達(dá)一個(gè)概念床估,然后通過 Move Method 來講相關(guān)的操作挪動(dòng)到該類中。
  3. 如果使用基本數(shù)據(jù)類型來表示狀態(tài)鬼雀,可以選擇使用 Replace Type Code with Class(以類取代類型碼)顷窒,并將相關(guān)的操作移動(dòng)到類中蛙吏,避免 Switch 語句源哩。場景可以參考《Java有限狀態(tài)機(jī)的4種實(shí)現(xiàn)對(duì)比》

07 冗贅類(Lacy Class)

這是單一職責(zé)的一個(gè)極端表現(xiàn),即拆分了很多類鸦做,每個(gè)類的職責(zé)過度單一励烦。

為什么冗贅類是一種代碼壞味道?

因?yàn)槊總€(gè)類都是有閱讀成本低的泼诱,職責(zé)拆分的過細(xì)坛掠,意味著多個(gè)關(guān)聯(lián)性強(qiáng)的職責(zé)也被拆分了,因此閱讀代碼來成本不一定提升,反而因?yàn)檫^分的分散而導(dǎo)致理解起來需要會(huì)非常費(fèi)勁屉栓。

如何解決冗贅類這種代碼壞味道舷蒲?

這個(gè)壞味道也給開發(fā)者一個(gè)提醒,極端的追求某些原則同樣會(huì)導(dǎo)致不必要的麻煩友多,因此需要通過不斷的練習(xí)和思考來獲取平衡的這種點(diǎn)牲平。

代碼中一旦遇到職責(zé)過度拆分的情況就可以通過 Inline Class 或者 Collapse Hierarchy 來刪除一些類,將概念合并到一個(gè)類中域滥。

當(dāng)代碼更多的是處理業(yè)務(wù)邏輯的時(shí)候纵柿,那么其中的類應(yīng)該像領(lǐng)域語言靠近,盡量避免憑空制造一些概念启绰,拆分職責(zé)的時(shí)候和業(yè)務(wù)相結(jié)合更有利于我們將代碼寫的簡單易讀昂儒。

08 過度耦合的消息鏈

這種代碼味道值得是不斷從獲取到的對(duì)象的子對(duì)象,導(dǎo)致很長的調(diào)用鏈委可。

例如

public class User {
        ...
        private Address address;
        ...
}

public class Address {
        ...
        private City city;
        ...
}

public class City {
        ...
        private PostCode postCode;
        ...
}

public class PostCode {
        ...
        private String code;
        ...
}

多度耦合的消息鏈代碼如下

String postCode = user.getAddress()
                                            .getCity()
                                            .getPostCode()
                                            .getCode();

為什么過度耦合的消息鏈?zhǔn)且环N代碼壞味道渊跋?

  1. 上面的實(shí)現(xiàn)雖然能夠正常運(yùn)行,但是會(huì)導(dǎo)致類之間的耦合撤缴,即 User 類的調(diào)用者需要在自己的內(nèi)部來獲得沒有直接練習(xí)的 postCode 的實(shí)現(xiàn)刹枉;
  2. 降低了可讀性。將整個(gè)消息鏈讀完之后才能知道得到了什么屈呕,而這個(gè)過程的很多很多消息鏈中的信息是我們并不需要知道的微宝。

如何解決過度耦合的消息鏈這種代碼壞味道?

可以通過 Extract Method 來提煉函數(shù)虎眨,然后 通過 Move Method 來將提煉的方法移動(dòng)到合適的位置蟋软。

如果讀過《重構(gòu)》還會(huì)提到 Hide Delegate(隱藏代理關(guān)系)的重構(gòu)手法。不過不推薦使用嗽桩,因?yàn)樗攵鄠€(gè) Middle Man 這種實(shí)現(xiàn)岳守,當(dāng)消息鏈過長的時(shí)候,這是一個(gè)有工作量且重復(fù)的工作碌冶,另外增加了很多很多耦合性的方法湿痢。

因此可以有限照顧可讀性,通過 Extract Method 和 Move Method 來進(jìn)行重構(gòu)扑庞,從而獲取實(shí)現(xiàn)和維護(hù)性上的平衡譬重。

09 異曲同工的類

即兩個(gè)類做的同一件事或者同一類事。這種代碼很常見罐氨,比如兩個(gè)開發(fā)者同時(shí)執(zhí)行自己的開發(fā)工作臀规,創(chuàng)建了功能類似但是方法不同的類,Code Review 的時(shí)候很容易發(fā)現(xiàn)這種代碼栅隐。

為什么異曲同工的類是一種代碼壞味道塔嬉?

按照上面的描述玩徊,如果保留兩個(gè)職責(zé)類似的類會(huì)有什么不好?

  1. 后續(xù)調(diào)用實(shí)現(xiàn)類時(shí)會(huì)導(dǎo)致選擇上的疑慮谨究,兩個(gè)類應(yīng)該選擇用哪個(gè)恩袱,而疑慮之下就是時(shí)間的浪費(fèi)。
  2. 添加代碼的時(shí)候胶哲,只向其中一個(gè)類中添加了邏輯憎蛤,后續(xù)調(diào)用時(shí) 就會(huì)困擾調(diào)用者,而且容易導(dǎo)致兩個(gè)類中容易出現(xiàn)重復(fù)的代碼纪吮。

異曲同工的類是后續(xù)很多壞味道的開始俩檬。

如何解決異曲同工的類這種代碼壞味道?

  1. 一般情況碾盟,如果兩個(gè)類是一般的工具類棚辽,可以選擇使用Renove Method 和 Move Method 將類的職責(zé)描述清楚,并將相關(guān)的代碼移動(dòng)到一個(gè)類中冰肴,完成兩個(gè)類的合并屈藐。

  2. 如果兩個(gè)類存并非普通的工具類而是存在一定的繼承關(guān)系,可以采用 Extract SuperClass (提煉超類)熙尉。

當(dāng)遇到代碼中的壞味道的時(shí)候联逻,請(qǐng)避免延遲決策和延遲解決,因?yàn)樗芸赡芎罄m(xù)導(dǎo)致其他的壞味道检痰。及時(shí)個(gè)人意識(shí)到可以延遲決策但是放在團(tuán)隊(duì)中會(huì)可能在這個(gè)地方重復(fù)遇到問題包归,導(dǎo)致后續(xù)壞味道不斷被擴(kuò)散。一次一旦遇到類似的壞味道可以遵守“童子軍軍規(guī)”:讓營地比你來的時(shí)候更干凈铅歼!

10 純數(shù)據(jù)類

純數(shù)據(jù)類指的是:一個(gè)類中只有屬性和這些屬性所涉及到的 getter公壤、setter。

為什么純數(shù)據(jù)類是一種代碼壞味道椎椰?

純數(shù)據(jù)類有其使用場景厦幅,比如 DTO 經(jīng)常這種貧血模型。但是如果結(jié)合業(yè)務(wù)到的純數(shù)據(jù)類頻繁出現(xiàn)慨飘,那可不是什么好的事情确憨,因?yàn)椴僮鬟@個(gè)類中屬性的方法將會(huì)散落在各個(gè)類中,即存在者多處強(qiáng)耦合瓤的。

如何解決純數(shù)據(jù)類這種代碼壞味道休弃?

建議使用充血模型,一個(gè)類中除了擁有屬性也應(yīng)該包含具有一定業(yè)務(wù)邏輯的行為堤瘤。那么可以選擇

  1. Extract Method 將部分調(diào)用邏輯進(jìn)行提煉玫芦,提煉成一定的方法浆熔;
  2. 再使用 Move Method 將方法移動(dòng)到類中本辐,
  3. 最后 Hide Method 刪除純出局類中的 getter 和 setter桥帆。

純數(shù)據(jù)類有其使用場景,但是應(yīng)該時(shí)刻注意到哪些場景下數(shù)據(jù)類會(huì)引入壞味道慎皱,一旦發(fā)現(xiàn)盡早解決老虫。

參考

《重構(gòu)》

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市茫多,隨后出現(xiàn)的幾起案子祈匙,更是在濱河造成了極大的恐慌,老刑警劉巖天揖,帶你破解...
    沈念sama閱讀 221,430評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件夺欲,死亡現(xiàn)場離奇詭異,居然都是意外死亡今膊,警方通過查閱死者的電腦和手機(jī)些阅,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,406評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來斑唬,“玉大人市埋,你說我怎么就攤上這事∷×酰” “怎么了缤谎?”我有些...
    開封第一講書人閱讀 167,834評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長褐着。 經(jīng)常有香客問我坷澡,道長,這世上最難降的妖魔是什么含蓉? 我笑而不...
    開封第一講書人閱讀 59,543評(píng)論 1 296
  • 正文 為了忘掉前任洋访,我火速辦了婚禮,結(jié)果婚禮上谴餐,老公的妹妹穿的比我還像新娘姻政。我一直安慰自己,他們只是感情好岂嗓,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,547評(píng)論 6 397
  • 文/花漫 我一把揭開白布汁展。 她就那樣靜靜地躺著,像睡著了一般厌殉。 火紅的嫁衣襯著肌膚如雪食绿。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,196評(píng)論 1 308
  • 那天公罕,我揣著相機(jī)與錄音器紧,去河邊找鬼。 笑死楼眷,一個(gè)胖子當(dāng)著我的面吹牛铲汪,可吹牛的內(nèi)容都是我干的熊尉。 我是一名探鬼主播,決...
    沈念sama閱讀 40,776評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼掌腰,長吁一口氣:“原來是場噩夢啊……” “哼狰住!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起齿梁,我...
    開封第一講書人閱讀 39,671評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤催植,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后勺择,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體创南,經(jīng)...
    沈念sama閱讀 46,221評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,303評(píng)論 3 340
  • 正文 我和宋清朗相戀三年省核,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了扰藕。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,444評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡芳撒,死狀恐怖邓深,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情笔刹,我是刑警寧澤芥备,帶...
    沈念sama閱讀 36,134評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站舌菜,受9級(jí)特大地震影響萌壳,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜日月,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,810評(píng)論 3 333
  • 文/蒙蒙 一袱瓮、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧爱咬,春花似錦尺借、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,285評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至蜂绎,卻和暖如春栅表,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背师枣。 一陣腳步聲響...
    開封第一講書人閱讀 33,399評(píng)論 1 272
  • 我被黑心中介騙來泰國打工怪瓶, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人践美。 一個(gè)月前我還...
    沈念sama閱讀 48,837評(píng)論 3 376
  • 正文 我出身青樓洗贰,卻偏偏與公主長得像找岖,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子哆姻,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,455評(píng)論 2 359