首页 > 编程语言 >DDD的函数式编程实现

DDD的函数式编程实现

时间:2024-08-21 23:49:24浏览次数:6  
标签:FP 架构 函数 代码 编程 DDD

DDD是一种成熟的软件设计方法,旨在确保领域专家和开发人员能够有效合作,创造出高质量的软件。

本文介绍咋将FP(函数式编程)应用于DDD的实现,使其既优雅又简洁。C4模型中,软件架构图分为四个层次:“系统上下文”、“容器”、“组件”和“代码”。

“组件”是构成容器的基本单位,也是本文描述的层次。

1 代码组织结构

随应用程序复杂性增加,管理这种复杂性的一种方法是根据应用程序的职责或关注点将其拆分。分层架构是一种遵循这一原则的方法,它有助于保持不断增长的代码库的组织性,使开发人员能够轻松找到某个功能的实现位置。

分层架构中,代码被水平拆分为不同的层次,每一层通过面向对象(OO)设计进行封装。请求从顶层进入,代码从上到下执行,输出从顶层产生。

这种设计的一个问题是,多个层次不仅分离了关注点,还将同一业务功能的上下文分离到不同的位置,这意味着在修改同一业务功能时,可能需要同时修改多个层次。

另一个问题是,表示层和应用层通常被设计为外观模式,这易导致上帝对象的出现,而上帝对象被认为是一种反模式

FP本质是组合。FP更倾向于垂直组织代码,而不是水平拆分代码。多个函数通过Monad组合成一个函数流水线来实现一个业务功能(通常是一个API)。

基于函数式编程的垂直代码结构:

2 信任边界

现实世界中,问题域之间的边界是模糊的。限界上下文是计算机系统中对现实世界问题的人工投影:

  • 边界之外的世界不可信,因为它包括来自用户的各种输入
  • 边界之内的世界则是可信的、合法的、共享的领域模型

这要求我们在限界上下文的边界处引入验证和转换,从而防止外部输入并验证输出的合法性。

常见的验证和转换包括:

  • 将输入数据转换为领域模型
  • 验证输入数据的有效性,例如确保用户名和电子邮件不为空
  • 输出检查器,防止如用户密码等敏感信息被包含在输出数据中

在FP中,Applicative通常用于验证和转换输入数据为领域模型。一旦输入数据突破信任边界,你就无需担心用户名是否为空或电子邮件格式是否正确。你应专注于使用ADT进行领域建模,并通过纯函数处理业务规则。

3 使用状态机进行领域建模

业务模型可以通过不同状态的转换来建模。你总是可以通过联合类型(和类型)将领域建模为状态机。另一个好处是,在FP中,模式匹配迫使你处理联合类型的每个分支,以避免遗漏情况。

状态之间的转换

以用户注册为例:注册可以分为三个步骤:

  • 输入用户名和密码
  • 验证电子邮件
  • 支付会员费

这三个步骤可以通过联合类型记录为三个明确的状态。诸如注册、添加电子邮件、验证电子邮件等行为可以通过对这个领域模型进行模式匹配设计为函数。

4 保持领域纯粹

遵循依赖倒置原则的应用程序倾向于实现洋葱架构或整洁架构。其核心思想是将业务逻辑和领域模型置于应用程序的中心,而不是让业务逻辑依赖于数据访问或其他基础设施。依赖关系被倒置:基础设施和实现细节依赖于应用程序核心。

同样,在FP中,我们倾向于在每个API请求中将函数组合为流水线。与洋葱架构类似,我们尽可能将副作用置于领域之外,以保持领域的纯粹性。纯函数遵循持久性无知原则,它们专注于实现业务规则。

洋葱架构:

5 总结

通常,面向对象编程语言是实现DDD的首选,函数式编程则被认为适合数据科学的管道处理。实际上,DDD只是一个强调应专注于领域的思想,它并不依附于任何特定的编程范式。你可以利用FP的特性,如可组合性、Monad、Applicative和模式匹配,在“组件”架构层级上实现DDD。

关注我,紧跟本系列专栏文章,咱们下篇再续!

作者简介:魔都架构师,多家大厂后端一线研发经验,在分布式系统设计、数据平台架构和AI应用开发等领域都有丰富实践经验。

各大技术社区头部专家博主。具有丰富的引领团队经验,深厚业务架构和解决方案的积累。

负责:

  • 中央/分销预订系统性能优化
  • 活动&券等营销中台建设
  • 交易平台及数据中台等架构和开发设计
  • 车联网核心平台-物联网连接平台、大数据平台架构设计及优化
  • LLM Agent应用开发
  • 区块链应用开发
  • 大数据开发挖掘经验
  • 推荐系统项目

