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

来源:互联网 发布:贴贴相传网络曝光 编辑:程序博客网 时间:2024/04/27 17:25

文章来源:

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


0 0
原创粉丝点击