想必有很多工程師跟小弟一樣會碰到要幫別人維護code的差事
在維護別人的code時難免會發現
想必有很多工程師跟小弟一樣會碰到要幫別人維護code的差事
在維護別人的code時難免會發現
- 前人因為某些因素導致code寫的不夠完善需要調整
- 或是系統需求有變動
- 也或許是有更好的做法而必須改程式
通常系統沒有錯誤當然是能不改就不改
但是當系統有錯誤或開發尚未完成等
其實是有技巧用來改善原本的程式的
什麼技巧?
不就是經驗嗎~
經驗老到的工程師往往可以用很快的速度將程式翻新、改善的
不過其實還有另外一門學問叫做重構
重構的理由非常多
大多數的理由是為了接下來的開發能夠更順利(廢話)
好比將過度肥大的Method切割
將奇怪命名的Method等重新調整為語意清楚的命名方式(好比小弟就曾看過有工程師喜歡用xx、oo、GetEmlByDept1、GetEmpByDept2等的命名方式)
讓類別責任清楚
讓程式容易理解等等~
最近小弟因為手頭的程式實在不小
原本不想變動的(基於成是看起來似乎沒有錯誤)
但是實在是越看越不對勁(一個類別有上千行程式,且部分程式很明顯應該是屬於另外的Class Family(註 1)的)
所以我就忍痛邊測試邊重構了
基本上我只用了move method跟extract method
開始吧(底下的程式只擷取部分的故僅僅做為sample用,並不多考慮實務上設計)
首先我的專案中有兩種種類的類別
第一種是類似Table Class的類別我將它放在 XXX.Model的命名空間下
命外一種是用來取得資料的類別,我將它放在XXX.DAL的命名空間下
今天我發現在DAL.Employee中包含了過多的關於Department的資訊
所以我決定把Employee的Method移回Department
class Employee
{
string _name;
public string Name
{
get { return _name; }
set { _name = value; }
}
public List<string> GetEmployeeName()
{
Department _dept = new Department();
List<string> _result = new List<string>();
List<Employee> _employeeList = _dept.GetEmployee("IT");
foreach (Employee item in _employeeList)
{
_result.Add(item.Name);
}
return _result;
}
}
class Department
{
public List<Employee> GetEmployee(string departmanetName)
{
List<Employee> _result;
DbProviderFactory dbHelp = DbProviderFactories.GetFactory("System.Data.SQLite");
DbConnection _conn = dbHelp.CreateConnection();
DbCommand _cmd = ....
return _result;
}
...
....
}
假設原本的Code是這樣的
我想GetEmployeeName放在Department會比放在employee更適合吧
所以我打算 move method
在我Move他之前我先確定了一下目前系統中有多少地方參照到要被我搬移的Method
如果我發現參照到次method的地方沒超過3個我想我會直接把整個GetEmployeeName移到Department中即可
並在做完move method後到每個有參照到的地方改寫原本的
Employee _emp = new Employee();
_emp.GetEmployeeName("IT");
為以下
Department _dept = new Department();
_dept.GetEmployeeName("IT");
如果我發現目前系統已經有太多地方參照它了
那麼我會改為使用工具協助(會比人工輕鬆一點)
我使用CodeRushXpress來協助我的作業
我只要將要被搬移的程式反白按下Ctrl + `就會出現此畫面
選完Extract method to Department按下Enter後
然後我改變return Department.GetEmployeeNameExtracted(departmentName);的method name為GetEmployeeName
我只要改變return中的method name在department中的method name也會變動
接下來我需要將 department中GetEmployeeName的static拿掉並在emplayee中的GetEmployeeName改為要instance department並調整
在department中的GetEmployeeName不需要再instance department囉
最後我的code會長成這樣
目前就先這樣吧,
先讓類別做自己該做的事
不要做不相關的事
這樣也可以消除掉employee對department過度的相依性
另外您也可以考慮使用ObsoleteAttribute套用在被取代掉的Method
例如
[Obsolete("此Method已經過期,請改用XXX")]
public List<string> GetEmployeeName()
{
這樣以後維護的人員在compiler時就會注意到此method要改用新類別中的method了
註 1:這是參考深入淺出設計模式中的演算法家族說法,相同性質功能的類別歸類為同一個家族,因為我想不到更好的說法,抱歉。