如何實施代碼重構(gòu)?

image

閱讀《重構(gòu)》的筆記獻上。

重構(gòu)的定義

重構(gòu)是在不改變軟件可觀察行為的前提下改善其內(nèi)部結(jié)構(gòu)。

重構(gòu)的節(jié)奏

以微小的步伐修改程序。如果你犯下錯誤,很容易便可發(fā)現(xiàn)它。

  • 一個方法里面,不應該有很多的代碼,我們可以通過分解后重組。
  • 好的代碼應該清楚的表達出自己的功能,變量名稱是代碼清晰的關(guān)鍵。
  • 盡量減少臨時變量,大量參數(shù)被傳來傳去,很容易跟丟,可讀性差。
  • 提煉出邏輯代碼,以便功能復用。

重構(gòu)(名詞):對軟件內(nèi)部結(jié)構(gòu)的一種調(diào)整,目的是在不改變軟件可觀察行為的前提下,提高其可理解性,降低其修改成本。
重構(gòu)(動詞):使用一系列重構(gòu)首發(fā),在不改變軟件可觀察行為的前提下,調(diào)整其結(jié)構(gòu)。

為何重構(gòu)?

  • 重構(gòu)改進軟件設計
  • 重構(gòu)是軟件更容易理解
  • 重構(gòu)幫助找到bug
  • 重構(gòu)提高編程速度

何時重構(gòu)?

幾乎任何情況下我都反對專門拔出時間進行重構(gòu)。在我看來重構(gòu)本來就不是一件應該特別撥出時間做的事情,重構(gòu)應該隨時隨地的進行。你不應該為重構(gòu)而重構(gòu),你之所以重構(gòu),是因為你想做別的什么事,而重構(gòu)可以幫助你把那些事做好。

三次法則

第一次做某件事只管去做,第二次做類似的事情會有反感,第三次再做類似的事,你就應該重構(gòu)。
事不過三,三則重構(gòu)。

  • 添加功能時重構(gòu)
  • 修補錯誤時重構(gòu)
  • 復審代碼時重構(gòu)

為什么重構(gòu)有用?

難以修改的程序

  • 難以閱讀的
  • 邏輯重復的
  • 添加新行為需要修改已有代碼的
  • 帶復雜條件邏輯的

好的程序

  • 容易閱讀
  • 所有邏輯都只是在唯一地點指定
  • 新的改動不會危及現(xiàn)有行為
  • 盡可能簡單表達條件邏輯

重構(gòu)是這樣一個過程:它在一個目前可運行的程序上進行,在不改變程序行為的前提下使其具備上述美好性質(zhì),使我們能夠繼續(xù)保持高速開發(fā),從而新增程序的價值。

何時不該重構(gòu)?

  • 無法穩(wěn)定運行直接重寫不用重構(gòu)
  • 項目以及接近最后期限,不應該重構(gòu),雖然重構(gòu)能夠提高生產(chǎn)力,但是你沒有足夠的時間,通常標示你其實早該進行重構(gòu)了。

代碼的壞味道

  • Duplicated Code 重復代碼
  • Long Method 過長函數(shù)
  • Large Class 過大的類
  • Long Parameter List 過長參數(shù)列
  • Divergent Change 發(fā)散式變化
  • Shotgun Surgery 散彈式修改
  • Feature Envy 依戀情結(jié) (Strategy\Visitor)
  • Data Clumps 數(shù)據(jù)泥團
  • Primitive Obsession 基本類型偏執(zhí)
  • Switch Statements switch驚悚現(xiàn)身 (使用多態(tài)性替換)
  • Parallel Inheritance Hierarchies 平行繼承體系
  • Lazy Class 冗贅類
  • Speculative Generality 夸夸其談未來性
  • Temporary Field 令人迷惑的暫時字段
  • Message Chains 過渡耦合的消息鏈
  • Middle Man 中間人
  • Inappropriate Intimacy 狎昵關(guān)系
  • Alternative Classes with Different Interfaces 異曲同工的類
  • Incomplete Library Class 不完美的庫類
  • Data Class 純稚的數(shù)據(jù)類
  • Refused Bequest 被拒絕的遺贈
  • Comments 過多的注釋

