輔助審查系統(tǒng)的代碼書寫規(guī)范


title: 輔助審查系統(tǒng)的代碼書寫規(guī)范
date: 2019/10/26 09:43
remark: 本系統(tǒng)采用SpringBoot + Dubbo進(jìn)行開發(fā)


前言

近期在重構(gòu)輔助審查系統(tǒng)囚灼,發(fā)現(xiàn)隨著項目的發(fā)展涯雅,代碼變得異常混亂,完全違背了當(dāng)初定下來的規(guī)范,當(dāng)然這其實是無法避免的,畢竟時間緊任務(wù)重,哪里有時間讓你深思熟慮的考慮這段代碼該怎樣寫仙逻。

之前的代碼規(guī)范只在自己的心中,隨著時間就會慢慢遺忘涧尿,在寫新的代碼的時候系奉,可能就想不到那么多,從而導(dǎo)致代碼的“味道”越來越差姑廉,由此我決定花一天時間缺亮,將其落實到紙上,日后寫代碼的時候可以看一下桥言,盡量保證代碼的味道不要太差萌踱。

當(dāng)然,由于項目時間緊任務(wù)重号阿,可能沒辦法所有的代碼都按照規(guī)范來寫并鸵,有的時候只能尋找一些捷徑,這樣也是不可避免的倦西;希望大家日后有時間的時候能真,可以按照本規(guī)范,將違背了規(guī)范的地方進(jìn)行重構(gòu)扰柠。

注:由于輔助審查系統(tǒng)的特殊性,本規(guī)范可能不適用于其它系統(tǒng)疼约。

一卤档、工程架構(gòu)模型

1.1 如何分層

p3c規(guī)范中的分層模型

本系統(tǒng)采用的分層結(jié)構(gòu)與p3c規(guī)范中的基本相同。

Dao層

數(shù)據(jù)訪問對象(Data Access Object)程剥,用于對數(shù)據(jù)庫進(jìn)行訪問劝枣,負(fù)責(zé)數(shù)據(jù)的CURD。

當(dāng)然 Dao 不僅限于與數(shù)據(jù)庫進(jìn)行交互织鲸,假如日后系統(tǒng)引入的ElasticSearch舔腾、Mongo 甚至Redis,我認(rèn)為都可以定義一個Dao對其進(jìn)行訪問搂擦。

這樣的定義稳诚,可以將數(shù)據(jù)的CURD和業(yè)務(wù)邏輯進(jìn)行分離。

Manager層

p3c規(guī)范中對其定義如下:

  1. 對第三方平臺封裝的層瀑踢,預(yù)處理返回結(jié)果及轉(zhuǎn)化異常信息
  2. 對 Service 層通用能力的下沉扳还,如緩存方案才避、中間件通用處理
  3. 與 DAO 層交互,對多個 DAO 的組合復(fù)用

由這個定義并結(jié)合我們的系統(tǒng)氨距,可以得出Manager層主要作用為:

  1. 可以通過 Manager 層調(diào)用第三方服務(wù)(指標(biāo)系統(tǒng)桑逝、全文檢索服務(wù),因為他們是基礎(chǔ)服務(wù)俏让,所以不要在 web 層調(diào)用他們)楞遏,對返回結(jié)果進(jìn)行簡單的處理之后返回 Service 層。
  2. 如果需要對基礎(chǔ)服務(wù)進(jìn)行調(diào)用首昔,并將其結(jié)果處理后入庫(例如:檔案管理系統(tǒng)橱健、模型系統(tǒng))這種用法時,直接通過 Dao 層進(jìn)行保存沙廉。
  3. 可以將 Manager 理解為對通用邏輯的封裝拘荡,避免 Service 與 Service 進(jìn)行相互調(diào)用,以及對通用邏輯的管理撬陵。

