功能编程和业务领域模型

Tuo*_*nen 2 database entity domain-driven-design functional-programming clojure

函数式编程不鼓励可变状态,并将数据结构限定为永久值.可以为变量分配一个新值(从纯函数派生的新数据结构),但是现有的数据结构永远不应该变异.范式已从程序状态机转变为将功能建模为连接在一起的纯函数的长链.因此减少了系统中的耦合,理论上应该更容易推理和跟踪错误.

但是我们在Web开发中试图解决的问题的业务领域自然是面向对象的.我们谈论的是实体及其属性.身份和它的状态.状态存储在数据库中.当我们进行货币交易时,我们正在改变特定的银行账户以取款/存钱.我们不考虑为每笔交易更换新的银行账户.它们本身就是可变对象.某个地方必须以某种方式改变这种状态.我意识到函数式语言并不否认状态(毕竟这是不可避免的),但有利于副作用的自由语法,这使得变异操作感觉很尴尬.

现在,函数式语言的目标是如何针对现实世界的面向对象的本质?例如,clojure没有类的概念,因此我猜它没有ORM.它如何与企业业务的关系世界保持一致?范式甚至会知道称为实体的概念吗?是否允许改变这样的实体?或者功能编程是否需要改变我们存储数据的方式?

这整个功能方法似乎是理论上的,与现实世界相矛盾.如何在Web开发的真实场景中更好地了解所有这些是如何工作的?

Voi*_*son 8

从Stuart Halloway关于Clojure时间模型的演讲开始,这可能是值得.

不承诺做谈话正义:实体有国家.注意,有-A,而不是-A; 所以我们应该考虑构图.从概念上讲,我们认为对象是对不可变状态的可变引用.

现在,如果你通过Bertrand Meyer的CQS镜头看这个; 查询支持很简单 - 查询不会修改对象的状态,因此它们实际上是一个纯函数

result = query(this.currentState)
Run Code Online (Sandbox Code Playgroud)

另一方面,命令支持可以简单地分为两部分,一个产生新状态的查询,以及对可变引用的更改.

State nextState = query(this.currentState)
{ref-set} this.currentState = nextState
Run Code Online (Sandbox Code Playgroud)

正如Lee在评论中指出的那样,当前状态和历史彼此是双重的,也就是说,我们可以轻松地将上述示例转变为

// conceptually, this is still a _query_; we aren't mutating current state
// but are instead calculating a new value.
State nextState = this.currentState.apply(command)
{ref-set} this.currentState = nextState
Run Code Online (Sandbox Code Playgroud)

,我们对当前模型的命令输出与变化历史之间的区别更加谨慎,因此拼写看起来更像

// conceptually, this is still a _query_; we aren't mutating current state
// but are instead calculating a new value.
Events changes = command(this.currentState)
State nextState = this.currentState.apply(changes)
{ref-set} this.currentState = nextState
Run Code Online (Sandbox Code Playgroud)

你可以了解整个实体的历史

State state = fold(history, State.SEED)
{ref-set} this.currentState = state
Run Code Online (Sandbox Code Playgroud)

状态存储在数据库中.

几乎:状态存储在数据库中.

State nextState = database.currentState.apply(command)
{ref-set} database.currentState = nextState
Run Code Online (Sandbox Code Playgroud)

例如,Greg Young将Event Store描述为只有32个字节的可变状态.其他一切都是写一次.

这整个功能方法似乎是理论上的,与现实世界相矛盾.

完全没有 - 记住,过去是不可改变的; 允许你改变过去的模型不符合现实世界的约束.

如何在Web开发的真实场景中更好地了解所有这些是如何工作的?

首先,请查看Greg Young关于事件采购的讨论(尤其是他的新事件;随着时间的推移,他的功能越来越强),以及Mark Seemann的博客.除了Stuart或Rich Hickey所能找到的一切.