Yang

代码层面的可修改性战术

可修改性战术可分为局部化变更、防止连锁反应、推迟绑定时间,下面我们一个一个来看。

 

局部化变更

局部化变更代表模块化思想,局部化变更要求每一个模块功能要单一,不能承担过多的任务,这样在对代码进行某一个功能修改时,只需修改某一个模块的代码即可,这一点类似于设计模式中的单一职责原则,就是让一个模块只做一件事情,防止职责过多引起整体代码变更的繁琐、混乱,原则是高内聚、低耦合,具体针对的是类、方法、接口。

class Animal{
    public void eat(String animal){
        System.out.println(animal+"进食");
    }
}
public class Client{
    public static void main(String[] args){
        Animal animal = new Animal();
        animal.eat("狼");
        animal.eat("老虎");
        animal.eat("大象");
    }
}

像这个类中的Animal类中的eat方法,只做动物进食这件事,当需要修改修改动物的动作时,只需修改eat这个方法即可

还有一种实例类似于接口定义,具体方法实现,即接口只负责抽象、具体类实现接口中的方法

interface X {
    public void work1();
    public void work2();
    public void work3();
    public void work4();
    public void work5();
}

class B implements X{
    public void work1() {
        System.out.println(“类B实现b1工作");
    }
    public void work2() {
        System.out.println(“类B实现b2工作");
    }
    public void work3() {
        System.out.println(“类B实现b3工作
”);
    }
    public void work4() {}
    public void work5() {}
}

class A{
    public void fun1(X x){
         x.work1();
    }
    public void fun2(X x){
         x.work2();
    }
    public void fun3(X x){
        x.work3();
    }
}

public class Client{
    public static void main(String[] args){
        A a = new A();
        a.fun1(new B());
        a.fun2(new B());
        a.fun3(new B());
  }
}

还有类似于数据库的配置文件,一般独立于数据库的增删改查方法之外,这样当数据配置需要修改时,只需修改配置文件即可,不用修改代码,确保了局部化变更

<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
    <default-config>
        <property name="user">root</property>
        <property name="password">123</property>
        <property  name="driverClass">com.mysql.cj.jdbc.Driver</property>
        <property name="jdbcUrl">jdbc:mysql://localhost:3306/fang?serverTimezone=UTC</property>
    </default-config> 
</c3p0-config> 

 

防止连锁反应

防止连锁反应很好理解,就是修改了某一个模块的代码不会引起连锁反应,我们平时编程,无论是写函数还是写类,都需要被其他类还是函数调用,修改此函数或类就会影响到调用他的函数,这就是连锁反应。当一个模块与其他模块之间联系过于紧密,那么修改这个模块的功能时,很可能会发生连锁反应,所以要求再进行代码设计时,模块内的联系要强,模块间的联系要弱,基高内聚、低耦合

 防止连锁反应的方法:
     (1)信息隐藏。信息隐藏就是把某个实体的责任分解为更小的部分,并选择使哪些信息成为公有的,哪些信息成为私有的。
     (2)维持现有的接口。该战术的模式包括添加接口、添加适配器、提供一个占位程序。
     (3)限制通信路径。限制与一个给定的模块共享的模块,减少联系,一旦变更影响会小很多。
     (4)使用仲裁者。插入仲裁者来管理依赖之间的关系,就比如数据库的使用,通过数据库来管理不同的数据信息

 总结一下就是模块间要尽量隐藏信息,要将接口与实现细节分离、前端与后端分离,要想办法弱化代码间的联系,具体在代码上的战术是多使用关联关系来取代继承关系

例如桥接模式中的模拟毛笔问题

毛笔有两个属性:颜色和大小,分别用两个模块实现,桥接模式的作用在于弱化颜色和大小这两个模块间的联系,最终实现颜色和大小这两个模块可以自由独立变化

public abstract class Pen
{
    protected Color color;//关联关系进行调用
    public void setColor(Color color)
    {
        this.color=color;
    }
    public abstract void draw(String name);
} 

public interface Color
{

void bepaint(String penType,String             name);

}

public class MiddlePen extends Pen
{
    public void draw(String name)
    {
       String penType="中号毛笔绘制";
       //调用具体Color类中的方法
       this.color.bepaint(penType,name);            
    }    
}

public class Blue implements Color
{
    public void bepaint(String   penType,String name)
{
        System.out.println(penType + "蓝色的"+ name + ".");
    }
}

 

推迟绑定时间

推迟绑定时间。将有可能的修改,尽量用配置文件,或者其他后期让非开发人员可调整的方式实现

例如将数据库配置独立出来,放在c3p0-config.xml配置文件中,可以减少部署时间,甚至没有变更基础的人员也可以实现对数据库配置的修改

<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
    <default-config>
        <property name="user">root</property>
        <property name="password">123</property>
        <property  name="driverClass">com.mysql.cj.jdbc.Driver</property>
        <property name="jdbcUrl">jdbc:mysql://localhost:3306/fang?serverTimezone=UTC</property>
    </default-config> 
</c3p0-config> 

在一些框架中,也有类似的可修改战术的代码实践,例如近几年比较火的框架开发SSM

 

posted on 2021-04-08 14:54  yangliuliu  阅读(79)  评论(0编辑  收藏  举报

导航