Effective Ruby

一、 讓自己熟悉Ruby

1亭敢、理解 Ruby 中的 True

在 Ruby 中滚婉,除了 false 和 nil, 其他值都是真值帅刀。

false 和 nil 是唯二的假值让腹,因此用 true 對象表示真值是冗余的,任何非 false扣溺、非 nil 的對象都可以表示真值骇窍。

false == x ,盡可能的將判斷的標準寫在 '==' ?的左邊锥余,以避免被其他類所覆蓋

2腹纳、所有對象的值都可能為 nil

我們需要通過優(yōu)秀的測試挑出各種各樣的錯誤。

根據(jù)Ruby的類型系統(tǒng)運作方式驱犹,任何對象都可以為nil嘲恍。

在適合的時候用轉(zhuǎn)換方法,如to_s 和 to_i雄驹,可以將nil對象強制轉(zhuǎn)換為你期待的類型佃牛。

Array#compact方法返回去除所有nil元素的數(shù)組。

3医舆、避免使用 Ruby 中奇怪的 Perl 風格語法

方法 String#match 比 “ =~ ” 更符合語言習慣俘侠,并且該方法不使用任何操作符 “ =~ ” 所產(chǎn)生的特殊全局變量。

用 $LOAD_PATH 代替 全局變量 $:?