在開發(fā)中珊皿,我們經(jīng)常會遇到 AService 中的某個業(yè)務(wù)可以提供給 BService 調(diào)用,從而讓 BService 調(diào)用 AService 的方法巨税,認(rèn)為是 Service 之間具有共同的業(yè)務(wù)蟋定。其實 Service 之間沒有共同的業(yè)務(wù),而是具備通用的邏輯草添,這時應(yīng)該將其抽離出來放在 Manager 中驶兜。無論何種工程架構(gòu)都好,我都不贊同 Service 與 Service 之間的相互調(diào)用远寸。

  1. 如果2個(或2個以上)表之間有一定的關(guān)聯(lián)關(guān)系(一對多抄淑、多對多)并經(jīng)常一起使用,則通過一個 Manager 對他們進(jìn)行訪問驰后。
  2. 可以在這層加入緩存(當(dāng)然我們體量小肆资,一般只在service層加緩存),與我上面所說的為操作Redis定義對Dao進(jìn)行訪問灶芝。

Service層

對具體對業(yè)務(wù)邏輯進(jìn)行操作(復(fù)用性很低)郑原,由于我們使用的是dubbo,Service層可能會被其他人調(diào)用夜涕,所以最好還是做一下參數(shù)校驗(hibernate validate)

從p3c規(guī)范來看犯犁,如果不用Manager層來對多個Dao進(jìn)行組合,那么Service層可以直接與Dao進(jìn)行交互女器,但是這樣會給人一種很混亂對感覺酸役,所以我們定義:

Service對數(shù)據(jù)庫進(jìn)行操作時,必須通過Manager層,其實這也是為日后開發(fā)可能遇到對問題留有余地簇捍;如果我們使用Redis做Service層緩存的話只壳,那么可以直接調(diào)用對應(yīng)Redis的Dao。

Web層

web層只做簡單對參數(shù)校驗暑塑,或者簡單對業(yè)務(wù)處理等(例如:查詢審查任務(wù)實體吼句,但是前端只需要部分字段,進(jìn)行轉(zhuǎn)換的工作)事格;Web層與Service層一一對應(yīng)惕艳。

1.2 分層領(lǐng)域?qū)ο?/h3>

本系統(tǒng)采用對模型為貧血領(lǐng)域模型,p3c規(guī)范定義對數(shù)據(jù)傳輸對象過多驹愚,這樣就導(dǎo)致了一個對象可能會出現(xiàn)3次甚至4次轉(zhuǎn)換在一次請求中远搪,當(dāng)返回的時候同樣也會出現(xiàn)3-4次轉(zhuǎn)換,這樣有可能一次完整的“請求-返回”會出現(xiàn)很多次對象轉(zhuǎn)換逢捺。如果在開發(fā)中真的按照這么來谁鳍,恐怕就別寫其他的了,一天就光寫這個重復(fù)無用的邏輯算了吧劫瞳,所以我們只定義了幾個對象倘潜。

貧血領(lǐng)域模型中對象只作為數(shù)據(jù)載體,只有 getter/setter 方法志于,而不包含業(yè)務(wù)方法涮因。

DO(Data Object)

數(shù)據(jù)對象,對數(shù)據(jù)源數(shù)據(jù)的映射伺绽,如數(shù)據(jù)庫表养泡,ElasticSearch 索引的數(shù)據(jù)結(jié)構(gòu)。所在包一般命名為 data 奈应。

DTO(Data Transfer Object)

數(shù)據(jù)傳輸對象澜掩,業(yè)務(wù)層向外傳輸?shù)膶ο蟆H绻?strong>某個業(yè)務(wù)中需要多次查詢獲取不同的數(shù)據(jù)對象钥组,最后將會把這多個數(shù)據(jù)對象組合成一個 DTO 并對外傳輸输硝。所在包命名為 dto 。

VO(View Object)

顯示層對象程梦,通常是 Web 向模板渲染引擎層傳輸?shù)膶ο蟆,F(xiàn)在的項目多數(shù)為前后端分離橘荠,后端只需要返回 JSON 屿附,那么可以理解為 JSON 即是需要渲染成的“模板”。我一般會將這類對象命名為 xxxResponse 哥童,所在包命名為 response挺份。

