1. 复杂性应对之道 - 领域建模\_我的新书《代码精进之路:从码农到工匠》-CSDN博客

复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图1

复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图2

复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图3

复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图4

粉丝 关注 获赞

会员中心

会员特权


资源下载

千节精品课

千本电子书

VIP 技术文章

开通会员 查看完整会员权益

收藏

动态

消息

公告 评论 关注 点赞 私信 回答 系统通知 消息设置

创作中心

复杂性应对之道 - 领域建模

复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图5

张建飞(Frank) 2018-03-19 17:39:07 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图6
20606 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图7
复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图8
收藏 52

分类专栏: Java 系统架构 文章标签: DDD 架构 领域模型

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

本文链接:https://blog.csdn.net/significantfrank/article/details/79614915

版权

为什么要领域建模

维护过企业级业务系统的同学,基本上没有一个不抱怨业务代码烂的,过程式的面条代码充斥着屏幕,程序员的心力和体力都经受着极大的考验,怎么破?

DDD 革命

DDD 革命性在于,领域模型准确反映了业务语言,而传统 J2EE 或 Spring+Hibernate 等事务性编程模型只关心数据,这些数据对象除了简单 setter/getter 方法外,没有任何业务方法,被比喻成贫血模式

以银行账号 Account 为案例,Account 有 “存款”,“计算利息” 和“取款”等业务行为,但是传统经典的方式是将 “存款”,“计算利息” 和“取款”行为放在账号的服务 AccountService 中,而不是放在 Account 对象本身之中。我们不能因为用了计算机,用了数据库,用了框架,业务模型反而被技术框架给绑架了,就像人虽然是由母亲生的,但是人的吃喝拉撒母亲不能替代,更不能以母爱名义剥夺人的正常职责行为,如果是这样,这个人就是被母爱绑架了。

DDD 不是银弹

软件的世界里没有银弹,是用事务脚本还是领域模型没有对错之分,关键看是否合适。就像自营和平台哪个模式更好?答案是都很好,所以亚马逊可以有三方入住,阿里也可以有自建仓嘛。

实际上,CQRS 就是对事务脚本和领域模型两种模式的综合,因为对于 Query 和报表的场景,使用领域模型往往会把简单的事情弄复杂,此时完全可以用奥卡姆剃刀把领域层剃掉,直接访问 Infrastructure。

我个人也是坚决反对过度设计的,因此对于简单业务场景,我强力建议还是使用事务脚本,其优点是简单、直观、易上手。但对于复杂的业务场景,你再这么玩就不行了,因为一旦业务变得复杂,事务脚本就很难应对,容易造成代码的 “一锅粥”,系统的腐化速度和复杂性呈指数级上升。目前比较有效的治理办法就是领域建模,因为领域模型是面向对象的,在封装业务逻辑的同时,提升了对象的内聚性和重用性,因为使用了通用语言(Ubiquitous Language),使得隐藏的业务逻辑得到显性化表达,使得复杂性治理成为可能。

接下来,让我们看一个银行转账的实例,对比下事务脚本和领域模型两者编程模型的不同。

DDD 初体验

银行转账事务脚本实现

在事务脚本的实现中,关于在两个账号之间转账的领域业务逻辑都被写在了MoneyTransferService的实现里面了,而 Account 仅仅是 getters 和 setters 的数据结构,也就是我们说的贫血模型:

  1. public class MoneyTransferServiceTransactionScriptImpl
  2. implements MoneyTransferService {
  3. private AccountDao accountDao;
  4. private BankingTransactionRepository bankingTransactionRepository;
  5. . . .
  6. @Override
  7. public BankingTransaction transfer(
  8. String fromAccountId, String toAccountId, double amount) {
  9. Account fromAccount = accountDao.findById(fromAccountId);
  10. Account toAccount = accountDao.findById(toAccountId);
  11. . . .
  12. double newBalance = fromAccount.getBalance() - amount;
  13. switch (fromAccount.getOverdraftPolicy()) {
  14. case NEVER:
  15. if (newBalance < 0) {
  16. throw new DebitException("Insufficient funds");
  17. }
  18. break;
  19. case ALLOWED:
  20. if (newBalance < -limit) {
  21. throw new DebitException(
  22. "Overdraft limit (of " + limit + ") exceeded: " + newBalance);
  23. }
  24. break;
  25. }
  26. fromAccount.setBalance(newBalance);
  27. toAccount.setBalance(toAccount.getBalance() + amount);
  28. BankingTransaction moneyTransferTransaction =
  29. new MoneyTranferTransaction(fromAccountId, toAccountId, amount);
  30. bankingTransactionRepository.addTransaction(moneyTransferTransaction);
  31. return moneyTransferTransaction;
  32. }
  33. }

上面的代码大家看起来应该比较眼熟,因为目前大部分系统都是这么写的。需求评审完,工程师画几张UML图完成设计,就开始向上面这样怼业务代码了,这样写基本不用太费脑,完全是面向过程的代码风格。有些同学可能会说,我这样写也可以实现系统功能啊,还是那句话“just because you can, doesn’t mean you should”。说句不好听的,正是有这么多“没有追求”、“不求上进”的码农才造成了应用系统的混乱、败坏了应用开发的名声。这也是为什么很多应用开发工程师觉得工作没意思,技术含量低,觉得整天就是写if-else的业务逻辑代码,系统又烂,工作繁琐、无聊、没有成长、没有成就感,所以转向去做中间件啊,去写JDK啊,觉得那个NB。实际上,应用开发一点都不简单也不无聊,业务的变化比底层Infrastructure的变化要多得多,解决的难度也丝毫不比写底层代码容易,只是很多人选择了用无聊的方式去做。其实我们是有办法做的更优雅的,这种优雅的方式就是领域建模,唯有掌握了这种优雅你才能实现从工程师向应用架构的转型。同样的业务逻辑,接下来就让我们看一下用DDD是怎么做的。

银行转账领域模型实现

