架构的“一小步”,业务的一大步

前言:

谈到“架构”这两个字,会有好多的名词闪现,比如:分层架构、事件驱动架构、DDD、CQRS等。亦或者一堆的软件设计原则,如:KISS原则(Keep it Simple and Stupid)、SOLID原则(单一责任原则、开放封闭原则、里氏替换原则、接口分离原则、依赖导致原则)等。甚至如状态图、用例图、时序图、活动图等UML建模,GOF设计模式等。
本文不会讨论这些架构概念,而是从闲鱼详情页这个业务场景出发,分析出当前的业务问题和痛点,然后通过一步步的架构推导设计,解决这些痛点。随着业务的发展,相信这些问题大家都会遇到。而解决问题的过程,或多或少的会用到上面的设计原则。

一:老的业务架构 - MVC架构

很多同学开始写业务的时候,基本都会先建表,然后生成CURD,最后再堆业务逻辑,从DAO->Manager->Service->Controller一路写到底。在业务小的时候,这种架构非常的简单实用,可以快速的开发上线。
但随着业务发展,人员不断增加,老的架构难以支撑业务的发展,稳定性和效率受到极大挑战。蛮荒时代已过,精耕细作的时代到来,急需一种更合适的架构来支撑业务的发展。
以闲鱼的详情页举例,在业务初期,详情的样式只有普通的开价宝贝一种,但随着业务的发展,演变出拍卖、免费送、租房、玩家等细分领域的商品详情页(我们将细分领域的业务命名为“垂直业务”)。

图2:闲鱼详情页业务演变
 此时,还不断的在老的业务逻辑里添加新的业务逻辑,导致所有的详情业务逻辑堆在一起。于是乎,会出现下面的场景:
1)今天A详情业务线的同学,加了段逻辑,挂了,影响了所有业务线的同学;
2)B详情业务线的同学想做单独的监控、缓存、降级等,做不到啊,大家的逻辑在一起,改造成本太高;
3)C详情业务线的同学本想只关注C详情业务逻辑,发现所有业务都在一起,不得不将所有业务都理清楚一遍;
4)D详情业务线的同学发现前面的业务逻辑太复杂,为了将影响面减少到最小,找了一个认为最安全的地方,加了一段D详情业务的特殊处理。

图3:详情页堆逻辑代码
有人可能会问,堆逻辑正常的啊,加几行代码,业务就上线了,互联网提倡的敏捷开发,当然是怎么快怎么来。但敏捷开发 != 提需求 + 编码 + 发布,加几行代码交付业务上线,可能会带来眼前的收益,但一直这么下去,代码会越来越臃肿,没有设计和文档沉淀的系统,难以维护,出故障只是时间问题。

二:新的业务架构 - 业务隔离 + 领域建模

吉德林法则讲:把难题清清楚楚地写出来,便已经解决了一半。 老的架构的问题,归纳起来讲:
1.业务没有做隔离,所有的垂直业务逻辑都堆在一起,互相影响。
2.详情页业务足够的复杂,却没有统一的模型,形成统一的认知。
因此,架构的设计方案就着重解决这两个问题。

2.1 业务隔离架构推导与设计

一个业务,有多种形态的实现,很容易对应到设计模式里的策略模式。最粗暴的方式,每个垂直业务都自己实现详情页。

图4 使用策略模式,隔离每个业务的实现

这种方式,业务虽然隔离了,但维护成本极高,添加一个通用的功能,所有业务都需要添加一遍。 因此需要将共性内容(不变的部分)抽象出来,将变化的部分由各个垂直业务去实现。

图5,抽象出共性(不变)和特性(变)的内容

这种方式,解决了业务的隔离,共性的内容统一维护,变化的部分由各个垂直业务独立维护。但此时,所有的业务团队还是在一个应用工程里写业务代码,会出现如下场景:
1)开发阶段,各业务线都在这个应用里拉取一个分支进行开发,集成部署时,代码冲突难以避免。
2)A业务线添加了一段自己业务线的逻辑,部署失败了,导致其它业务线也无法使用。
3)N业务线不在自己的团队内,属于外部合作团队,如何添加该业务线的逻辑。