Query

數(shù)據(jù)查詢對象,數(shù)據(jù)查詢對象贮懈,各層接收上層的查詢請求匀泊。

其實一般用于 Controller 接受傳過來的參數(shù)优训,可以將其都命名為 xxxQuery,而我個人習(xí)慣將放在 request body 的參數(shù)(即 @RequestBody)包裝為 xxxRequest 各聘,而如果使用表單傳輸過來的參數(shù)(即 @RequestParam)包裝為 xxxForm 揣非,并分別放在包 request 和包 form 下。

注:web層向service層傳輸對query對象躲因,絕對不能傳輸?shù)組anager層早敬,因為Manager層是通用的邏輯

層間對象傳遞

領(lǐng)域?qū)ο笤诓煌瑢又g的傳遞

其中DTO如果不可復(fù)用大脉,那么可以直接傳輸給前端搞监。

1.3 包結(jié)構(gòu)及其含義

輔助審查服務(wù)模塊包設(shè)計

x5456deMBP:dgp-dubbo-server-root x5456$ tree dgp-ars-server-service/src -d -L 8
dgp-ars-server-service/src
├── main
│   ├── java
│   │   └── com
│   │       └── dist
│   │           └── ars
│   │               ├── aop
│   │               ├── config
│   │               ├── dao
│   │               ├── manager
│   │               │   └── remote
│   │               │        ├── ams
│   │               │        ├── ims
│   │               │        ├── mms
│   │               │        ├── pms
│   │               │        └── sms
│   │               └── service
│   └── resources
│       ├── META-INF
│       │   ├── dubbo
│       │   └── services
│       ├── config
│       ├── db
│       │   ├── oracle
│       │   │   ├── create
│       │   │   └── update
│       │   └── pg
│       │       └── create
│       └── libs
└── test
    └── java
        └── com
            └── dist
                └── ars
                    ├── service
                    └── manager

輔助審查Api模塊包設(shè)計

tree dgp-ars-server-api/src -d -L 8
dgp-ars-server-api/src
└── main
    └── java
        └── com
            └── dist
                └── ars
                    ├── constants
                    ├── exceptions
                    ├── helper      # web層與service共用的輔助類
                    ├── model
                    │   ├── dto
                    │   ├── entity
                    │   ├── query
                    │   │   ├── request
                    │   │   ├── form
                    │   │   ├── webQuery        # 由web層封裝向service層傳輸?shù)牟樵儗ο?                    │   │   └── commonQuery     # 由service層封裝傳輸?shù)組anager層的通用查詢對象
                    │   └── vo
                    └── service

helper包

開發(fā)中會遇到一些很基礎(chǔ)的,通用的業(yè)務(wù)邏輯镰矿,例如我們可能會根據(jù)每個用戶的信息生成一個唯一的 account id 琐驴。又或者說有一個用戶排名的需求,我們將從用戶的相關(guān)信息中計算出一個分?jǐn)?shù)秤标,從而根據(jù)這個分?jǐn)?shù)進(jìn)行排名绝淡。那么這時候我們可能會將這些邏輯寫在 User 數(shù)據(jù)對象或是其他相應(yīng)對應(yīng)的數(shù)據(jù)對象下。

由于我們采用的是貧血領(lǐng)域模型抛杨,數(shù)據(jù)對象中不應(yīng)該包含業(yè)務(wù)邏輯够委,所以我們將這些通用的業(yè)務(wù)邏輯都抽出來,放到 helper 包中進(jìn)行統(tǒng)一管理怖现。如會將生成 account id 的邏輯放在 AccountIdGenerator 中茁帽,將計算排名分?jǐn)?shù)的邏輯放在 RankCalculator 中。