當你感覺需要撰寫注釋時,請先嘗試重構(gòu),試著讓所有注釋變得多余。

構(gòu)建測試體系

  • 確保所有測試都完全自動化,讓他們檢查自己的測試結(jié)果。
  • 一套測試就是一個強大的bug偵察器,能夠大大縮減查找bug所需要的時間。
  • 頻繁地運行測試。每次編譯請把測試也考慮進去—— 每天至少執(zhí)行每個測試一次。
  • 每當你收到bug報告,請先寫一個單元測試來暴露這個bug。
  • 編寫未完善的測試并執(zhí)行,好過對完美測試的無盡等待。
  • 考慮可能出錯的邊界條件,把測試火力集中在那兒。
  • 當事情被認為應該會出錯時,別忘了檢查是否拋出了預期的異常。
  • 不要因為測試無法捕捉所有bug就不寫測試,因為測試可以捕捉到大多數(shù)的bug。

重構(gòu)列表

重構(gòu)記錄格式

  • 名稱
  • 概要
    • 描述解決的問題
    • 描述要做的事情
    • 速寫圖展示重構(gòu)前和重構(gòu)后的示例
  • 動機
  • 做法
  • 范例

重構(gòu)的基本技巧—小步前進、頻繁測試

模式和重構(gòu)之間有著一種與生俱來的關(guān)系。模式是你希望到達的目標,重構(gòu)則是到達之路。

重新組織函數(shù)

  • Extract Method 提煉函數(shù)
    • 你有一段代碼可以被組織在一起并獨立出來。將這段代碼放進一個獨立函數(shù)中,并讓函數(shù)名稱解釋該函數(shù)的用途。
  • Inline Method 內(nèi)聯(lián)函數(shù)
    • 一個函數(shù),其本體應該與其名稱同樣清楚易懂。在函數(shù)調(diào)用點插入函數(shù)本體,然后移除該函數(shù)。
  • Inline Temp 內(nèi)聯(lián)臨時變量
    • 你有一個臨時變量,只被一個簡單表達式賦值一次,而它妨礙了其他重構(gòu)方法。將所有對該變量的引用動作,替換為對它賦值的那個表達式本身。
  • Replace Temp with Query 已查詢?nèi)〈R時變量
    • 你的程序以一個臨時變量(temp)保存某一個表達式的運算結(jié)果。將這個表達式提煉到一個獨立函數(shù)(query查詢式)中。將這個臨時變量的所有被引用點替換為對新函數(shù)的調(diào)用。新函數(shù)可被其他函數(shù)使用。
  • Introduce Explaining Variable 引入解釋性變量
    • 你有一個復雜的表達式。將該復雜表達式(或其中一部分)的結(jié)果放進一個臨時變量,以此變量名稱來解釋表達式用途。
  • Split Temporary Variable 分解臨時變量
    • 你的程序有某個臨時變量被賦值超過一次,它既不是循環(huán)變量,也不是一個集用臨時變量(collecting temporary variable)。針對每次賦值,創(chuàng)造一個獨立。對應的臨時變量。
  • Remove Assignments to Parameters 移除對參數(shù)的賦值
    • 你的代碼對一個參數(shù)進行賦值動作。以一個臨時變量取代該參數(shù)的位置。
  • Replace Method with Method Object 以函數(shù)對象取代函數(shù)
    • 你有一個大型函數(shù),其中對局部變量的使用,使你無法采用Extract Method。將這個函數(shù)放在一個獨立的對象中,如此一來局部變量就變成了對象內(nèi)的值域,然后你可以在同一個對象中將這個大型函數(shù)分解為數(shù)個小型函數(shù)。
  • Substitute Algorithm 替換算法
    • 你想要把某個算法替換為另一個更清晰的算法。將函數(shù)本體替換為另一個算法。

