1. 程式人生 > >《程式碼簡潔之道》-學習筆記

《程式碼簡潔之道》-學習筆記

命名:

   1、有意義,名副其實:降低程式碼的模糊度,明確說明程式碼的用途;

         2、避免誤導:accountList的型別最好就是List;

         3、避免使用多個不同之處較小的名稱;

         4、避免使用字母l和O,因為它們像數字1和0;

         5、做有意義的區分,只有意義不同時才使用不同的名字;

         6、廢話是無意義的區分,是冗餘;

         7、使用可搜尋的名稱:用巨集定義數字比直接用數字好,避免使用單字母變數和數字常量;

         8、不必使用帶型別的匈牙利標記法;

         9、避免成員變數使用類名字首;

         10、類名和物件名一般都是名詞和名詞短語;

         11、方法名一般是動詞和動詞短語;get,set,is字首;

         12、使用解決方案領域內的名稱;

         13、新增有意義的語境:使用有意義的字首,建立一個類並將變數宣告為成員變數;

         14、命名要精確:不要新增無意義的語境;

函式:

1、短小:函式中的縮排層級不應該多於一層或者兩層;

         2、函式應該做一件事,做好一件事,只做一件事;

         3、每個函式只有一個抽象層級,其他的交給下面的抽象層來做;

         4、判斷函式只做了一件事:不能分函式區段;

         5、閱讀程式碼,自頂向下規則:每個函式後面都跟著下一個抽象層的函式;

         6、如何讓switch只做一件事:通過類工廠建立實際類並返回父類引用,再使用抽象類(父類引用)呼叫實際類重寫的函式;

         7、使用描述性的名字;

         8、函式引數:為了便於測試,應該少於2個;

         9、一元函式的3種形式:

      ①詢問關於引數的問題(判斷),②轉換引數的內容(要有返回值),③引數是個事件(無返回值)

         10、如果函式超過2元:應該將其中的某些引數封裝成類;

         11、函式名字:動/名詞形式;

         12、避免使用輸出引數:如果需要,應該修改所屬物件的狀態;

         13、一個函式要麼做一件事(指令),要麼回答一件事(詢問);

         14、使用異常代替返回錯誤碼:這樣錯誤程式碼可以從主路徑程式碼中分離出來,避免巢狀;

         15、分離try/catch塊:集中在一個函式中;

註釋:

  1、  整潔清楚的程式碼比註釋要好得多;

  2、  真正好的註釋就是考慮不用寫註釋;

  3、  需要註釋的地方:提供法律資訊;解釋方法的意圖;提供警告資訊;

  4、  ToDo註釋,提示尚未完成的工作;

  5、  避免括號後面的註釋,應當減少巢狀,寫成方法;

  6、  刪掉被註釋掉的程式碼;

  7、  註釋就是一種失敗;

格式:

  1、  垂直上的間隔:不同的邏輯之間用空格間隔;

  2、  垂直上的靠近:關係密切的邏輯要靠近才會更加清晰;

  3、  變數在離使用最近的地方宣告;

  4、  相關函式:放在一起,呼叫者放在被呼叫者的上面;

  5、  概念相關:命名模式相同,應該放在一起;

  6、  水平方向:以不拖動滾動條為準則;

  7、  =,+=等前後的空格可以起強調的作用;

  8、  縮排

  9、  團隊規則

物件和資料結構(過程式程式碼):

  隱藏實現關乎抽象,並不是簡單的新增取值器和賦值器;

  1、  物件和資料結構的反對稱性:

    過程式程式碼便於在不改變既有程式碼的同時,新增新的函式(過程)

    面向物件便於在不改變既有函式的情況下,新增新的類(物件),但是如果抽象類新增新的函式,就需要修改抽象類的所有子類;

  2、  資料結構應該只有公共變數;物件應該只有私有變數和公有函式;

  3、  物件暴露行為,隱藏資料;便於新增新物件型別而無需修改既有行為,同時也難以在既有的物件中新增新行為。

    資料結構暴露資料,沒有明顯的行為;便於向既有資料結構新增新行為,同時也難以向既有函式新增新資料結構。

      4、The law of demoter : 模組不應瞭解它所操縱物件的內部情況。 火車失事,混雜,隱藏結構。