避免使用隱式讀寫全局變量 $_ 的方法(比如蔬将, Kernel#print爷速、Regexp#~ 等)。

4霞怀、留神惫东,常量是可變的

總是將常量凍結(jié),從而防止其被改變里烦。

如果常量引用了一個集合對象比如數(shù)組或者散列凿蒜,那么凍結(jié)這個集合及其所有元素。

要防止常量被重新賦值胁黑,可以凍結(jié)定義它的那個模塊废封。

5、留意運行時警告

使用命令行選項 “ -w ” 來運行 Ruby 解釋器以啟用編譯時和運行時的警告丧蘸,設(shè)置環(huán)境變量 RUBYOPT 為 “ -w ”也可以達到相同目的漂洋。

如果必須禁用運行時的警告遥皂,可以臨時將全局變量 $VERBOSE 設(shè)置為nil。


二刽漂、類演训、對象和模塊

6、了解 Ruby 如何構(gòu)建繼承體系

要尋找一個方法贝咙、Ruby 只需要向上搜索類體系样悟。 如果沒有找到這個方法,就從起點開始搜索 method_missing 方法庭猩。

包含模塊時 Ruby 會悄悄地創(chuàng)建單例類窟她,并將其插入在繼承體系中包含它的類的上方。

單例方法(類方法和針對對象的方法)存儲于單例類中蔼水,它也會被插入繼承體系中震糖。

對象是變量的容器。類是方法和常量的容器趴腋。超類是一個類的父類的花哨名字吊说。Ruby 可以通過 include 方法將模塊引入類,實現(xiàn)類似多繼承的效果优炬。單例類是繼承體系不可見的類颁井,也僅僅是沒有名字的、被加以限制的常規(guī)類穿剖。

7蚤蔓、了解 super 的不同行為

當你想重載繼承體系中的一個方法時,關(guān)鍵字 super 可以幫你調(diào)用它糊余。

不加括號地無參調(diào)用 super 等價于講宿主方法的所有參數(shù)傳遞給要調(diào)用的方法。這樣使用 super 僅僅在目標方法和宿主方法接受相同數(shù)量的參數(shù)時才可用单寂。

如果希望使用 super 并且不向重載方法傳遞任何參數(shù)贬芥,必須使用空括號,即super()宣决。

當 super 調(diào)用失敗時蘸劈,自定義的 method_missing 方法將丟棄一些有用的信息。第30條中有 method_missing 的替代解決方案尊沸。

如果你希望調(diào)用一個定義在超類的方法威沫,而同時如果包含的模塊中也定義了同名方法,super 會在找到第一個匹配的同名方法后停下來洼专,而那時包含的模塊中的方法棒掠,不是超類中的。如果真的遇到這種情況屁商,可能是設(shè)計上存在嚴重的問題烟很。可以考慮使用組合而非繼承了。

8雾袱、初始化子類時調(diào)用 super

當創(chuàng)建子類對象時恤筛,Ruby 不會自動調(diào)用超類中的 initialize 方法。作為替代芹橡,常規(guī)的方法查詢規(guī)則也適用于 initialize 方法毒坛,只有第一個匹配的副本會被調(diào)用。

當為顯式使用繼承的類定義 initialize 方法時林说,使用 super 來初始化其父類煎殷。在定義 initialize_copy 方法時,應(yīng)使用相同的規(guī)則述么。

initialize 并不是構(gòu)建新對象的唯一方式蝌数。Ruby允許我們使用 dup 和 clone 方法創(chuàng)建對象的副本。當你使用這些方法任意一個時度秘,可以通過定義 initialize_copy 方法對新創(chuàng)建的副本對象執(zhí)行一些特別的邏輯顶伞。

9、提防 Ruby 最棘手的解析

setter 方法在調(diào)用時需要顯式的接收者剑梳。沒有接收者時唆貌,會被 Ruby 解析為變量賦值。

在實例方法仲調(diào)用 setter 方法時垢乙,使用 self 作為接收者锨咙。

在調(diào)用非 setter 方法時,不需要顯式指定接收者追逮。換句話說酪刀,不要使用不必要的 self , 那會弄亂你的代碼钮孵。

10骂倘、推薦使用 Struct 而非 Hash 存儲結(jié)構(gòu)化數(shù)據(jù)

在處理結(jié)構(gòu)化數(shù)據(jù)時,如果創(chuàng)建一個新類不那么合適時巴席,推薦使用 Struct 而非 Hash历涝。

將 Struct::new 的返回值賦給常量,并像類一樣使用它漾唉。

使用 Struct 在屬性名拼錯的時候會引發(fā)一個 NoMethodError 異常荧库,使用哈希時不會有這個問題,因為訪問非法鍵的時候只會返回nil赵刑,不過也意味著在之后的代碼中分衫,你將被卷入更難發(fā)現(xiàn)的 TypeError 異常。

11料睛、通過在模塊中嵌入代碼來創(chuàng)建命名空間

通過在模塊中嵌入代碼來創(chuàng)建命名空間丐箩。

讓你的命名空間結(jié)構(gòu)和目錄結(jié)構(gòu)相同摇邦。

如果使用時可能出現(xiàn)歧義,可使用 “ :: ” 來限定頂級常量(比如:::Array)

12屎勘、理解等價的不同用法

絕不要重載 equal? 方法施籍。該方法的預(yù)期行為是,嚴格比較兩個對象概漱,僅當它們同時指向內(nèi)存中同一個對象時其值為真(即丑慎,當它們具有相同的 object_id 時)。

Hash 類在沖突檢測時使用 eql? 方法來比較鍵對象瓤摧。默認實現(xiàn)可能和你的想象不同竿裂。遵循第13條的建議之后再使用別名 eql? 來替代 “ == ” 書寫更合理的 hash 方法。

使用 “ == ” 操作符來測試兩個對象是否表示相同的值照弥。有些類比如表示數(shù)字的類會有一個粗糙的等號操作符進行類型轉(zhuǎn)換腻异。

case 表達式使用 “ == ” 操作符來測試每個 when 語句的值。左操作數(shù)是 when 的參數(shù)这揣,右操作數(shù)是 case 的參數(shù)悔常。

13、通過 “ <=> ” 操作符實現(xiàn)比較和比較模塊

通過定義 “ <=> ” 操作符和引入 Comparable 模塊實現(xiàn)對象的排序给赞。( Comparable 模塊包含 “<” 机打、"<=" 、"==" 片迅、">" 残邀、">=")

如果左操作數(shù)不能與右操作數(shù)進行比較,“ <=> ” 操作符應(yīng)該返回 nil柑蛇。

如果要實現(xiàn)類的 “ <=> ” 運算符芥挣,應(yīng)該考慮將 eql? 方法設(shè)置為 “ == ” 操作符的別名,特別是當你希望該類的所有實例可以被用來作為哈希鍵的時候耻台,就應(yīng)該重載哈希方法九秀。

14、通過 protected 方法共享私有狀態(tài)

封裝是面向?qū)ο缶幊讨械闹饕獪蕜t之一粘我,它是指一個對象的內(nèi)部實現(xiàn)僅可被內(nèi)部訪問,不可被外部訪問痹换。

