SpringMVC Web应用结构

应用层次结构

应用分层的目的是什么?复用,解耦,提高代码的可读性,减少代码的维护成本。这些目的都很重要,大家也都清楚。我想说的是一个大家忽略的同时也是最重要的目的,就是减少同事代码归置出错的概率。这怎么解释呢?一个项目不是一人吃饱全家不饿的情况,都是大家协作完成。由于大家技术能力不大相同,特别是当有很多刚毕业的同事时,良好的层次结构能提供一种约束力减少代码归置出错的概率,并且在Review代码的时候,更加简单轻松,通过率更高。因此,以下任何一个依据都可以做作为分成的必要条件:
1. 复用,解耦,提高代码的可读性,减少代码的维护成本
2. 提高代码归置的约束力,减少自己和同伴代码归置出错的概率

  • Controller(Action):
    1. 为公司App、公司Web、第三方提供的接口
  • Facade:
    1. 主要为Controller服务
    2. 总领本领域的所有Service
    3. 提供给其他模块的Service引用
  • Service:

    1. 提供给其他sevice类平行引用,禁止相互引用
    2. 主要处理业务逻辑
    3. 处理业务聚合后的cache
    4. 如果service代码量过多,请阅读下面“值得玩味的service”的内容

    其实这样也不能处理所有情况,更复杂的情况请看下面“值得玩味的Service”标题的内容。

  • InkService(Invoker Service):

    1. 屏蔽RPC接口的变化对项目的影响
    2. 封装invoker接口数据、缓存invoker接口数据
    3. 只处理invoker,invoker接口聚合,cache
    4. 能被多个模块的service引用
  • Manager:
    1. 只处理db,cache
    2. 只能被本模块的Service引用
  • Dao:
    1. 处理db
  • Invoker:
    1. interface
  • InvokerImpl:
    1. 简单的包装公司内部RPC接口
  • Remoter:
    1. interface
  • RmiImpl:
    1. 简单的包装公司内部RPC接口
  • Component
    1. 主要包括一个模块中Service群共同依赖的Service方法
    2. 只能本模块Service引用,辅助Service执行去职能
  • Helper:
    1. 只做共用数据打包和接口聚合逻辑,不做业务逻辑
    2. 只能本模块Service、Component引用

值得玩味的Service

如果Service的内容特别多,造成难维护的情况。有两种选择可以参考:

  1. 如果有必要,对目前的Service再进行domian划分,建立新的Service模块;
  2. 对目前的Service再进行更小的domian划分,分裂成多个Service。本领域的Service变多了也不好维护,并且相互依赖,怎么办?用Helper和
    Component辅助Service执行其职能,Helper和Component的具体内容请看层次结构介绍。

代码逻辑分解推荐

代码分为业务处理逻辑、业务异常处理逻辑、其他异常处理逻辑、数据打包逻辑、数据获取和存储逻辑等等

上面的划分只是个人观点。有种说法是所有代码逻辑都是业务处理逻辑,我觉得概念太过笼统。我细分了一下这些概念,其中“业务处理逻辑”的概念只是业务变更的那段逻辑,这样做的目的是剥离出真正的业务最关注的代码部分。例如,报备楼盘到带看楼盘的过程中,“业务处理逻辑”的概念只是报备状态0便变成带看状态1。

Spring注释规则


  1. Controller:@Controller用于标注控制层组件(如struts中的action)
  2. Service:@Service用于标注业务层组件
  3. Manager、InvokerImpl、RmiImpl:@Repository用于标注数据访问组件
  4. Dao:@MasterMapper、@SlaveMapper 自定义关于MyBits选择库的注释
  5. Other:@Component泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。

在目前的 Spring 版本中,这 3 个注释和 @Component 是等效的,但是从注释类的命名上,很容易看出这 3 个注释分别和持久层、业务层和控制层(Web 层)相对应。虽然目前这3个注释和 @Component 相比没有什么新意,但 Spring 将在以后的版本中为它们添加特殊的功能。所以,如果 Web 应用程序采用了经典的三层分层结构的话,最好在持久层、业务层和控制层分别采用上述注解对分层中的类进行注释。

实施难点


  1. 抽象domain,划分Service边界
  2. 各层次只做职能当中的事情,禁止跨层调用。如果有,请拿上你的案例和我讨论!

最大难点:你想不想做,去不去做?

常见问题

问题一

Q:把代码写在哪里才正确? 
A:代码逻辑见上图

问题二

Q:如何抽象domian
A:详情请参考《大象-Think in UML》

问题三

Q:如何重构代码
A:详情请参考《重构-改善代码既有设计》

问题四

Q:如何避免大量service相互循环依赖?
A:目前service只允许循环平行引用,当出现相互循环依赖的问题时请考虑如下原因:
  原因一:service的domian划分出现了问题,请重新考虑边界问题;
  原因二:可以考虑抽象更加下层service领域,然后相互循环依赖的service再引用这个下层service;
  如果还有其他原因,请带上案例来和我讨论吧!

编写代码时的“警惕”


  1. domian
  2. 全能函数
  3. 超过64K的文件类
  4. 长函数体
  5. 长函数名
  6. 不明其意的命名
  7. 命名困难
  8. switch-case/if-else等多个Type的问题
  9. 接口VS继承
  10. 用多态处理一些问题,想想设计模式
  11. 数据类是否是合理的冗余
  12. 尽量简单,只做一件事

更多警惕请见《重构-改善代码既有设计》的第三章,以及书本最后几页,以及《程序性能优化》第三章3.5节。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值