这些场景存在的原因在于,业务代码虽然隔离了, 但人员的开发过程并没有隔离。有如下3中方法可供选择:
a. 将共性的内容打成二方依赖包,每个垂直业务依赖这个二方包,进行独立应用开发。
这种二方依赖的方法最常用,但在二方服务里添加一个通用功能的时候,要告知所有业务方都升级二方包,还要发版,升级的成本高。

图6.a 共性内容打成二方包


b. 垂直业务独立应用开发,然后将代码打成jar包,再集成到共性业务应用里,一起部署。
该方法依赖关系跟方法a相反,但部署方式不够灵活。如果要实现垂直业务的独立部署,改造成本太高,需要做类隔离,budle隔离等。

图6.b 垂直业务打成二方包

  1. 综合a和b的优点,将共性的业务独立部署,垂直业务既可以独立部署,也可以写在共性内容应用里。当调用某个垂直业务实现时,可以自动路由到具体的垂直业务实现(这个垂直业务实现可以是一个本地调用,也可以是一个远程调用)。这样,垂直业务的开发人员就可以在自己的应用中开发、部署、运维,解决开发人员的隔离问题。

    图6.c  互不依赖,部署方式可选
    至此,业务的隔离,开发人员的隔离问题都已解决。但该架构方案显然不只有详情这一个场景可用,其他类似的业务场景也有相似的问题。因此,架构的代码不能与业务的代码耦合在一起,需要将架构的代码独立出来,形成通用的技术工具,以应用于所有类似的业务,业务开发应该只关心业务的事情。我们特地为此开发了一个多实现“业务隔离”路由工具,最终的隔离架构设计图如下:.

图7: 总体架构图。

2.2.领域模型在详情页的使用

隔离的问题解决了,再来谈谈详情页的领域建模。
为何需要领域建模?好多java开发的同学,大都会遇到这样的问题:1)一门OO(面向对象)的语言,写出来的代码都没有OO的感觉,到像是过程式的代码,面向对象的思想基本没有使用到。2)虽然代码满足了业务需求,但从代码中,完全看不到业务领域的影子,业务领域和代码是脱节的。3)随着业务的越来越复杂,里面的依赖关系梳理起来非常困难,业务模块没有边界可言。
为了不给后人挖坑,为了解决详情页复杂的逻辑,为了让代码更有范,为了让接手详情的同学都有统一的业务领域认知,因此决定对详情领域进行领域建模。



图8: 领域驱动设计-模型关系总图
Eric Evans的那本《领域驱动设计——软件核心复杂性应对之道》经典书籍大行其道十几年,网上关于领域建模的文章也是浩如烟海,自顶向下、自底向上、四色原型建模、问题空间领域模型抽象方法论也非常的多。但这些文章和书籍,要么谈论理论概念,要么谈论建模方式,对初学者来说,看完之后,还是写不出相应的代码。
所以本文不在重复的去讲领域建模的概念,直接通过闲鱼详情页这个业务场景,讲述建模的步骤、DDD的代码展示,给读者一个更直观的参考。

2.2.1 详情页领域建模

闲鱼详情页是一个纯展示的页面,用一句话可以概括为,“详情页是包括:商品、卖家、买家、鱼塘、认证、互动等内容的信息聚合展示页” 。
这里我们使用四色原型建模法进行建模。上面的这句话最骨干的内容为:详情页是一个“信息聚合展示页”(瞬间事件)。

image.png
图9: 详情页是一个信息聚合展示页
骨干内容定义好后,为了更好的描述详情页是什么,需要补充一些实体对象,详情页主要包含商品、卖家、买家、鱼塘这些实体(人-物-地点)。


图10: 详情页中包含的主要实体
在此基础上,进一步的进行抽象,用户实体中,有卖家、买家这个角色存在;鱼塘实体中,又有塘主、塘民角色存在(塘主也是塘民,所以塘主应该继承自塘民)。加入角色后的模型如图11所示:


图11: 详情页中的角色
最后,再把一些描述信息放进去


图12: 模型中补充描述信息


有了模型的设计,再转为类图设计。根据模型的抽象,详情页是信息展示的聚合,因此它是个聚合根,包含了商品、卖家、买家、鱼塘这些实体信息。 商品信息描述里,又有视频、图片、文本、互动等信息。视频、图片可以抽象为媒体信息。使用UML设计出最终的类图,如图13所示

图13: 详情页类图结构

2.2.2 DDD代码展示

