網頁

搜尋此網誌

2013年3月27日 星期三

Refactoring: Improving the Design of Existing Code 重構:改善既有程式的設計

什麼是重構(Refactoring)?所謂重構是這樣的一個過程:「在不改變程式碼外在行為的前提下,對程式碼做出修改,以改進程式的內部結構」。重構是一種有紀律的、經過訓練的、有條不紊的程式整理方法,可以將整理過程中不小心引入錯誤的機率降到最低。本質上說,重構就是「在程式碼寫好之後改進他的設計」。p. xvi

這是一本介紹「重構」技術的書籍,如果你想認識並瞭解這門技術,「重構:改善既有程式的設計」絕對是聖經本。一開始作者以案例方式帶領讀者進入重構的過程,第一章藉由案例認識重構的方式與準則。接著第二章說明重構的基礎知識,包括何謂重構、為何需要重構、何時應該重構...等基本問題,再來第四章用「程式的壞味道」來判斷何時應該開始重構、何時應該停止重構,第四章則是說明重要的觀念:重構的前提必須是擁有一個可靠的測試環境。大致上來說,如果你閱讀完前四章,那你對於重構技術已經有完整的認識了。


Martin Fowler等著,侯捷、熊節合譯,重構:改善既有程式的設計,台北:台灣培生教育出版:碁峰資訊發行,2008。
譯自:Refactoring: Improving the Design of Existing Code,作者群:Martin Fowler, Kent Beck, John Brant, William Opdyke, Don Roberts。

接著第5章至第12章則是作者在工作中整理出來的「重構名錄(catalog of refactorings)」,這些重構名錄是這本書的核心,利用這些重構名錄所記載的重構方法,我們可以很方便的改善既有程式的設計。這些重構方法如下(也就是書的目錄一部份),這些方法可分成7大類總共72個:
  • 重新組織你的函式 (Composing Methods)
    1. Extract Method (提煉函式)
    2. Inline Method (將函式內聯化)
    3. Inline Temp (將暫時變數內聯化)
    4. Replace Temp with Query (以查詢取代變數)
    5. Introduce Explaining Variable (引入解釋性變數)
    6. Split Temporary Variable (剖解暫時變數)
    7. Remove Assignments to Parameters (移除對參數的賦值動作)
    8. Replace Method with Method Object (以函式物件取代函式)
    9. Substitute Algorithm (替換你的演算法)
  • 在物件之間移動特性 (Moving Features Between Objects)
    1. Move Method (搬移函式)
    2. Move Field (搬移欄位)
    3. Extract Class (提煉類別)
    4. Inline Class (將類別內聯化)
    5. Hide Delegate (隱藏「委託關係」)
    6. Remove Middle Man (移除中間人)
    7. Introduce Foreign Method (引入外加函式)
    8. Introduce Local Extension (引入區域性擴展)
  • 重新組織你的資料 (Organizing Data)
    1. Self Encapsulate Field (自我封裝欄位)
    2. Replace Data Value with Object (以物件取代資料值)
    3. Change Value to Reference (將實質物件改為引用物件)
    4. Change Reference to Value (將引用物件改為實質物件)
    5. Replace Array with Object (以物件取代陣列)
    6. Duplicate Observed Data (複製「被監視資料」)
    7. Change Unidirectional Association to Bidirectional (將單向關聯改為雙向)
    8. Change Bidirectional Association to Unidirectional (將雙向關聯改為單向)
    9. Replace Magic Number with Symbolic Constant (以符號常數/字面常數 取代魔術數字)
    10. Encapsulate Field (封裝欄位)
    11. Encapsulate Collection (封裝群集)
    12. Replace Record with Data Class (以資料類別取代記錄)
    13. Replace Type Code with Class (以類別取代型別代碼)
    14. Replace Type Code with Subclasses (以子類別取代型別代碼)
    15. Replace Type Code with State/Strategy (以 State/Strategy 取代型別代碼)
    16. Replace Subclass with Fields (以欄位取代子類別)
  • 簡化條件句 (Simplifying Conditional Expressions)
    1. Decompose Conditional (分解條件式)
    2. Consolidate Conditional Expression (合併條件式)
    3. Consolidate Duplicate Conditional Fragments (合併重複的條件片段)
    4. Remove Control Flag (移除控制旗標)
    5. Replace Nested Conditional with Guard Clauses (以衛述句取代巢狀條件式)
    6. Replace Conditional with Polymorphism. (以多型取代條件式)
    7. Introduce Null Object (引入Null物件)
    8. Introduce Assertion (引入斷言)
  • 簡化函式呼叫 (Making Method Calls Simpler)
    1. Rename Method (重新命名函式)
    2. Add Parameter (添加參數)
    3. Remove Parameter (移除參數)
    4. Separate Query from Modifier (以查詢函式和修改函式分離)
    5. Parameterize Method (令函式攜帶參數)
    6. Replace Parameter with Explicit Methods (以明確函式取代參數)
    7. Preserve Whole Object (保持物件完整)
    8. Replace Parameter with Method (以函式取代參數)
    9. Introduce Parameter Object (引入參數物件)
    10. Remove Setting Method (移除設值函式)
    11. Hide Method (隱藏某個函式)
    12. Replace Constructor with Factory Method (以工廠函式取代建構式)
    13. Encapsulate Downcast (封裝「向下轉型」動作)
    14. Replace Error Code with Exception (以異常取代錯誤碼)
    15. Replace Exception with Test (以測試取代異常)
  • 處理繼承關係 (Dealing with Generalization)
    1. Pull Up Field (欄位上移)
    2. Pull Up Method (函式上移)
    3. Pull Up Constructor Body (建構式本體上移)
    4. Push Down Method (函式下移)
    5. Push Down Field (欄位下移)
    6. Extract Subclass (提煉子類別)
    7. Extract Superclass (提煉超類別)
    8. Extract Interface (提煉介面)
    9. Collapse Hierarchy (摺疊繼承體系)
    10. Form Template Method (塑造模板函式)
    11. Replace Inheritance with Delegation (以委託取代繼承)
    12. Replace Delegation with Inheritance (以繼承取代委託)
  • 大型重構 (Big Refactorings)
    1. Tease Apart Inheritance (梳理並分解繼承體系)
    2. Convert Procedural Design to Objects (將程序式設計轉化為物件設計)
    3. Separate Domain from Presentation (將領域和 表述/顯示 分離)
    4. Extract Hierarchy (提煉繼承體系)