錯誤的處理:

  1、  不要返回null值:這樣的話呼叫者就要處理null,增加工作量;

    解決:丟擲異常或者返回特例物件;

  2、  不要傳遞null值:

  3、  異常的處理:丟擲異常或者返回特例物件;如果是呼叫第三方api可能產生異常,可以新建一個方法或異常類將第三方api打包;

  4、  避免使用可控異常(checked exception):因為處理它們需要修改函式頭,違反了開放-閉合原則;應該使用不可控異常(runtime exception),

保持邊界整潔:(電子書缺失)

  1、  學習性測試:在專案中引入第三方api的新版本,測試專案是否正常工作;

  2、  處理邊界問題方法:用新類包裝第三方api;用adapter模式將我們的介面轉換為第三方提供的介面;

單元測試:

     1、測試驅動開發,整潔的測試有助於進行程式碼的改動;

  2、整潔測試的標準:可讀性;

  3、雙重標準:由於執行環境的差異,測試程式碼和生產程式碼可以有不同的標準,如效率、記憶體等;

  4、單個測試的斷言數量應該最小化,只測試一個概念;

  5、F.I.R.S.T規則:

    F fast:測試需要頻繁執行,因此要能快速執行;

    I Independent:測試應該相互獨立;

    R Repeatable:測試應當能在任何環境中重複;

    S Self-validating:自足驗證,測試應該能看到成功與否的結果;

    T timely:測試應該及時編寫,應該恰好在生產程式碼之前編寫;

類:

  1、類的組織:自頂向下原則,變數列表(公共先於私有,靜態先於實體),方法列表(工具方法緊跟在所屬方法之後);

  2、類應該短小:類名越明確,類的職責就越清晰;

    (1)每個類單一權責,只有一個修改它的原因,並與少量的其他類協同完成工作;

    (2)內聚:類中含有最少的變數,且每個方法都使用每個變數,此時內聚度最高,類應該是內聚高的;

  3、隔離修改:具體類實現細節,抽象類只呈現概念,利用介面和抽象類可以隔離因為細節的改變而帶來的改變類的風險;

系統:

  1、構造與應用程式碼應該隔離開:就好像建設大樓時,構建大樓的吊車、剷車之類的東西,在大樓投入使用時已經完全不存在一樣;軟體系統應該講啟動過程和啟動過程之後的執行時邏輯分開,在啟動過程中建立應用物件,也會存在相互的依賴。

    public Service getService(){

      return new MyServiceIml(...);

    }

    這種延遲化賦值的好處是:在使用物件之前不用關心這種架空構造;壞處是:必須實現這個構造方法,不然無法編譯,即使這個物件在執行時永遠不會被使用。

  解決方法:

  (1)分解main,將系統中的全部構造過程搬遷到main或者main模組中:main函式建立物件,再將物件傳遞給應用,應用直接使用;

  (2)工廠,可以讓應用控制實體建立的時機;

  (3)依賴注入,控制反轉IoC是依賴管理的手段,它將應用需要的依賴物件的建立權責從物件中拿出來,放在一個專注於此事的物件中,並通過依賴注入(賦值器)將依賴物件傳遞給應用;

  2、擴容

  AOP,面向方面變成。Java中三種方面和類似方面的機制:代理,純AOP框架,AspectJ

    (1)Java代理:Proxy.newInstance(被代理介面,InvocationHandler h)方法執行後,被代理類的所有方法都會被加上Handler的處理邏輯,這是簡單的AOP,但是太複雜;

    (2)純AOP框架:Spring AOP(需進一步瞭解)

    (3)AspectJ語言

  最佳的系統架構由模組化的關注面領域組成,每個關注面均用純Java物件實現。不同的領域之間用最不具有侵害性的方面或類方面工具整合起來。這種架構能測試驅動,就像程式碼一樣。

2011-6-24 讀到173