在對象之間搬移特性

  • Move Method 搬移函數(shù)
    • 你的程序中,有個函數(shù)與其所駐class之外的另一個class進行更多交流:調(diào)用后者,或被后者調(diào)用。在函數(shù)最常引用的class中建立一個有著類似行為的新函數(shù)。將舊函數(shù)變成一個單純的委托函數(shù),或是將舊函數(shù)完全移除。
  • Extract Class 提煉類
    • 你的程序中,某個field(值域)被所駐class之外的另一個class更多地用到。在target class 建立一個new field ,修改source field 的所有用戶,令它們改用new field.
  • Inline Class 將類內(nèi)斂化
    • 某個class做了應該由兩個classes做的事情。建立一個新的class,將相關(guān)的值域和函數(shù)從就class搬移到新class。
  • Hide Delegate 隱藏委托類
    • 客戶直接調(diào)用其server object(服務對象)的delegate class。在sever端(某個class)建立客戶所需要的所有函數(shù),用以隱藏委托關(guān)系。
  • Remove Middle Man 移除中間人
    • 某個class做了過多的簡單委托(simple delegation).讓客戶直接調(diào)用delegate(受托類)。
  • Introduce Foreign Method 引入外加函數(shù)
    • 你所使用的server class 需要一個額外函數(shù),但你無法修改這個class。在client class 中建立一個函數(shù),并以一個server class實體作為第一引數(shù)(argument)。
  • Introduce Local Extension 引入本地擴展
    • 你所使用的server class 需要一些額外函數(shù),但你無法修改這個class。建立一個新class,使它包含這些額外函數(shù)。讓這個擴展品成為source class的subclass(子類)或(wrapper)外覆類。

重新組織數(shù)據(jù)

  • Self Encapsulate Field 自封裝字段

    • 你直接訪問一個值域(field),但與值域直接的耦合關(guān)系變得逐漸變得笨拙。為這個值域建立取值/設值函數(shù),并且只有這些函數(shù)來訪問值域。
  • Replace Data Value with Object 以對象取代數(shù)據(jù)值

    • 你有一筆數(shù)據(jù)項(data item),需要額外的數(shù)據(jù)和行為。將這筆數(shù)據(jù)項變成一個對象。
  • Change Value to Reference 將值對象改成引用對象

    • 你有一個class,衍生出許多相等視圖(equal instance),你希望將它們替換為單元對象。將這個 value object(實值對象)變成一個reference object(引用對象)。
  • Change Reference to Value 將引用對象改成值對象 (equals hashCode)

    • 你有一個reference object(引用對象),很小且不可變,而且不易管理。將他變成一個value object(實值對象)。
  • Replace Array with Object 以對象取代數(shù)組

    • 你有一個數(shù)組(array),其中的元素個各自代表不同的東西,以對象替換數(shù)組。對于數(shù)組中的每個元素,以一個值域表示之。
  • Duplicate Observed Data 復制“被監(jiān)聽數(shù)據(jù)”

    • 你有一些domain data 置身GUI控件中,而domain method 需要訪問之。即那個該筆數(shù)據(jù)拷貝到以到domain object。建立一個observer模式,用以對domain object和GUI object 內(nèi)的重復數(shù)據(jù)進行同步控制(sync).
  • Change Unidirectional Association to Bidirectional 將單向關(guān)聯(lián)改為雙向關(guān)聯(lián)

    • 兩個classes都需要使用對方特性,但其間只有一條單向連接。添加一個反向指針,并使修改函數(shù)能夠同時更新兩條連接。
  • Change Bidirectional Association to Unidirectional 將雙向關(guān)聯(lián)改成單向關(guān)聯(lián)

    • 兩個classes之間有雙向關(guān)聯(lián),但其中一個class如今不再需要另一個class的特性。去除不必要的關(guān)聯(lián)(association)。
  • Replace Magic Number with Symbolic Constant 以字面常量取代魔法數(shù)

    • 你有一個字面值,帶有特別的含義。創(chuàng)造一個常量,根據(jù)其意義為它命名,并將上述的字面數(shù)值替換為這個常量。
  • Encapsulate Field 封裝字段

    • 你的class存在一個public值域。將它聲明為private,并提供相應的訪問函數(shù)。
  • Encapsulate Collection 封裝集合

    • 有個函數(shù)返回一個群集(collection)。放這個函數(shù)返回該群集的一個只讀映件,并在這個class中提供添加移除群集元素的函數(shù)。
  • Replace Record with Data Class 以數(shù)據(jù)類取代記錄

    • 你需要面對傳統(tǒng)編程環(huán)境中的record structure(記錄結(jié)構(gòu))。為該record(記錄)創(chuàng)建一個啞數(shù)據(jù)對象(dumb data object)。
  • Replace Type Code with Class 以類取代類型碼

    • class之中有一個數(shù)值別碼,但他并不影響class的行為。以一個新的class替換數(shù)值型別碼。
  • Replace Type Code with Subclasses 以子類取代類型碼 (多態(tài)機制)

    • 你有一個不可變的type code,它會影響class的行為。以一個subclass取代這個type code。
  • Replace Type Code with State/Strategy 以State/Strategy取代類型碼

    • 你有一個type code,它會影響class 的行為,但你無法使用subclassing。以state object取代type code.
  • Replace Subclass with Fields 以字段取代子類

    • 你的各個subclasses的唯一差別只在返回常量數(shù)據(jù)的函數(shù)身上。修改這些函數(shù),使他們返回superclass中的某個(新增)值域,然后銷毀sublcasses。