當設(shè)計一個具有內(nèi)部狀態(tài)的類時征字,正確的做法是盡可能減少對該狀態(tài)的直接訪問,而是使用最小數(shù)量的訪問方法娇豫。


通過protected方法共享私有狀態(tài)匙姜。

一個對象的protected方法若要被顯示接收者調(diào)用,除非改對象與接收者是同類對象或具有相同的定義該protected方法的超類冯痢。

15氮昧、優(yōu)先使用實例變量而非類變量

Ruby 語言存在兩種用 @ 標識的變量: 實例變量和類變量框杜。

如果你的程序存在多線程控制,那么在不使用互斥鎖的情況下改變?nèi)魏巫兞慷际遣话踩摹?/p>

優(yōu)先使用實例變量而非類變量袖肥。

類也是對象咪辱,所以它們擁有自己的私有實例變量集合。

三椎组、集合

16油狂、在改變作為參數(shù)的集合之前復制它們

Ruby 中參數(shù)時按引用傳遞的,而不是值傳遞寸癌。這個規(guī)則有一個例外值注意: 它不適用于 Fixnum 對象专筷。

在改變集合之前先復制它們。

dup 方法和 clone 方法只會進行淺拷貝蒸苇。

對于多數(shù)對象來說磷蛹,可以使用 Marshal 來完成深拷貝。

17溪烤、使用 Array 方法將 nil 及標量對象轉(zhuǎn)換成數(shù)組

使用 Array 方法將 nil 及標量對象轉(zhuǎn)換成數(shù)組味咳。

不要講哈希傳給 Array 方法,它會被轉(zhuǎn)化成一個嵌套數(shù)組的集合氛什。

18莺葫、考慮使用集合高效檢察元素的包含性

Ruby 自帶了兩套不同的類庫,核心庫已經(jīng)被每個程序預(yù)先加載枪眉,另一套就是標準庫捺檬,龐大而且不會被自動加載,在你使用的時候需要正確的引入它們贸铜。

Array 的 include? 方法的性能是最差的堡纬。當數(shù)組中的元素增加時,可以考慮轉(zhuǎn)用哈希來代替蒿秦。

如果你不需要元素按照某一特定順序來排列烤镐,無需隨機訪問任一元素,且需要高效的檢測元素的包含性棍鳖,Set 類就是你需要的炮叶。

插入 Set 的對象必須也被當作哈希的鍵來使用。并且使用之前必須引入它渡处。

19镜悉、了解如何通過 reduce 方法折疊集合

總是要給累加器一個初始值。

給予 reduce 的塊總是要返回一個累加器医瘫。對當前累加器的修改是可行的薄风,要記住從塊中返回颗搂。

20莺禁、考慮使用默認哈希值

考慮使用默認的 Hash 值。

使用 has_key? 方法或它的任意別名來檢查哈希是否包含某個鍵吼具。也就是說,不要以為當訪問一個不存在的鍵是都會返回 nil矩距。

如果某段代碼在接受哈希的非法鍵時會返回 nil拗盒,不要為傳入該方法的哈希使用默認值。

相比使用默認值剩晴,有些時候使用 Hash#fetch 方法能更加安全锣咒。

21、對集合優(yōu)先使用委托而非繼承

對集合優(yōu)先使用委托而非繼承

不要忘記編寫用來復制委托目標的 initialize_copy 方法

編寫 freeze赞弥、taint 以及 untaint 方法時毅整,先傳遞信息給委托目標,之后調(diào)用 super 方法绽左。

四悼嫉、異常

22、使用定制的異常而不是拋出字符串

避免使用字符串作為一場拼窥,它們會被轉(zhuǎn)換成原聲 RuntimeError 對象戏蔑。取而代之,創(chuàng)建一個定制的異常類鲁纠。

