这些年背过的面试题——领域模型落地篇

简介: 本文是技术人面试系列领域模型落地篇,也是面试题系列的完结篇,感谢大家对本系列文章的支持~面试中关于领域模型落地都需要了解哪些内容?一文带你详细了解,欢迎收藏!

一、拆分微服务

微服务内高内聚,微服务间低耦合。

微服务内高内聚即单一职责原则


每个微服务中的代码变化都是同一类原因。因这类原因而需要变更的代码都在这个微服务中,与其他微服务无关,那么就可以将代码修改的范围缩小到这个微服务内。把这个微服务修改好了,独立修改、独立发布,该需求就实现了。这样,微服务的优势才能发挥出来。


微服务间低耦合开放封闭原则


就是说在微服务实现自身业务的过程中,如果需要执行的某些过程不是自己的职责,就应当将这些过程交给其他微服务去实现,你只需要对它的接口进行调用。这样,微服务之间的调用就实现了解耦。


领域建模就是将一个系统划分成了多个子域,每个子域都是一个独立的业务场景,每个子域的边界就是“限界上下文”。该业务场景会涉及许多领域对象,但分析建模始终需要围绕着业务场景的上下文进行。


领域事件通知机制最有效的方式就是通过消息队列,实现领域事件在微服务间的通知。


“核心通讯录”微服务只负责发送变更消息到消息队列,不管谁会接收并处理这些消息; “门禁管理”微服务只负责接收照片变更消息,不管谁发送的这个消息。


二、关联微服务

  1. 按照限界上下文进行微服务的拆分,将领域模型划分到多个问题子域
  2. 基于充血模型与贫血模型设计各个微服务的业务领域层(Service、Entity、Value)
  3. 通过领域事件通知机制和微服务调用的推拉结合,将各个子域进行解耦关联
  • 核心:
  • 通讯录 | 短信 | 推送通知 | 支付 | 文件服务
  • 智慧通行

解决物业多品牌、多系统应用造成的信息孤岛,数据混乱的问题

  • 人脸门禁 | 可视对讲 | 电梯梯控 | 停车系统 | 访客预约
  • 安全社区

通过图像视频识别、传感数据采集,实现报警联动和风险预警

  • 视频监控 | 周界报警 | 高空抛物 | 跨域追踪
  • 全屋智能

围绕业主需求,逐步引入社区医疗、社区养老、社区团购、社区家政等服务

  • 超级面板 | 无线门锁 | 烟感雾感
  • 增值服务

实现跨品牌的产品体验,支持基于matrix引擎的智能生活场景裂变能力

- 智能充电 | 云广播 | 出入提醒 | 定向投放


三、微服务的落地

通过合理的微服务设计,尽量让每次的需求变更都交给某个小团队独立完成,让需求变更落到某个微服务上进行变更。唯有这样,每次变更只需独立地修改这个微服务,独立打包、独立升级,新需求独立实现,才能发挥微服务的优势。
  • 数据隔离:数据库中用户信息表的读写只有通讯录微服务。当其他微服务需要读写用户信息时,就不能直接读取用户信息表,而是通过 API 接口去调用通讯录微服务。
  • 接口复用:因此,当多个团队向你提需求时,必须要对这些接口进行规划,通过复用尽可能少的接口满足他们的需求;当有新的接口提出时,要尽量通过现有接口解决问题。
  • 向前兼容:当调用方需要接口变更时怎么办?变更现有接口应当尽可能向前兼容,即接口的名称与参数都不变,只是在内部增加新的功能。宁愿增加一个新的接口也最好不要去变更原有的接口。
  • 本地调用:访客申请微服务的本地,增加一个查询用户Service的 feign 接口。这样,访客申请Service就像本地调用一样调用查询用户Service,再通过 feign 接口实现远程调用。这种防腐层的设计,可以隔离当前微服务以外的其他微服务拆分变更导致的接口的失效的影响。
  • 数据库去中心化:
  • 微服务中通讯录服务健康码服务分别对应的用户库与权限库,它们的共同特点是数据量小但频繁读取,可以选用小型的 MySQL 数据库并在前面架设 Redis 来提高查询性能;
  • 微服务中访客通行生活缴费分别对应的通行记录库、订单库,其特点是数据量大并且高并发写,选用一个数据库显然扛不住这样的压力,因此可以选用了 TiDB 这样的 NewSQL 数据库进行分布式存储,将数据压力分散到多个数据节点中,从而解决 I/O 瓶颈;
  • 微服务中数据分析通讯录查询这样的查询分析业务,则选用 NoSQL 数据库大数据平台,通过读写分离将生产库上的数据同步过来进行分布式存储,然后宽表一系列的预处理,应对海量历史数据的决策分析与秒级查询。( NoSQL 为空的字段是不占用空间的,因此字段再多都不影响查询性能)


