关于java:微服务体系中的分层设计和领域划分

4次阅读

共计 11029 个字符,预计需要花费 28 分钟才能阅读完成。

作者:汤波

起源:https://tbwork.org/2018/10/25…

本文取得阿里巴巴《第二届研发效力征文》优良文章奖,并在阿里第二届能效峰会上展出。

引言

看题目感觉这个货色很实践,比起“高并发、多线程”、“分布式 CAP、一致性、Paxos”、“高可用 SLA”等具体的干货技术点,软件体系常识显得很“湿”,仿佛人人都有本人的意识,但又很少有人能说残缺,有一点能够确定的是,如果你将来须要独立设计一个简单的零碎中台,并使之将来能疾速应答各种需要变动的话,科学合理的畛域划分和边界界定须要咱们“处女座级”的坚持下去,这对避免人力失控、缩小我的项目烂尾很有帮忙。正当的界定了边界后,即使某个微服务很蹩脚,也能够就输入输出以很少的人力投入进行重构,相同的就是牵一发而动全身,加上业务需要频繁而来,很容易烂尾或是达不到如期的成果。

其实很多技术大神都是某一个技术点的好手,但可能在整体软件体系上思考并不多,每个人都有本人的设计办法,大部分容易想到的设计办法解决个别的零碎曾经够了,前面产生问题缓缓打补丁就行了,当咱们面对各种需要变动陷入开发窘境的时候咱们就该想想了,咱们零碎的体系设计上是否出了问题?

本文不打算波及领域建模和设计模式等代码级别的详述,而是探讨如何将一个简单的大零碎进行分层和拆分,这是设计一个柔美零碎的第一步,置信对各 BU 共事们疾速搭建零碎中台也是很有参考意义的。文中的一些例子大家也可能遇到过,大家如果在开发中遇到窘境,能够多来圈子交换和发表问题,大家一起学习提高。大略晓得内容背景的能够间接跳到第 3 局部。想理解一个大我的项目如何进行迷信人员安顿的能够间接看 5.4 局部。如果你的组里还有人把数据库模型当接口契约用,能够倡议他看下 5.1 局部。如果你在开发过程中遇到一些他人的开发设计习惯,你感觉不是很好,然而又不晓得如何压服他,都能够到评论区聊聊,大家一起探讨探讨。

1. 摘要

本文论述了一种将分层设计和 DDD 畛域设计思维利用于微服务体系架构的计划实际,也是集体的最佳实际。对于大部分互联网公司来说,咱们主张将其 Web 服务架构分为五层:基础设施层、畛域服务层、应用服务层、网关层和用户界面层(表示层)。

畛域服务层和应用服务层均能够采纳微服务设计进行拆分,其中畛域服务层将依照 DDD 畛域设计进行畛域划分,设计为一个个畛域模块微服务,每个微服务高度内聚,仅关注本人的业务,畛域服务间通过接口调用进行松耦合。这种设计方案能够大大简化大零碎,并且在前期的保护中劣势会日渐凸显,然而把大零碎分而治之拆成微服务同时也对架构师和开发人员提出了更高的要求。

第 2 局部介绍了相干背景,接着第 3 局部探讨了分层设计以及每一层的性能,第 4 局部联合微服务和 DDD 对畛域服务层进行服务模块划分和设计。第 5 局部则就分层设计和 DDD 畛域设计中常见的问题进行了整顿。

2. 背景介绍

想写这样一篇文章很久了,尽管本迷信的是软件工程,但碍于本人能力无限,从 08 年写代码以来始终断断续续的思考,始终对我的项目模块设计和分层结构设计没有一个能够让本人感觉称心且无纠结点的答案,假如了某个设计,很快在实践中又会发现其存在着一些问题。直到 2014 年毕业工作理解了 DDD 畛域驱动设计后,才有了绝对清晰的方向。实际上早在 2004 年,Eric Envas 的《畛域驱动设计:软件外围复杂性应答之道》就已出版,毕竟软件开发自计算机遍及以来曾经存在很长一段时间了,晚期国外程序员对软件开发实践的钻研也非常昌盛,现在成熟后反而钻研的绝对少了,基本上依葫芦画瓢即可。

