最后
ActiveMQ消息中间件面试专题
- 什么是ActiveMQ?
- ActiveMQ服务器宕机怎么办?
- 丢消息怎么办?
- 持久化消息非常慢怎么办?
- 消息的不均匀消费怎么办?
- 死信队列怎么办?
- ActiveMQ中的消息重发时间间隔和重发次数吗?
ActiveMQ消息中间件面试专题解析拓展:
redis面试专题及答案
- 支持一致性哈希的客户端有哪些?
- Redis与其他key-value存储有什么不同?
- Redis的内存占用情况怎么样?
- 都有哪些办法可以降低Redis的内存使用情况呢?
- 查看Redis使用情况及状态信息用什么命令?
- Redis的内存用完了会发生什么?
- Redis是单线程的,如何提高多核CPU的利用率?
Spring面试专题及答案
- 谈谈你对 Spring 的理解
- Spring 有哪些优点?
- Spring 中的设计模式
- 怎样开启注解装配以及常用注解
- 简单介绍下 Spring bean 的生命周期
Spring面试答案解析拓展
高并发多线程面试专题
- 现在有线程 T1、T2 和 T3。你如何确保 T2 线程在 T1 之后执行,并且 T3 线程在 T2 之后执行?
- Java 中新的 Lock 接口相对于同步代码块(synchronized block)有什么优势?如果让你实现一个高性能缓存,支持并发读取和单一写入,你如何保证数据完整性。
- Java 中 wait 和 sleep 方法有什么区别?
- 如何在 Java 中实现一个阻塞队列?
- 如何在 Java 中编写代码解决生产者消费者问题?
- 写一段死锁代码。你在 Java 中如何解决死锁?
高并发多线程面试解析与拓展
jvm面试专题与解析
- JVM 由哪些部分组成?
- JVM 内存划分?
- Java 的内存模型?
- 引用的分类?
- GC什么时候开始?
JVM面试专题解析与拓展!
-
订单=客户+商品信息
-
维修单=客户+商品信息+维修信息
-
客户=名字+电话
这里,维修单模型里面似乎包含了一个完整的订单(客户+商品信息),为什么不直接复用订单呢?也许是因为维修部门也负责别的地方购买的商品。另外,客户的名字和电话更新之后,是不是要直接修改已经完成的订单和维修单呢?值得商椎,已经完成的信息不应该有意料之外的变化。还有,如果客户是一个单独的模型,那么背后的团队会是怎么样呢?需要仔细考虑。
当数据模型可以完全覆盖业务需要,建模也就初步完成了。
那么,为什么要建模?第一,要把心智模型提取出来,显性化,让不同的人对业务的理解达成一致;第二,要归类复用,避免重复的工作,让人可以关注更高层面的事务。
如前面所示,即便是建立简单的模型,我们也需要诸多考虑。把这些需要考虑的点体系化,就引出了下一个问题:怎么建模才合理?
怎么建模才合理
判断模型好坏的重要依据是它的使用效率(扩展度、灵活度、与组织的对应度),所以建模的合理性也围绕这个来展开。
为了形成高扩展度、高灵活度并且顺应康威定律的模型,Eric Evans 汇总并命名了DDD这种方法论。它的独特之处,是它认可了“人”这种生物在做抽象过程中的一些必然缺憾,并且提出了一些解决方案。
首先,它明确指出了“自然语言”这个工具的不精确性。其次,它明确指出了人在设计和实现上的矛盾性,即:人类的预测能力很差,所以我们拥抱变化;但同时,我们不能纯寄希望于误打误撞地演化出一个好结果,应该提前深思熟虑地做好设计,再辅之以小的改进。
语言的不精确性,可以用“普通话”(Ubiquitous Language)来解决,即大家在讨论任何东西之前先规范语言,统一词汇的定义。兼顾稳固和灵活的设计,则由良好的分层来做到。
DDD把模型分成四层。
·Ul层,负责界面展示。
·应用层(Application Layer),负责业务流程。
·领域层(Domain Layer),负责领域逻辑。
·基建层(Infrastructure Layer),负责提供基建。
分类的依据是:越往上,预期变动越频察;越往下,预期变动越少。
对于程序员来说,UI和基建应该很容易分清,一个只管展示,一个只管提供持续储存、网络传输等等基础设施,都没有“业务”的参与。容易混淆的是应用层和领域层,在这两层中存在的,就是应用模型和领域模型。
这就引出了下一个问题:到底什么是领域模型?
什么是“领域”模型
按DDD的定义,领域模型应该捕捉“业务规则”或者“领域逻辑"(business rules/domain logic),而应用模型则捕捉“应用逻辑”(application logic)。
模型属于哪一层,有个粗略的判断方式。如果是一个实体(entity)和针对实体的增删改查,就属于领域层;如果是一个场景,比如出现在UI菜单上的选项,就属于应用层。
比如:账单,用户,编辑商品,编辑库存,这些是领域层;“购买商品”,则是应用层。
前者是针对实体的操作。每一个实体都只有增删改查这样的操作。与之相反的是,要完整实现“购买商品”这个场景,也许需要检查库存、创建订单、创建交易等多个操作。
这样看来,领域模型就像是数据库的表。不过,除了字段定义之外,领域模型还需要有领域逻辑。关系型数据库通常可以部分实现领域逻辑,比如使用外键、自增ID等等,但是更为复杂的领域逻辑则需要用代码来实现。比如,在创建订单的时候,需要扣除相应数量的库存;当订单失效,则需要恢复库存。
我们可以从两个方面理解领域逻辑。
第一,领域逻辑就是显性的专业知识,是相对容易理解和学习的部分。买了东西要给钱,出了货要扣库存,飞机来了要腾跑道,炮弹来了要拦截,这些都是专业知识中符合逻辑,可以很容易地推导和学习。与之相对的是隐性的专业知识,或者Martin Fowler 所说的“业务非逻辑"(business illogic),指的是逻辑很难推论的软知识,与人相关的部分,与不可抗拒的、稀奇古怪的意外情况相关的部分。
第二,领域逻辑是提纯、通用的规则。不管是买手机、买房、买汽车,都会有创建订单、创建交易这样的零售领域模型,它是高度提纯、通用的。如果我们需要去修改领域模型,说明我们已经进入了另一个领域。此外,规则的存在是为了维护某个事物,这个事物,就是领域模型的正确、完整性。对领域模型的正常操作,总会给我们一个“合规”的领域。
不管我们怎么去玩弄订单、交易、商品模型,增删改查,乱搞一通,最后出来的结果都应该符合规则。创建订单的时候,订单模型会尝试减库存,成功,则创建,失败,则不允许创建,如此云云。
最后出来的结果不会有逻辑问题,比如订单上的商品不存在,或者交易对应的订单不存在。
当然,领域模型只管“合规”,但不管“合理”。大型超市里,一位收银员决定把所有货品下架,这是否合理?这个不属于领域模型关心的范围,领域模型只知道,要把货物库存的位置从货架转移到仓库,目标仓库必须有能存放这个货物的空位,转移完毕时从货架的可用空间中减去货物的大小。至于谁做,为什么做,能不能做,这么做合不合理,(通常)不在领域层的关心范围,而是放到应用层去做。
在前面的例子中,如果一个客户在黑名单中,不允许购买,那么这个检查,通常是在应用层去检查。这样,我们就可以很容易地复用领域模型或者调整应用规则,而不至于把易变的应用规则混到稳定的业务规则里去。
模型的设计和实现
那么,DDD的模型属于业务描述还是代码、数据库定义?作者想表达的意思很明确,二者都是。好的业务描述应该能非常好地对应到代码,代码也应该以最清晰地方式来呈现业务描述。当然,转换和适配肯定不可少,毕竟有先例摆在那。想要达到设计即代码的UML,尸体都还是温的。
设计和实现的最佳契合点,其实就在“界面”之中。“界面”这个名字本身已经体现了这层意思。所以,建好的模型,和暴露出来的界面、接口,应该有相当高(或者完全一致)的对应关系。这个界面,可能是一个类的公开成员函数,也可能是一个微服务上暴露出来的RESTful接口,或者是一个公开的普通WebAPl,都没有差,只要和设计符合就行。
最后,总结起来,就是:
-
DDD把业务分成UI、应用、领域、基建四层,其核心是高度提纯、通用、少变化的领域层,是谓“领域驱动";
-
领域层中包含领域模型,捕捉领域逻辑,暴露出接口用于操作领域模型,这些接口提供的操作可以确保领域是自治的;
-
领域模型既是业务描述,又是代码实现的结构设计,二者的结合点在于公开出来的界面、接口。
总结一下,领域模型具有如下的特点:
-
领域模型是业务概念的可视化描述,是需求分析的产物
-
领域模型用于指导程序设计,但领域模型与实现方式无关,领域建模时不应该考虑如何实现
-
领域模型需要同项目所有成员(客户、项目经理、开发、测试…)达成共识
(1)找出用例模型中的名词,
(2)然后识别这些名词本身的相关信息,
(3)以及名词之间的相互关联关系,
(4)用UML画出领域模型。
第一步:找出用例模型中的名词
原有用例如下,用蓝色加黑标出名词(重复的就不标了):
1)顾客携带商品到收银台;
2)收银员扫描商品条形码;
3)系统根据条形码获取并显示商品信息;
4)收银员重复2~3步,直到所有商品扫描完毕;
5)系统计算商品总额;
。。。。。。。。。。。。。。。。。。。。
n)系统打出商品清单,完成交易。
这个用例中的名词有“顾客”、“商品”、“收银台”、“收银员”、“商品条形码”、“系统”、“商品信息”、“商品总额”、“商品清单”、“交易”。稍加整理:
1)“顾客”、“收银员”是系统的外部对象,不需要我们进行设计,但这些对象要和系统进行交互;
2)“商品”、“商品条形码”、“商品信息”、“商品总额”、“商品清单”、“交易”是领域对象,但“商品条形码”、“商品信息”可以算作“商品”的属性、“商品总额”可以算作“交易”的属性,最后从这个用例总结出来的领域对象有“商品”、“商品清单”、“交易”三个。
总结
总体来说,如果你想转行从事程序员的工作,Java开发一定可以作为你的第一选择。但是不管你选择什么编程语言,提升自己的硬件实力才是拿高薪的唯一手段。
如果你以这份学习路线来学习,你会有一个比较系统化的知识网络,也不至于把知识学习得很零散。我个人是完全不建议刚开始就看《Java编程思想》、《Java核心技术》这些书籍,看完你肯定会放弃学习。建议可以看一些视频来学习,当自己能上手再买这些书看又是非常有收获的事了。
以看一些视频来学习,当自己能上手再买这些书看又是非常有收获的事了。
[外链图片转存中…(img-AoX6fSgV-1715686993917)]