[重构]Duplicated code

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


展开阅读全文

没有更多推荐了,返回首页