DDD 畛域驱动设计对软件设计各个环节的人员都有较高的要求, 用《畛域驱动设计》一书的话来说它须要一个“畛域驱动团队”[1],它要求从分析阶段,产品经理、项目经理、架构师以及开发工程师就应用对立的模型语言(Ubiquitous Language)来进行沟通,并且他们都懂一些代码、产品和建模相干的常识,事实上这在国内很难施行,国内的产品经理约等于需要整顿工,对其计算机根底的要求是少之又少,在我所从事的公司里,也曾产生过产品经理间接领导开发,以至于前面单方了解的同一个词有着不同含意的状况。所以本文不打算去论述 DDD 畛域外部建模代码级别的实际,甚至本文并不认为贫血模型是不好的,本文次要探讨畛域之间的划分和分层设计,正如引言说提到的,这是设计柔美零碎的第一步。另外提一句:其实正当设计的微服务体系中的服务自身就是性能繁多边界清晰的小利用,届时贫血也好、DDD 领域建模也好,其实都能够胜任。

近年来,随着分布式的倒退,传统中小型机集中式服务器曾经不在风行,所以微服务体系也成为了各大互联网公司支流的抉择。直观的感触下 微服务 DDD两者,仿佛一个是微零碎,另一个则是大零碎的设计办法,仿佛两者天生互斥,微服务化的小零碎也用不着 DDD,其实并不是,DDD 是针对整个简单的软件解决方案的一种迷信设计办法,微服务化也是把简单的大零碎拆分为小零碎,不便保护和治理,所以两者都有一个特点——为简单的大零碎服务。上面咱们就来探讨下,如何把 DDD 的畛域设计和其主张的分层设计利用到微服务体系架构中。须要阐明的是本文次要是集体多年来的一点总结,未必适宜所有场景,有更好通用性更为宽泛的计划请不吝赐教。

3. 分层设计

精确的说分层设计(Layered Architecture)跟 DDD 没有必然的分割,我最早接触分层设计是在携程网,过后外部应用的应该只是简略的业务层(Biz)和表示层,数据库拜访之类的也是放在各自的业务包下的。起初接触和学习了《畛域驱动设计:软件外围复杂性应答之道》,书的第 4 章“拆散畛域”中说到了四层分层设计,即:基础设施层、畛域层、应用层和用户界面层(表示层)。DDD 产生的年代微服务还未风行,过后甚至基于浏览器的 Web 利用都比拟少,更多的是 PC 软件和 EJB 等网络应用,所以作者更多的是想表白对简单零碎的逻辑分层,并不在意每个畛域是独自的零碎还是一个软件系统内不同的模块。

所以为了跟其做辨别,咱们倡议的四层为在其根底上引入“服务”两个字,即:基础设施层、畛域服务层、应用服务层和用户界面层。这样做的用意是让开发人员立即能够理解到——每个畛域模块即一个微服务(一个畛域能够对应一个或者多个模块 Module)。摘要中提到咱们主张的分层体系中还有一个层,即 网关层 ,这又是什么鬼呢。刚刚提到的 DDD 的时代背景,PC 软件系统或者企业外部应用的网络应用零碎是基本没有网关层(有也是网络网关设施)这一说的,而现如今互联网公司产品的输入模式无外乎 Web 利用(网站、或者网络服务),并且为了更好的适配 PC 站和 App,个别会采纳 前后端拆散 的利用设计方案,这时候会产生一个需要——外部网络应用零碎如何把本人的服务输入到互联网上,供内部零碎或者浏览器网页拜访。最间接的形式就是把应用层间接裸露在公网上,但咱们不倡议这么做,应用层服务更多的是关注业务利用,对网络级的零碎安全性(防 DDOS、钓鱼、跨域等)、申请监控等不足思考,这些工作交给网关层对立治理会轻松很多(比方淘宝的 TOP 平台)。

这时候咱们在 Web 利用零碎中引入网关层用于连接 表示层 应用层,因为这样能够更好的划分各层的职能。网关层也能够看作是应用服务层的对外包装层。如果肯定要把网关层做到应用服务层里实践上也是可行的,比方针对于 Spring Cloud 这种框架下的微服务体系,能够思考间接裸露应用层,只需辅助一些运维伎俩进行对立的平安验证和监控即可。假如咱们抉择引入网关层,那么咱们就失去了以下网络应用零碎分层体系:

其中,各层的职能和作用为[2]:

  • 用户界面层:负责向用户显示和解释用户指令。这里指的用户能够是另一个计算机系统,不肯定是应用用户界面的人(比方内部利用调用对应接口)。在全零碎的视角看,通常状况下,这里指的是前端,但实际上,随着前端的日益简单,前端也能够分为多层,那种状况另当别论。
  • 网关层:负责提供对外的 HTTP 服务或者其余网络应用层协定(这里是指 OSI 七层协定中的应用层,别混同了哦)服务。该层从非业务逻辑角度对裸露到内部的接口进行鉴权、计费、风控、资源调配等操作。有些繁难的零碎中,改成能够合并入应用服务层中作为一个 AOP 存在。
  • 应用服务层:定义软件要实现的工作,并且指挥表白畛域概念的对象来解决问题。这一层所负责的工作对业务来说意义重大,也是与其余零碎的应用层进行交互的必要渠道。应用层要尽量简略,不蕴含业务规定或者常识,而只为下一层中的畛域对象协调工作,调配工作,使他们相互合作。它没有反馈业务状况的状态,然而却能够具备另外一种状态,为用户或者程序显示某个工作的进度。
  • 畛域服务层:负责表白业务概念,业务状态信息以及业务规定。只管保留业务状态的技术细节是由基础设施层实现的,然而反馈业务状况的状态是由本层管制并且应用的。畛域层是业务软件的外围。
  • 基础设施层:为下面各层提供通用的技术能力,为应用层传递音讯,为畛域层提供长久化机制,为用户界面层绘制屏幕组件(PS:这个在互联网利用中简直用不到)等等。互联网 Web 利用零碎中基础设施蕴含了数据长久化服务,中间件服务(数据库,Redis,Memcached,zookeeper,ELK 等等)以及第三方服务等。

各层除了实现本人的性能外,还须要恪守以下准则:

  1. 每一层设计放弃内聚,并且只依赖于它的下方的层。
  2. 上层向下层发动的通信只能通过中间件等间接形式进行。[2]
  3. 下层和上层只能有涣散耦合(各自为独立个体,通过简略援用关联)。在某些微服务框架比方 Dubbo 中,能够把 api 包提供给下层援用即可。这也合乎依赖倒置准则。

这里重点阐明应用服务层和畛域服务层之间的关系。举一个我常常跟部门其余开发举的一个例子:有一家上市企业 A 公司,靠卖水果发家,其首席架构师科学合理的依照 DDD 搭建了一套基于微服务体系的卖水果利用,其架构图如下:

往年水果行情个别,而房地产非常炽热,A 公司高层发现房地产带动的五金行业也非常炽热,于是下达任务给技术部,要求其立刻着手搭建五金销售零碎,货源曾经谈好。得益于首席架构师之前优良的架构设计,他发现只须要做一个卖五金的网站以及另外对微服务进行微量的调整即可满足老板的需要——因为卖五金和卖水果并无本质区别,他们波及的环节简直统一。退出五金售卖的零碎架构图如下:

可见应用服务层代表是某一个业务利用,它代表的更多的是从需要登程的利用定义,而畛域服务层则是业务畛域依照本身的边界进行设计的一个高内聚的服务体。应用层通过协调和组合各个领域服务即可造成一个新的应用服务。《畛域驱动设计》中明确指出,在设计畛域服务时无需思考表示层和长久层服务的货色。我在事实开发中总是遇到大量工程师依照产品的设计稿一溜烟的从上至下设计应用层服务和畛域层服务,齐全没有思考业务畛域的概念,导致前面微服务数量收缩,性能反复度高。这种开发习惯代表的是《畛域驱动设计》作者竭力吐槽的一种模式——SMART UI“反模式”[5]。

4. 畛域划分和微服务化

