领域驱动设计实践合订版(战略+战术)

这个过程是一个覆盖软件全生命周期的设计闭环,每个环节的输出都可以作为下一个环节的输入,而在其中扮演重要指导作用的则是“领域模型”。这个设计闭环是一个螺旋式的迭代设计过程,领域模型会在这个迭代过程中逐渐演进,在保证模型完整性与正确性的同时,具有新鲜的活力,使得领域模型能够始终如一的贯穿领域驱动设计过程、阐释着领域逻辑、指导着程序设计、验证着编码质量。

如果仔细审视这个设计闭环,会发现在针对问题域和业务期望提炼统一语言,并通过统一语言进行领域建模时,可能会面临高复杂度的挑战。这是因为对于一个复杂的软件系统而言,我们要处理的问题域实在太庞大了。在为问题域寻求解决方案时,需要从宏观层次划分不同业务关注点的子领域,然后再深入到子领域中从微观层次对领域进行建模。宏观层次是战略的层面,微观层次是战术的层面,只有将战略设计与战术设计结合起来,才是完整的领域驱动设计。

点击了解《领域驱动设计实践(合订版)》。

战略设计阶段

领域驱动设计的战略设计阶段是从下面两个方面来考量的:

  • 问题域方面:针对问题域,引入限界上下文(Bounded Context)上下文映射(Context Map)对问题域进行合理的分解,识别出核心领域(Core Domain)子领域(SubDomain),并确定领域的边界以及它们之间的关系,维持模型的完整性。
  • 架构方面:通过分层架构来隔离关注点,尤其是将领域实现独立出来,能够更利于领域模型的单一性与稳定性;引入六边形架构可以清晰地表达领域与技术基础设施的边界;CQRS 模式则分离了查询场景和命令场景,针对不同场景选择使用同步或异步操作,来提高架构的低延迟性与高并发能力。

Eric Evans 提出战略设计的初衷是要保持模型的完整性。限界上下文的边界可以保护上下文内部和其他上下文之间的领域概念互不冲突。然而,如果我们将领域驱动设计的战略设计模式引入到架构过程中,就会发现限界上下文不仅限于对领域模型的控制,而在于分离关注点之后,使得整个上下文可以成为独立部署的设计单元,这就是“微服务”的概念,上下文映射的诸多模式则对应了微服务之间的协作。因此在战略设计阶段,微服务扩展了领域驱动设计的内容,反过来领域驱动设计又能够保证良好的微服务设计。

一旦确立了限界上下文的边界,尤其是作为物理边界,则分层架构就不再针对整个软件系统,而仅仅针对粒度更小的限界上下文。此时,限界上下文定义了技术实现的边界,对当前上下文的领域与技术实现进行了封装,我们只需要关心对外暴露的接口与集成方式,形成了在服务层次的设计单元重用。

边界给了实现限界上下文内部的最大自由度,这也是战略设计在分治上起到的效用,我们可以在不同的限界上下文选择不同的架构模式。例如,针对订单的查询与处理,选择 CQRS 模式来分别处理同步与异步场景;还可以针对核心领域与子领域重要性的不同,分别选择领域模型(Domain Model)和事务脚本(Transaction Script)模式,灵活地平衡开发成本与开发质量。在宏观层面,面对整个软件系统,我们可以采用前后端分离与基于 REST 的微服务架构,保证系统具有一致的架构风格。

战术设计阶段

整个软件系统被分解为多个限界上下文(或领域)后,就可以分而治之,对每个限界上下文进行战术设计。领域驱动设计并不牵涉到技术层面的实现细节,在战术层面,它主要应对的是领域的复杂性。领域驱动设计用以表示模型的主要要素包括:

  • 值对象(Value Object)
  • 实体(Entity)
  • 领域服务(Domain Service)
  • 领域事件(Domain Event)
  • 资源库(Repository)
  • 工厂(Factory)
  • 聚合(Aggregate)
  • 应用服务(Application Service)

Eric Evans 通过下图勾勒出了战术设计诸要素之间的关系:

面对客户的业务需求,由领域专家与开发团队展开充分的交流,经过需求分析与知识提炼,以获得清晰的问题域。通过对问题域进行分析和建模,识别限界上下文,利用它划分相对独立的领域,再通过上下文映射建立它们之间的关系,辅以分层架构与六边形架构划分系统的逻辑边界与物理边界,界定领域与技术之间的界限。之后,进入战术设计阶段,深入到限界上下文内对领域进行建模,并以领域模型指导程序设计与编码实现。若在实现过程中,发现领域模型存在重复、错位或缺失时,再进而对已有模型进行重构,甚至重新划分限界上下文。