目前主攻市级软件项目设计、构建服务全社会的应用系统。

参考:

本文由博客一文多发平台 OpenWrite 发布!

标签:FP,架构,函数,代码,编程,DDD
From: https://www.cnblogs.com/JavaEdge/p/18372752

相关文章

  • 六:《Python基础语法汇总》— 函数
    一:函数入门​函数:就是可以重复使用的具有一定功能的代码。除了一些Python内置的函数以外,函数也可以自己定义​自定义函数:通过def定义的函数自定义函数格式:def函数名(参数):函数要去实现的功能代码#调用函数函数名(参数)​命名函数名和参数名时要符合变......
  • Secure Coding in C and C ++ (四)局部静态构造函数 虚函数
    前言上一章节我们讲解了关于C++静态和指针与引用的部分我们先来回顾一下相关的内容:指针说白了就是地址,inta;int*ptr=&a这里的整形指针就是存放的整数变量的地址静态static有两种层面:第一种层面就是在其他的文件里,如果加入了static修饰那么被修饰的在link......
  • 「字符串」前缀函数|KMP匹配:规范化next数组 / LeetCode 28(C++)
    概述为什么大家总觉得KMP难?难的根本就不是这个算法本身。在互联网上你可以见到八十种KMP算法的next数组定义和模式串回滚策略,把一切都懂得特别混乱。很多时候初学者的难点根本不在于这个算法本身,而是它令人痛苦的百花齐放的定义。有的next数组从0下标开始,有的从1开始;有的表......
  • 浅谈面向对象三大特性(着重介绍虚函数实现的多态)
        写在前面:文章内容分享为主,如有不当之处,恳请批评指正。        今天在使用C++的工厂模式的时候,突然发下有些生疏,就想着发一篇博客,巩固一下,但突然想到工厂模式中设计的继承以及多态的特性,决定先发一篇有关于C++多态的文章,其他的就丢给明天吧!一、面向对象三......
  • 字符串函数
    文章目录1.strcmp函数strcmp函数的使用:strcmp函数的模拟实现:2.strncpy函数3.strncat函数4.strstr函数strstr函数的使用:strstr函数的模拟现实:5.strtok函数6.strerror函数1.strcmp函数第⼀个字符串⼤于第⼆个字符串,则返回⼤于0的数字第⼀个字符串等于第⼆个字符串......
  • IPC对象通信方式---共享内存 | 网络通信 -编程
    共享内存共享内存机制其允许两个或多个进程共享一个给定的存储区,这一段存储区可以被两个或两个以上的进程映射至自身的地址空间中,一个进程写入共享内存的信息,可以被其他使用这个共享内存的进程,通过一个简单的内存读取错做读出,从而实现了进程间的通信。是内核预留的内存空间,最......
  • 标准IO函数:fprintf和fscanf,fread和fwrite
    1.使用分文件编译,实现注册登录界面,使用fgets,fscanf,fpritnf函数。主函数#include"log.h"intmain(intargc,constchar*argv[]){ intkey; while(1) { printf("**********1.注册**********\n"); printf("**********2.登录**********\n"); printf(&quo......
  • 人工智能 | 结对编程助手GithubCopilot
    简介GitHubCopilot是一款AI结对程序员,可帮助您更快、更少地编写代码。它从注释和代码中提取上下文,以立即建议单独的行和整个函数。GitHubCopilot由GitHub、OpenAI和Microsoft开发的生成式AI模型提供支持。它可作为VisualStudioCode、VisualStudio、Neovim和Jet......
  • 粒子群算法求解多元函数拟合问题
    在一元线性回归中,我们使用最小二乘法估计出k与b,这其实就是一个求拟合函数的过程。当一元扩展到多元,我们也可以用最小二乘的思想估计出参数目录一、最小二乘法二、将最小二乘法视为最值问题1.利用有约束的fmincon函数(1)定义目标函数(2)进行求解2.利用无约束最小值函数(1)利用fminsearch......
  • 一门多范式的编程语言Scala学习的第二天-函数的使用
    2.12scala中的函数式编程*scala中的函数式编程**面向对象编程:将对象当作参数一样传来传去*1、对象可以当作方法参数传递*2、对象也可以当作方法的返回值返回*当看到类,抽象类,接口的时候,今后无论是参数类型还是返回值类型,都需要提供对应的实现类对象**面向函数式编程......