依据 DDD 实践,领域建模次要产生在畛域服务层,各畛域模块都应该是高内聚低耦合的,具备清晰的业务边界。本文不打算探讨具体的 DDD 建模(服务,工厂,仓库,实体,值对象,聚合等),这须要对 DDD 有较深刻的钻研,就目前所从事过的公司来看,仿佛没有一家真正严格依照 DDD 进行我的项目代码设计的,就像摘要中说的,这对整个软件工程链路上的人员都有较高的要求。有机会能够独自写一篇对于本人对 DDD 建模的思考和倡议,本文更多的是探讨高视角下的畛域服务拆分,从而搭建一个低耦合高内聚的微服务体系。如果肯定要将微服务和 DDD 分割起来的话,畛域层的微服务就对应了 DDD 中的畛域模块 Module,每个 Module 由多个 Service 模式对象以及对应的模型对象(实体, 值对象以及它们的聚合)组成。

从《畛域驱动设计:软件外围复杂性应答之道。》中我学到的次要有两块:畛域设计思维和领域建模模式。本文更多的是对前者的使用,后者的对抗模式是贫血模型,大家日常用到的也都是贫血模型,我也感觉贫血模型有存在的必要性,所以本文咱们次要从其中借鉴一下畛域设计思维。本文所形容的设计理念,并不影响具体的模型设计办法,咱们依然能够在每个微服务中应用 DDD 领域建模。

如何切分畛域模块并没有一个明确的规定,不同的场景下可能雷同的业务块边界也不尽相同。这里提几点畛域划分的集体心得:

  • 畛域设计肯定要有清晰的性能边界。一个畛域服务对应了一个性能汇合,这些性能肯定是有一些共性的。比方,订单服务,那么创立订单、批改订单、查问订单列表,个别是订单域的性能汇合。
  • 畛域拆分并不是一步到位的,该当依据理论状况逐渐开展。从单体利用到微服务体系的拆分过程能很好的阐明这个问题,一上来拆的很细的革新计划肯定会死的很惨。所以如果一开始不晓得应该划分多细,齐全能够先粗粒度划分,而后随着须要,初步拆分。比方一个电商一开始索性能够拆分为商品服务和交易服务,一个负责展现商品,一个负责购买领取。随后随着交易服务越来越简单,就能够逐渐的拆分成订单服务和领取服务。
  • 畛域拆分并不是变化无穷的,该当具体情况具体分析。2015 年在公众点评的时候,其订单服务就拆分为了 order-service 和 order-query-service,一来为了读写拆散,二来 order-query-service 作为独自利用能够按需程度扩容。
  • 畛域能够是多个子畛域的一个虚构汇合,换句话说多个微服务也能够造成一个大域,不用纠结于畛域和微服务之间的数量对应关系。咱们在做架构设计 PPT 的时候可能就把订单域作为一个畛域,代表了这个域就是对于订单的,具体该有几个微服务,这须要更细的具体设计来提供。
  • 畛域层服务设计该当是调用者无关的。这一点有点像第一点,然而它强调的是畛域层服务的设计不应该受调用者的影响,这个观点在《畛域驱动设计:软件外围复杂性应答之道》这本书里也能够找失去[4]。畛域层服务开发和设计的理念是关注本人的域,一旦边界划分分明了,开发所须要思考的永远都只是输出和输入,提供的服务肯定是尽可能通用的,面向性能来开发的,而不是面向调用方来开发的。比方某个调用方提出了一个需要:调用方 B 心愿 A 服务提供一个买汽车的接口,那么 A 服务设计的接口就应该是 buyCar(),而不是 buyCarForB()。

5.Q&A

5.1 能不能在所有层应用数据长久层模型,简略快捷?