两个不同阶段的设计目标是保持一致的,它们是一个连贯的过程,彼此之间又相互指导与规范,并最终保证一个有效的领域模型和一个富有表达力的实现同时演进

分享交流

我们为本课程付费读者创建了微信交流群,以方便更有针对性地讨论课程相关问题。入群方式请到第 1-4 课末尾添加小编的微信 ,并注明「DDD」。

点击了解《领域驱动设计实践(合订版)》。

第1-2课:深入分析软件的复杂度

软件复杂度的成因

Eric Evans 的经典著作《领域驱动设计》的副标题为“软件核心复杂性应对之道”,这说明了 Eric 对领域驱动设计的定位就是应对软件开发的复杂度。Eric 甚至认为:“领域驱动设计只有应用在大型项目上才能产生最大的收益”。他通过 Smart UI 反模式逆向地说明了在软件设计与开发过程中如果出现了如下问题,就应该考虑运用领域驱动设计:

  • 没有对行为的重用,也没有对业务问题的抽象,每当操作用到业务规则时,都要重复这些业务规则。
  • 快速的原型建立和迭代很快会达到其极限,因为抽象的缺乏限制了重构的选择。
  • 复杂的功能很快会让你无所适从,所以程序的扩展只能是增加简单的应用模块,没有很好的办法来实现更丰富的功能。

因此,选择领域驱动设计,就是要与软件系统的复杂作一番殊死拼搏,以降低软件复杂度为己任。那么,什么才是复杂呢/p>

什么是复杂/h3>

这个定义庶几可以表达软件复杂度的特征。定义中的组成部分对于软件系统来说,就是我所谓的“设计单元”,基于粒度的不同可以是函数、对象、模块、组件和服务。这些设计单元相对简单,然而彼此之间的相互作用却导致了软件系统的复杂行为。

Jurgen Appelo 从理解力与预测能力两个维度分析了复杂系统理论,这两个维度又各自分为不同的复杂层次,其中,理解力维度分为 Simple 与 Comlicated 两个层次,预测能力维度则分为 Ordered、Complex 与 Chaotic 三个层次,如下图所示:

整洁架构的目的在于识别整个架构不同视角以及不同抽象层次的关注点,并为这些关注点划分不同层次的边界,从而使得整个架构变得更为清晰,以减少不必要的耦合。要做到这一点,则需要合理地进行职责分配,良好的封装与抽象,并在约束的指导下为架构建立一致的风格,这是许多良好系统的设计特征。

点击了解《领域驱动设计实践(合订版)》

拥抱变化

变化对软件系统带来的影响可以说是无解,然而我们不能因此而消极颓废,套用 Kent Beck 的话来说,我们必须“拥抱变化”。除了在开发过程中,我们应尽可能做到敏捷与快速迭代,以此来抵消变化带来的影响;在架构设计层面,我们还可以分析哪些架构质量属性与变化有关,这些质量属性包括:

  • 可进化性(Evolvability)
  • 可扩展性(Extensibility)
  • 可定制性(Customizability)

要保证系统的可进化性,可以划分设计单元的边界,以确定每个设计单元应该履行的职责以及需要与其他设计单元协作的接口。这些设计单元具有不同的设计粒度,包括函数、对象、模块、组件及服务。由于每个设计单元都有自己的边界,边界内的实现细节不会影响到外部的其他设计单元,我们就可以非常容易地替换单元内部的实现细节,保证了它们的可进化性。

要满足系统的可扩展性,首先要学会识别软件系统中的变化点(热点),常见的变化点包括业务规则、算法策略、外部服务、硬件支持、命令请求、协议标准、数据格式、业务流程、系统配置、界面表现等。处理这些变化点的核心就是“封装”,通过隐藏细节、引入间接等方式来隔离变化、降低耦合。一些常见的架构风格,如基于事件的集成、管道—过滤器等的引入,都可以在一定程度上提高系统可扩展性。