註:侯捷先生在他的網站上有公布書中第一章至第六章的內容,有興趣的讀者可以先上網試讀!網站是http://jjhou.boolan.com/jjtbooks-refactoring.htm
###

2013年3月13日 星期三

徹底研究Python:談關鍵字(keywords)

徹底研究Python:談關鍵字(keywords)。

討論一下Python程式語言的關鍵字,所謂關鍵字指的是程式語言本身保留的識別名稱(Identifiers ),我們不能使用這些關鍵字作為程式的識別名稱,例如變數名稱、函式名稱或類別名稱等等。

Pythony總共有31個關鍵字,可以匯入keyword模組找出有哪些關鍵字,存取keyword.kwlist就會列出關鍵字的串列資料。Python的關鍵字如下:
  1. and
  2. as
  3. assert
  4. break
  5. class
  6. continue
  7. def
  8. del
  9. elif
  10. else
  11. except
  12. exec
  13. finally
  14. for
  15. from
  16. global
  17. if
  18. import
  19. in
  20. is
  21. lambda
  22. not
  23. or
  24. pass
  25. print
  26. raise
  27. return
  28. try
  29. while
  30. with
  31. yield
注意到print在Python 2是關鍵字,然而在Python 3的版本則是內建函式。

###

2013年3月8日 星期五

徹底研究Python:談型別(type)

徹底研究Python:談型別(type)。

Python內建型別總共28個,這些型別本身也是一種物件(在Python程式語言裡面所有的都是物件),稱為型別物件(type objects),使用type()函式可以知道物件的型別是什麼型別物件。

在Python的標準程式庫中,types模組定義部分型別的型別名稱,我們可以使用這些型別名稱取得型別物件,像是types.IntType就是取的int型別物件,注意到並不是所有的型別物件都有定義名稱,只有16個型別有定義名稱,整理如下表。

內建型別物件型別名稱
basestring
boolBooleanType
bufferBufferType
bytearray
bytes (bytes型別是Python 3.0才正式新增, 2.x等於str)
classmethod
complexComplexType
dictDictType, DictionaryType 
enumerate
fileFileType
floatFloatType
frozenset
intIntType
listListType
longLongType
memoryview
objectObjectType
property
reversed
set
sliceSliceType
staticmethod
strStringType
super
tupleTupleType
typeTypeType
unicodeUnicodeType
xrangeXRangeType

另外在內建常數的部分,types模組定義定義3個型別名稱,分別是:

內建常數型別名稱
NoneNoneType
NotImplementedNotImplementedType
EllipsisEllipsisType