定制的異常類應(yīng)該繼承自 StandardError , 且類名應(yīng)以 ’Error‘ 結(jié)尾总棵。

當為一個工程創(chuàng)建了不止一個異常類時,從創(chuàng)建一個繼承自 StandardError 的基類開始改含。其他的異常類應(yīng)該繼承自該定制的基類情龄。

如果你對你的定制異常類編寫了 initialize 方法,務(wù)必確保其調(diào)用了 super 方法捍壤,最好在調(diào)用時以錯誤信息作為參數(shù)骤视。

在 initialize 方法中設(shè)置錯誤信息時,請牢記: 如果在 raise 方法中再度設(shè)置錯誤信息會覆蓋原本在 initialize 中設(shè)置的那一條鹃觉。

23专酗、捕獲可能的最具體的異常

只捕獲那些你知道如何恢復的異常

當捕獲異常時,首先處理最特殊的類型盗扇。在異常的繼承關(guān)系中位置越高的祷肯,越應(yīng)該排在 rescue 鏈的后面。

避免捕獲如 StandardError 這樣的通用異常疗隶。如果你已經(jīng)這么做了躬柬,就應(yīng)該想想你真正想做的是不是能夠用 ensure 語句來實現(xiàn)。

在異常發(fā)生的情況下抽减,從 rescue 語句中拋出的異常將會替換當前異常并離開當前的作用域。


24橄碾、通過塊和 rescue 管理資源

通過 ensure 語句來釋放任何已獲得的資源卵沉。

公國在類方法上使用塊和 ensure 語句講資源管理的邏輯抽離出來颠锉。

確保 ensure 語句中使用的變量已經(jīng)被初始化過了。

25史汗、通過臨近的 end 退出 ensure 語句

避免在 ensure 語句中顯式使用 return 語句琼掠。這意味著方法體內(nèi)存在著某些錯誤的邏輯。

同樣停撞,不要再 ensure 語句中直接使用 throw瓷蛙。你應(yīng)該將 throw 放在方法主體呢。

當執(zhí)行迭代時戈毒,不要再 ensure 語句中執(zhí)行 next 或 break艰猬。仔細想想在迭代內(nèi)到底需不需要 begin 塊。將關(guān)系反轉(zhuǎn)或許更加合理埋市,就是將迭代放在 begin 塊中冠桃。

一般來說,不要再 ensure 語句中改變控制流道宅。在 resucue 語句中完成這樣的工作食听,你的意圖會更加清晰。

26污茵、限制 retry 次數(shù)樱报,改變重試頻率并記錄異常信息。

永遠不要無條件 retry泞当,要把它看做代碼中的隱式循環(huán)迹蛤;在代碼塊的外圍定義重試次數(shù),當超出最大重試次數(shù)時重新拋出異常零蓉。

retry 時記錄具有審計作用的異常信息笤受, 如果重試有問題的代碼解決不了問題,需要追根溯源地去了解異常是如何發(fā)生的敌蜂。

當在 retry 之前使用延時時箩兽,需要考慮增加延時避免加劇問題。

27章喉、throw 比 raise 更適合用來跳出作用域

在復雜的流程控制中汗贫,可以考慮使用 throw 和 raise,這種方法一個額外的好處是可以把一個對象傳遞到上層調(diào)用棧并作為 catch 的最終返回值秸脱。

盡量使用簡單的方法來控制程序結(jié)果落包,可以通過方法調(diào)用和 return 重寫 catch 和 throw。

五摊唇、元編程

28咐蝇、熟悉 Ruby 模塊和類的鉤子方法

所有的鉤子方法都需要被定義為單例方法。

添加巷查、刪除有序、取消定義方法的鉤子方法參數(shù)是方法名抹腿,而不是類名,如果需要旭寿,使用 self 去獲取類的信息警绩。

定義 singleton_method_added 會觸發(fā)自身。

不要覆蓋 extend_object盅称、append_features 和 prepend_features 方法肩祥,使用 extended、included 和 prepended 替代缩膝。

29混狠、在類的鉤子方法中執(zhí)行 super 方法

在類的鉤子方法中執(zhí)行 super。

