谈谈应用层切面设计

AOP概要理解纠偏

说到AOP,这个东东如今已经不是一个新词汇了,咱们拿一下百度词条来看看是下面的样子的: html

在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,经过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP能够对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度下降,提升程序的可重用性,同时提升了开发的效率。

可是今天我要说,这个定义太过狭义,实际上AOP的概念要比上面的定义要宽泛得多,今天我就给你们来扯扯AOP的事儿。

从AOP这三个单词来看,它的定义仍是很是准确的,就是面向切面编程。可是后面的这一堆解释: java

经过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP能够对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度下降,提升程序的可重用性,同时提升了开发的效率。

这明显是鬼扯了,明显是把一种具体的实现做为它定义,这就有点“白马即马”的意思了。

主要的变化就是把中间一段与具体的实现有关系的部分去掉。 编程

经过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。

这一段太过狭隘,已经远远不能知足软件技术发展的须要了,面向切面就面向切面,与什么预编译的方式有毛关系?与运行期代理有毛关系?与Spring、函数式编程有毛关系? 缓存

所以,今天悠然就把AOP的概念从新缕缕: 性能优化

在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,经过对某一领域进行高内聚低偶合方式进行实现,并经过非偶合的方式与其它业务逻辑进行整合,以对不一样切面的实现逻辑进行隔离,从而使得不一样领域的实现逻辑之间的耦合度下降,提升程序的可重用性、提升开发效率,同时也大大下降集成与整合难度的一种编程方法。

嗯嗯,虽然不必定严谨,可是比原来的普遍多了,也更能体现AOP的真正意涵。它不只包含原有定义里的模式,还包含各类各样其它AOP模式,今天悠然就来给你们试着阐述一下。

AOP在软件编程中的应用场景

传统意义上的AOP

传统意义上的AOP,是针对业务处理过程当中的切面进行提取,它所面对的是处理过程当中的某个步骤或阶段,来得到逻辑过程当中各部分之间低耦合性的一些隔离效率,好比:常见的应用场景有: 架构

  1. Authentication 权限
  2. Caching缓存
  3. Context passing内容传递
  4. Error handling 错误处理
  5. Lazy loading 延时加载
  6. Debugging 调试
  7. logging, tracing, profiling and monitoring 记录跟踪 优化 校准
  8. Performance optimization性能优化
  9. Persistence 持久化
  10. Resource pooling资源池
  11. Synchronization 同步
  12. Transactions事务
  13. 全文索引
  14. 等等

确实,AOP的应用场景有许多许多,也取得了良好的应用效果,这个已经通过了充分的实践,许多书里也都进行了充分的阐述,这里再也不赘述。 框架

非传统意义上的AOP

嗯嗯,今天的重点是这里,别人说得好的地方悠然说不过,所以最好的办法就是不说,悠然说别人不说的地方,这样就压力小多了:) 模块化

如下针对@红薯 的猜想纯属臆断,若有雷同纯属巧合: 函数式编程

在正式开始以前,咱们来举个实践场景: 函数

@红薯 的开源中国博客1.0

话说,在开源中国的博客列表中,每一篇博客是像下面同样展现的:

从这一块内容中,咱们能够看到以下内容:

  1. 原创的图标
  2. 置顶的图标
  3. 博客的标题
  4. 博客的分类
  5. 博客的统计信息30评、2594阅、7赞
  6. 博客的编辑、删除

咱们从看到的这些信息里面,能够猜一下@红薯 的表结果是怎么设计的:

表BLOG结构:

  • 博客标识
  • 博客标题
  • 博客标题内容
  • 是否原创
  • 是否置顶
  • 评论次数
  • 阅读次数
  • 获赞次数
  • ....

固然这里应该也有一些其余的字段,咱们上面的图片里看不到,咱们就当它们不存在。

咱们再想一想,估计@红薯 还有详细的记录,好比:谁评论的,评论的内容是什么?谁阅读的,是何时阅读的?谁点赞的,是何时点赞的

因而就有了下面的表:

    评论详情:

  • 博客标识
  • 评论者
  • 评论时间
  • 评论内容
  • ...

    阅读详情:

  • 博客标识
  • 阅读者
  • 阅读时间

    点赞详情:

  • 博客标识
  • 点赞者
  • 点赞时间

嗯嗯,@红薯 仔细想了一想感受差很少了的样子,这个时候@红薯 缕着他的头发,点上一支烟进入了写代码的酸爽状态。

好比,功能是这样写的:

//博客点赞

保存点赞(博客标识,点赞者标识){
    博客biz.添加点赞(博客标识,点赞者标识);
}

class 博客biz{
     添加点赞(博客标识,点赞者标识){
          博客dao.增长点赞数(博客标识);
          点赞详情dao.增长点赞详情(博客标识,点赞者标识);
     }
}

伴随着一阵阵欢快的噼里啪啦键盘声,开源中国博客1.0 OK了。

@红薯 的开源中国新闻1.0