簡化條件表達式

  • Decompose Conditional 分解條件表達式
    • 你有一個復雜的條件語句。從if、then、else三個段落中分別提出獨立函數(shù)。
  • Consolidate Conditional Expression 合并條件表達式
    • 你有一系列條件測試,都得到相同結(jié)果。將這些測試合并為一個條件式,并將這個條件式提煉成為一個獨立函數(shù)。
  • Consolidate Duplicate Conditional Fragments 合并重復的條件片段
    • 在條件式的每一個分支上著相同的代碼。將這個段重復代碼搬移到條件式之外。
  • Remove Control Flag 移除控制標記 (break/continue/return)
    • 在一系列布爾表達式中,某個變量帶有控制標記的作用,以break語句或return語句取代控制標記。
  • Replace Nested Conditional with Guard Clauses 以衛(wèi)語句取代嵌套條件表達式 (單獨判斷被稱為“衛(wèi)語句”)
    • 函數(shù)中的條件邏輯使人難以看清正常的執(zhí)行路徑。使用衛(wèi)語句表現(xiàn)所有特殊的情況。衛(wèi)語句就是把復雜的條件表達式拆分成多個條件表達式,比如一個很復雜的表達式,嵌套了好幾層的if - then-else語句,轉(zhuǎn)換為多個if語句,實現(xiàn)它的邏輯,這多條的if語句就是衛(wèi)語句
  • Replace Conditional with Polymorphism 以多態(tài)取代條件表達式
    • 你手上有個條件式,它根據(jù)對象型別的不同而選擇不同的行為。將這個條件式的每個分支放進一個subclass內(nèi)的覆寫函數(shù)中,然后將原始函數(shù)聲明為抽象函數(shù)。
  • Introduce Null Object 引入Null對象
    • 你需要再三檢查某個是否為null value。將null value(無效值)替換為null object(無效物)
  • Introduce Assertion 引入斷言
    • 某一段代碼需要對程序狀態(tài)做出某種假設。以assertion(斷言)明確表現(xiàn)這種假設。