在实现详情页时,依据的是DDD中的定义。DDD中最主要的内容包括:entity、value object、aggregate、repository、factory和service (如图8所示), 以及Infrastructure, Domain, application和User Interface 分层结构,如图14所示:

图14 领域驱动设计分层架构


Infrastructure主要用于持久化数据的读取和写入;Domain为领域层,提供领域信息,这是业务的核心所在;Application是很薄的一层,没有业务逻辑,用来协调应用活动;User Interface负责用户信息展示。将这个分层结构映射到工程结构如图15所示。

图15:DDD领域建模工程结构
这里的Applicaiton层没有业务逻辑,只作为二方服务对外提供。此外,工程结构中没有写User Interface层,因为该应用是以二方服务提供,当然,如果提供REST服务,则可以写在这一层。
多数的用户对MVC架构比较了解,因此,图16对比了DDD的分层架构和MVC的架构,以做参考。

图16:DDD分层对比MVC分层

根据上文的模型抽象,领域对象主要有 ItemEntity, SellerEnity, BuyerEntity, FishPoolEntity,并通过详情页聚合根DetailAggregate聚合。

图17: 详情页聚合根
在图15应用结构分层中,有3种类型的数据对象,DO对象表示持久化的数据对象, Entity为领域对象,DTO为对外的传输对象。
首先通过领域层的Repository,调用基础设置层的Dao读取DO结构,再使用Convertor转为Entity领域对象。

图18: Repository的定义


图19: Converor转化器的定义
领域entity处理各自的领域业务逻辑,然后通过领域层的DetailService,对聚合根DetailAggregate进行整体详情页业务领域处理。最后转为DTO传输对象提供对外服务。

三: 总结和思考

本文从详情页业务出发,当业务越来越复杂时,如何做业务的隔离,做开发人员的隔离,以及如何通过领域建模,形成统一认知。给大家提供一个可行的参考。
但没有任何一种架构可以适用于所有的场景,也没有任何一个架构是最优的,所谓架构,都在解决“边界”的问题。因此都需要从实际的业务场景出发,明确出问题的边界在哪里,要达到什么样的目标,再遵循一些基本的原则和方法,基本都能够设计出符合自己业务特性的架构。

接下来将会给大家分享一篇从不同的视角出发,进行的业务架构设计。

 


原文链接
本文为云栖社区原创内容,未经允许不得转载。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/519784.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

牵手大企,关于图形计算、HPC与AI,NVIDIA言有尽而意无穷!

戳蓝字“CSDN云计算”关注我们哦!作者 | 晶少出品 | CSDN云计算(ID:CSDNcloud)在黄仁勋看来,随着摩尔定律消亡,GPU加速才是撬动未来高性能计算发展的有力杠杆。有数据显示,目前NVIDIA已经销售了…

如何合理的规划jvm性能调优

JVM性能调优涉及到方方面面的取舍,往往是牵一发而动全身,需要全盘考虑各方面的影响。但也有一些基础的理论和原则,理解这些理论并遵循这些原则会让你的性能调优任务将会更加轻松。为了更好的理解本篇所介绍的内容。你需要已经了解和遵循以下内…

如何衡量研发效能?阿里资深技术专家提出了5组指标

阿里妹导读:新的一年,相信很多产品技术团队把研发效能提升列为重要的目标,甚至还有团队为此专门成立了项目组。然而,到底什么是好的研发效能,却很少有人能够表达清楚。标准不清晰,又何谈提升? …

官宣!2020年,这5类程序员要过苦日子!网友:明年咋活?!

2020年就要来了,有人说:经历了2019年的“市场变革”后,未来这一年将会至关重要,是决定各自命运的定型年。那么对于程序员来说,明年的风向标是如何?哪些编程语言会持续大热,哪些要做好被“淘汰”…

Perseus-BERT——业内性能极致优化的BERT训练方案【阿里云弹性人工智能】

一,背景——横空出世的BERT全面超越人类 2018年在自然语言处理(NLP)领域最具爆炸性的一朵“蘑菇云”莫过于Google Research提出的BERT(Bidirectional Encoder Representations from Transformers)模型。作为一种新型的…

Kubernetes的共享GPU集群调度

问题背景 全球主要的容器集群服务厂商的Kubernetes服务都提供了Nvidia GPU容器调度能力,但是通常都是将一个GPU卡分配给一个容器。这可以实现比较好的隔离性,确保使用GPU的应用不会被其他应用影响;对于深度学习模型训练的场景非常适合&#…

