DDD+Javascript领域建模示例 -Alex Lawrence

解道jdon 2021-01-23 12:51:01
javascript DDD 领域 ddd+javascript 领域建模


这篇文章使用一个简单的示例说明了域建模过程。第一步,确定实际问题。接下来,找到一种解决方法。接下来是创建初始域模型。之后,提供第一实施方式。然后,讨论并解决了技术和逻辑上的挑战。此外,还将解释域模型及其实现之间的差异。该帖子最后建议即使对于小型项目,也应使用以问题为中心和模型驱动的方法。

 

问题识别

领域驱动设计强调解决的问题及其涉及的知识领域。在我的书中,领域模型被定义为“专注于[..]解决特定问题的知识抽象集”。这意味着,为了创建有用的模型,首先需要确定问题。作为一个具体示例,请考虑当在读书时遇到的以下问题:我想知道文本中单个单词的出现情况。

开始这问题提得似乎很有用,但是,它并不是真正描述问题,而是已经暗示了特定的解决方案。相关的问题是:我试图通过计算单个单词的出现来解决什么问题?由于我不是英语母语,因此我通常不确定自己的词汇多样性。我想以某种方式衡量。因此,要解决的真正问题是确定文本的词汇多样性。

 

解决方法

发现问题后,就可以确定特定的解决方案。我的想法是,我可以通过查看单个单词的出现情况来确定词汇的多样性。但是,这种方法暗示仅软件部分还不是完整的解决方案。相反,它将仅生成有助于推导词汇使用指示的数据。确定实际的多样性将由我作为用户来完成。

 

初始域模型

如前所述,域模型是一组知识抽象。因此,它不必具有特定的表现形式或表示形式。更重要的是,虽然通常以某种方式表达模型,但各个工件通常只是信息的子集。对于词汇示例,可以通过纯文本传达知识抽象。请注意,这种方法没有对问题或域模型的复杂性做出任何声明。

目的是确定文本中词汇多样性的程度。“文本”代表单词和标点符号的集合。“词汇”可以定义为单个单词的集合。术语“多样性”包含了不同单词的出现及其出现。表述“度”表示边界和边界之间的离散步骤。例如,词汇多样性被认为是不能通过软件计算的主观指标。

总而言之,可以将域模型方面总结为以下几点:

  • 给定文本,应确定词汇多样性
  • 文本是单词和标点符号的集合
  • 词汇是一组单个单词
  • 词汇多样性是手动确定的主观指标

 

第一次实施

在定义域模型之后,可以开始实施。对于该示例,假定迭代软件开发过程。结果,在域模型的完整性和正确性方面有较低的要求。相反,以上定义可以看作是进一步发展的初始草案。理解它的另一种方式是,以下迭代是实验阶段的一部分,而无需构建生产软件。

以下代码是计算文本中单个单词的出现次数的第一个实现:

const countWordOccurrences = text => {
  wordOccurrences = {};
  text.split(' ').forEach(word => {
    if (wordOccurrences[word] == null) wordOccurrences[word] = 0;
    wordOccurrences[word]++;
  });
  return wordOccurrences;
};
const wordOccurrences = countWordOccurrences(`This is a basic example.
  Also, this is only one of many possible examples.`);
console.log(wordOccurrences);
/* output: {
  This: 1, is: 2, a: 1, basic: 1, 'example.\n': 1, '': 1, 'Also,': 1,
  this: 1, only: 1, one: 1, of: 1, many: 1, possible: 1, 'examples.': 1
} */

该示例用法及其输出演示了初始解决方案的功能。

 

技术问题

第一次实施存在一些技术问题。这些方面不是由于模型中的缺陷所致,而是与将隐式需求正确集成到代码中有关:一个问题是标点符号被错误地视为单词的一部分。对于换行符也是如此。另一个问题是,多个空格导致创建空单词条目。这些方面不适合作为模型的显式部分,因为它们应被视为常识。

以下代码提供了经过重做的实现,克服了上述问题:

const wordRegex = /[a-z0-9]{1}[a-z0-9-]*/gi;
const countWordOccurrences = text => {
  wordOccurrences = {};
  Array.from(text.matchAll(wordRegex), match => match[0]).forEach(word => {
    if (wordOccurrences[word] == null) wordOccurrences[word] = 0;
    wordOccurrences[word]++;
  });
  return wordOccurrences;
};
const wordOccurrences = countWordOccurrences(`This is a basic example.
  Also, this is only one of many possible examples.`);
console.log(wordOccurrences);

第二段代码通过使用正则表达式解决了上述技术问题。此表达式定义两个规则。首先,每个单词都必须以字母数字字符开头。其次,第一个字符后面可以是字母数字字符和破折号的任意组合。

 

模型改进

重新设计的实现是一种改进,但仍然面临问题。有一些问题提示域模型中存在Bug缺陷:

  1. 一个Bug是该实现是区分大小写的,这导致具有不同大小写的相同单词的多个条目。
  2. 另外一个是:一个单词的单数和复数形式被认为是不同的事物。

可以如下更新域模型定义:

  • 给定文本,应确定词汇多样性
  • 文本是单词和标点符号的集合
  • 词汇集是单个单词
  • 词汇多样性是指示语言质量的指标
  • 一个单词的不同大小写被认为是相同的
  • 一个单词的单数和复数被认为是相同的

最后一个示例提供了一个反映最新域模型的实现:

const wordRegex = /[a-z0-9]{1}[a-z0-9-]*/gi;
const countWordOccurrences = (text, {asSingular}) => {
  wordOccurrences = {};
  text = text.toLowerCase();
  Array.from(text.matchAll(wordRegex), match => match[0]).forEach(word => {
    word = asSingular(word);
    if (wordOccurrences[word] == null) wordOccurrences[word] = 0;
    wordOccurrences[word]++;
  });
  return wordOccurrences;
};
const pluralize = require('pluralize');
const wordOccurrences = countWordOccurrences(`This is a basic example.
  Also, this is only one of many possible examples.`,
  {asSingular: pluralize.singular});
console.log(wordOccurrences);
/* output: {
  this: 2, is: 2, a: 1, basic: 1, example: 2,
  also: 1, only: 1, one: 1, of: 1, many: 1, possible: 1
} */

通过使输入文本为小写字母来减轻大小写敏感性。对于单数和复数形式的合并,实现中引入了dependency asSingular。此参数必须分配有一个单词并返回单数形式的操作。例如,将pluralize加载npm模块,并将其功能singular()作为依赖关系传入。这种方法可确保正确表达模型行为,同时又不受具体依赖。

 

模型与代码

域模型和实现所表达的知识之间存在差异。考虑一下我的书中的以下摘录:“实际的实现可能只反映基础抽象的一个子集,并最终处理无关的技术方面。” 词汇多样性示例说明了这两种说法。一方面,该实现没有表达完整的模型,因为它仅对每个单词的出现次数进行计数。其次,它还处理纯粹的技术问题,例如多个空格或换行符。

 

DDD小问题

这篇文章说明的另一方面是所谓的简单问题可能会给他们带来很多复杂性。对于具有丰富和复杂域的大型软件项目,通常建议使用域驱动设计及其单独的模式。但是,从问题空间开始并在实施之前创建有用的概念模型总是有益的。即使对于诸如确定词汇多样性之类的小功能,以问题为中心和模型驱动的方法也很有价值。

                   