簡化函數(shù)調(diào)用

  • Rename Method 函數(shù)改名
    • 函數(shù)的名稱未能揭示函數(shù)的用途,修改函數(shù)名稱。
  • Add Parameter 添加參數(shù)
    • 某個函數(shù)需要從調(diào)用端得到更多信息。為此函數(shù)添加一個對象參數(shù),讓該對象帶進函數(shù)所需信息。
  • Remove Parameter 移除參數(shù)
    • 函數(shù)本體不再需要某個參數(shù),將該參數(shù)去除。
  • Separate Query from Modifier 講查詢函數(shù)和修改函數(shù)分離
    • 某個函數(shù)即返回函數(shù)對象狀態(tài)值,又修改對象狀態(tài)。將來兩個不同的函數(shù),其中一個負責查詢,另一個負責修改。
  • Parameterize Method 令函數(shù)攜帶參數(shù)
    • 若干函數(shù)做了類似的工作,但在函數(shù)本體中卻包含了不同的值。建立單一函數(shù),以參數(shù)表達那些不同的值。
  • Replace Parameter with Explicit Methods 以明確函數(shù)取代參數(shù)
    • 你有一個函數(shù),其內(nèi)完全取決于參數(shù)值而采取不同反應。針對該參數(shù)的每一個可能值,建立一個獨立函數(shù)。
  • Preserve Whole Object 保持對象完整
    • 你從某個對象中取出某個值,將它們作為某一次函數(shù)調(diào)用的參數(shù)。該引用(傳遞)整個對象。
  • Replace Parameter with Methods 以函數(shù)取代參數(shù)
    • 對象調(diào)用某個函數(shù),并將所得結(jié)果作為參數(shù),傳遞給另一個函數(shù)。而接受該參數(shù)的函數(shù)也可以調(diào)用前一個函數(shù)。讓參數(shù)接受者去除該項參數(shù),并直接調(diào)用前一個函數(shù)。
  • Introduce Parameter Object 引入?yún)?shù)對象
    • 某個參數(shù)總是很自然地同時出現(xiàn)。以一個對象取代這些參數(shù)。
  • Remove Setting Method 移除設置函數(shù)
    • 你的class中的某個值域,應該在對象初創(chuàng)時被設值,然后就不再改變。去掉該值域的所有設置函數(shù)。
  • Hide Method 隱藏函數(shù)
    • 有一個函數(shù),從來沒有被其他任何class用到。將這個函數(shù)改為private。
  • Replace Constructor with Factory Method 以工廠函數(shù)取代構(gòu)造函數(shù)
    • 你希望在創(chuàng)建對象時不僅僅是對它做簡單的構(gòu)建工作,將construcotr(構(gòu)造函數(shù))替換為factory method(工廠函數(shù))
  • Encapsulate Downcast 封裝向下轉(zhuǎn)型
    • 某個函數(shù)返回的對象,需要由函數(shù)調(diào)用者執(zhí)行向下轉(zhuǎn)型動作。將向下轉(zhuǎn)型動作移到函數(shù)中。
  • Replace Error Code with Exception 以異常取代錯誤碼
    • 某個函數(shù)返回一個特定的代碼,用以表示某種錯誤情況。改用異常。
  • Replace Exception with Test 以測試取代異常
    • 面對一個調(diào)用者可預先加以檢查的條件,你拋出一個異常。修改調(diào)用者,使它在調(diào)用函數(shù)之前先做檢查。