华为云WeLink正式发布,这是更懂企业的智能工作平台一枚!

今日,华为云在京发布智能工作平台WeLink。 对此,华为云副总裁、联接与协同业务总裁薛浩表示:“华为云WeLink源自华为数字化转型实践,是更懂企业的智能工作平台,具备智能高效、安全可靠、开放共赢三大核心优势&#xff…

一致性协议浅析:从逻辑时钟到Raft

前言 春节在家闲着没事看了几篇论文,把一致性协议的几篇论文都过了一遍。在看这些论文之前,我一直有一些疑惑,比如同样是有Leader和两阶段提交,Zookeeper的ZAB协议和Raft有什么不同,Paxos协议到底要怎样才能用在实际工…

PMP 随堂笔记

CPi挣值管理 临界比值 不属于挣值管理 临界比值 1为分界点 党校与1时,差 大于1时为好 成本激励由有3种场景: 第一种场景:超出目标费用 目标10w 利润1w 分摊比例70/30 实际成本12w 也就是多花了(12w-10w(目标费用)2w 甲方罚乙方利润费用&…

Objective-C中的associated object释放时机问题

如果对象A持有对象B,B作为A的associated object,并且表面上B没有其他被强引用的地方,那么对象A被释放时,对象B一定会同时释放吗?大部分情况下是,但真有不是的时候。最近实现代码的时候不小心就碰到了这样的…

开放共赢,华为云WeLink生态联盟正式成立!

今日,华为在京发布了“更懂企业”的智能工作平台华为云WeLink,并携手合作伙伴成立华为云WeLink生态联盟。其中首批加入华为云WeLink生态联盟的伙伴主要包括(排名不分先后):金山办公、中软国际、致远互联、罗技、华为商…

指明方向与趋势!2019开发者技能报告出炉!!!

近日国外开发者平台 HankerRank 发布了 2019 年开发者技能调查报告,该报告根据对71,281开发者的调查得出。 2018 年最受欢迎的开发语言  经过调查,2018年的所有开发语言中,JavaScript是最受欢迎的语言,2017年最受欢…

阿里研究院入选中国企业智库系统影响力榜

2019年2月1日,上海社会科学院智库研究中心发布《2018年中国智库影响力评价与排名》。阿里研究院入围三项排名榜单,位居企业智库系统影响力榜单第2位,中国智库社会影响力榜单第13位,中国智库综合影响力排名榜单第42位。 阿里研究院…

如何给女朋友解释什么是3PC?

戳蓝字“CSDN云计算”关注我们哦!一顿愉快的小火锅之后,悠哉悠哉的回家了,于是只能开始新一轮的家庭科普了。分布式一致性幸好在《漫话:如何给女朋友解释什么是2PC(二阶段提交)?》中介绍过关于2…

Tensorflow源码解析1 -- 内核架构和源码结构

1 主流深度学习框架对比 当今的软件开发基本都是分层化和模块化的,应用层开发会基于框架层。比如开发Linux Driver会基于Linux kernel,开发Android app会基于Android Framework。深度学习也不例外,框架层为上层模型开发提供了强大的多语言接…

基于 Kubernetes 实践弹性的 CI/CD 系统

大家好,我是来自阿里云容器服务团队的华相。首先简单解释一下何为 Kubernetes 来帮助大家理解。Kuberentes 是一个生产可用的容器编排系统。Kuberentes 一方面在集群中把所有 Node 资源做一个资源池,然后它调度的单元是 Pod,当然 Pod 里面可以有多个容器…

35岁真的是一个坎吗?听完35岁码农的话,我放心了!

戳蓝字“CSDN云计算”关注我们哦!之前看过一个有关程序员从刚入职到中年状态的一个视频,刚入职的程序员激情澎湃,一心想做自己想做的事情,并且想创业,就想拉拢身边的程序员同事一起创业,可是身边的同事就一…

开年巨制!千人千面回放技术让你“看到”Flutter用户侧问题

导语 发布app后,开发者最头疼的问题就是如何解决交付后的用户侧问题的还原和定位,是业界缺乏一整套系统的解决方案的空白领域,闲鱼技术团队结合自己业务痛点在flutter上提出一套全新的技术思路解决这个问题。 我们透过系统底层来捕获ui事件流…