大家肯定据说过不同层的数据模型的叫法不同的概念,比方数据长久层的模型对象叫 DBO(database object)或者 DPO(data persistence object), 畛域层的模型对象叫 DMO(Domain Model Object)或者就叫 Model,数据传输层的模型对象叫 DTO(Data Transfer Object)。那为啥要这么多模型呢,间接应用 Mybatis 等 ORM 框架生成 DBO,而后一路吐给前端不是更爽(还真有共事尝试立项写 Mybatis 插件来实现这种所谓的代码自动化)。我集体倡议如果您真的是要搭建一个简单的大零碎,大平台,肯定不要偷这种懒,最好的就是做到”一层一模型”(网关层应用应用层模型即可)。各层之间采纳手动的数据赋值(getter,setter)来实现,或者应用一些转换框架来简化转换代码,集体在用 getter/setter 时感觉并不会耽搁什么,在一个个 set 的时候,恰好能够对模型的字段细节进一步确认,并且回绝应用 BeanUtils.copyProperties()这种工具类,因为这样的工具类会让”一层一模型”形同虚设,开发会热衷于把 DPO 拷贝到畛域中换个名字以保障能够用拷贝工具。上面咱们来细谈下不能在每一层都是用数据长久层模型的具体起因:

  • 应用层对接网关层,是向面向 C 端或者调用者的一个数据进口,然而调用者只须要这个进口输入用户感兴趣的数据,并且有些敏感数据不能吐进来。如果应用层(面向调用者)应用的依然是数据库模型,而开发人员没有在应用层把无关值置空的话(置信我,需要一多,工作一忙,鬼才会在意这些细节),那么数据库里的整条记录就作为接口输入吐进来了。比方订单记录,用户订单列表可能只须要订单 ID,商品名称,订单金额。而像商家结算价这种就不能吐进来,万一被有心人察觉到了,用户肯定会投诉——你跟商家结算价 200,卖给我 400?
  • 前端或者接口调用方会很苦楚,一个接口契约多一两个无关字段是没关系的,然而一个契约里给的 30 个字段,我只用到 5 个,前端会骂娘的,我亲眼见过这种事,设计准则里有个准则叫”迪米特法令”,也叫最小常识准则,接口设计也能够参考这个准则,尽量让你的调用方晓得尽可能少的信息点就能实现相干的工作。
  • “一层一模型”实质是解耦模型依赖。我在上家公司做架构师时为了兼顾开发的感触,决定让他们能够在畛域层和基础设施层都是用数据长久层模型,而只须要在应用层做数据管制(解决第一个问题),然而我的斗争也缓缓露出弊病,开发有时候感觉某个数据库字段命名不适合批改之后,整个援用了该模型的微服务都须要批改,如果一层一模型的话,只须要关联数据库拜访的服务批改下 DPO 和 DM 的映射就行了,其余下层微服务都是依赖 DM 的。尽管咱们不激励随便改变数据库字段,但设计框架上最好能反对这种状况。

刚开始推广”一层一模型”的时候,会有耍小聪明的开发去把下一层的模型 POJO 间接拷贝过去改个名字,而后用 BeanUtils.copyProperties()实现赋值,这样跟间接应用数据长久层模型就没有区别了,所以要杜绝这种状况的产生。

5.2 为啥须要应用层,畛域层微服务间接通过网关裸露不就行了吗?

对于习惯了单体利用开发者来说,一个微服务很可能就直观对应成了一个个垂直的应用服务,每个服务间的关系是这样的:

其实这样的体系实质上依然不能解决软件的复杂性,这只是把零碎简略粗犷的拆分了,耦合问题依然很重大,甚至这很有可能比原来的单体利用更简单(多对多依赖),如果应用微服务体系来解决简单零碎,其服务体系该当是这样的:

这两幅图的区别在于,其实第一幅图中的每个服务都蕴含了残缺的 2~3 层,所以不再须要独自的应用层。而第二幅图各个领域模块相互合作,对外提供服务时,则须要有一层直面用户需要的应用层。