看着开源中国博客1.0的稳步运行,PV+UV双丰收,@红薯 缕着头发咧着大板牙笑开了花,那就再整个开源中国新闻1.0呗!

因而红薯开始设计表结构:

表NEWS结构:

  • 新闻标识
  • 新闻标题
  • 新闻标题内容
  • 是否置顶
  • 评论次数
  • 阅读次数
  • 获赞次数
  • ....

固然,考虑到新闻也有点赞,也有评语,也有阅读,因而下面的表结构也是须要的:

    评论详情:

  • 新闻标识
  • 评论者
  • 评论时间
  • 评论内容
  • ...

    阅读详情:

  • 新闻标识
  • 阅读者
  • 阅读时间

    点赞详情:

  • 新闻标识
  • 点赞者
  • 点赞时间

嗯嗯,红薯看了下,尼玛除了少个原创,别的都差很少的样子么,可是不同仍是不同的,那就再作一遍吧,因而一阵阵噼里啪啦以后又搞定了,红薯抹着汗水,再仔细看一下代码,尼玛,怎么这两边的代码几乎同样?感受哪里有些不对的样子。

管呢,先运行起来再说,哥去泡个妹子放松一下,因而红薯打开了MAC,IPAD,IPHONE7S....

初级AOP方式

运行了一段时间,红薯以为要加个动态功能,发现要在两边都增长代码,愈来愈以为不对劲,因而拿起新买的《企业级JavaEE架构实践》翻看起来,唉当时看书的时候不仔细,这个用切面来解决不是挺好的?

因而红薯把表结构重构了一下:

    评论详情:

  • 评论类型
  • 评论对象标识
  • 评论者
  • 评论时间
  • 评论内容
  • ...

    阅读详情:

  • 阅读类型
  • 阅读对象标识
  • 阅读者
  • 阅读时间

    点赞详情:

  • 点赞类型
  • 点赞对象标识
  • 点赞者
  • 点赞时间

另外增长一个动态表

  • 动态类型
  • 动态对象标识
  • 动态者
  • 动态时间
因而红薯把原来的代码重构了一下,把原来重复作了两遍的的评论、阅读、点赞都抽到了一个里面,而后把原来在业务代码里调用相关评论、阅读、点赞的业务逻辑都抽到了切面当中。嗯嗯,红薯感受棒极了,脑海中又出现了妹子的身影,对了,IPHONE8P哪里去了?

高级AOP方式

自从引入了切面功能,红薯的工做明显轻松多了,可是惟一不爽的是 随着开源中国的用户愈来愈多,投资人要求功能方面也要快速推动,如今的红薯几乎已经没有能够缕的头发了,投资人要增长日历、要增长勋章、要增长TAG、要增长提醒,要增长的东西愈来愈多,同时开源中国的访问者们的眼界又愈来愈宽了,要求愈来愈高了,今天这个作的丑了,明天那个作得不人性化了, 红薯开发、测试、发布、切面配置、界面调整、控制层啥都要作,这不又出问题了:


红薯的手习惯的抬起来缕头发了,可是随着OSC功能的增长,头发已经几乎找不到了,红薯狠的把烟屁股拧进烟灰缸,是要完全解决这个问题了,看起来还得读书啊,再翻企业级JavaEE架构实践,看看有没有啥思路。

Think Big, Start small , Scale Fast.

这是什么鬼?
好的软件是品出来的。
品个屁,如今解决问题才是正点,能不能让我不要每次都改这么多东西?再翻翻目录,看看有啥值得研究的?

仔细看了几遍,红薯的眼睛突然亮了起来,只要把全部的评论、点赞、评论、动态、以及其它杂7杂8的东西都让它高内聚,低耦合,我作博客只管作博客、作新闻只管作新闻,哪怕再作他多少个,也是仅仅关注我要作的东西,而把这些东西都作成一个个的切面让这些切面去完整的解决这些问题,这样我不就轻松了?原来虽然也引入了AOP技术,可是因为只是初级切面,因此只解决了部分问题,并无完全的解决问题。若是我能把切面也切到控制层、界面层,这样就能够真正的作到高内聚、松耦合,并且是真正的业务切面。

技术的切面仍是初级的,业务层级的切面才是终级的。

具体实现起来,仍是没有什么思路,听听悠然有没有什么思路?

终级解决方案

经过上面对开源中国两个功能模块的分析,咱们大体清楚了问题的症结所在,并经过对红薯的心路历程进行分析,大体引入了问题的解决思路,可是真正的落地却不是那么简单的。一个问题的抽象的程度越高,其通用性越好,可是它的易理解程度和易实现程度也就越难。我对实现者面对面屡次沟通这个思路时,更多的时候看到的是他们茫然的眼神,以及屡次感受理解了,可是真正实现的时候却又达不到要求,直到许屡次反复以后,才慢慢进入状态。

因此我会尽力讲清楚,可是不能保证你必定能理解到我心里所想。

要解决的问题