30逞盆、推薦使用 define_method 而非 method_missing

define_method 優(yōu)于 method_missing檀蹋。

如果必須使用 method_missing,最好也定義 respond_to_missing云芦?方法俯逾。

31、了解不同類型的 eval 間的差異

使用 instance_eval 和 instance_exec 定義的是單例方法舅逸。

class_eval桌肴、 module_eval、 class_exec 和 module_exec 方法只可以被模塊或者方法使用琉历。通過這些定義的方法都是實例方法坠七。

32、猴子補丁

盡管 refinement 已經(jīng)不再是實驗性的功能旗笔,它仍然有可能被修改得更為成熟彪置。

在不同的語法作用域,在使用 refinement 之前必須先激活它蝇恶。

33拳魁、使用別名鏈執(zhí)行被修改的方法

在設(shè)置別名鏈時,需要確保別領(lǐng)是獨一無二的撮弧。

必要的時候要考慮提供一個撤銷別名鏈的方法潘懊。

34、 支持多種 Proc 參數(shù)數(shù)量

與弱 proc 對象不同贿衍,在參數(shù)數(shù)量不匹配時授舟,強 Proc 對象會拋出 ArgumentError 異常。

可以使用 Proc#arity 方法得到 Proc 期望的參數(shù)數(shù)量贸辈,如果返回的是正數(shù)释树,則意味著有多少參數(shù)時必須的。如果返回的是負數(shù),則意味著 Proc 有些參數(shù)是可選的躏哩,可以通過 ’ ~ ‘ 來得到有多少是必須參數(shù)署浩。

35、使用模塊前置時請謹慎思考

prepend 方法在使用時對類體系結(jié)構(gòu)的影響是:它將模塊插入到接收者之前扫尺。這和 include 方法有很大不同:include 則是將模塊插入到接收者和其超類之間。

與 included 和 extended 模塊鉤子一樣炊汤,前置模塊也會觸發(fā) prepended 鉤子正驻。

六、測試

36抢腐、熟悉單元測試工具 MiniTest

測試方法需要以 ' test_ ' 作為前綴姑曙。

簡短的測試更容易理解,也更容易維護迈倍。

使用合適的斷言方法生成更易讀的出錯信息伤靠。

斷言和反演的文檔在 MiniTest::Assertions 中。

37啼染、熟悉 MiniTest 的需求測試

使用 describe 方法創(chuàng)建測試類宴合,使用 it 定義測試用例。

雖然在需求說明測試中迹鹅,斷言仍然可用卦洽,但是更推薦使用諸如到 Object 中的期望方法。

在 MiniTest::Expectations 模塊中斜棚,可以找到關(guān)于期望方法更詳細的文檔阀蒂。

38、使用 Mock 模擬特定對象

使用 Mock 來隔離外部系統(tǒng)的不穩(wěn)定因素弟蚀。

Mock 或者替換沒有被測試過的方法蚤霞,有可能會讓這些被 Mock 的代碼在生產(chǎn)環(huán)境中出現(xiàn)問題。

請確保在測試方法代碼的最后調(diào)用了 MiniTest::Mock#verify 方法义钉。

39昧绣、力爭代碼被有效測試過

使用模糊測試和屬性測試工具,幫助測試代碼的快樂路徑和異常路徑断医。

測試覆蓋率工具會給你一種虛假的安全感滞乙,因為被執(zhí)行過的代碼不代表這行代碼是正確的。

在編寫特性的同事就加上測試鉴嗤,會讓測試容易很多斩启。

在你開始尋找導致 bug 的根本原因之前,先寫一個針對該 bug 測試醉锅。

盡可能多地自動化你的測試兔簇。

40、學會使用 Ruby 文檔

ri 工具用來讀取文檔,rdoc 工具用來生成文檔垄琐。

使用命令行選項 ’ -d doc ‘ 來為 RI 工具指定在 ’ doc ‘ 路徑下查找文檔边酒。

運行 doc 時,后面跟上命令行選項 ’ -f ri ‘ 來為 RI 工具生成文檔狸窘。另外墩朦,用 ’ -f darkfish ‘ 來生成 HTML 格式文檔。