我將這些類都?xì)w為 Helper 屈嗤,用于提供底層的業(yè)務(wù)計算邏輯潘拨。而為什么不放在通用工具層中呢?因為這些 Helper 其實都是依賴于特定的領(lǐng)域饶号,即特定的業(yè)務(wù)铁追。而通用工具類則是業(yè)務(wù)無關(guān)的,任何系統(tǒng)茫船,只要有需要都可以引用琅束。

二、代碼風(fēng)格

2.1 命名規(guī)范

https://mp.weixin.qq.com/s/WLHXrdfKc71b0EU0vi09gA

類名使用名詞或者形容詞 + 名詞算谈。

方法名為動詞或動詞短語涩禀。

包名使用小寫,只能有一個自然語意的英語單詞然眼。包名使用單數(shù)艾船,但如果類名有復(fù)數(shù)含義,則可以使用復(fù)數(shù)。

抽象類以Base/Abstract開頭屿岂;異常類以Exception結(jié)尾践宴;測試類以被測類名開頭,Test結(jié)尾爷怀;枚舉采用Enum結(jié)尾阻肩。

2.2 Google Java編程規(guī)范

源文件結(jié)構(gòu)

1、許可證或版權(quán)信息(如有需要)

2霉撵、package語句

3磺浙、import語句

4、一個頂級類(只有一個)

注:以上每個部分之間用一個空行隔開

類成員順序

1徒坡、變量

2撕氧、構(gòu)造方法

3、公有方法

4喇完、getter/setter方法

5伦泥、私有方法

注:重載方法永不分離。

換行

一般情況下锦溪,一行長代碼超出列限制(80或100個字符)不脯,我們就需要將其分為多行。

換行的基本準(zhǔn)則是:更傾向于在更高的語法級別處斷開刻诊。

  1. 如果在非賦值運(yùn)算符處斷開防楷,那么在該符號前斷開(比如+,它將位于下一行)则涯。
  2. 如果在賦值運(yùn)算符處斷開复局,通常的做法是在該符號后斷開(比如=,它與前面的內(nèi)容留在同一行)粟判。這條規(guī)則也適用于 foreach 語句中的分號亿昏。
  3. 方法名或構(gòu)造函數(shù)名與左括號留在同一行。
  4. 逗號(,)與其前面的內(nèi)容留在同一行档礁。

換行時角钩,至少縮進(jìn)4個空格。

空行

以下情況需要使用一個空行:

  1. 類內(nèi)連續(xù)的成員之間:字段呻澜,構(gòu)造函數(shù)递礼,方法,嵌套類羹幸,靜態(tài)初始化塊宰衙,實例初始化塊。
  2. 在函數(shù)體內(nèi)睹欲,語句的邏輯分組間使用空行。
  3. 類內(nèi)的第一個成員前或最后一個成員后的空行是可選的(既不鼓勵也不反對這樣做,視個人喜好而定)窘疮。

變量聲明

不要組合聲明袋哼,例如:

int a,b = 0;

變量需要使用時才聲明

2.3 p3c規(guī)范總結(jié)

http://www.reibang.com/p/329dd85cde4f

2.4 Effective Java總結(jié)

http://www.reibang.com/p/61e8b5b96e98

三、單元測試

單元測試是針對程序的最小單元來進(jìn)行正確性檢驗的測試工作闸衫。程序單元是應(yīng)用的最小可測試部件涛贯。一個單元可能是單個程序、類蔚出、對象弟翘、方法等

3.1 為什么要寫單元測試

提高代碼質(zhì)量

對一個單元進(jìn)行測試時骄酗,需要將其隔離外部的依賴(數(shù)據(jù)庫稀余、第3方接口),保證外部依賴不影響當(dāng)前單元的邏輯趋翻。

正因為如此睛琳,他會促進(jìn)我們對工程進(jìn)行組件化拆分,整理工程依賴關(guān)系踏烙,更大程度減少代碼耦合师骗。

提升重構(gòu)自信心