可定制性意味着可以提供特别的功能与服务。Fielding 在《架构风格与基于 络的软件架构设计》提到:“支持可定制性的风格也可能会提高简单性和可扩展性”。在 SaaS 风格的系统架构中,我们常常通过引入元数据(Metadata)来支持系统的可定制。插件模式也是满足可定制性的常见做法,它通过提供统一的插件接口,使得用户可以在系统之外按照指定接口编写插件来扩展定制化的功能。

分享交流

我们为本课程付费读者创建了微信交流群,以方便更有针对性地讨论课程相关问题。入群方式请到第 1-4 课末尾添加小编的微信 ,并注明「DDD」。

点击了解《领域驱动设计实践(合订版)》

「战术」访谈录:聊聊领域驱动设计

相信很多朋友对领域驱动设计会有这样或那样的困惑,比如领域驱动设计是什么在工作中有什么作用什么国内关于这方面的书籍少之又少… 为了解决这些疑惑,有幸邀请到专家张逸老师来聊聊领域驱动设计,下面是 GitChat 独家采访记录。

GitChat:在探讨领域驱动设计问题时,每个人都有每个人的认识,有的时候可能谁也无法说服对方,这时候该怎么办呢/p>

张逸:简单说,就是 show me your code。不管领域设计做得怎么样,最终都是要落地的,看实现的效果最有说服力。当然,为了保证交流的顺畅与效率,代码这种形式可能容易让人迷失到纷繁复杂的细节中去,因此还有一种方式就是 show me your model

这里说的 model 就是领域模型。注意,团队在交流领域驱动设计问题时,不应该只是对建模活动的产出物进行讨论,建模的过程同样非常重要。现在诸如 Event Storming 等活动都非常强调利用可视化手段把业务专家与开发团队都包含进来,大家一块协作一块交流,并利用便利贴等工具直观地展现建模活动中的每一个步骤,可以更容易消除误会与分歧。

GitChat:可以谈谈领域驱动设计的流程吗如是先建模是做设计及应用的场景是什么/p>

张逸:领域驱动设计强调的是将分析、设计与实现统一到一个领域模型中来,同时又相对清晰地划分为战略设计和战术设计两个阶段。当然,这两个阶段并非瀑布式的,而是迭代和演进的过程。

我认同领域模型对分析、设计与实现的统一,这个思想没有问题。但在我亲身经历的项目中,我还是发现由于沟通角色与建模目标的不同,分析、设计与实现在三个不同的活动是无法完全统一的,就好像在重构时不能实现新功能,这三顶帽子自然也不能同时戴起来。因此,我在《领域驱动战术设计实践》课程中,清晰地将这三个活动称之为领域分析建模、领域设计建模与领域实现建模,它们各自的产出是领域分析模型、领域设计模型与领域实现模型,这三者合起来就是领域模型,而这个过程就是领域模型驱动设计。

之所以在模型驱动设计前面加上“领域”作为定语,是因为我认为二者不能划等 ,例如采用数据模型的,同样是模型驱动设计。在《领域驱动战术设计实践》GitChat 课程中,我根据建模视角的不同,将其分别定义为数据模型驱动设计、服务模型驱动设计、领域模型驱动设计,并用了相当篇幅的内容分别介绍了这三种不同的模型驱动设计过程。

点击了解《领域驱动设计实践(合订版)》

GitChat:针对一些设计能力不足的开发团队,可以采用领域驱动设计来改进设计和编码质量吗/p>

张逸:我个人的观点,这二者之间有关系,但并非必要关系。领域驱动设计的关键不是设计能力,而是要抓住设计的驱动力,必须是领域,且必须要求领域专家参与到分析建模活动中来。

要说明的是,这个所谓“领域专家”不是一个头衔,也不是对技能级别的要求,它其实就是一个指代,代表“懂业务”的人:可以是客户,可以是 Product Owner,可以是业务分析师,可以是产品经理,也可以是懂业务的开发人员,甚至可以是一个负责业务分析的团队。

领域驱动设计能否成功,还是要看建模尤其是分析建模做得是否足够好,这其实是整个设计过程的上游。至于设计能力,则要看领域驱动设计与什么样的编程范式结合见的编程范式包括结构范式、对象范式和函数范式。因此这里的“设计能力不足”,究竟指的是哪方面的设计能力不足呢/p>