剩下的型別名稱則是常用的物件,因此types模組定義這些物件的型別名稱,總共17個
  1. BuiltinFunctionType
  2. BuiltinMethodType
  3. ClassType
  4. CodeType
  5. DictProxyType
  6. FrameType
  7. FunctionType
  8. GeneratorType
  9. GetSetDescriptorType
  10. InstanceType
  11. LambdaType
  12. MemberDescriptorType
  13. MethodType
  14. ModuleType
  15. StringTypes
  16. TracebackType
  17. UnboundMethodType

列出內建型別的程式碼
if __name__ == "__main__":
    import types
    for item in dir(__builtins__):
        attr = getattr(__builtins__, item)
        if type(attr) is types.TypeType and \
           not issubclass(attr, BaseException):
            print attr

###

2013年3月6日 星期三

徹底研究Python:談內建(built-in)物件

徹底研究Python:談內建(built-in)物件。

啟動Python interpreter之後,就已經可以使用一些東西,這些東西稱為Python的內建(built-in)物件,是Python程式語言本身的一部分(即Python的核心)。我們可以使用「__builtin__」模組存取這些內建物件,使用len(dir(__builtin__))或len(__builtins__)指令可以發現總共有144個,這些內建物件可以分成下列4類:
  • 內建常數,共11個
    • Python程式語言本身內建,共6個
      1. False
      2. True
      3. None
      4. NotImplemented
      5. Ellipsis
      6. __debug__
    • 因Python自動匯入site模組,額外加入常數至內建名稱空間之中,共5個
      1. quit
      2. exit
      3. copyritht
      4. license
      5. credits
  • 內建型別,共28個
    1. basestring
    2. bool
    3. buffer
    4. bytearray
    5. bytes (bytes型別是Python 3.0才正式新增,2.x版的bytes等於str型別)
    6. classmethod
    7. complex
    8. dict
    9. enumerate
    10. file
    11. float
    12. frozenset
    13. int
    14. list
    15. long
    16. memoryview
    17. object
    18. property
    19. reversed
    20. set
    21. slice
    22. staticmethod
    23. str
    24. super
    25. tuple
    26. type
    27. unicode
    28. xrange
  • 內建函式,共53個
    1. __import__
    2. abs
    3. all
    4. any
    5. apply
    6. bin
    7. callable
    8. chr
    9. cmp
    10. coerce
    11. compile
    12. delattr
    13. dir
    14. divmod
    15. eval
    16. execfile
    17. filter
    18. format
    19. getattr
    20. globals
    21. hasattr
    22. hash
    23. help:因Python自動匯入site模組,額外加入至內建函式中
    24. hex
    25. id
    26. input
    27. intern
    28. isinstance
    29. issubclass
    30. iter
    31. len
    32. locals
    33. map
    34. max
    35. min
    36. next
    37. oct
    38. open
    39. ord
    40. pow
    41. print
    42. range
    43. raw_input
    44. reduce
    45. reload
    46. repr
    47. round
    48. setattr
    49. sorted
    50. sum
    51. unichr
    52. vars
    53. zip
  • 內建例外,共48個
    1. ArithmeticError
    2. AssertionError
    3. AttributeError
    4. BaseException
    5. BufferError
    6. BytesWarning
    7. DeprecationWarning
    8. EOFError
    9. EnvironmentError
    10. Exception
    11. FloatingPointError
    12. FutureWarning
    13. GeneratorExit
    14. IOError
    15. ImportError
    16. ImportWarning
    17. IndentationError
    18. IndexError
    19. KeyError
    20. KeyboardInterrupt
    21. LookupError
    22. MemoryError
    23. NameError
    24. NotImplementedError
    25. OSError
    26. OverflowError
    27. PendingDeprecationWarning
    28. ReferenceError
    29. RuntimeError
    30. RuntimeWarning
    31. StandardError
    32. StopIteration
    33. SyntaxError
    34. SyntaxWarning
    35. SystemError
    36. SystemExit
    37. TabError
    38. TypeError
    39. UnboundLocalError
    40. UnicodeDecodeError
    41. UnicodeEncodeError
    42. UnicodeError
    43. UnicodeTranslateError
    44. UnicodeWarning
    45. UserWarning
    46. ValueError
    47. Warning
    48. ZeroDivisionError
上述數量加起來共140個,剩下4個是模組屬性(attribute):
  • _:上一次最新輸出的結果(last printed expression)
  • __doc__:文件字串
  • __name__:名稱
  • __package__:套件

###

熱門文章