如果用DDD的方式实现,Account实体除了账号属性之外,还包含了行为和业务逻辑,比如debit( )credit( )方法。

  1. // @Entity
  2. public class Account {
  3. // @Id
  4. private String id;
  5. private double balance;
  6. private OverdraftPolicy overdraftPolicy;
  7. . . .
  8. public double balance() { return balance; }
  9. public void debit(double amount) {
  10. this.overdraftPolicy.preDebit(this, amount);
  11. this.balance = this.balance - amount;
  12. this.overdraftPolicy.postDebit(this, amount);
  13. }
  14. public void credit(double amount) {
  15. this.balance = this.balance + amount;
  16. }
  17. }

而且透支策略OverdraftPolicy也不仅仅是一个Enum了,而是被抽象成包含了业务规则并采用了策略模式的对象。

  1. public interface OverdraftPolicy {
  2. void preDebit(Account account, double amount);
  3. void postDebit(Account account, double amount);
  4. }
  5. public class NoOverdraftAllowed implements OverdraftPolicy {
  6. public void preDebit(Account account, double amount) {
  7. double newBalance = account.balance() - amount;
  8. if (newBalance < 0) {
  9. throw new DebitException("Insufficient funds");
  10. }
  11. }
  12. public void postDebit(Account account, double amount) {
  13. }
  14. }
  15. public class LimitedOverdraft implements OverdraftPolicy {
  16. private double limit;
  17. . . .
  18. public void preDebit(Account account, double amount) {
  19. double newBalance = account.balance() - amount;
  20. if (newBalance < -limit) {
  21. throw new DebitException(
  22. "Overdraft limit (of " + limit + ") exceeded: " + newBalance);
  23. }
  24. }
  25. public void postDebit(Account account, double amount) {
  26. }
  27. }

而Domain Service只需要调用Domain Entity对象完成业务逻辑即可。

  1. public class MoneyTransferServiceDomainModelImpl
  2. implements MoneyTransferService {
  3. private AccountRepository accountRepository;
  4. private BankingTransactionRepository bankingTransactionRepository;
  5. . . .
  6. @Override
  7. public BankingTransaction transfer(
  8. String fromAccountId, String toAccountId, double amount) {
  9. Account fromAccount = accountRepository.findById(fromAccountId);
  10. Account toAccount = accountRepository.findById(toAccountId);
  11. . . .
  12. fromAccount.debit(amount);
  13. toAccount.credit(amount);
  14. BankingTransaction moneyTransferTransaction =
  15. new MoneyTranferTransaction(fromAccountId, toAccountId, amount);
  16. bankingTransactionRepository.addTransaction(moneyTransferTransaction);
  17. return moneyTransferTransaction;
  18. }
  19. }

通过上面的DDD重构后,原来在事务脚本中的逻辑,被分散到Domain Service,Domain Entity和OverdraftPolicy三个满足SOLID的对象中,在继续阅读之前,我建议可以自己先体会一下DDD的好处。

领域建模的好处

DDD最大的好处是:接触到需求第一步就是考虑领域模型,而不是将其切割成数据和行为,然后数据用数据库实现,行为使用服务实现,最后造成需求的首肢分离。DDD让你首先考虑的是业务语言,而不是数据。DDD强调业务抽象和面向对象编程,而不是过程式业务逻辑实现。重点不同导致编程世界观不同

面向对象

  • 封装:Account的相关操作都封装在Account Entity上,提高了内聚性和可重用性。
  • 多态:采用策略模式的OverdraftPolicy(多态的典型应用)提高了代码的可扩展性。

业务语义显性化

  • 通用语言:“一个团队,一种语言”,将模型作为语言的支柱。确保团队在内部的所有交流中,代码中,画图,写东西,特别是讲话的时候都要使用这种语言。例如账号,转账,透支策略,这些都是非常重要的领域概念,如果这些命名都和我们日常讨论以及PRD中的描述保持一致,将会极大提升代码的可读性,减少认知成本。说到这,稍微吐槽一下我们有些工程师的英语水平,有些神翻译让一些核心领域概念变得面目全非。
  • 显性化:就是将隐式的业务逻辑从一推if-else里面抽取出来,用通用语言去命名、去写代码、去扩展,让其变成显示概念,比如“透支策略”这个重要的业务概念,按照事务脚本的写法,其含义完全淹没在代码逻辑中没有突显出来,看代码的人自然也是一脸懵逼,而领域模型里面将其用策略模式抽象出来,不仅提高了代码的可读性,可扩展性也好了很多。

如何进行领域建模

初步建模

好的模型应该是建立在对业务深入理解的基础上。就我自己的经验而言,建模是一个不断迭代的过程,一开始可以简单点来。

首先抓住一些核心概念,这些业务知识和核心概念可以通过和业务专家沟通,也可以通过头脑风暴的形式从User Story或者Event Storming去扣。

然后假设一些业务场景走查一下,再写一些伪代码验证一下run一下,看看顺不顺,如果很顺滑,说明没毛病,否则就要看看是不是需要调整一下模型,随着项目的进行和对业务理解的不断深入,这种迭代将持续进行。

举个栗子,比如让你设计一个中介系统,一个典型的User Story可能是“小明去找工作,中介说你留个电话,有工作机会我会通知你”,这里面的关键名词很可能就是我们需要的领域对象:
- 小明是求职者。
- 电话是求职者的属性。
- 中介包含了中介公司,中介员工两个关键对象。
- 工作机会肯定也是关键领域对象;
- 通知这个动词暗示我们这里用观察者模式会比较合适。

然后再梳理一下领域对象之间的关系,一个求职者可以应聘多个工作机会,一个工作机会也可以被多个求职者应聘,M2M的关系,中介公司可以包含多个员工,O2M的关系。对于这样简单的场景,这个建模就差不多了。