完整的 RDoc 文檔可以在 RDoc::Markup 類中找到翻擒。

41氓涣、認識 IRB 的高級特性

利用下劃線變量( ’ _ ‘ )來獲取上一個表達式的結(jié)果。

irb 命令可以用來創(chuàng)建一個新的會話陋气,并將當前的評估上下文改變成任意對象劳吠。

考慮 Pry gem 作為 IRB 的替代品。

42巩趁、用 Bundler 管理 Gem 依賴

在加載完 Bundler 之后痒玩,使用 Bundler,require 會犧牲一點點靈活性,但是可以加載 Gemfile 仲所有的 gem议慰。

當開發(fā)應(yīng)用時蠢古, 在 Gemfile 中列出所有的 gem,然后把 Gemfile.lock 添加到版本控制系統(tǒng)中褒脯。

當打包 RubyGem便瑟, 在 gem 規(guī)格文件中列出 gem 所有依賴,但不要把 Gemfile.lock 添加到你的版本系統(tǒng)中番川。

43到涂、為 Gem 依賴設(shè)定版本上限

忽略掉版本上限需求相當于你說了你可以支持未來所有的版本。

相當于悲觀版本操作符颁督,更加傾向于使用明確的版本范圍践啄。

當公開發(fā)布一個 gem 時,致命依賴包的版本先知要求沉御,在安全的范圍內(nèi)越寬越好屿讽,上線可以擴展到下一個主要發(fā)布版本之前。

八吠裆、內(nèi)存管理與性能

44伐谈、熟悉 Ruby 的垃圾收集器

垃圾收集器通過維護一個由頁組成的堆來管理內(nèi)存。頁又由槽組成试疙,每個槽存儲一個對象诵棵。

在垃圾收集過程中,可以訪問的對象唄標記祝旷,而沒有標記的對象將被清楚履澳,釋放槽來儲存新對象嘶窄。

新對象被稱為年輕代對象,如果再一個垃圾收集周期后依然存活距贷,會被升級為年老代對象柄冲,年老代對象會在次要標記階段自動被標記為活躍,因此忠蝗,只有在主要標記階段后才能被清除现横。

GC::stat 方法會以散列的形式返回垃圾收集器所有的統(tǒng)計數(shù)據(jù)。

你可以通過設(shè)定環(huán)境變量來調(diào)優(yōu)垃圾收集器阁最,使其更實用于你的應(yīng)用程序长赞。

45、用 Finalizer 構(gòu)建資源安全網(wǎng)

最好使用 ensure 子句來保護有限的資源闽撤。

如果必須要在 ensure 子句外暴露一個資源,那么就給它創(chuàng)建一個 finalizer脯颜。

永遠不要再這樣一個綁定中創(chuàng)建 finalizer Proc哟旗。改綁定引用一個注定會被銷毀的對象。啫會造成垃圾收集器無法釋放改對象栋操。

記住闸餐,finalizer 可能在一個對象銷毀后以及程序終止前的任何時間被調(diào)用。

46矾芙、認識 Ruby 性能分析工具

在修改性能差的代碼之前舍沙,先使用性能分析工具收集性能相關(guān)的信息。

在 ruby-prof gem 和 Ruby 自帶的標準 profile 庫之間剔宪,選擇前者拂铡,因為前者更快而且可以提供多種不同的報告。

如果使用 Ruby 2.1 或者更新的版本葱绒,應(yīng)該考慮使用 stackprof gem 和 memory_profiler gem感帅。

47、避免在循環(huán)中使用對象字面量

將循環(huán)中的不會變化的對象字面量變成常量地淀。

在 Ruby 2.1 及更高的版本中凍結(jié)字符串字面量失球,相當于把它作為常量,可以被整個運行程序共享帮毁。

48实苞、考慮從記憶化大開銷計算

考慮提供一個方法通過將緩存的變量職位 nil 來重置記憶化。

確保時鐘認真考慮過這些由記憶化而跳過副作用所導致的后果烈疚。

如果不希望調(diào)用者修改緩存的變量黔牵,那應(yīng)該考慮讓被記憶化的方法返回凍結(jié)對象。

