架构漫谈系列(1) 关注点分离

很想写相关的内容,一直以来这方面的东西很杂,自己各方面都多多少少有些总结,但是没有系统的成文,始终觉得是个遗憾。
这是这个系列的第一篇。
本文说的架构,还并不是说的Tier层的架构,这里面不会涉及到分布式、缓存、网络结构等等的布局,而是集中在软件的内部,是代码层级的,考虑这点架构的点,目的是在于帮助我们写出清晰、易维护的软件。

关注点分离(Separation of concerns, SoC)

这个准则应该作为我们开发和架构的指导性的原则。在该原则下,软件应该按照其业务来将软件本身划分成不同的部分,从而进一步降低耦合性,不过,这感觉是句废话,大家好像都懂。

那么首先,关注点是什么呢?

比如说一组对代码有影响的业务逻辑,或对某个具体业务有影响的业务规则。它其实可以很通用,比如针对x86环境优化代码的细节;也可以很具体,比如某个将要初始化的类的名字,只要它对我们是有用的,我们就称它为其中的一个关注点。

举例来说,如果某个软件有个逻辑:是将某些产品高亮显示出来,以显示这些产品的独特性。
那么,把这些产品挑选出来的逻辑,应该和把这些产品做高亮的逻辑分离开来,这是两个不同的关注点(只是刚好这两个关注点是互相关联的而已)。

在架构上,如何去应用这条准则呢?比如说,把业务逻辑的行为分成基本的实现层(infrastruture)和UI层(理想的情况下,业务规则和业务逻辑都应该分离到不同的项目里面去,他们也不能互相产生依赖的关系)。这种结构能帮助我们保证业务逻辑更容易的测试和应用,而且在底层也没有互相耦合在一起。
关注点分离是我们对于软件分层的一个核心的考虑点。

把握好这个尺度,有助于我们建造模块化的应用程序。它的价值在于简化开发和提高维护性。这个准则做好了,各独立部分就能重用,也可以相对独立的开发和更新,某个模块更新了,其他的模块不必做额外的修改。

但是,听起来还是好抽象的感觉。

举例来说,ASP.NET MVC就是关注点分离的一个体现,它将原来的ASP.NET WebForm分离成模型(model)-视图(view)-控制器(controller),从而把业务逻辑、数据、界面分离,这也是组织代码结构的一个形式。

MVC的基本结构:

  • Model层表示应用程序的数据核心,通常负责在数据库中存取数据。

  • View是应用程序的显示层,通常是依据模型的数据而建立。

  • Controller是用来控制和处理输入输出的,是处理用户交互的部分,也负责向模型(Model层)发送数据。

    MVC的这个设计各个关注点是分开的,这样有助于我们管理和开发复杂的应用程序,我们可以在某个时间点只集中精力在其中的某一个关注点,而不是所有的部分。举例来说,前端的开发人员可以配合设计团队绕过业务逻辑,专注在视图和交互设计部分。另外的一端,DBA也可以配合某个团队专注在数据持久化的部分,而中间的业务逻辑层又可以由其他团队集中精力来负责。这种分层也简化了分组开发,让测试也更为容易。

除了ASP.NET MVC还有其他的框架也是这样的关注点分离的思想,比如Django,Structs,Spring等等。

那么分层思想都有哪些方法呢,总不至于只是用个MVC就结束了吧?

其实东西还是比较多的,下面,将介绍一些分层的思想。

纵向分离

大家都懂,即便是最初级的程序员也都接触过,可能是你并没有意识到而已。
我们十好几年前的三层架构,界面层(UI Layer),业务逻辑层(Business Layer)和数据持久化层(Data Access Layer),就是这一种自上而下的纵向的分层手法。

横向分离

大家也懂。我们倡导的模块化的编程,把我们的软件拆分成模块或子系统。
从左到右是模块1、模块2、模块3,这是一种水平方向的切割。
这跟纵向的分离是两个不同的方向,横向分离大多是模块化的过程。

切面分离

有些内容是多个层之间都需要的,比如日志(logging),在你的系统里面,界面层、逻辑层、数据访问层可能都需要写日志,这种跨到多层同样逻辑就可以考虑切面分离。
在asp.net mvc中,我们可以使用filter来实现, Spring中也有SpringAOP等等。

依赖方向分离

我们考虑这几点:

  • 有些类要修改的几率比其他的类修改的几率大得多。
  • 具体的类比抽象类修改的几率大得多。
  • 修改被依赖得很多的类可能引起很大的改动。
  • 某些类比其他类被重用的可能性大得多。

依据这些考虑点,我们来决定某个类应该放在哪个层次里面,或者考虑将某一层切割成多层。

关注数据分离

在组织数据时,应该尽量考虑数据本身的固有属性,如果不是它们的固有属性,那么应该分离出来。

比如产品的类就不应该关联customer类,因为产品不应该跟客户直接产生数据关系,产品的颜色、型号、描述才是产品该有的固有属性。

至于客户,应该是用订单类来把他们联系在一起。

关注行为分离

跟上面讲的一样,行为也应该是事物或对象的固有的本身的行为,明显偏离原来行为的,应该考虑成另外的关注点儿分离开。

比如有一个函数叫做CreateNewCustomer(),那么CreateNewCustomer的行为就应该限定在创建一个新客户上面,给新客户自动发优惠券的动作就不能放到这个函数里面。

扩展分离

如果基于某种设计,原先不具有某些行为需要增加,可以考虑通过扩展或插件的形式来完成,将这些功能放入到插件或扩展中,就是扩展分离。

比如Firefox、Chrome的去广告的插件,这些功能增加了系统原本的行为,将这些行为分离到插件里面去,就是扩展分离。

委托分离

如果某个行为还无法具体确定,可以使用委托的方式。
比如C#的delegate,当我们还不知道某些具体行为应该如何实现,或者不应该在此处对该行为进行实现,或者有多个行为可以互相替代,就可以将函数的参数指定为一个delegate。

至于delegate具体怎样实现,那是其他部分应该关注的点。

比如现在需要将Customer的信息持久化,就可以把这个请求委托给DatabaseManager或WebSerivceManager,由他们自行处理数据,然后返回给我结果。

反转分离

现在有了很多的依赖注入的框架,像Autofac,Unit,Castle Windsor等等,这些帮助我们做依赖翻转,从而倒置依赖关系。

要指出是,上面提到了9种分离层次的概念,每一种概念都可以任意的与其他概念组合在一起,从而产生更多的变化。

在实际的开发过程中,没有东西是一成不变的,而层次和架构也应该是在开发的过程里面不断完善和重构。

初级程序员最烦的是需求或业务的修改,一些我们觉得奇奇怪怪的修改导致大家不断的修改代码,心里很烦,在心里也默默的把产品经理被翻过来倒过去骂了千百遍。

但是,在实际的工作中你会发现,软件开发就是这样,没有什么是不变的。

如果一定要找出一个不变的点,我想那应该是:

唯一不变的,就是变化。

关于不断的修改与重构,也可以参考《重构-改善既有代码的设计》,记得封面上写的是:

软件开发的不朽经典
生动阐述重构原理和具体做法
普通程序员进阶到编程高手必须修炼的秘笈

呃,再往下面离题越来越远了。
至此,关注点分离这块内容暂告一段落。

小春微信
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,053评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,527评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,779评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,685评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,699评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,609评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,989评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,654评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,890评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,634评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,716评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,394评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,976评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,950评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,191评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,849评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,458评论 2 342

推荐阅读更多精彩内容