最近在看一本書"
The Pragmatic Programmer",裡有不少與重構相關的範例,值得參考,有與趣人可以買來看看。因此書,筆者心血來潮,分享一下自己的開發經驗。
在專案開發程式的過程,常會因時間壓力或市場考量,不得不加入很多非計畫中的程式碼。
開發時間越久,就漸漸難以維護,增加新功能更為秏時;當人力不足以達成出貨時程,便開始增加人力,最後日積月累,專案程式變成一個大怪物;直至某一日砍掉重練。
而筆者近年來,使用重構方法,使得自己不用一直為解專案bug而加班。
重構(Refactoring) 英文是一個現在進行式,表示這個動作需要一直不斷發生。
其中,"重構"的最重要的基石就是自動化測試程式,如每當重構程式碼中重覆的部分時,執行一下自動化測試程式,便可很快的確認程式修改後的正確性。
接下來我們來看一些筆者常用的小技巧,以下範例使用Python語言。
def show_animal_info0(animal):
if animal == 'dog':
print("The dog has four legs")
elif animal == 'chick':
print("The chick has two legs")
else:
print("There is an unknown animal")
show_animal_info0("dog")
show_animal_info0("chick")
show_animal_info0("cat") |
重構if-else
通常if-else會越加越長,慢慢變得難以除錯。
animal_info_dict = {
"dog": "four legs",
"chick": "two legs"
}
def show_animal_info1(animal):
try:
info = animal_info_dict[animal]
print("The %s has %s." % (animal, info))
except:
print("There is unknown animal") |
| 用dict結構表格取代if-else, 也可用來取代switch |
重構重覆呼叫函式
這種函式大部分由copy and paste而來。
show_animal_info0("dog")
show_animal_info0("chick")
show_animal_info0("cat") |
def main():
animals = ["dog", "chick", "cat"]
for name in animals:
show_animal_info1(name)
if __name__== "__main__":
main() |
重構屬性
紅色legs部分也是重覆程式碼的狀況之一
animal_info_dict = {
"dog": "four legs",
"chick": "two legs"
}
def show_animal_info1(animal):
try:
info = animal_info_dict[animal]
print("The %s has %s." % (animal, info))
except:
print("There is unknown animal") |
animal_info_dict = {
"dog": {"leg": "four"},
"chick": {"leg": "two"},
"cat": {"leg": "four"}
}
def show_animal_info1(animal):
try:
info = animal_info_dict[animal]
legs = info['leg']
print("The %s has %s legs." % (animal, legs))
except:
print("There is unknown animal.") |
自動化測試程式
要進行自動化測試,以本範例為例:
1. 將邏輯與資料顯示動作分離
def show_animal_info1(animal):
try:
info = animal_info_dict[animal]
legs = info['leg']
print("The %s has %s legs." % (animal, legs))
except:
print("There is unknown animal.") |
def get_animal_info1(animal):
try:
info = animal_info_dict[animal]
legs = info['leg']
msg = "The %s has %s legs." % (animal, legs)
except:
msg = "There is unknown animal."
return msg |
2. 比對預期函式回傳值結果
使用pyunit 來實作自動測試
import unittest
from code_for_automation import *
class DefaultTestCase(unittest.TestCase):
def testTestDog(self):
sample="The dog has four legs."
msg = get_animal_info1('dog')
assert msg == sample , 'test dog message'
def testTestChick(self):
sample="The chick has two legs."
msg = get_animal_info1('chick')
assert msg == sample , 'test chick message'
def testTestCat(self):
sample="The cat has four legs."
msg = get_animal_info1('cat')
assert msg == sample , 'test cat message'
if __name__ == '__main__':
myTestSuite = unittest.makeSuite(DefaultTestCase,'test')
runner = unittest.TextTestRunner()
runner.run(myTestSuite) |
3. 統計測試結果
$ python 05_automation.py
...
----------------------------------------------------------------------
Ran 3 tests in 0.000s
OK |
以上範例程式均可由
tip1下載
結論
當有了自動化測試程式之後,可提高自行重構的信心,又不用花費手動一個個輸入測試的時間。
本文雖以python為例,但觀念是相通的,其他語言也有其自動測試函式庫可供使用,歡迎不吝指教。