Duplicated Code(重复代码)
影响:程序中到处都是相同结构的表达式。若想修改此表达式,需要修改多个地方。
目标:相同表达式合并成一起,避免多处修改。降低修改成本。
下面是常见的几种。如果有没涉及到的Duplicated Code 欢迎补充。
1、同一个类有相同的表达式。
Demo:一个DepartmentController
public class DepartmentController { DepartmentRepository Repository = new DepartmentRepository(); public string SaveDepartment(object obj) { //Build obj logic var result = Repository.Save(obj); return string.Format("your operation {0} at {1}", result, DateTime.Now.ToLongDateString()); } public string RemoveDepartment(object obj) { //Build obj logic var result = Repository.Remove(obj);; return string.Format("your operation {0} at {1}", result, DateTime.Now.ToLongDateString()); } }
由于每个method都要返回一个Result。而此类中出现多次:return string.Format("your operation {0} at {1}", result, DateTime.Now.ToLongDateString());。故:Duplicated
解决方案:将Build Result 的动作Extract一个私有方法,提高此方法重用性,消除Duplicated。
public class DepartmentController { public string SaveDepartment(object obj) { //Save logic const string result = Repository.Save("...obj"); return BuildResult(result); } public string RemoveDepartment(object obj) { //Remove Logic const string result = Repository.Remove("...obj");; return BuildResult(result); } private static string BuildResult(string result) { return string.Format("your operation {0} at {1}", result, DateTime.Now.ToLongDateString()); } }
2、两个类(或子类)有相同表达式
Demo:加一个EmployeeController,两个Controller。
public class EmployeeController { EmployeeRepository Repository = new EmployeeRepository(); public string SaveDepartment(object obj) { //Save logic var result = Repository.Save(obj); return BuildResult(result); } public string RemoveDepartment(object obj) { //Remove Logic var result = Repository.Remove(obj);; return BuildResult(result); } private static string BuildResult(string result) { return string.Format("your operation {0} at {1}", result, DateTime.Now.ToLongDateString()); } }EmployeeController 就是DepartmentController的克隆,除了Repo类型不一样。
此时应该Extract一个基类Repository,让两个Controller继承它,达到消除子类重复的效果。
简单的实现。
public class RepositoryBase<T> { protected RepositoryBase<T> Repository = null; public virtual string Save(T obj) { throw new NotImplementedException(); } public string Remove(T obj) { throw new NotImplementedException(); } }Controller:
public class EmployeeController : RepositoryBase<Employee>
3、两个子类有相同的表达式。
那么现在两个子类(Controller)中的Save方法直接调用基类的Save,然后获取Result,在返回Result.
public class EmployeeController : RepositoryBase<Employee> { public string SaveEmployee(Employee employee) { //other logic var result = Repository.Save(employee); return BuildResult(result); } private static string BuildResult(string result) { return String.Format("your operation {0} at {1}", result, DateTime.Now.ToLongDateString()); } }
有没有注意到两个子类中都含有BuildResult方法?没错,Duplicated Code。用Pull Up Method 把它整到父类里!(可以合并到Save方法里,也可以放在外面提供给子类调用。这里是后者。)
public string SaveDepartment(Employee emp) { var result = Repository.Save(emp); return Repository.BuildResult(result); }
当然上面的的情况是很明显的Bad Smell。两个表达式完全相同,可以直接看出。
如果两个子类里含有的表达式并非完全相同,而是有一部分相同,这个时候把相同的部分提出来。然后把相同的部分整到父类里。
4、两个不相干的类含有相同表达式。
如果两个不相干的类中有相同的表达式,那么把这个表达式提到一个Common类中。然后让这2个类分别调用我们新建的Common类。
除此之外还有其他的Duplicated Code。欢迎大家补充。
2012/8/15