咱们在应用开发过程当中,一部分是与具体的业务相关的,另一部分它与具体的业务并不相关,可是在业务过程当中又是有这样那样关系的。若是咱们能把这些与具体业务没有直接关系,但又是对业务数据的一种维度的补充或描述能独立出来,想用或不想用仅在一念间,那么这个时候作软件就是一种享受了,并且业务和切面均可以独立变化,而没必要考虑彼此的影响。

这个时候从开发效率来讲,因为你们各自高内聚低耦合,因此开发、测试、验证、发布都会方便快速许多,集成的时候因为也没必要有配置和代码及界面上的协做和引用,这样就能够大大的下降系统集成过程当中的开发、测试工做,也避免了由此致使的一系列的可能出现的问题。

那么接下来,咱们就用上面分析问题时的例子来阐述,如何解决这个问题,整个实现思路采用Tiny框架相关技术进行解决,非TINY技术平台或框架也是能够实现的,固然实现细节可能会有不一样,须要相关的架构师进行相应的调整。

解决问题的思路

每一个切面的内容都在本身的业务单元中实现,同时要能在能出来的时候它就能出来。

这里咱们就拿上面说的一个场景"评论"来示例

   评论详情:

  • 评论类型
  • 评论对象标识
  • 评论者
  • 评论时间
  • 评论内容
围绕着这个,当能够能够知道它的DAO层代码怎么写,逻辑层代码怎么写(若是是SOA体系还有服务层代码怎么写),最后还有就是界面层的部分。

既然是高内聚低耦合,那固然主是要统一界面的样式。

评价的使用场景通常来讲是在显示完主要业务内容以后(如:博客、新闻、文档、软件、etc),能够进行评论,能够进行回复,能够进行引入,固然也要能把已经评论的内容显示出来。

可是须要搞清楚的是,这些内容的展示与人机交互过程明显与不一样的业务内容没有一点关系,这也就为进行切面提供了基础。为了便于进行说明问题,这里采用AJAX模式进行解释,虽然采用非AJAX方式也是能够解释得通的,可是应用到的技术的复杂度与解释起来的困难都很是更加复杂。

举个例子,作出来的效果是相似下面的样子:

这个时候,问题就转换为,如何把当前要处理的业务类型和业务数据的标识让评论部分知晓,这个也很是简单,只要用下面的样子写一段模板便可:

#comment("BLOG",blog.blogId)
上面的模板语言是指:如今我是在给一个BLOG类型的业务对象作评论,业务对象的标识是blog对象的blogId属性。

嗯嗯,这个时候较之前的开发,已经省了很是大的工做量了,只是简单的声明一下就能够了。

更进一步的思考

虽然上面的思路已经比较好的解决了问题,可是这里有一个问题:那就是实现时序问题。

也就是说,博客功能是红薯先加的,而评论功能是红薯后加的。这里就出现一个问题:为何后增长的功能,须要我在已经实现的妥妥的功能要进行调整??这岂不是说,你后面不断的增长功能,我这里都要不断的进行声明?虽然也有必定的道理,可是是不符合好莱坞原则的。实际上也是违反常理的===我是先来的,为何要为你一个后到的作调整?我根本就不知道你的存在好么?!

出于咱们对完美架构的追求之前咱们不将就的态度,咱们固然要更好的解决此问题。

咱们能够在应用当中预设一些扩展点,可是具体扩展些什么东西我是无论的。

这个时候,咱们就能够只在界面中增长以下的一段模板语言:

#extendPoint("VIEW","BLOG",blog.blogId)

上面的脚本表示,我这里是一个VIEW类型的扩展点,业务类型是BLOG,业务对象标识是blog对象的blogId属性。

而后由extendPoint决定往里面塞哪些东西。

这个时候,我只要在评论工程里增长以下的配置:

<extend-points>
    <extend-point type="page" order="10">
        #comment(bizType,bizId)
    </extend-point>
</extend-points>
而后若是这个时候,咱们又要增长一个留脚印的功能

咱们只要增长一个留脚本的功能模块,在这个模块中增长下面的配置:

<extend-points>
    <extend-point type="page" order="9">
        #footprint(bizType,bizId)
    </extend-point>
</extend-points>

总结

经过上面的改进,红薯同窗不再用薅头发了,原有的业务代码不再用动,这功能竟然自动在全部功能中自动出现了。

想到这里,悠然就深深的自责,早点给红薯出主意,红薯同窗的一头黑发就留下来了。

固然,上面只是说了一个思想,真正的实现的时候用到的技术仍是很是多的:
  • 模块化
  • AOP
  • SOA(若是是互联网应用是须要的,普通的小工程能够不用)
  • 模板语言或相似技术

若是本人没有说清楚,或者读者朋友们没有理解,本人深感自责,也但愿同窗们可以理解,并在下面的回复博客提问,本人定尽力给出解释。

有喜欢本人博客内容的同窗请加关注,以便及时获知本人精品内容!

相关文章
相关标签/搜索