• 3种方式帮助我们修改代码


     

        在实际的项目开发中我们可能经常要修改已有的代码,可能我们经常说开闭原则对已有的代码不准修改,但是实际上很难,那么下面的3种方法也许能帮助我们改善对代码的修改。

    1:新生方法

    有时候在我们开发的时候需要像系统加入新的功能时候这个时候我们就可能改变我们原有方法的结构。那么下面有一个简单例子

    以前添加用户的业务

    public void Add(IList<UserInfo> userInfos)
            {        
                if (userInfos!=null)
                {
                    Controller.Add(userInfos);
                }
            }

    现在用户分级别,不同级别的存入不同的表,下面是白金用户的添加

    public void Add(IList<UserInfo> userInfos)
            {        
                if (userInfos!=null)
                {
                    IList<UserInfo> mUserInfos=userInfos.ToList().FindAll(p=>p.Type=="白金").ToList();
                    Controller.Add(userInfos);
                }
            }
    

    很明显这种写法导致新老代码混合在一起,我们没法对新的代码进行测试操作。那么我们就可以新生一个方法

    public void Add(IList<UserInfo> userInfos)
            {
                if (userInfos != null)
                {
                    userInfos = GetUserInfosByType(userInfos, "白金");//此处引用
                    Controller.Add(userInfos);
                }
            }
            /// <summary>
            /// 新生的方法
            /// </summary>
            protected virtual IList<UserInfo> GetUserInfosByType(IList<UserInfo> userInfos, string type)
            {
                return userInfos.ToList().FindAll(p => p.Type == type).ToList();
            }

    这就是一个新生方法的例子。以下使我们采取的步骤:

    1:确定需要修改的地方

    2:确定新生方法需要向源方法返回的值(如果需要的话)

    3:把新生的方法采用受保护的虚方法,因为这样可以加入测试(如果条件不允许的话就可以放弃对老代码的测试)

    优点:新老代码隔离,即使是无法对老代码进行测试,那么新加上的代码可以进行测试。

    缺点:暂时放弃了老的代码,你基本不在为他编写测试也不会对他进行改善。

    2:包装方法

    这个和上面一个很相似。同样我们需要向一个现存的方法添加行为,这个很容易实现,但是如果我们的项目本身没有单元测试这个就变得很危险。在早期的设计我们的目的肯定是做一个单一的功能,但是由于业务的需要导致这个现存的方法变得越来越膨胀,而且耦合度极高,没有接缝,那么我们就无法进行分离。所以我们可以采取包装方法的模式来应对业务的改变

    比喻我们原来的代码只是添加员工(下面只是简单例子,实际肯定比这复杂)

    public void AddEmployee(UserInfo userInfo)
            {
                .......
                Controller.Add(userInfo);  
                .......          
            }

    但是现在对于重要的信息加入操作日志所以我采取把原来的老方法包装成Add如下

    public void AddEmployee(UserInfo userInfo)
            {
                Add(userInfo);
                AddLog(userInfo);//日志操作
            }
    
            public void Add(UserInfo userInfo)
            {
                ......
                Controller.Add(userInfo);   
                ...... 
            }

    我们使用包装方式的步骤:

    1:确实要修改的地方

    2:修改旧方法的名字

    3:在新方法调用旧方法和其他需要调用的方法

    缺点:

    1:新添加的逻辑无法与以前旧的方法紧密联合在一起,在他们之前或者之

    2:需要为旧方法重新命名(这个很难)可能导致代码的可读性变得很差

    优点:

    1:新的代码变得可测

    2:在引入接缝的同时加入了添的逻辑

     3:包装类

    其实包装类采用的是组合模式,把原来的旧的类重新进行包装,然后导入新添加行为的类中,这样就可以添加新的行为但是却没有破坏旧类的行为。举一个简单例子

    public class LogEmplyee
        {
            private Employee e;
    
            public LogEmplyee(Employee employee)
            {
                e = employee;
            }
    
            public void AddEmployee(UserInfo userInfo)
            {
                e.Add(userInfo);
                AddLog(userInfo);
            }
        }

    其实这采用也是我们经常说的装饰模式。

    什么情况下我们使用包装类

    1:我们旧的类已经很大了,实在不想让他继续膨胀

    2:我们添加新的行为很多,并且大多使用了旧类中的方法,并且有先后顺序,我们就可以考虑

    小结:通过上面三种方式,我们可以使他们来修改代码,而不需要为现存的类编写测试,当时从设计的角度来考虑确实不是很好理解,但是这么做起码让我们来改善我们的设计了,我们把新方法和旧方法进行了隔离,我们留下了接缝以后后期需要测试我们可以加入测试,来为我们的代码提供保障。慢慢一点点的改变相信会使代码变得更好。

  • 相关阅读:
    C#驱动mysql明明数值不为空却一直说DBNull.Value的诡异情况
    WinForm解决UI假死
    js实现的简单遮罩层
    mongodb C#连接报错 Invalid credentials for database 'admin'
    c#记录代码运行的耗时。
    C# LINQ
    timeScale减速对动画影响的处理方法(转)
    委托
    Unity3D单例类模板类
    Unity协程(Coroutine)管理类——TaskManager工具分享(转)
  • 原文地址:https://www.cnblogs.com/YzpJason/p/6668948.html
Copyright © 2020-2023  润新知