当然我们的业务场景往往比这个要复杂,而且不是所有的名词都是领域对象也可能是属性,也不是所有的动词都是方法也可能是领域对象,再者,看的见实体好找,看不见的、隐藏的,需要深入理解业务,需要“无中生有”才能得到的抽象就没那么容易发现了,所以要具体问题具体对待,这个进化的过程需要我们有很好的业务理解力,抽象能力以及建模的经验(知道为什么公司的job model里那么强调技术人员的业务理解力和抽象能力了吧。

比如通常情况下,价格和库存只是订单和商品的一个属性,但是在阿里系电商业务场景下,价格计算和库存扣减的复杂程度可以让你怀疑人生,因此作为电商中台,把价格和库存单独当成一个域(Domain)去对待是很必要的。

当然这个只是最初级的模型,接下来我会通过DDD中的一些核心概念的介绍,让大家更清楚的了解建模的过程。

领域事件(Domain Event)

An event is something that has happened in the past. A domain event is, logically, something that happened in a particular domain, and something you want other parts of the same domain (in-process) or domain in aonther bounded context to be aware of and potentially react to.

Domain Event是由一个特定领域触因为一个用户Command触发的发生在过去的行为产生的事件,而这个事件是系统中其它部分感兴趣的。

为什么Domain Event如此重要? 因为在现在的分布式环境下,没有一个业务系统是割裂的,而Messaging绝对是系统之间耦合度最低,最健壮,最容易扩展的一种通信机制。因此理论上它是分布式系统的必选项。

但是目前大部分系统的Event都设计的很随性,没有统一的指导和规范,导致Event滥用和无用的情况时有发生,而Domain Event给我们一个很好的方向,指引我们该如何设计我们系统的Event。

Event命名

Your Domain Event type names should be a statement of a past occurrence, that is, a verb in the past tense.

因为表示的是过去事件,所以推荐命名为Domain Name + 动词的过去式 + Event。这样比较可以确切的表达业务语义。

下面是几个举例:
1. CustomerCreatedEvent,表示客户创建后发出的领域事件。
2. OpportunityTransferedEvent,表示机会转移后发出的领域事件。
3. LeadsCreatedEvent,表示线索创建后发出的领域事件。

Event内容

Event的内容有两种形式:

  1. Enrichment:也就是在Event的payload中尽量多多放data,这样consumer就可以自恰(Autonomy)的处理消息了。
  2. Query-Back:这种是在Event中通过回调拿到更多的data,这种形式会加重系统的负载,performance也会差一些。

所以如果要在Enrichment和Query-Back之间做选择的话,首先推荐使用Enrichment。

Event Sourcing

Event Sourcing是在Domain Event上面的一个扩展,是一个可选项。也就是要有一个Event Store保存所有的Events,其实如果你是用MetaQ作为Event机制的话,这些Events都是存储在MetaQ当中的,只是MetaQ并没有提供很好的Event查询和回溯,所以如果决定使用Event Sourcing的话,最好还是自己单独建立一个Event Store。

使用Event Sourcing主要有以下好处,如果用不到的话,完全可以不用,但是Domain Event还是强烈建议要使用。

  1. Event Sourcing存储了所有发生在Core Domain上面的事件。
  2. 基于这些事件,我们可以做系统回放,系统Debug,以及做用户行为的分析(类似于打点)

Event Storming

事件风暴是《DDD Distilled》书中提出的一个业务分析的方法论,其主要作用是从Domian事件出发,来分析用户Command,来找到Ubiquitous Languange,来抽象Domain Entity以及Bounded Context。

可以和User Story的方法论结合起来使用,其最大的优点是,这种分析方式即使是non-tech的人,比如产品,业务专家等也能听得懂,也能参与进来。相比较一上来就使用UML画领域模型图而言。

聚合根(Aggreagte)

聚合根(Aggregate Root)是DDD中的一个概念,是一种更大范围的封装,把一组有相同生命周期、在业务上不可分隔的实体和值对象放在一起考虑,只有根实体可以对外暴露引用,也是一种内聚性的表现。

确定聚合边界要满足固定规则(Invariant),是指在数据变化时必须保持的一致性规则,具体规则如下
- 根实体具有全局标识,最终负责检查规定规则
- 聚合内的实体具有本地标识,这些标识在Aggregate内部才是唯一的
- 外部对象不能引用除根Entity之外的任何内部对象
- 只有Aggregate的根Entity才能直接通过数据库查询获取,其他对象必须通过遍历关联来发现
- Aggegate内部的对象可以保持对其他Aggregate根的引用
- Aggregate边界内的任何对象修改时,整个Aggregate的所有固定规则都必须满足

还是看银行的例子,Account(账号)是CustomerInfo(客户信息)Entity和Address(值对象)的聚合根,Tansaction(交易)是流水(Journal)的聚合根,因为流水是因为交易才产生的,具有相同的生命周期。
复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图9

最后提醒一下,聚合根是一个逻辑概念,主观性很强,所以在建模过程中很容易产生分歧,因此在日常工作中千万不要教条,把握住一条主要原则,我们的最终目的是为了业务语义显现化,如果因为聚合根把模型弄的晦涩难懂那就得不偿失了

领域服务(Domain Service)

什么是领域服务

有些领域中的动作,它们是一些动词,看上去却不属于任何对象。它们代表了领域中的一个重要的行为,所以不能忽略它们或者简单地把它们合并到某个实体或者值对象中。当这样的行为从领域中被识别出来时,最佳实践是将它声明成一个服务。 这样的对象不再拥有内置的状态。它的作用仅仅是为领域提供相应的功能。Service往往是以一个活动来命名,而不是Entity来命名。例如开篇转账的例子,转账(transfer)这个行为是一个非常重要的领域概念,但是它是发生在两个账号之间的,归属于账号Entity并不合适,因为一个账号Entity没有必要去关联他需要转账的账号Entity,这种情况下,使用MoneyTransferDomainService就比较合适了。
识别领域服务,主要看它是否满足以下三个特征:
1. 服务执行的操作代表了一个领域概念,这个领域概念无法自然地隶属于一个实体或者值对象。
2. 被执行的操作涉及到领域中的其他的对象。
3. 操作是无状态的。

领域服务陷阱

在使用领域服务时要特别当心,一个比较常见的错误是没有努力为行为找到一个适当的对象,就直接抽象成领域服务,这会使我们的代码逐渐转化为过程式的编程,一个极端的例子是把所有的行为都放到领域服务中,而领域模型退化成只有属性的贫血DO,那DDD就没有任何意义了。所以一定要深入思考,既不能勉强将行为放到不符合对象定义的对象中,破坏对象的内聚性,使其语义变得模糊。也不能不加思考的都放到领域服务中,从而退化成面向过程的编程。

应用服务和领域服务如何划分

在领域建模中,我们一般将系统划分三个大的层次,即应用层(Application Layer),领域层(Domain Layer)和基础实施层(Infrastructure Layer),关于这三个层次的详细内容可以参考我的另一篇SOFA框架的分层设计。可以看到在App层和Domain层都有服务(Service),这两个Service如何划分呢,什么样的功能应该放在应用层,什么样的功能应该放在领域层呢?
决定一个服务(Service)应该归属于哪一层是很困难的。如果所执行的操作概念上属于应用层,那么服务就应该放到这个层。如果操作是关于领域对象的,而且确实是与领域有关的、为领域的需要服务,那么它就应该属于领域层。 总的来说,涉及到重要领域概念的行为应该放在Domain层,而其它非领域逻辑的技术代码放在App层,例如参数的解析,上下文的组装,调用领域服务,消息发送等。还是银行转账的case为例,下图给出了划分的建议:
复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图10

边界上下文(Bounded Context)

领域实体是有边界上下文的,比如Apple这个实体不同的上下文,表达的含义就完全不一样,在水果店它就是水果,在苹果专卖店它就是手机。

所以边界上下文(Bounded Context)在DDD里面是一个非常重要的概念,Bounded Context明确地限定了模型的应用范围,在Context中,要保证模型在逻辑上统一,而不用考虑它是不是适用于边界之外的情况。在其他Context中,会使用其他模型,这些模型具有不同的术语、概念、规则和Ubiquitous Language的行话。

上下文映射(Context Mapping)

那么不同Context下的业务要互相通信怎么办呢?这就涉及跨边界的Context Mapping(上下文映射),首先不同上下文之间的通信可以是同步的,也可以是异步的,同步的话一般是RPC或者RESTFul,异步的话会推荐上文提到的Domain Event.

Mapping的方式有很多种,有Shared Kernal(共享内核),Conformist(追随者),以及Anti-Corruption(防腐层)等等。

我个人比较推崇Domain Event + AC,这样可以将系统之间的耦合降到最低。

以我们真实的业务场景举个例子,比如会员这个概念在ICBU网站是指网站上的Buyer,但是在CRM领域是指Customer,虽然很多的属性都是一样的,但是二者在不同的Context下其语义和概念是有差别的,我们需要用AC做一下转换:
复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图11

边界上下文和微服务

先来说一下微服务,抛开以Docker为代表的底层容器化技术不看,微服务和我们之前的SOA么有本质区别。

这不是我一个人的观点,关于这个想法我还专门求证了业界大牛Randy Shoup,问他微服务和SOA的区别,下面是他给我的回答
复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图12

那么如何划分系统,才能得到一个比较合适的粒度,不会太粗,也不会太细呢。此时我们可以考虑DDD的战略设计,即从战略角度整体描述业务领域全貌,然后通过边界上下文将不同的实体归类到相对应的域里面。

比如在CRM领域,我们按照下面的战略设计图,我会自然的把CRM系统划分成销售服务,组织权限服务,营销服务,售卖服务。
复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图13

模型重构

最后我想强调的是,建模不是一次性的工作,也不可能是一次性的工作,业务在演化,随之而来的模型也需要演化和重构,当模型和业务部匹配的时候,你还是要霸王硬上弓的往里面塞,其结果可想而知。

模型统一

建模的过程很像盲人摸象,不同背景人用不同的视角看同一个东西,其理解也是不一样的。比如两个盲人都摸到大象鼻子,一个人认为是像蛇(活的能动),而另一个人认为像消防水管(可以喷水),那么他们将很难集成。双方都无法接受对方的模型,因为那不符合自己的体验。事实上,他们需要一个新的抽象,这个抽象需要把蛇的“活着的特性”与消防水管的“喷水功能”合并到一起,而这个抽象还应该排除先前两个模型中一些不确切的含义和属性,比如毒牙,或者卷起来放到消防车上去的行为,这就是模型的统一。统一完的模型也许还不叫大象鼻子,但是已经很接近大象鼻子的属性和功能了,随着我们对模型对象、对业务理解的越来越深入、越来越透彻,我们会不断的调整演化我们的模型,所以建模不是一个one-time off的工作,而是一个持续不断演化重构的过程。

模型演化

世界上唯一不变的就是变化,模型和代码一样也需要不断的重构和精化,每一次的精化之后,开发人员应该对领域知识有了更加清晰的认识。 这使得理解上的突破成为可能,之后,一系列快速的改变得到了更符合用户需要并更加切合实际的模型。其功能性及说明性急速增强,而复杂性却随之消失。这种突破需要我们对业务有更加深刻的领悟和思考,然后再加上重构的勇气和能力,勇气是项目工期很紧你敢不敢重构,能力是你有没有完备的CI保证你的重构不破坏现有的业务逻辑。

实体在演变
以开篇的银行账号为例,假如一开始账号都有withdraw(取钱)的行为,此时只需要在Account上加上withdraw方法就好了。
- 演变一:
随着业务的发展,我们需要支持ATM账号和Online账号,而Online账号是不能withdraw的,此时最差的做法是保持模型不变,而是在withdraw方法中判断如果是OnlineAccount则抛出异常。这种简单的代码堆砌可以满足业务功能,但是其业务语义完全被掩盖。更好的重构方法应该是将withdraw抽成一个接口IWithdrawable。
- 演变二:
好的,没有什么可以阻挡业务对变化的向往。现在公司出于安全性的考虑,为新开通的ATMAccount设置了取款上线,超过则不能支取。简单做法是在IWithdrawable中再加入一个setLimit行为,可是我们并不想改动影响到老的账号业务,所以更好的重构应该是重新写一个ILimitedWithdrawable接口,让其继承老接口,这样老的代码就可以保持不变了。
复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图14

通过上面的例子,我们可以看到领域模型和面向对象是一对孪生兄弟,我们会用到大量的OO原则,比如上面的重构就用到了SOLID的SRP(单一职责)和OCP(开闭原则)。在实际工作中,我的确也有这样的体会,自从践行DDD以后,我们采用OOA和OOD的时候比以前明显多了很多,OO的能力也在不断的提升。

引入新抽象
还是以开篇的转账来举个例子,假如转账业务开始变的复杂,要支持现金,信用卡,支付宝,比特币等多种通道,且没种通道的约束不一样,还要支持一对多的转账。那么你还是用一个transfer(fromAccount, toAccount)就不合适了,可能需要抽象出一个专门的领域对象Transaction,这样才能更好的表达业务,其演化过程如下:
复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图15

业务可视化和可配置化

好的领域建模可以降低应用的复杂性,而可视化和可配置化主要是帮助大家(主要是非技术人员,比如产品,业务和客户)直观地了解系统和配置系统,提供了一种“code free”的解决方案,也是SaaS软件的主要卖点。要注意的是可视化和可配置化难免会给系统增加额外的复杂度,必须慎之又慎,最好是能使可视化和配置化的逻辑与业务逻辑尽量少的耦合,否则破坏了原有的架构,把事情搞的更复杂就得不偿失了。

可扩展设计中,我已经介绍了我们SOFA架构是如何通过扩展点的设计来支撑不同业务差异化的需求的,那么可否更进一步,我们将领域的行为(也叫能力)和扩展点用可视化的方式呈现出来,并对于一些不需要编码实现的扩展点用配置的方式去完成呢。 当然是可以的,比如还是开篇转账的例子,对于透支策略OverdraftPolicy这个业务扩展点,新来一个业务说透支额度不能超过1000,我们可以完全结合规则引擎进行配置化完成,而不需要编码。

所以我能想到的一种还比较优雅的方式,是通过Annotation注解的方式对领域能力和扩展点进行标注,然后在系统bootstrap阶段,通过代码扫描的方式,将这些能力点和扩展点收集起来上传到中心服务器,然后再通过GUI的方式呈现出来,从而做到业务的可视化和可配置化。大概的示意图如下:
复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图16

有同学可能会问流程要不要可视化,这里要分清楚两个概念,业务逻辑流和工作流,很多同学混淆了这两个概念。业务逻辑流是响应一次用户请求的业务处理过程,其本身就是业务逻辑,对其编排和可视化的意义并不是很大,无外乎只是把代码逻辑可视化了,在我们的SOFA框架中,是通过扩展点和策略模式来处理业务的分支情况,而我看到我们阿里很多的内部系统将这种响应一次用户请求的业务逻辑用很重的工作流引擎来做,美其名曰流程可编排,实质上往往是把简单的事情复杂化了。而工作流是指完成一项任务所需要不同节点的连接,节点主要分为自动节点和人工节点,其中每个人工节点都需要用户的参与,也就是响应一次用户的请求,比如审批流程中的经理审批节点,CRM销售过程的业务员的处理节点等等。此时可以考虑使用工作流引擎,特别是当你的系统需要让用户自定义流程的时候,那就不得不使用可视化和可配置的工作流引擎了,除此之外,最好不要自找麻烦。我曾在银行工作过,亲眼看见过IBM是怎么忽悠银行使用它们的BPM系统,然后把系统弄的巨复杂无比,所以我对工作流引擎的印象并不好,当然也不排除有用的特别合适的案例,只是我还没看见,如果有看见的同学麻烦告诉我一声,学习一下。因为我们现在还没有让用户自定义流程的诉求,所以使用工作流引擎并不在我们现阶段的考虑范围之内。

  • 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图17 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图18 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图19 点赞 33
  • 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图20 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图21 评论 15
  • 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图22 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图23 分享

    x

    海报分享

    复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图24

    扫一扫,分享海报

  • 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图25 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图26 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图27 收藏 52

  • 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图28 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图29 打赏

    打赏

    复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图30

    张建飞(Frank)

    你的鼓励将是我创作的最大动力

    C币 余额

    ¥2 ¥4 ¥6 ¥10 ¥20 ¥50

    您的余额不足,请先充值哦~去充值

  • 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图31 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图32 举报

  • 已关注 关注
  • 一键三连

    点赞Mark关注该博主, 随时了解TA的最新博文复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图33

已标记关键词 清除标记

领域建模——架构设计的第一步(上)

zhangbijun1230的专栏

03-12 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图34 4007

[

领域建模——架构设计的第一步(上) 《深入剖析架构师角色》中我们提到,架构师需要能够从问题领域出发推导出满足业务需求的架构体系,同时又能够从实现方法入手设计出能够满足业务架构需求的技术架构体系,最终实现业务架构和技术架构的统一。在上一篇《架构设计的核心问题》中我们也认识到架构设计的两个层次,即面向问题领域的业务架构和面向解决方案的技术架构。诚然,对于架构师的需求主要体现在技术架构上,但业务架构是…

](https://blog.csdn.net/zhangbijun1230/article/details/88430662)

《领域驱动设计-软件核心复杂性__应对之道》笔记

flyweilai1287的专栏

06-02 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图35 2342

[

问题: 1、 何为领域驱动设计(DOMAINDriven DESIGN)? 2、 UBIQUITOUS LANGUAGE(领域通用语言)应该是如何去描述 3、 笔记: 1、 交流的重要性:和领域专家良好的沟通是建立模型的首要条件,要具备表达清晰,逻辑分析强等能力,具备UML熟练操作的技能。 第二部分 模型驱动设计的构造块 第四章 分离模型 分层架构如图:

](https://blog.csdn.net/flyweilai1287/article/details/28120969)

复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图36

复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图37

插入表情

复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图38 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图39 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图40 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图41 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图42 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图43 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图44 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图45 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图46 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图47 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图48 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图49 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图50 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图51 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图52 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图53 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图54 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图55 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图56 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图57 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图58 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图59 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图60 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图61 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图62 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图63 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图64 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图65 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图66 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图67 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图68 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图69 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图70 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图71 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图72 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图73 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图74 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图75 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图76 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图77 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图78 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图79 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图80 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图81 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图82 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图83 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图84 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图85 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图86 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图87 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图88 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图89 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图90 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图91 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图92 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图93 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图94 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图95 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图96 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图97 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图98 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图99 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图100 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图101

添加代码片

  • HTML/XML
  • objective-c
  • Ruby
  • PHP
  • C
  • C++
  • JavaScript
  • Python
  • Java
  • CSS
  • SQL
  • 其它

还能输入1000个字符

  • 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图102

    tmp_user001:“领域对象Transaction”这里为啥要抽象一个新的对象出来,而是不是transferService有多个实现类呢,CashTransferService、AliTransferService2 月前回复复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图103 举报

    复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图104 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图105 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图106

  • 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图107

    梁嘉成:最后一段感觉就是TMF2.0的逻辑2 月前回复复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图108 举报

    复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图109 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图110 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图111

  • 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图122

    Colingo:点赞!1 年前回复复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图123 举报

    复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图124 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图125 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图126

  • 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图127

    three__stones:请教下博主,领域模型的行为可以依赖外部的service 或者 repository (spring 的一个bean) 吗2 年前回复复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图128 举报

    复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图129 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图130 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图131

  • 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图132

    zhaozhi406:写的太好了,受益匪浅2 年前回复复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图133 举报

    复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图134 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图135 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图136

  • 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图137

    他山之石头:1. CRM中的合同审批流程是一个典型的工作流场景,工作流引擎能够帮助我们将流控和业务逻辑解耦; 2. Enrichment和Query-Back我更推荐结合使用,不变的内容放到消息中,易变的内容Query-Back;2 年前回复复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图138 举报

    复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图139 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图140 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图141

  • 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图142

    WalkOffTheEarth:这篇DDD讲的非常清楚易懂,有所感谢和收获,谢谢博主2 年前回复复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图143 举报

    复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图144 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图145 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图146

  1. 1. `大家好,我是10多年开发,也设计过一些系统,对DDD在研究,希望更多的同行案例一起学习,`
  2. 2. `建立了QQ群:DDD领域模型研究 849832577 大家交流啊`
  3. ```
  4. 3 年前回复![](https://csdnimg.cn/release/blogv2/dist/pc/img/commentMore.png)
  5. 举报
  6. ![](https://csdnimg.cn/release/blogv2/dist/pc/img/commentUnHeart.png)
  7. ![](https://csdnimg.cn/release/blogv2/dist/pc/img/commentActiveHeart.png)
  8. ![](https://csdnimg.cn/release/blogv2/dist/pc/img/commentActiveHeart.png)
  • <
  • 1
  • 2
  • >

相关推荐

[

复杂性__应对之道 - 领域建模_happylzs2008的专栏

](https://blog.csdn.net/happylzs2008/article/details/103179305)

11-26

[

实际上,CQRS就是对事务脚本和领域模型两种模式的综合,因为对于Query和报表的场景,使用领域模型往往会把简单的事情弄复杂,此时完全可以用奥卡姆剃刀把领域层剃掉,直接…

](https://blog.csdn.net/happylzs2008/article/details/103179305)

[

复杂性__应对之道 - 领域建模_人工智能_rugaxm的专栏

](https://blog.csdn.net/rugaxm/article/details/100538615)

5-30

[

目前比较有效的治理办法就是领域建模,因为领域模型是面向对象的,在封装业务逻辑的同时,提升了对象的内聚性和重用性,因为使用了通用语言(Ubiquitous Language),使得隐藏…

](https://blog.csdn.net/rugaxm/article/details/100538615)

领域驱动设计之我见-__领域建模

乔布斯基的博客

07-18 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图148 2061

[

前面两节絮絮叨叨重点讲了一句话:领域驱动设计的核心在领域模型,领域建模核心在精通领域业务。那么该如何做好领域建模呢?需要精通的能力都没有捷径可走,但是也不是没有方法可循,下文就领域业务和建模两方面做一下讲解。 做好领域建模,首先要做的工作是要精通领域业务知识,那么领域业务知识从哪里来呢?前面章节讲了从事软件研发的工程师并非全部来自于科班出身的学生,有些计算机相关学科天然带着领域业务知识,例如GI…

](https://blog.csdn.net/tidu2chengfo/article/details/81106194)

复杂性__应对之道 - 领域建模

张硕的博客

11-18 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图149 626

[

最近重构系统,脑子里不停的思考一些问题,为什么很多系统是“一坨”?真的就停留在一坨了吗?真的就甘心接受所谓的一坨吗? 今天偶然发现Frank的文章,跟作者沟通后,以下作为转载,文末点击查看原文。感谢在这个浮躁的氛围中,还有人具备如此珍贵的思考与实践!感谢 为什么要领域建模 维护过企业级业务系统的同学,基本上没有一个不抱怨业务代码烂的,过程式的面条代码充斥着屏幕,程序员的心力和体力都经受着极大的考验…

](https://lemon.blog.csdn.net/article/details/84201574)

[

复杂性__应对之道 - 领域建模_maoyeqiu的专栏

](https://blog.csdn.net/maoyeqiu/article/details/108986862)

12-24

[

目前比较有效的治理办法就是领域建模,因为领域模型是面向对象的,在封装业务逻辑的同时,提升了对象的内聚性和重用性,因为使用了通用语言(Ubiquitous Language),使得隐藏…

](https://blog.csdn.net/maoyeqiu/article/details/108986862)

[

《领域驱动设计:软件核心复杂性__应对之道(修订版)》—第…

](https://blog.csdn.net/weixin_33963594/article/details/90564654)

1-30

[

本节书摘来自异步社区《领域驱动设计:软件核心复杂性__应对之道(修订版)》一书中的第1章,第1.1节有效建模的要素,作者【美】埃里克•埃文斯(Eric Evans), 马利…

](https://blog.csdn.net/weixin_33963594/article/details/90564654)

复杂度应对之道 - COLA应用架构

我的新书《代码精进之路:从码农到工匠》

01-04 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图150 2万+

[

前言 从业这么多年,接触过银行的应用,Apple的应用,eBay的应用和现在阿里的应用,虽然分属于不同的公司,使用了不同的架构,但有一个共同点就是都很复杂。导致复杂性的原因有很多,如果从架构的层面看,主要有两点,一个是架构设计过于复杂,层次太多能把人绕晕。另一个是根本就没架构,ServiceImpl作为上帝类包揽一切,一杆捅到DAO(就简单场景而言,这种Transaction Script也还凑合…

](https://blog.csdn.net/significantfrank/article/details/85785565)

领域建模的思想和方法

zhaome的专栏

01-07 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图151 1万+

[

领域模型是作为设计软件对象的启发来源,也是后续工件的必须输入。领域模型是说明问题域里(对建模者来说)有意义的领域类,它是面向对象分序的时候要创建的最重要的工作(必须说明,用例虽然也是一个重要的分析工作,但它并不是面向对象的,它是强调的概念的过程视图)。 一、领域建模的思想及其方法学问题 什么是“问题域”和“领域建模”?问题域:现实世界中系统所要解决问题的领域为“问

](https://blog.csdn.net/zhaome/article/details/5154193)

[

《领域驱动设计-软件核心复杂性__应对之道》阅读笔记(三)

](https://blog.csdn.net/Frank19910526/article/details/114198736)

3-10

[

如果约束的存在掩盖了对象的基本职责,或者如果约束在领域中非常突出但在模型中却不明显,那么就可以将其提取到一个显式的对象中,甚至可以把它建模为一个对象和关系…

](https://blog.csdn.net/Frank19910526/article/details/114198736)

领域模型详解

u014028063的博客

06-19 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图152 1万+

[

学会了面向对象的语法,却依然写不出面向对象的程序,因此我们需要了解如何从需求分析到面向对象设计这样一个过程。一,什么是领域模型领域建模。 从领域模型开始,我们就开始了面向对象的分析和设计过程,可以说,领域模型是完成从需求分析到面向对象设计的一座桥梁。 顾名思义,就是显示最重要的业务概念和它们之间关系,是真实世界各个事物的表示(现实世界的可视化抽象字典)而不是软件中各构件的表示。(类:表示业务概念,…

](https://blog.csdn.net/u014028063/article/details/80737325)

DDD领域驱动(四)——之领域建模

学会改变自己——才能突破

07-23 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图153 1027

[

前边两篇,我们讲述为什么用DDD?DDD如何做好需求梳理?DDD如何在系统的层面拆分为粗细粒度合适微服务,以及微服务的架构划分。也就是我们经常说的自顶向下的拆分,现在我们将要做的功能具体拆分到具体的服务上了,也有了菱形架构、四边形架构等骨架,那么接下来就需要我们进行领域的建模了,也就是传统软件设计中的详细设计了。先看下,这个阶段的重要点: 好,先说一下,我们传统的软件详细设计都是怎么做的?ER图进行业务抽象建模,根据ER图进行数据设计,功能流程图、时序图,数据流图,类图、状态图等通过抽象分析设计表、流

](https://liujiahan.blog.csdn.net/article/details/107528880)

复杂性__应对之道-__领域建模

02-24

[

本文来自于作者张建飞,文章主要介绍了如何进行领域建模、领域服务以及模型重构等相关内容。维护过企业级业务系统的同学,基本上没有一个不抱怨业务代码烂的,过程式的面条代码充斥着屏幕,程序员的心力和体力都经受着极大的考验,怎么破?DDD革命性在于,领域模型准确反映了业务语言,而传统J2EE或Spring+Hibernate等事务性编程模型只关心数据,这些数据对象除了简单setter/getter方法外,没有任何业务方法,被比喻成贫血模式。以银行账号Account为案例,Account有“存款”,“计算利息”和“取款”等业务行为,但是传统经典的方式是将“存款”,“计算利息”和“取款”行为放在账号的服务A

](https://download.csdn.net/download/weixin_38606294/15452638)

领域驱动设计:软件核心复杂性__应对之道

01-18

[

领域建模已被业界普遍认为是软件设计成败的关键。通过领域建模,软件开发人员能够展示丰富的功能并将这些功能实现为真正满足用户需要的软件。尽管领域建模非常重要,但市面上介绍如何将有效的领域建模结合到软件开发过程中的著作却非常少。   本书就是为此目的而编写的。它向读者系统地讲述了领域驱动设计的方法,介绍了大量优秀的设计示例、技术经验以及用于处理复杂领域软件工程的基本原则。本书做到了设计和开发实践相结合,在介绍领域驱动设计的同时,还提供了大量的Java示例。   通过本书,读者将获得对领域驱动设计的总体认识,了解领域驱动设计中涉及的关键原则和术语。   面向对象的开发人员、系统分析师以及设计师在深入思

](https://download.csdn.net/download/yesha347/9408209)

领域驱动设计-软件核心复杂性__应对之道

Great haste makes great waste

06-25 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图154 362

[

每个软件程序是为了执行用户的某项活动,或是满足用户的某种需求。 这些用户应对软件的问题区域就是软件的领域。 领域模式并非魔种特殊的图,而是这种图索要传达的思想。它绝不单单是领域专家头脑中的知识,而是对这类知识严格的组织且有选择的抽象。图可以表示和传达一种模型,同样,精心书写的代码或文字也能达到同样的目的。 领域建模并不是要尽可能建立一个符合”现实”的模型。即使是对具体、真实世界的事物进行建模,所…

](https://blog.csdn.net/xiaodongxiexie/article/details/93625852)

《代码精进之路:从码农到工匠》——抽象

我的新书《代码精进之路:从码农到工匠》

06-21 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图155 3195

[

写本文的原因是,抽象是软件设计中最重要的概念,但抽象这个概念本身又很抽象,值得我们花时间去好好探究一番。 抽象的力量 没有抽象思维,就没有人类光辉灿烂的现代文明。 原始人看到一片树林,不会给它们一个名字,比如叫“松树”。他们会给每一棵树取一个独特的名字,可能叫“silisiba”。原始人只知道某棵具体的树。 随着意识水平的发展,人类开始有意识地将具有相同特征的事物归并到一起,从“silisiba”…

](https://blog.csdn.net/significantfrank/article/details/93173386)

正则表达式表单验证(姓名、性别、电话、邮箱、密码)及知识点总结

saber的博客

08-23 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图156 1万+

[

正则表达式(regular expression)是一种表达文本模式(即字符串结构)的方法,有点像字符串的模板,常常用来按照“给定模式”匹配文本。 本人在学习之后写了一个表单验证demo,话不多说,上代码 <!DOCTYPE html> &…

](https://blog.csdn.net/saber04/article/details/100042797)

Rocketmq - 2 集群架构模型和部署结构图

liang

08-19 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图157 4074

[

RocketMQ的Broker集群搭建 Master和slaver类似Redis和MySql的主从,Slaver只有读的权限,没有写的权限。 RocketMQ提供了多种的集群搭建,具体如下: 1.单个 Master 这种方式风险较大,一旦 Broker 重启或者宕机时,会导致整个服务不可用,不建议线上环境使用 2. 多 Master 模式 一个集群无 Slave,全是 Master,…

](https://blog.csdn.net/qq_32020035/article/details/81834849)

复杂性__应对之道 - 领域建模

一个天秤座的架构师

12-17 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图158 111

[

为什么要领域建模 维护过企业级业务系统的同学,基本上没有一个不抱怨业务代码烂的,过程式的面条代码充斥着屏幕,程序员的心力和体力都经受着极大的考验,怎么破? DDD革命 DDD革命性在于,领域模型准确反映了业务语言,而传统J2EE或Spring+Hibernate等事务性编程模型只关心数据,这些数据对象除了简单setter/getter方法外,没有任何业务方法,被比喻成贫血模式。 以银行账号Ac…

](https://blog.csdn.net/u012921921/article/details/103574323)

验证表单——正则表达式

LY

06-16 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图159 1310

[

练习了密码的强弱长度,之后继续联系验证表单 首先需要掌握一些例子的正则表达式(验证表单需要严格模式) qq号码:为5-_11位,首位不为0,/^[1-9]\d{4,10}$/ 邮箱:/^[0-9a-zA-Z.__-]+[@][0-_9a-zA-Z.__-]+([.][a-_zA-Z]+){1,2}$/(重点) 手机号码:11位,首位不为0,/^[1-_9]\d{10}$/ <!DOCTYPE ht…

](https://blog.csdn.net/qq_42853241/article/details/92239254)

代码精进之路-__-从码农到工匠读书笔记

Nyiragongo的博客

12-29 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图160 1438

[

1.技术人的素养 1) 不教条 首先学会基本的规则,然后知道什么时候打破规则 2)软件开发的生命周期风格类似一个光谱,从瀑布式到敏捷,以及他们之间存在多种可能性 3)批判性思维 4)成长型思维 5)结构化思维 逻辑 + 套路的模式 6)工具化思维 7) 好奇心 8)记笔记 9)有目标 10)选择的自由 11)平和的心态 12)精进 …

](https://blog.csdn.net/Nyiragongo/article/details/103755632)

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页

张建飞(Frank) CSDN认证博客专家 CSDN认证企业博客

码龄14年 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图166 暂无认证

[

94

原创

](https://blog.csdn.net/significantfrank)

[

4691

周排名

](https://blog.csdn.net/rank/writing_rank)

[

1万+

总排名

](https://blog.csdn.net/rank/writing_rank_total)

30万+

访问

复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图167

等级

4147

积分

1705

粉丝

615

获赞

257

评论

1550

收藏

复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图168

复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图169

复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图170

复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图171

私信

已关注

复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图172

热门文章

分类专栏

复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图191

最新评论

最新文章

2021年2篇

2020年12篇

2019年17篇

2018年3篇

2015年1篇

2014年15篇

2013年15篇

2012年19篇

2011年5篇

2010年2篇

2009年4篇

2008年4篇

目录

  1. 为什么要领域建模
    1. DDD革命
    2. DDD不是银弹
  2. DDD初体验
    1. 银行转账事务脚本实现
    2. 银行转账领域模型实现
  3. 领域建模的好处
    1. 面向对象
    2. 业务语义显性化
  4. 如何进行领域建模
    1. 初步建模
    2. 领域事件(Domain Event)
      1. Event命名
      2. Event内容
      3. Event Sourcing
      4. Event Storming
    3. 聚合根(Aggreagte)
    4. 领域服务(Domain Service)
      1. 什么是领域服务
      2. 领域服务陷阱
      3. 应用服务和领域服务如何划分
    5. 边界上下文(Bounded Context)
      1. 上下文映射(Context Mapping)
      2. 边界上下文和微服务
    6. 模型重构
      1. 模型统一
      2. 模型演化
  5. 业务可视化和可配置化

目录

  1. 为什么要领域建模
    1. DDD革命
    2. DDD不是银弹
  2. DDD初体验
    1. 银行转账事务脚本实现
    2. 银行转账领域模型实现
  3. 领域建模的好处
    1. 面向对象
    2. 业务语义显性化
  4. 如何进行领域建模
    1. 初步建模
    2. 领域事件(Domain Event)
      1. Event命名
      2. Event内容
      3. Event Sourcing
      4. Event Storming
    3. 聚合根(Aggreagte)
    4. 领域服务(Domain Service)
      1. 什么是领域服务
      2. 领域服务陷阱
      3. 应用服务和领域服务如何划分
    5. 边界上下文(Bounded Context)
      1. 上下文映射(Context Mapping)
      2. 边界上下文和微服务
    6. 模型重构
      1. 模型统一
      2. 模型演化
  5. 业务可视化和可配置化

分类专栏

举报

选择你想要举报的内容(必选)

  • 内容涉黄
  • 政治相关
  • 内容抄袭
  • 涉嫌广告
  • 内容侵权
  • 侮辱谩骂
  • 样式问题
  • 其他

原文链接(必填)

请选择具体原因(必选)

  • 包含不实信息
  • 涉及个人隐私

请选择具体原因(必选)

  • 侮辱谩骂
  • 诽谤

请选择具体原因(必选)

  • 搬家样式
  • 博文样式

补充说明(选填)

取消

确定

复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图206 新手
引导复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图207 客服 举报 复杂性应对之道 - 领域建模_我的新书《代码精进之路:从码农到工匠》-CSDN博客 - 图208 返回
顶部 https://blog.csdn.net/significantfrank/article/details/79614915 ```