四、领域模型的意义

贫血模型、充血模型、策略模式、装饰者模式只是DDD实现的方式,而DDD的真谛是领域建模

做事不能仅凭一腔热血,一定要符合自然规律。其实软件的设计开发过程也是这样。对业务理解不深刻全局架构设计往往是过度设计,这时候应该抓主要流程,开始领域建模。

  • 接着,每次添加新功能的时候,一方面要满足当前的需求,另一方面业务相关的领域建模设计刚刚满足需求,从而使设计最简化、代码最少。
  • 这样的设计过程叫小步快跑。采用小步快跑的设计方法,一开始不用思考那么多问题,从简单问题开始逐步深入。领域模型就像小树一样一点儿一点儿成长,最后完成所有的功能。

保持软件设计不退化的关键在于每次需求变更的设计,只有保证每次需求变更时做出正确的设计,才能保证软件以一种良性循环的方式不断维护下去。

有没有一种方法,让我们在第十次变更、第二十次变更、第三十次变更时,依然能够找到正确的设计呢?有,那就是领域驱动设计。

那么在每次需求变更时,将变更还原到真实世界中,看看真实世界是什么样子的,根据真实世界进行变更。


五、战略建模

image.png

六、相关名词

领域和子域(Domain/Subdomain)


上下文地图构建的领域中,对应模块,使用限界上下文划分领域,对应微服务


限界上下文(Bounded Context)


在一个领域/子域中,有概念上的领域边界,任何领域对象在该边界内部的有不依赖外部的确切含义。


领域对象


服务、实体与值对象是领域驱动设计的领域对象,可以通过贫血模型充血模型转换为程序设计


实体和值对象


通过一个唯一标识字段来区分真实世界中的每一个个体的领域对象,称为实体。真实世界中那些一成不变的、本质性的事物的领域对象,称为值对象。可变性是实体的特点,而不变性则是值对象的本质。


贫血模型与充血模型


POJO对象中只保存get/set方法,没有任何业务逻辑,这样的设计被称为贫血模型。


充血模型是封装和继承思想的体现,门禁设备实体中,包含特征值下发、广告下发、通行记录回调等方法,不同厂商的实体针对多态进行聚合,并通过工厂或仓库对外提供服务。在充血模型中, Service 只干一件非常简单的事,就是直接去调用对象中的工厂方法生成不同产品,其他的什么都不干。


聚合


聚合体现的是一种整体与部分的关系。正是因为有这样的关系,在操作整体的时候,整体就封装了对部分的操作。如何正确理解是否存在聚合的关系:就是当整体不存在时,部分就变得没有了意义。部分是整体的一个部分,与整体有相同的生命周期。


工厂


通过装配,创建领域对象,是领域对象生命周期的起点。譬如,系统要通过 ID 装载一个访客申请:


  1. 表单工厂分别调用表单信息DAO、表单明细 DAO 和用户DAO 去进行查询;


  1. 将得到的表单明细对象、用户对象进行装配,分别 set 到表单信息对象的表单明细与用户属性中;


  1. 最后,表单工厂将装配好的表单对象返回给表单仓库。


仓库


如果服务器是一个非常强大的服务器,那么我们不需要任何数据库。系统创建的所有领域对象都放在仓库中,当需要这些对象时,通过 ID 到仓库中去获取。


  • 当客户程序通过 ID 去获取某个领域对象时,仓库会通过这个 ID 先到缓存中进行查找:
  • 查找到了,则直接返回,不需要查询数据库;
  • 没有找到,则通知工厂,工厂调用 DAO 去数据库中查询,然后装配成领域对象返回给仓库。
  • 仓库在收到这个领域对象以后,在返回给客户程序的同时,将该对象放到缓存中。


【这些年背过的面试题】系列文章欢迎点击阅读原文查看合集!



来源  |  阿里云开发者公众号
作者  |  淘苏