處理概括關(guān)系

  • Pull Up Field 字段上移
    • 兩個subclass擁有相同的值域。將此一值域移至superclass。
  • Pull Up Method 函數(shù)上移
    • 有些函數(shù),在各個subclass中產(chǎn)生完全相同的效果。將該函數(shù)移至superclass。
  • Pull Up Constructor Body 構(gòu)造函數(shù)本體上移
    • 你的各個subclass中擁有一些構(gòu)造函數(shù),它們的本體幾乎完全一致。在superclass中新建一個構(gòu)造函數(shù),并在subclass構(gòu)造函數(shù)中調(diào)用它。
  • Push Down Method 函數(shù)下移
    • superclass中的某個函數(shù)只與部分(而非全部)subclass有關(guān)。將這個函數(shù)移到相關(guān)的那些subclasses去。
  • Push Down Field 字段下移
    • superclass中的某個值域只被部分subclass用到。將這個值域到需要它的那些subclasses去。
  • Extract Subclass 提煉子類
    • class中某些特性只被某些而非全部實體用到。新建一個subclass,將上面所說的那一部分特性移到subclass中。
  • Extract Superclass 提煉超類
    • 兩個classes有相似特性。為這連個classes建立一個superclass.將相同特性移至superclass.
  • Extract Interface 提煉接口
    • 若干客戶使用class接口中的同一子集。或者,兩個Classes的接口有部分相同。將相同的子集提煉到一個獨立接口中。
  • Collapse Hierarchy 折疊繼承體系
    • superclass和subclass之間無太大區(qū)別。將它們和為一體。
  • Form Template Method 塑造模板函數(shù)
    • 有一些subclasses,其中相應的某些函數(shù)以相同順序執(zhí)行類似的措施,但各措施實際上有所不同。將各個措施分別放進獨立函數(shù)中,并保持它們都有相同的簽名式,于是原函數(shù)也就變得相同了。然后將原函數(shù)上移至superclass。
  • Replace Inheritance with Delegation 以委托取代繼承
    • 某個subclass只使用superclass接口中的一部分,或是更本不需要繼承而來的數(shù)據(jù)。在subclass中新建一個值域用以保存superclass;調(diào)整subclass函數(shù),令它改而委托superclass;然后去掉兩者之間的繼承關(guān)系。
  • Replace Delegation with Inheritance 以繼承取代委托
    • 你的兩個classes之間使用了委托關(guān)系,并經(jīng)常為整個接口編寫許多極其簡單的請托函數(shù)。讓請托Class繼承受托class。

大型重構(gòu)

  • Tease Apart Inheritance 梳理并分解繼承體系
    • 某個繼承體系同時承擔兩項責任。建立兩個繼承體系,并通過委托關(guān)系讓其中一個可以調(diào)用另一個。
  • Convert Procedural Design to Objects 將過程化設計轉(zhuǎn)化為對象設計
    • 你手上有一些代碼,以傳統(tǒng)的過程化風格寫就。將數(shù)據(jù)記錄變成對象,將行為分開,并將行為移入相關(guān)對象中。
  • Separate Domain from Presentation 將領域和表述/顯示分離
    • 某些GUI classes之中包含了domain login(領域邏輯)。將domain loginc(領域邏輯)分離出來,為它們建立獨立的domain classes.
  • Extract Hierarchy 提煉繼承體系
    • 你有某個class做了太多工作,其中一個部分工作以大量條件式完成的。建立繼承體系,以一個subclass表示一種特殊情況。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,646評論 6 533
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,595評論 3 418
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,560評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,035評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,814評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,224評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,301評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,444評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,988評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,804評論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,998評論 1 370
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,544評論 5 360
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,237評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,665評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,927評論 1 287
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,706評論 3 393
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,993評論 2 374

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

  • 一個項目運行久了,經(jīng)過業(yè)務需求的迭代,開發(fā)人員的變更,總會產(chǎn)生一些質(zhì)量不高的代碼,要么來源于對某些業(yè)務理解的不太深...
    高廣超閱讀 1,394評論 0 23
  • 何時重構(gòu)、何時停止重構(gòu)學會判斷一個類內(nèi)有多少實例變量算是太大、一個函數(shù)內(nèi)有多少行代碼算太長 下面是對各種壞味道的簡...
    每天學點編程閱讀 1,521評論 0 4
  • 轉(zhuǎn)至元數(shù)據(jù)結(jié)尾創(chuàng)建: 董瀟偉,最新修改于: 十二月 23, 2016 轉(zhuǎn)至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 1,751評論 0 9
  • 人生總是有太多時候發(fā)生我們意想不到的事情,讓我們來不及接受,來不及消化,但是我們依然要去面對;生活中總是...
    hiliary閱讀 220評論 0 0
  • 老公覺得自己的名字很普通,想啟個有文化內(nèi)涵的名字,今天他突然興高采烈的告訴我,他終于想出一個高端大氣上檔次的名字,...
    張娜0922閱讀 274評論 0 0