达成了微服务体系是解决简单零碎的前途之一这个共识后,咱们再来看”应用层服务存在的必要性”有哪些理由:

  • 对立权限校验 :如上文所说,网关层只负责网络级的平安防护,业务层的权限校验则须要应用层来实现,试想一个没有应用层的微服务体系,就意味着每一个微服务都须要加上权限校验逻辑,这不仅编码上艰难(能够用过滤器,AOP),而且对于成千上万个微服务(据理解,腾讯目前微服务数量曾经超过 2 万,公众点评有将近千个微服务)来说,这会节约大量工夫,调用链越长,节约的工夫越多。换句话说,微服务体系有一个不突出然而很重要的特色—— 畛域间环境平安,畛域间的通信该当是可信的,否则分布式的毛病(多服务意味着屡次通信)会被加剧。
  • 业务数据网关 :举个例子,一个 order-service 提供了一个 queryOrder 的接口,输出起始日期查问对应的订单列表,其有 2 个消费者: C 端网站应用服务 报表应用服务 C 端网站应用服务 只须要晓得订单的根本信息如下单工夫、商品名称、金额就能够了,而报表应用服务是给管理者看的,须要的订单数据很全,除了 C 端网站应用服务 须要的之外,还须要看平台与商家的结算金额。依据第 4 局部最初一点的思路,咱们必定不能为调用方写定制接口(写不完的,有的要这个数据,有的要那个数据,每次新增调用方,畛域服务还得找人批改)。而如果咱们对立应用的全量数据,并且没有应用层(同样的也没有应用层模型 DTO 了),那么很可能咱们吐进来的数据蕴含了咱们与商家的结算价,这会引发很多不必要的麻烦的。所以应用层还充当了业务数据网关的作用,应用层应用服务须要保障仅吐出调用方感兴趣的数据。
  • 资源管制和缓存:设想一下双十一高并发的状况,如果查问库存每次都查库是如许恐怖的一件事。所以个别仅在领取的时候做一次库存校验,而在商品展现时查缓存的库存即可。那么问题来了,如果没有应用层,缓存间接放在库存微服务上是否可行呢?首先这会入侵库存畛域,库存微服务须要依照调用方的需要做特定工夫的缓存,而不是本人想缓存多久就多久,我想库存微服务的开发者也会很不满的,他会提出,让你本人去做缓存。他的计划是迷信的,因为还有一些其余服务可能须要实时的数据。这时候就须要有一层来做对其下方微服务返回的数据依照利用本身的需要进行必要的缓存,而不是把这些需要都推给资源提供方,设想一下一个资源提供方有多少需求者,每个需求方都有本人的定制需要,该多苦楚。当然这一点也不是说微服务本身不能做缓存,微服务本身的缓存肯定是思考本身域的合理性后的一个措施(比方订单查问服务会做一个 500ms 的缓存,因为不会有正常人 500ms 里点两次查问还必须要求两次都是最新的),而不是由调用方来决定的。
  • 资源聚合和加工:其实第 2 点也有加工的滋味在外面,只是这里更多的是形容应用层利用依据本身需要来对上层返回的数据进行聚合和解决的过程。举个例子就能很好的阐明这一点:任何 APP 都有首页,而首页的数据可能是形形色色的,能够有用户昵称、最近下的订单简要信息、最近收入曲线、积分信息等。这 4 个信息能够来自 4 个畛域微服务,他们是:用户核心、订单核心、领取核心和积分核心。那么有读者会说,间接裸露微服务让前端别离调用 4 个接口再做聚合不是也行吗?显然这种粗犷的形式是极其不合理的,会额定减少广域网网络调用 3 次不说,还传输了很多不必要的信息。
  • 利用隔离和流控:如果将每个畛域服务间接裸露到网关层对外提供服务,那么在多利用场景下,多个利用间是共享这些服务能力的,在服务降级的时候,如果须要依照利用进行降级(比方将优先级不高的利用进行限流),就很难实现。但如果每个利用对应了一个应用层服务,只须要对其裸露的网关接口进行对立限流就行了,或者在应用层做一个开关,将其流量阻止在应用层,而不是拖垮整个畛域服务。举个例子,如果咱们的平台不仅有本人的网站服务,还有第三方的对接服务,如果某个第三方被攻打而咱们间接将畛域服务裸露了进来,那么咱们就须要在各个领域层服务里去编写对应的开关,这将侵入畛域层服务,导致不必要的耦合。而有了应用层这些都不是问题,因为应用层充当了一个调度者的角色,调度者能够很轻松的决定是否调度上层的服务。

为了加深对应用层的了解,咱们举个代码的例子,如果咱们写一个很简略的首页利用:

Response getHomeData(Request request){String nickName = userService.getNickName(request.getUserId()); 
    OrderInfo orderInfo = orderService.queryLatestOrder(request.getUserId());
    CostTrend costTrend = payService.queryCostTrend(request.getUserId());
    Integer points = pointService.queryAvailablePoints(request.getUserId());
    return new Response(nickName, orderInfo, costTrend, points);
}

