一些感悟
代码结构和规范关系到项目的可持续维护以及维护的周期,非常重要,但真正重视并落地的很少
经典的MVC模式一般都能说出来,但真正落地到项目代码结构的时候,却缺少思考
当写代码和找代码让人感觉别扭的时候,就该考虑如何去优化了
一切皆对象,在规划代码结构的时候也需要有面向对象的思维方式
很多张口就是高并发、大数据、高流量等之类高大上词汇的人,缺很少注重代码的基础结构,写出的代码很难让人轻易上手
如果代码结构和规范做得好一点,一般项目有一两个顶梁柱再加一些新手就完全可以搞定。这样既可以节省人力成本,也可以快速培养新人,新加入的成员也能快速融入
以下是整理的一般类型的项目代码结构,仅供参考。部分模块是使用spring boot开发项目的命名,但总体结构思路是一样的,如果不使用spring boot开发项目,只是修改一下名字即可
建议的包结构及简单说明
说明
此代码结构是使用spring boot、spring cloud作为主要开发技术。如果不使用spring boot + spring cloud,大体结构类似,比如:maven模块的划分、model/view/controller对应包的划分
model模块可以使用工具根据数据库表结构自动生成对应的文件
代码结构中的接口是http形式的接口,如果是rpc方式,api模块做对应调整即可
代码规范和结构的几点建议
service不需要接口,直接写java对象,区别在于spring会使用cglib作为代理的生成方式(如果是写接口和实现类,会使用jdk代理)。理由:在应用内部的各层次(controller、service、dao)之间进行调用,每次修改都是在应用内修改,不存在接口的调用方和实现方单独升级的情况,如果同时去修改接口和实现类,显得很多余;如果是应用之间的调用,必须定义接口。(个人认为原因可能是所谓的面向接口编程被过度理解和使用。应用内如果有一些复杂的业务逻辑,可适当考虑使用接口+多实现的方式,如遇这些情况,多参考设计模式的一些思想)
如果service需要写接口,接口以I开头,实现类以接口名去掉I命名。有的实现类会以impl结尾,个人认为没有必要。理由:impl表示的是类的层次结构,这个在包名上已经体现出来,并且类名应该主要体现实现的业务(见名知义),再有service的类名已经以service结尾,体现出了分层的意义,没有必要在命名上重复体现
mybatis的mapper建议使用sqlid的方式调用,这样能提高mapper.xml内代码的重用性;如果用定义接口与mapper.xml的id对应的方式,只能一一对应,不方便公用。比如User对象的查询功能:
使用sqlid调用方式的话,dao中的查询可以公用同一个sqlid:
如果使用写接口与mapper对应的方式,mapper.xml则需要写三个select,或者通过传入参数进行判断处理,返回值也根据使用情况需要处理
关于使用eureka注册中心,个人认为只是在原有web应用之前加了一层控制,而不应该因此将原web应用的controller写成service,因为原web应用虽然是相当于提供服务给eureka调用,但毕竟也是通过一般web应用的http方式调用的,两者是独立存在的,不应该因此把类名称耦合起来,更不应该在两者之间定义接口来将两者耦合在一起
减少事务开启时间,建议尽量将接收到的参数的判断、对象的初始化、vo与po的转换等放到事务开启之前,因为service只是调用不同dao或公用service对数据的操作来组合成controller需要的业务,并做事务控制,所以service应该只接收自己需要的并且正确的数据对象
方法名去掉冗余的部分,java定义方法签名是方法名+参数,只要根据方法签名能够知道其意思即可,如:
可以改为
写工具类或封装的时候考虑级联操作,即对对象属性的操作方法返回当前对象,如下是自己封装的controller统一使用的返回对象
使用的时候可以这样:
以上,纯属个人观点,但也基本都是经过实践后认为还不错的一些方式
领取专属 10元无门槛券
私享最新 技术干货