先用工具分析程序的性能胞得,再考慮是否需要記憶化荧止。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末屹电,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子跃巡,更是在濱河造成了極大的恐慌危号,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,470評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件素邪,死亡現(xiàn)場離奇詭異外莲,居然都是意外死亡,警方通過查閱死者的電腦和手機兔朦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評論 3 392
  • 文/潘曉璐 我一進店門偷线,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人沽甥,你說我怎么就攤上這事声邦。” “怎么了摆舟?”我有些...
    開封第一講書人閱讀 162,577評論 0 353
  • 文/不壞的土叔 我叫張陵亥曹,是天一觀的道長。 經(jīng)常有香客問我恨诱,道長媳瞪,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,176評論 1 292
  • 正文 為了忘掉前任照宝,我火速辦了婚禮蛇受,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘厕鹃。我一直安慰自己兢仰,他們只是感情好,可當我...
    茶點故事閱讀 67,189評論 6 388
  • 文/花漫 我一把揭開白布熊响。 她就那樣靜靜地躺著旨别,像睡著了一般。 火紅的嫁衣襯著肌膚如雪汗茄。 梳的紋絲不亂的頭發(fā)上秸弛,一...
    開封第一講書人閱讀 51,155評論 1 299
  • 那天,我揣著相機與錄音洪碳,去河邊找鬼递览。 笑死,一個胖子當著我的面吹牛瞳腌,可吹牛的內(nèi)容都是我干的绞铃。 我是一名探鬼主播,決...
    沈念sama閱讀 40,041評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼嫂侍,長吁一口氣:“原來是場噩夢啊……” “哼儿捧!你這毒婦竟也來了荚坞?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,903評論 0 274
  • 序言:老撾萬榮一對情侶失蹤菲盾,失蹤者是張志新(化名)和其女友劉穎颓影,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體懒鉴,經(jīng)...
    沈念sama閱讀 45,319評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡诡挂,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,539評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了临谱。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片璃俗。...
    茶點故事閱讀 39,703評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖悉默,靈堂內(nèi)的尸體忽然破棺而出城豁,到底是詐尸還是另有隱情,我是刑警寧澤抄课,帶...
    沈念sama閱讀 35,417評論 5 343
  • 正文 年R本政府宣布钮蛛,位于F島的核電站,受9級特大地震影響剖膳,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜岭辣,卻給世界環(huán)境...
    茶點故事閱讀 41,013評論 3 325
  • 文/蒙蒙 一吱晒、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧沦童,春花似錦仑濒、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,664評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至氏豌,卻和暖如春喉酌,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背泵喘。 一陣腳步聲響...
    開封第一講書人閱讀 32,818評論 1 269
  • 我被黑心中介騙來泰國打工泪电, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人纪铺。 一個月前我還...
    沈念sama閱讀 47,711評論 2 368
  • 正文 我出身青樓相速,卻偏偏與公主長得像,于是被迫代替她去往敵國和親鲜锚。 傳聞我的和親對象是個殘疾皇子突诬,可洞房花燭夜當晚...
    茶點故事閱讀 44,601評論 2 353

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

  • 理解Ruby中的true 所有對象的值都可能為nil 避免使用Ruby中古怪的Perl風格語法 常量是可變的 留意...
    Jayzen閱讀 652評論 0 0
  • 蘋果官方文檔翻譯 《Objective-C語言編程》(Programming with Objective-C) ...
    fever105閱讀 25,668評論 19 130
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法苫拍,類相關(guān)的語法,內(nèi)部類的語法旺隙,繼承相關(guān)的語法绒极,異常的語法,線程的語...
    子非魚_t_閱讀 31,622評論 18 399
  • 姓名:陳芬 公司:寧波慈星股份有限公司 寧波盛和塾《六項精進》224期學員催束,利他二組學員 【日精進打卡第292天】...
    龍芬浩閱讀 166評論 0 0
  • 小哥給了藍牙耳機 雖然沒啥用 新品會很吵 我不是主角 也不能吃喝 還忍受著噪音和火鍋味
    角落蜷縮閱讀 323評論 0 0