版权声明
本文为[解道jdon]所创,转载请带上原文链接,感谢
https://www.jdon.com/55637

  1. 【计算机网络 12(1),尚学堂马士兵Java视频教程
  2. 【程序猿历程,史上最全的Java面试题集锦在这里
  3. 【程序猿历程(1),Javaweb视频教程百度云
  4. Notes on MySQL 45 lectures (1-7)
  5. [computer network 12 (1), Shang Xuetang Ma soldier java video tutorial
  6. The most complete collection of Java interview questions in history is here
  7. [process of program ape (1), JavaWeb video tutorial, baidu cloud
  8. Notes on MySQL 45 lectures (1-7)
  9. 精进 Spring Boot 03:Spring Boot 的配置文件和配置管理,以及用三种方式读取配置文件
  10. Refined spring boot 03: spring boot configuration files and configuration management, and reading configuration files in three ways
  11. 精进 Spring Boot 03:Spring Boot 的配置文件和配置管理,以及用三种方式读取配置文件
  12. Refined spring boot 03: spring boot configuration files and configuration management, and reading configuration files in three ways
  13. 【递归,Java传智播客笔记
  14. [recursion, Java intelligence podcast notes
  15. [adhere to painting for 386 days] the beginning of spring of 24 solar terms
  16. K8S系列第八篇(Service、EndPoints以及高可用kubeadm部署)
  17. K8s Series Part 8 (service, endpoints and high availability kubeadm deployment)
  18. 【重识 HTML (3),350道Java面试真题分享
  19. 【重识 HTML (2),Java并发编程必会的多线程你竟然还不会
  20. 【重识 HTML (1),二本Java小菜鸟4面字节跳动被秒成渣渣
  21. [re recognize HTML (3) and share 350 real Java interview questions
  22. [re recognize HTML (2). Multithreading is a must for Java Concurrent Programming. How dare you not
  23. [re recognize HTML (1), two Java rookies' 4-sided bytes beat and become slag in seconds
  24. 造轮子系列之RPC 1:如何从零开始开发RPC框架
  25. RPC 1: how to develop RPC framework from scratch
  26. 造轮子系列之RPC 1:如何从零开始开发RPC框架
  27. RPC 1: how to develop RPC framework from scratch
  28. 一次性捋清楚吧,对乱糟糟的,Spring事务扩展机制
  29. 一文彻底弄懂如何选择抽象类还是接口,连续四年百度Java岗必问面试题
  30. Redis常用命令
  31. 一双拖鞋引发的血案,狂神说Java系列笔记
  32. 一、mysql基础安装
  33. 一位程序员的独白:尽管我一生坎坷,Java框架面试基础
  34. Clear it all at once. For the messy, spring transaction extension mechanism
  35. A thorough understanding of how to choose abstract classes or interfaces, baidu Java post must ask interview questions for four consecutive years
  36. Redis common commands
  37. A pair of slippers triggered the murder, crazy God said java series notes
  38. 1、 MySQL basic installation
  39. Monologue of a programmer: despite my ups and downs in my life, Java framework is the foundation of interview
  40. 【大厂面试】三面三问Spring循环依赖,请一定要把这篇看完(建议收藏)
  41. 一线互联网企业中,springboot入门项目
  42. 一篇文带你入门SSM框架Spring开发,帮你快速拿Offer
  43. 【面试资料】Java全集、微服务、大数据、数据结构与算法、机器学习知识最全总结,283页pdf
  44. 【leetcode刷题】24.数组中重复的数字——Java版
  45. 【leetcode刷题】23.对称二叉树——Java版
  46. 【leetcode刷题】22.二叉树的中序遍历——Java版
  47. 【leetcode刷题】21.三数之和——Java版
  48. 【leetcode刷题】20.最长回文子串——Java版
  49. 【leetcode刷题】19.回文链表——Java版
  50. 【leetcode刷题】18.反转链表——Java版
  51. 【leetcode刷题】17.相交链表——Java&python版
  52. 【leetcode刷题】16.环形链表——Java版
  53. 【leetcode刷题】15.汉明距离——Java版
  54. 【leetcode刷题】14.找到所有数组中消失的数字——Java版
  55. 【leetcode刷题】13.比特位计数——Java版
  56. oracle控制用户权限命令
  57. 三年Java开发,继阿里,鲁班二期Java架构师
  58. Oracle必须要启动的服务
  59. 万字长文!深入剖析HashMap,Java基础笔试题大全带答案
  60. 一问Kafka就心慌?我却凭着这份,图灵学院vip课程百度云