当然,从主流的领域驱动设计来看,主要采用的还是对象范式的设计思想与领域驱动设计结合,这就要求团队掌握基本的面向对象设计能力。这方面能力不足的团队,确实会影响到最终的设计和编码质量。这是必须要正视的问题,因此我建议那些希望实践领域驱动设计的团队,不要忘了去提高团队的面向对象设计能力

提升设计能力并非一朝一夕就可以做到。正是考虑到面向对象设计能力不足对领域驱动设计的影响,我在《领域驱动战术设计实践》GitChat 课程中尝试总结了一个相对固化的设计过程。这个过程结合了 DCI、职责驱动设计等设计方法,它不要求团队掌握太多面向对象设计思想、原则与模式,只要懂业务,完全可以以“知其然而不知其所以然”的方式去实践领域驱动设计。

这种方法不能让你的设计变得非常优秀,却可以保证你的设计不至于太糟糕,甚至可以说是不错的设计。

GitChat:应用服务与领域服务的区别是什么呢/p>

张逸:这个是老生常谈的问题了。从分层架构的角度看,应用服务属于应用层,领域服务属于领域层。应用层是一个包装的外观,按照该层的职责来说,应用服务根本就不该干业务的活儿,它只是一个对外公开的接口而已。

从业务粒度看,应用服务的每个公开方法会对应一个具有业务价值的业务场景或者说用例。领域服务则不然,它实现了业务功能,这个业务功能或者是无状态的,又或者是因为需要协调多个聚合,又或者需要和外部资源协作。

在针对业务场景驱动设计时,应用服务的一个方法往往会暴露给调用者,然后它再将该请求委派给领域层的对象。一般要求领域服务的粒度要小,这样可以避免设计为事务脚本的过程方式,也可以在一定程度上避免贫血模型。

总结:

  • 应用服务:一组面向业务场景的业务外观方法,只是一个对外提供接口、对内分配职责的协作对象,属于应用层。
  • 领域服务:一个领域服务对应最多一个业务场景,往往需要和聚合、Repository、甚至领域服务一起协作。

GitChat:已经上线的《领域驱动战略设计实践》与刚上线的《领域驱动战术设计实践》之间的区别是学习的先后顺序吗/p>

张逸:这两个课程刚好对应领域驱动设计的战略设计与战术设计。

前者强调系统层面的架构模式,包括限界上下文、上下文映射、分层架构等,可以运用这些模式对整个系统的领域进行“分而治之”,从而降低业务复杂度,同时围绕“领域”为核心,建立业务复杂度与技术复杂度的边界。

后者强调领域层面的设计模式,以“模型驱动设计”为主线,贯穿分析、设计与编码实现这三个不同的建模活动,并引入领域驱动设计的战术设计要素,如实体、值对象、领域服务、领域事件、聚合、资源库、工厂等。

当然在我的《领域驱动战术设计实践》课程中,我扩大了领域驱动战术设计的范畴,讲解了数据模型驱动与服务模型驱动,探讨了建模范式与编程范式之间的关系。同时,在设计过程中,我引入了职责驱动设计和 DCI 模式来阐释实体、值对象、领域服务与应用服务之间的协作关系。在编码实现过程中,我又引入了测试驱动开发来推进从设计模型到实现模型。

战略设计和战术设计并非单向的过程,而是一个迭代演进与不断融合的过程。整体来讲,前者更偏向于架构设计,后者更偏向于详细设计与编码。主要还是看读者的关注点与侧重点,并没有一个绝对的学习先后顺序。我个人还是建议先学习《领域驱动战略设计实践》,虽然它更偏向于理论,难度更高一些,但是它毕竟概括了领域驱动设计的全貌。

GitChat:「战略」这个课程分析了“EAS 系统”,在「战术」课程也介绍了“EAS 系统”,两者的侧重点有什么不同吗/p>

张逸:与战略设计和战术设计的侧重点一样,在「战术」课程中,会针对 EAS 系统进行领域建模,并最终对其进行编码实现。从内容来看,后者会更接地气一些,毕竟讲的是落地的实现。

将战略和战术的 EAS 系统案例结合起来,就是一个系统的完整设计案例了。

到这里,访谈录的内容就结束了,大家若对 DDD 的内容比较感兴趣的话,欢迎订阅本课程,有任何关于本课程内容的疑惑可在读者圈留言或加群交流~

点击了解《领域驱动设计实践(合订版)》

「战术」开篇词 | 领域驱动设计的不确定性