重構(gòu),每個開發(fā)者都會經(jīng)歷讨惩,重構(gòu)后把代碼改壞了的情況并不少見辟癌。以往,寫完一個框架荐捻,運(yùn)行一下黍少,沒什么問題,完事靴患;由于最初的框架并不是你寫的仍侥,可謂牽一發(fā)動全身,你改1個方法導(dǎo)致整個框架運(yùn)行失敗鸳君。有了單元測試后农渊,我們重構(gòu)時自然就會多一分勇氣。

測試驅(qū)動開發(fā)(TDD):

測試驅(qū)動開發(fā)是戴兩頂帽子思考的開發(fā)方式:先戴上實現(xiàn)功能的帽子或颊,在測試的輔助下砸紊,快速實現(xiàn)其功能;再戴上重構(gòu)的帽子囱挑,在測試的保護(hù)下醉顽,通過去除冗余的代碼,提高代碼質(zhì)量平挑。測試驅(qū)動著整個開發(fā)過程:首先游添,驅(qū)動代碼的設(shè)計和功能的實現(xiàn)系草;其后,驅(qū)動代碼的再設(shè)計和重構(gòu)唆涝。

3.2 單元測試的原則

AIR原則

A:Automatic(自動化)

I:Independent(獨(dú)立性找都,不同的單元測試之間要互相獨(dú)立)

R:Repeatable(可重復(fù)執(zhí)行)

BCDE原則

編寫單元測試時要保證測試粒度足夠小,這樣有助于精確定位問題廊酣,用例默認(rèn)是方法級別的能耻。單測不負(fù)責(zé)檢查跨類或者跨系統(tǒng)的交互邏輯,那是集成測試需要覆蓋的范圍亡驰。編寫單元測試用例時晓猛,為了保證被測模塊的交付質(zhì)量,需要符合BCDE原則凡辱。

  • B: Border戒职,邊界值測試,包括循環(huán)邊界煞茫、特殊取值帕涌、特殊時間點(diǎn)、數(shù)據(jù)順序等续徽。
  • C: Correct蚓曼,正確的輸入,并得到預(yù)期的結(jié)果钦扭。
  • D: Design纫版,與設(shè)計文檔相結(jié)合,來編寫單元測試客情。(沒有設(shè)計文檔其弊,不懂這條什么意思)
  • E: Error,單元測試的目標(biāo)是證明程序有錯膀斋,而不是程序無錯梭伐。為了發(fā)現(xiàn)代碼中潛在錯誤,我們需要編寫測試用例時仰担,有一些強(qiáng)制的錯誤輸入(如非法數(shù)據(jù)糊识、異常流程、非業(yè)務(wù)允許輸入等)來得到預(yù)期的結(jié)果摔蓝。

使用Mock對象

由于單元測試只是系統(tǒng)集成測試前的小模塊測試赂苗,有些因素往往是不具備的,因此需要進(jìn)行Mock贮尉,例如:

(1)功能因素拌滋。比如被測試方法內(nèi)部調(diào)用的功能不可用。

(2)時間因素猜谚。比如雙十一還沒有到來败砂,與此時間相關(guān)的功能點(diǎn)赌渣。

(3)環(huán)境因素。政策環(huán)境吠卷,如支付寶政策類新功能;多端環(huán)境锡垄,如PC、手機(jī)等祭隔。

(4)數(shù)據(jù)因素。線下數(shù)據(jù)樣本過小路操,難以覆蓋各種線上真實場景疾渴。

(5)其他因素。為了簡化測試編寫屯仗,開發(fā)者也可以將一些復(fù)雜的依賴采用Mock方式實現(xiàn)搞坝。

優(yōu)秀的單元測試

(1)單元測試是“白盒測試”碎乃,應(yīng)該覆蓋各個分支流程赂弓、異常條件蹬竖。

(2)單元測試面向的是一個單元(Unit)秧饮,是由Java中的一個類或者幾個類組成的單元摧茴。