这里的 4 个服务类实例 userService,orderService、payService 和 pointService 如果都是本地的办法,那么这就是一个单体利用,而微服务化后这 4 个可能都是微服务了,然而应用层利用的构造还是能够不必变动(当初很多的 RPC 框架都做到了与调用本地办法无差别)。这就是应用层的地位所在。

5.3 什么是反模式?

这里的反模式是指《畛域驱动设计:软件外围复杂性应答之道》这本书里提到的与 DDD 相违反的模式,也是 Eric 极其拥护的一种模式,即 SmartUI 模式(留神反模式不等于 SmartUI,只是在本书中作为一个反模式的例子而已),这是一种什么样的模式呢,其实我很早之前做 C ++ Builder(和 Delphi 很像)的时候还不晓得,C++ Builder 就是一种 SmartUI 模式。但其实 SmartUI 并没有错,对于小规模的 PC 本地利用开发来说也是有很多益处的。举个例子,C++ Builder 中在窗体上增加一个按钮,而后双击按钮增加事件,这样就跟实际操作的时候有机的联合了起来。换句话说就是应用界面驱动业务开发。在大型零碎的开发上,这种模式是害人精,我很了解 Eric 为啥这么厌恶它。曾有一次我率领着一个团队做封闭式开发,在过完产品需要后,家里出了点事我请了几天假,回来后发现产品经理居然指挥让开发依照 UI 原型来设计数据库,我审核的时候发现这些开发设计的表有极其多的冗余,而有一些重要的过程变量值却没有思考到。比方他们会为每个页面建几个表,这显然是行不通的,迷信的办法是拆分畛域,每个畛域本人建设本人的表。UI 只是应用层整合了各畛域服务的数据并且解决后输入的一种展现。

5.4 分层设计的开发步骤是怎么的?

假如咱们以一个规范的 SaaS 我的项目为主,也就是表示层是前端页面(能够是 APP,H5,M 站,小程序,PC 站等),那么高效的一种开发步骤能够是这样的:

  1. 业务、产品、开发 PM 进行需要评审(可行性等)
  2. 产品筹备好原型
  3. 产品、开发(前后端)、架构师(或有架构师能力的资深开发)散会过 PRD,理解要做什么
  4. 架构师开始设计畛域(资深架构师一下午就能搞定),前端开始切图,应用层开发开始依照 UI 和 PRD 设计前端每个页面应用的 Restful 接口(比方间接 Springfox 代码生成 Swagger)
  5. 架构师设计完畛域后分工给畛域层开发,进行畛域边界明确,而后畛域层开发开始设计数据库表等。
  6. 这样前后端开发就同时动工了。
  7. 开发初步实现后,自测加连调。
  8. 后续就是测试公布了。

具体阶段和工夫线能够参考下图:

6. 结语

实在技术开发日常探讨的常常是高并发、多线程、大数据,分布式、RPC,很少有人探讨软件架构设计方面的,架构师文化不应该只是对某个技术点的深刻开掘,也应该多探讨些大型软件设计理念方面的~ 欢送大家有任何软件 / 零碎 / 平台设计办法方面的问题一起来留言区探讨~

参考文献

  1. 畛域驱动设计:软件外围复杂性应答之道。Eric Envas,2016 年 6 月第二版,前言局部。
  2. 畛域驱动设计:软件外围复杂性应答之道。Eric Envas,2016 年 6 月第二版,Page.44。
  3. 畛域驱动设计:软件外围复杂性应答之道。Eric Envas,2016 年 6 月第二版,Page.45。
  4. 畛域驱动设计:软件外围复杂性应答之道。Eric Envas,2016 年 6 月第二版,Page.46。
  5. 畛域驱动设计:软件外围复杂性应答之道。Eric Envas,2016 年 6 月第二版,Page.48。

近期热文举荐:

1.1,000+ 道 Java 面试题及答案整顿(2021 最新版)

2. 别在再满屏的 if/ else 了,试试策略模式,真香!!

3. 卧槽!Java 中的 xx ≠ null 是什么新语法?

4.Spring Boot 2.5 重磅公布,光明模式太炸了!

5.《Java 开发手册(嵩山版)》最新公布,速速下载!

感觉不错,别忘了顺手点赞 + 转发哦!

正文完
 0