课程背景

大家好,我是张逸,去年在 GitChat 平台上上线了一门[《领域驱动战略设计实践》]达人课,销量已过 4000 份,同时建了两个读者群,也邀请了十几位领域驱动设计方面的专家加入到了读者群,共同探讨和交流领域驱动设计的相关知识。

至今,两个群依然很活跃,每天都有许多问题抛出,同时又有许多问题得到了解答,还有更多的问题悬而未决,因为每个人都有自己心目中的“哈姆雷特”,谁也无法说服对方,谁也无法给出一个让所有人都认同的标准答案。这恰恰是领域驱动设计最棘手的一部分,当然,也是最让人神往的一部分——唯有不确定,方才值得去探索

在探讨领域驱动战术设计的一些问题时,总会有人纠结:这个领域对象应该定义成实体,还是值对象域服务和应用服务的区别是什么合的边界该怎么划分是,各种设计问题纷至沓来,问题越辩越糊涂,到了最后,已经脱离了最初探讨问题的场景,变成了“空对空导弹”一阵乱发射,最后蓦然回首,才发现目标已然消失了。

这是不合理的。在软件开发领域,没有什么一劳永逸的实现,也没有什么放之四海而皆准的标准,必须结合具体的业务场景做出合理的决策,无论建模和设计再怎么完美,也需要通过落地的检验才知道好还是坏。任何脱离具体业务场景的问题分析,都是空谈;任何不落地的完美方案,都是浮夸。领域驱动设计没有标准,有的只是持续不断的不确定性。

正所谓“以不变应万变”,我们要从实证主义的角度看待领域驱动设计,窃以为,只需守住三项基本原则即可:

  • 必须通过领域建模来驱动设计
  • 领域专家或业务分析师必须参与到建模活动中
  • 设计必须遵循面向对象分析和设计的思想与原则

只要做到这三点,领域驱动战术设计就不会做得太差,剩下的不足,就需要靠经验来填补了。

点击了解《领域驱动设计实践(合订版)》

课程框架

本课程是我计划撰写的领域驱动设计实践系列的第二部分课程,要解决的正是前面所提及的战术层面的设计问题。单以战术设计阶段来看,我个人认为 Eric Evans 做出的贡献并不多。在《领域驱动设计》一书中,他讲到了模型驱动设计与领域建模,却没有深入阐述该如何正确地进行领域建模;他引入的资源库模式和工厂模式,不过是面向对象设计原则的体现;至于模型的演化与重构带来的突破,其实更多是经验之谈,缺乏切实可行的方法。整体而言,Eric Evans 在战术设计要素方面,最为重要的洞见在于:

  • 强调了领域建模的重要性,并与面向对象分析和设计的原则结合起来
  • 实体与值对象的区分,有利于我们明白模型对象的真相,并能够更好地避免贫血模型
  • 聚合提出了有别于模块粒度的边界,有效地保证了业务规则的不变性和数据的一致性

不可否认,若要做到优良的领域驱动设计,建模和设计的经验是必不可少的,这需要多年的项目实战打磨方可萃取而成,但如果在开始之初,能有一些更为具体的方法作为指引,或许可以让掌握技能的周期大幅度缩短。此外,我还清楚地看到:许多领域驱动设计的门外汉,之所以迟迟不得其门而入,是因为他(她)们连最为基本的面向对象分析和设计的能力都不具备,因此,无法理解领域驱动的战术设计要素也就不足为奇了。关键在于,许多设计问题因为其不确定性,根本没有标准答案,没有任何人能给你指出明确的设计方法和设计思路。这时,就必须要吃透面向对象分析和设计的思想与原则,用它们来指导我们的设计,而不是死板的遵循领域驱动设计的模式。

针对一些设计能力不足的开发团队,若希望采用领域驱动设计来改进设计和编码质量,往往会适得其反,做出来的是一锅“夹生饭”。从理想角度讲,决定是否采用领域驱动设计,不在于团队成员的能力高低,而在于业务的复杂度。然而,我们又不得不面对现实,如果团队成员的设计能力差了,是做不好领域驱动设计的。因此,我在本课程中,一方面分享了我的设计体验和方法,以帮助团队成员的成长,另一方面也给出了一个操作性强的设计过程,可以让基础相对薄弱的开发人员能够依样画葫芦,做出还算不错的设计与实现。