(3)單元測試的運(yùn)行速度一定要快!

(4)單元測試一定是可重復(fù)執(zhí)行的!

(5)單元測試之間不能有相互依賴赘理,應(yīng)該是獨(dú)立的!

(6)單元測試代碼和業(yè)務(wù)代碼同等重要翘紊,要一并維護(hù)!

3.3 怎樣寫

結(jié)合到本系統(tǒng)换薄,普通的增刪改查這樣過于簡單的功能就不需要進(jìn)行測試了鞠呈;

我們主要是對Manager層和Service層這兩層進(jìn)行測試融师,因為這兩層主要設(shè)計到了數(shù)據(jù)的處理。

Service層的單元測試引用Manager層的Mock對象蚁吝,Manager層引用Dao層的Mock對象旱爆。

如果像mms那樣具有復(fù)雜的邏輯,我們就要將其進(jìn)一步拆分成很小的單元進(jìn)行測試窘茁。

Demo

@ActiveProfiles("prod")
@RunWith(SpringRunner.class)
@SpringBootTest(classes = ArsServiceApplication.class)
public class ProjectReviewInfoDmnImplTest {

    @Autowired
    private IProjectReviewInfoManager projectReviewInfoDmn;

    @MockBean
    private VProjectReviewInfoRepository vProjectReviewInfoRepository;

    // 湖州市區(qū)域code
    private String regionCode = "330500000000";

    @Test
    public void findProjectReviewInfo() {

        this.mockFindProjectReviewInfo();

        // 湖州市及其下面層級的區(qū)域code
        List<String> subRegionCodeList = JsonUtils.toList("[\"330500000000\",\"330501000000\",\"330502000000\",\"330503000000\",\"330521000000\",\"330522000000\",\"330523000000\"]", String.class);

        CommonReviewTaskQuery commonReviewTaskQuery = new CommonReviewTaskQuery();
        commonReviewTaskQuery.setAreaLevel(StatusEnum.AreaLevelEnum.CITY.desc());
        commonReviewTaskQuery.setPlanType(StatusEnum.PlanTypeEnum.LAND_SPACE_PLAN.desc());
        commonReviewTaskQuery.setRolesName(Collections.singletonList("市總規(guī)科"));
        commonReviewTaskQuery.setRegionCodeList(subRegionCodeList);
        commonReviewTaskQuery.setKeyword("湖州");
        commonReviewTaskQuery.setTaskAreaLevel(StatusEnum.AreaLevelEnum.CITY.code());
        commonReviewTaskQuery.setQueryApprovalStage(false);

        List<VProjectReviewInfo> result = projectReviewInfoDmn.findProjectReviewInfo(commonReviewTaskQuery);
        Assert.assertEquals(JsonUtils.toString(result), "xxx");
    }

    @SuppressWarnings("unchecked")
    private void mockFindProjectReviewInfo() {
        String result = "xxx";
        Mockito.when(vProjectReviewInfoRepository.findAll(ArgumentMatchers.any(Specification.class), ArgumentMatchers.any(Sort.class)))
                .thenReturn(JsonUtils.toList(result, VProjectReviewInfo.class));
    }
}

3.4 總結(jié)

單元測試確實會帶給你相當(dāng)多的好處怀伦,但不是立刻體驗出來。正如買重疾保險山林,交了很多保費(fèi)房待,沒病沒痛,十幾年甚至幾十年都用不上捌朴,最好就是一輩子用不上理賠吴攒,身體健康最重要。單元測試也一樣砂蔽,寫了可以買個放心洼怔,對代碼的一種保障,有bug盡快測出來左驾,沒bug就最好镣隶,總不能說“寫那么多單元測試极谊,結(jié)果測不出bug,浪費(fèi)時間”吧安岂?

