吴超-----系统分层调用的艺术

文章来源:

http://www.superwu.cn/2013/08/15/463/


java分层开发、分层调用已经是业界的共识。通常有一套这样的理论在指导着我们:

1.系统应该划分层次,最经典的莫过于MVC分层,很多框架也是基于此开发的。我们通常把系统划分为视图层、控制层、业务逻辑层、数据访问层、数据存储层。

2.层次划分清楚,上层代码只能调用下层代码,下层代码不能调用上层代码。比如控制层代码可以调用业务逻辑层,业务逻辑层可以调用数据访问层等。

3.每层开发应该使用接口,对外公布接口。当有上层调用的时候,可以修改本层实现,而不必修改调用方的代码。

按照这个指导思想开发,可能会出现以下层次结构划分:


-视图层
-控制层
-业务逻辑层接口
-业务逻辑层实现
-数据访问层接口
-数据访问层实现
-数据存储层

那么,可能出现以下的代码调用现象


//控制层代码
public class UserAction{
    public UserService userService;
    public String listAll(){
        List<User> allUsers = userService.findAll();
        //省略其余代码
    }
}
//业务逻辑层接口
public interface UserService{
    public <User> findAll();
}
//业务逻辑层实现
public class UserServiceImpl implements UserService{
    private UserDao userDao;
    public List<User> findAll(){
        return userDao.findAll();
    }
    public void setUserDao(UserDao userDao){
        this.userDao = userDao;
    }
}
//数据访问层接口
public interface UserDao{
    public <User> findAll();    
}
//数据访问层实现
public class UserDaoImpl implements UserDao{
    public <User> findAll(){
        //省略JDBC调用逻辑
    } 
}

对于一个系统开发的大部分java后端代码而言,也是遵循二八律的,百分之八十是简单的增删改查操作,真正的复杂业务逻辑占百分之二十。代码越多,意味着bug可能越多。并且,对于大部分系统,只有一种接口实现。业务逻辑层调用数据访问层也是简单的一行代码。那么,上面的实现是否有些臃肿?

按照我的观点,确实非常臃肿。带来几个问题:

1.工作量增加,这是毫无疑问的,因为写的代码多了嘛;

2.代码越多,bug可能越多,风险可能越高;

3.维护难度增加。如果数据访问层接口改动了,那么至少要影响数据访问层实现代码、业务逻辑层实现代码的修改;

4.调用层次增加,系统能耗增加,可能会影响系统性能;

另外,在泛型大行其道的java开发中,不利用泛型,真是有些浪费了。基于此,我们可以进行如下改进:


//控制层
public class UserAction{
    private UserService userService;
    public String listAll(){
        List<User> userList = userService.findAll();
        //省略其他操作
    }
}
//业务逻辑层
public class UserService{
    private UserDao userDao;

    public List<User> findAll(){
        return userDao.findAll;
    }
    //省略注入代码
}
//数据访问层
public class UserDao{
    public List<User> findAll(){
        //省略JDBC代码
    }
}

这样改进之后,少了两个层次,代码质量一点没变。这解决了调用层次过多的问题,那么简单调用问题还没有解决。我们可以根据泛型,作进一步的简化


//控制层
public class UserAction{
    private UserService userService;
    public String listAll(){
        List<User> userList = userService.findAll();
        //省略其他操作
    }
}
//业务逻辑层
public class UserService{
    private UserDao userDao;

    public List<User> findAll(){
        return userDao.findAll;
    }
    //省略注入代码
}
//数据访问层基类
public abstract class BaseDao<T>{
    public List<T> findAll(){
        //省略JDBC代码
    }
    public T get(){
        //省略JDBC代码
    }
    public void save(T t){
        //省略JDBC代码
    }
    public delete get(T t){
        //省略JDBC代码
    }
    //省略其他操作
}
//数据访问层子类
public class UserDao extends BaseDao<User>{
    //可以不用写代码,已经继承了BaseDao的方法
}

这次改进是增加了数据访问层的基类BaseDao,增加了很多通用的操作。这样,具体Dao子类就可以仅仅是一个空壳了。UserDao的功能一点也没变,但是需要我们维护的代码量明显减少了。当然,你可以对业务逻辑层抽取出一个父类,控制层抽取出一个父类。

如果系统明显不复杂,甚至业务逻辑层和数据访问层合并成一个,也是可以的。

综上,我们的原则是效率优先,兼顾质量。非常优美的设计,如果不能按期完工,一样是无意义的。当然,这话,也不是全面否认设计的存在。

在我的EasyQuery中,我就权衡了代码质量和系统设计的关系,使用了大量避免代码重复的设计,尽量用少量的代码完成更多的功能。这样,以后维护的时候会更加的简单。


你可能感兴趣的:(吴超-----系统分层调用的艺术)