这些考虑帮助我确定了本课程的基本思路,即以能学习和模仿的战术设计方法来弥补经验之不足,以设计思想和设计原则作为指导来解决争议之问题,以能够落地的解决方案来体现领域驱动设计之价值。

本课程分为六部分,共 64 篇(含访谈录、开篇词)。

  • 第一部分:软件系统中的模型(第 1-1 课 ~ 第 1-15 课)

全面讲解和对比软件系统的数据模型、服务模型和领域模型,以这些模型作为不同的设计驱动力,讲解不同的模型驱动设计之过程与利弊,从而得出领域模型驱动设计的优势以及它适用的业务场景。

  • 第二部分:领域分析模型(第 2-1 课 ~ 第 2-7 课)

建立领域分析模型是领域模型驱动设计的起点和基础。领域分析过程是领域专家与开发团队合作最为紧密、沟通最为频繁的阶段,是领域驱动设计成败的关键。我将深入介绍名词动词法、分析模式、四色建模和事件风暴等重要的分析建模方法,在发现显式和隐式领域概念的基础上,建立高质量的领域分析模型。

  • 第三部分:领域设计模型(第 3-1 课 ~ 第 3-17 课)

实体、值对象、领域服务、领域事件、资源库、工厂和聚合是组成领域驱动战术设计的核心内容,也是衡量领域驱动设计质量的分水岭。只有正确地理解了这些设计要素,才能正确地完成领域驱动战术设计。这其中扮演关键角色的其实是面向对象分析与设计。我将围绕着职责驱动设计讲解角色、职责与协作三者之间的关系,通过分辨职责来寻找合理的对象,并结合 DCI 模式与主流设计模式,以时序图作为主要的设计驱动力获得高质量的设计方案。

  • 第四部分:领域实现模型(第 4-1 课 ~ 第 4-6 课)

领域实现模型帮助我们将领域设计模型落地,毕竟,只有交付可工作的软件才是软件开发的终极目标。除了要应对纷繁复杂的业务逻辑,我们还需要考虑如何与外部资源集成,实现数据持久化与消息通信等基础设施内容。在落地过程中,我们需要时刻维护业务复杂度与技术复杂度的边界,降低彼此的影响,同时还需要在编码层次提高代码的内建质量,包括代码的可读性、可重用性、可扩展性和可测试性。

  • 第五部分:融合:战略设计和战术设计(第 5-1 课 ~ 第 5-9 课)

领域驱动设计虽然分为战略设计阶段和战术设计阶段,但这两个阶段并非完全割裂的井水不犯河水的独立过程。我在[《领域驱动战略设计实践》]课程中介绍领域驱动设计过程时,就提到了这两个阶段的相辅相成与迭代的螺旋上升演进过程。我们必须将战略设计和战术设计融合起来,把分层架构、限界上下文、上下文映射与战术设计的诸要素融汇贯通,才能获得最佳的设计质量,并成为指导我们进行软件架构和设计的全过程。

  • 第六部分:EAS 系统的战术设计实践(第 6-1 课 ~ 第 6-8 课)

继续沿用战略设计实践中使用的全真案例——EAS 系统,采用领域模型驱动设计的过程对系统进行分析建模、设计建模和实现建模,并最终结合战略设计的方案,形成完整的解决方案和代码实现。

综上,本课程的内容并未完全遵照 Eric Evans 的《领域驱动设计》,不同的部分固然是我的一孔之见,未必正确,也未必遵守 Eric Evans 的设计思想,但我仍然不揣冒昧地进行了分享,不是因为我的无知者无畏,而是我认为针对具有不确定性的领域驱动设计,必须要容得下异见者,方能取得发展和突破。

为什么要学习领域驱动设计

如果你已经能设计出美丽优良的软件架构,如果你只希望脚踏实地做一名高效编码的程序员,如果你是一位注重用户体验的前端设计人员,如果你负责的软件系统并不复杂,那么,你确实不需要学习领域驱动设计!

领域驱动设计当然并非“银弹”,自然也不是解决所有疑难杂症的“灵丹妙药”,请事先降低对领域驱动设计的不合现实的期望。我以中肯地态度总结了领域驱动设计可能会给你带来的收获:

  • 领域驱动设计是一套完整而系统的设计方法,它能给你从战略设计

    声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2019年4月12日
下一篇 2019年4月12日

相关推荐