以下是個人對單元測試一些建議:

  • 越重要的代碼轻猖,越要寫單元測試;
  • 代碼做不到單元測試域那,多思考如何改進(jìn)咙边,而不是放棄;
  • 邊寫業(yè)務(wù)代碼次员,邊寫單元測試败许,而不是完成整個新功能后再寫;
  • 多思考如何改進(jìn)淑蔚、簡化測試代碼市殷。

四、重構(gòu)

http://www.reibang.com/p/e5276d50a7b5

五刹衫、日志

日志規(guī)約

本文參考文章

第一部分

1醋寝、應(yīng)用分層模型

2、你的項目應(yīng)該如何正確分層带迟?

3音羞、總結(jié)代碼風(fēng)格

4、到底需不需要Manager層邮旷?

第二部分

1黄选、碼出高效:Java開發(fā)手冊

2、總結(jié)代碼風(fēng)格

3婶肩、Google Java 編程規(guī)范(中文版)

第三部分

1办陷、談?wù)劄槭裁磳憜卧獪y試

2、碼出高效:Java開發(fā)手冊

3律歼、Mockito與PowerMock的使用基礎(chǔ)教程


定期對公司項目進(jìn)行基礎(chǔ)代碼的重構(gòu)民镜。合理的拆分業(yè)務(wù)無關(guān)的基礎(chǔ)代碼。

最好不要直接引用三方庫险毁,進(jìn)行再次的封裝

更新代碼時同時更新注釋和單元測試

盡量少寫代碼(lombok)

pom文件的管理(待google)

防御式編程:不要相信任何外來參數(shù)

類制圈、變量命名

日志、狀態(tài)碼

這是我現(xiàn)在的想法(2020.06.02)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末畔况,一起剝皮案震驚了整個濱河市鲸鹦,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌跷跪,老刑警劉巖馋嗜,帶你破解...
    沈念sama閱讀 218,204評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異吵瞻,居然都是意外死亡葛菇,警方通過查閱死者的電腦和手機(jī)甘磨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來眯停,“玉大人济舆,你說我怎么就攤上這事≥赫” “怎么了滋觉?”我有些...
    開封第一講書人閱讀 164,548評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長九府。 經(jīng)常有香客問我椎瘟,道長,這世上最難降的妖魔是什么侄旬? 我笑而不...
    開封第一講書人閱讀 58,657評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮煌妈,結(jié)果婚禮上儡羔,老公的妹妹穿的比我還像新娘。我一直安慰自己璧诵,他們只是感情好汰蜘,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,689評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著之宿,像睡著了一般族操。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上比被,一...
    開封第一講書人閱讀 51,554評論 1 305
  • 那天色难,我揣著相機(jī)與錄音,去河邊找鬼等缀。 笑死枷莉,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的尺迂。 我是一名探鬼主播笤妙,決...
    沈念sama閱讀 40,302評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼噪裕!你這毒婦竟也來了蹲盘?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,216評論 0 276
  • 序言:老撾萬榮一對情侶失蹤膳音,失蹤者是張志新(化名)和其女友劉穎召衔,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體严蓖,經(jīng)...
    沈念sama閱讀 45,661評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡薄嫡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,851評論 3 336
  • 正文 我和宋清朗相戀三年氧急,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片毫深。...
    茶點(diǎn)故事閱讀 39,977評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡吩坝,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出哑蔫,到底是詐尸還是另有隱情钉寝,我是刑警寧澤,帶...
    沈念sama閱讀 35,697評論 5 347
  • 正文 年R本政府宣布闸迷,位于F島的核電站嵌纲,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏腥沽。R本人自食惡果不足惜逮走,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,306評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望今阳。 院中可真熱鬧师溅,春花似錦、人聲如沸盾舌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽妖谴。三九已至窿锉,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間膝舅,已是汗流浹背嗡载。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留铸史,地道東北人鼻疮。 一個月前我還...
    沈念sama閱讀 48,138評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像琳轿,于是被迫代替她去往敵國和親判沟。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,927評論 2 355