代码架构设计-2.常用的两种web service代码架构

上文介绍了为什么要做好代码架构设计,接下来本文将为大家介绍两种常用的web service的代码架构。
在开始介绍这两种代码架构之前,先来回答一个问题:什么样的代码架构才是好的代码架构?

好的代码架构设计

这个问题的答案其实很简单,如同一份好的代码首先要有很好的可读性,并且能够达到松耦合,高内聚。这样一份代码就是好的代码。
同样,一个好的代码架构首先要能够便于阅读理解,只需要知道模块名称就知道是做什么的,什么东西应该放在哪里,其次,一个好的代码架构应该能够通过自身的规则,帮助开发人员更容易的写出松耦合,高内聚的代码。
由此可见,对于一个项目,一个工程来说,无论什么样的代码架构设计,只要能够达到上面的目标就可以了。并且随着项目的膨胀,代码架构也会有着不断地调整以适应现有的项目规模。
这里也只是列出两种代码架构,仅供大家参考。在大家选择自己的项目架构时,还需要结合自身情况,不建议盲目地照搬硬套。

基本的三层架构模型

通常在写web service的项目时,大家都会选择controller/api->service->repository/dao的模型。这里介绍的第一种代码架构就是基于该三层架构,只是对其增加了一些约束和扩展。类似于MVC模型,不过稍微有一些变动:


基本的三层架构模型
  • controller/api 层负责处理http request的传入参数,将传入参数转换为DTO,传入参数的基本验证以及一定程度的response数据的封装,仅当封装数据的逻辑和业务无关时才可以放在controller层,controller层之间的文件不能有依赖,controller层只能传递到service层。
  • service层主要做业务相关的逻辑业务,service层只接受DTO数据,并且return DTO数据。进入service层的DTO数据如有业务需要,可以进行validation。service层负责调用repository/dao获得Entity实例,简单的DTO<=>Entity转换可以在service层中进行,复杂的则需要单独的Converter
  • repository/dao层负责从数据库操作,只接受和返回Entity实例。repository/dao层不负责处理业务逻辑。
  • Entity只是数据库的字段的映射,只能包含一些简单的和Entity强相关的逻辑。
    这种三层架构的目录结构通常是扁平的:
.
├── controller
├── dao
├── dto
├── model
├── job
├── validation
├── service
└── utils

由上可知,由于所有的业务逻辑都会在service层处理,service层代码很容易膨胀使得内部代码太多,所以可以选择将原先的service细分为多个小的service,并且将其中的一些通用逻辑代码抽出来,独立一些新的package例如validation或者job等。之间串联关系依旧放在service层中。
然而随着项目扩张service层的臃肿化终究是一个问题,不过目前的解决方案通常是用划分微服务的方式将整个项目拆分为多个小的子项目,所以并不是一个太大的问题。总之,这种架构设计比较简单,开发人员的适应性也会强很多。
Note: 在微服务的架构下,上面讲的架构模型需要做一定的调整,本文的第三章将详细介绍这些细节,这里不再详述。

基于DDD的代码架构模型

DDD——Domain-driven design,目前可以看到很多人都开始推荐起DDD,对于DDD的概念细节本文并不做详述,DDD作为一种方法论也并非是万能的。基于DDD的代码架构设计有一定的优势之处,所以在这里像大家分享一下:

DDD的代码架构

可以看到相对于传统的三层模型,DDD相对要复杂很多,很多开发者在一开始面对DDD的代码架构时,会面临不知如何去写代码的困惑,这里像大家解释下:

  • resource层类似于上文的controller/api 层并没有太多变化,只是与它进行交接的facade
  • facade层不同于上文中的service层,值得注意的是facade层并不做真正的业务逻辑,他只是作为一个粘接层去衔接resourceentityfacade层负责
    1. 接收DTO数据;
    2. repository层读取entity实例,并且将从DTO中提取的纯粹数据或VO传进entity的函数中;
    3. 处理Domain=>DTO的转换(也可以由专门的converter或者factory处理,或者entity自己就直接可以返回自身对应的DTO);
    4. 调用repository层的持久化函数,保存/更新entity
    5. 一些entity到其他层的协调工作
  • repository 从数据库操作,只接受和返回Entity实例。
  • entityDDD概念中的domain的实例,具有业务含义,基本上针对一个domain的业务逻辑(除了它自身的create和delete)都应该放在该entity中去实现。
  • PO(persistent object)是数据库的字段的映射,只应该包含getter``setter方法。
  • factory用来做PO<=>Entity甚至DTO<=>Entity的转换
  • service的主要功能是当一个业务逻辑涉及到两个以上的domain,且这段逻辑不适合放在任何一个domain中时,就可以把该逻辑放在service中,可以说servicedomain之间的侨联。

可以看出DDD的代码架构比起三层架构的要复杂许多,而文件结构也会相对复杂一些:

├── dto
├── domain
│   ├── entity
│   ├── factory
│   ├── service
│   └── vo
├── facade
├── infrastructure
│   └── persistence
│       ├── repository
│       └── po
├── mapper
└── resource

个人理解,DDD式的代码架构所以流行是因为和restful API的理念非常一致,并且真正用到了面向对象的思想。restful强调所有的一切操作都是对资源的操作,而DDD也非常强调资源的聚合,并且就像面向对象所倡导的一样,设计好抽象,明确地将每个业务行为放在具体的抽象下面(就是domain里面)。
回忆面向对象编程提出的初衷:因为过程式的代码没有很好的方法去聚合操作,所以会产生出很多的冗余代码。而面向对象通过抽象,将会很好的减少代码的冗余程度,使代码高内聚,低耦合。DDD式的代码架构充分发挥了面向对象思想的优势。好的DDD式的代码架构通常需要新人一定时间的训练其掌握相关业务的所有领域知识,否则很难在现有代码上进行开发,而这也是它的一个好处:强迫所有人了解业务上下文。这点在一个项目上是非常重要的。
然而在笔者参与的大大小小的项目中,发现一个问题:虽然面向对象思想提出已经许多年,然而如今仍然只有少部分人能掌握其精髓。设计不好的面向对象的代码往往会成为一场灾难。DDD式的代码架构非常依赖每个人有意识地去维护,否则代码腐化速度甚至远超传统MVC模型的代码架构。而且DDD式的代码架构对团队内的每个开发人员的要求都远高于mvc模型。如果团队人员流动性很大,或者项目很急,没有多少code review和refactor的时间的情况下,非常不建议使用DDD式的代码架构。

我们介绍了两种常见的代码架构,希望大家可以参考并制定符合自己需求的代码架构。这里再多说一句,一套代码架构通常会有一些限制和约束,希望大家在遇到这种情况的时候,可以去多思考下为什么要这样做,这样是否真的有好处,多去思考和总结,总会有更多的收获,谢谢。

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

推荐阅读更多精彩内容