相关文章
|
10月前
|
存储 安全 Java
面试~双亲委派模型
面试~双亲委派模型
60 0
|
2月前
|
存储 缓存 NoSQL
Redis常见面试题(二):redis分布式锁、redisson、主从一致性、Redlock红锁;Redis集群、主从复制,哨兵模式,分片集群;Redis为什么这么快,I/O多路复用模型
redis分布式锁、redisson、可重入、主从一致性、WatchDog、Redlock红锁、zookeeper;Redis集群、主从复制,全量同步、增量同步;哨兵,分片集群,Redis为什么这么快,I/O多路复用模型——用户空间和内核空间、阻塞IO、非阻塞IO、IO多路复用,Redis网络模型
Redis常见面试题(二):redis分布式锁、redisson、主从一致性、Redlock红锁;Redis集群、主从复制,哨兵模式,分片集群;Redis为什么这么快,I/O多路复用模型
|
1月前
|
机器学习/深度学习 算法 数据挖掘
|
2月前
|
消息中间件 编解码 网络协议
京东面试 rockmq是推消息还是拉消息?他的消息模型是啥?
RocketMQ采用拉模式结合长轮询模拟推效果,减少延迟并优化资源使用。在长轮询中,服务器在无消息时保持请求开放,待有新消息时立即响应,提升实时性。利用Netty的TCP连接和异步处理,RocketMQ构建高效通信协议,适应不同吞吐量和实时性需求场景,兼顾控制与实时响应。
34 0
京东面试 rockmq是推消息还是拉消息?他的消息模型是啥?
|
2月前
|
存储 算法 安全
Java面试题:给定一个可能产生内存泄漏的场景,如何诊断并解决?实现一个生产者-消费者模型,使用适当的同步机制与并发工具类,Java并发工具包与框架:性能与调优
Java面试题:给定一个可能产生内存泄漏的场景,如何诊断并解决?实现一个生产者-消费者模型,使用适当的同步机制与并发工具类,Java并发工具包与框架:性能与调优
24 0
|
4月前
|
消息中间件 监控 Java
滴滴面试:谈谈你对Netty线程模型的理解?
Netty 线程模型是指 Netty 框架为了提供高性能、高并发的网络通信,而设计的管理和利用线程的策略和机制。 **Netty 线程模型被称为 Reactor(响应式)模型/模式,它是基于 NIO 多路复用模型的一种升级,它的核心思想是将 IO 事件和业务处理进行分离,使用一个或多个线程来执行任务的一种机制。** ## 1.**Reactor三大组件** Reactor 包含以下三大组件: ![image.png](https://cdn.nlark.com/yuque/0/2024/png/92791/1717079218890-89000a00-48bc-4a1a-b87e-e1b6
53 2
|
4月前
|
微服务 中间件 Nacos
01.【微服务架构】服务注册与发现:AP和CP,你选哪个?-- 面试准备+基本模型
【5月更文挑战第2天】面试准备应涵盖公司所使用的注册中心类型及其优缺点,了解其集群规模、QPS和机器性能。准备故障排查及优化案例。若公司未采用微服务,可熟悉ZooKeeper、Nacos或etcd的基本特性以讨论注册中心概念。面试时,可将话题引导至服务注册与发现,如被问及特定中间件,阐述为何选择它并讨论优缺点。当涉及微服务高可用性时,可强调服务注册与发现的作用。基础模型部分,需解释服务上线和下线流程,提及注册数据和分组功能,并举例说明。最后,简述服务注册与发现的高可用挑战。
90 8
|
4月前
|
数据可视化 Python
Python模型评估与选择:面试必备知识点
【4月更文挑战第17天】本文深入探讨了Python模型评估与选择在面试中的关键点,包括性能度量、过拟合与欠拟合识别、模型比较与选择、模型融合和偏差-方差权衡。强调了避免混淆评估指标、忽视模型验证和盲目追求高复杂度模型的常见错误,并提供相关代码示例,如交叉验证、网格搜索和超参数调优。通过理解这些概念和技巧,可在面试中展示出色的数据科学能力。
93 12
|
4月前
|
监控 负载均衡 API
Python模型部署与服务化:面试中的热门话题
【4月更文挑战第17天】本文探讨了Python模型部署与服务化的面试重点,包括模型导出、API设计、服务化平台、性能优化、安全与合规等方面。强调了Flask、FastAPI等本地部署,以及阿里云、AWS等云服务部署。易错点涉及环境差异、服务稳定性和版本管理。提供Flask部署模型服务和阿里云SLS日志服务监控的代码示例,建议面试者全面掌握相关知识和实践经验。
68 9
|
4月前
|
监控 安全 Java
【多线程学习】深入探究阻塞队列与生产者消费者模型和线程池常见面试题
【多线程学习】深入探究阻塞队列与生产者消费者模型和线程池常见面试题