为什么需要状态?

为什么需要状态呢?我们需要正视这个问题,状态究竟是怎样的一个东西。

把状态放在计算机当中成为了什么?

一台计算机全是01组成的,全是逻辑门电路,那么计算机里应该全是计算,若果成立,那么状态究竟是怎样一种计算?

当我们用变量保存状态时,存不存在悖论?

学了函数式后,很多观点,都开始产生裂缝。反思正是思维成长的证明。

0或1本身表示就是一种状态,是或非的逻辑状态啊。状态=时间+数值,是某个时刻代表的那个值。

建议探讨Statement 和expressions 区别,两者一个区别是前者有副作用,而后者没有。

计算机除了计算功能外,其实还有储存功能,储存为人服务的,信息管理系统, ERP等等基本都是一种数据跟踪系统,现实世界随着时间变化的数据储存起来,比如财务系统,每个月都有一个科目余额,结算到下一个月,随着你企业增长,这些都是表示你企业成立以来赚了多少钱,成本有哪些,等等。

命令式语言其实是一种人机交互命令的系统,属于软件工程派,此派和纯数学算法派是计算机世界两种至今存在的斗法流派,如同伊斯兰和基督教一样。

我个人感觉,很多人扎到纯数学算法派中,可能只有面向函数思维,特别是我们看到世界上一些大型流量网站,如facebook或twitter,其实他们的业务数据结构很简单,甚至是非结构化数据,所以,侧重面向函数的平台概念无疑对于他们是合适的,而大量企业软件实践中,不能忽视复杂业务场景,不能忽视业务领域中结构性特征,以及这些结构在某个时刻的值,也就是状态。

面向函数思维更适合做技术架构,命令式状态的思维更适合做业务架构。

[该贴被banq于2013-08-05 07:12修改过]

2013-08-05 06:57 "@banq "的内容
命令式语言其实是一种人机交互命令的系统,属于软件工程派,此派和纯数学算法派是计算机世界两种至今存在的斗法流派,如同伊斯兰和基督教一样。 ...

过去我也会是这样的观点,但现在我觉得之所以有这观点,是因为函数式没有很好的落地方式。函数式跟算法有很大不同,命令式的算法,仍然有很多局限性,通用性差,一旦在多线程的情况下,甚至会无法应用。而函数式的算法,其实是纯逻辑,过去我们都认为面向对象比起算法更接近自然语言,而现在我反而觉得函数式更接近自然语言。我不推崇算法,因为算法没有坚决抛离状态,而函数式的算法,我更倾向说逻辑,或者就说函数。算法没有逻辑组合,而函数和逻辑有。

用函数特有的方式来模拟指令式,你会发现函数写出来的实际上更可读,首先他不会隐蔽地改变定义,其次没有中间输出,再次它的逻辑组合能力跟自然语言的组合能力相近。
[该贴被SpeedVan于2013-08-05 17:53修改过]

我举个例子
f = {i = g
return (h i)}

f = do i <- g
h i

在指令式的理解下g的返回值给i,然后返回h i
函数式的理解是这是一种函数+函数 = 函数的方法,上面函数式等价:f = g>>= \i -> h i。这式子是说函数f是由函数g与函数\i->h i组合得出。可以看出差别在于,函数式表达的是f等价于各个“指令”的有机组合,而指令则是由最后一个指令来决定返回,要说得明白点就是,改变g,函数式的话,会使整个函数改变,而指令不会。

函数认为“指令= 指令+指令”递归下去有“指令=指令+(指令+(指令+。。。))”,也就是说决定指令的是+号。这跟我们自然语言的使用是一致的,一个句子的逻辑是词语的逻辑组合而成,而不是简单地把词语拼在一起。

今天看到一篇文章:Moving Away from State

文中提到,只在两种情况下需要状态:
1.模型对象或代表业务状态的领域对象
2.保留有GUI状态的viewmodels/controllers

我想如果采取REST+DDD架构,可能只需要一个聚合根实体这一个地方有状态即可。

远离了状态,你就相当于远离了goto语句或IF语句。
http://www.jdon.com/artichect/ifelse.htm
[该贴被banq于2013-08-06 07:52修改过]

一个弱弱的回复:

因为现实世界有状态,所以程序也需要有状态。例如,我去买车票,前边有人在排队,我跟在后面,那就是“排队”状态,买了之后就是“买到”状态,没有买到就是“没有买到”状态。

我不明白的是,状态和谁有仇呢?为什么一定要在设计和实现里摆脱状态这个东西呢?

而且,最简单的场景了,资源是共用共享的,大家都可以使用,但是使用时要排队,要等待,那就一定有状态这个概念的存在。

我看了ERLang等技术里,好像没有了概念这个东西,但是程序作为现实世界的一个映射,状态这个概念应该是存在的,而且会一直存在下去。

如果是担心影响了并发,带来了效率问题,那好,效率问题是后台的资源不足引起的,例如数据存取能力强了,每一个线程/进程自己连接数据库,那么就不需要连接池这个概念了;但是不管怎么来看,业务是不断增长的,用于支撑业务的资源,在一定的时间点上,都是有限的,这个什么时候都不能避免。


那么为了让编程模型简单而减少状态的使用呢?我觉得这个不成为问题。分析和编程能力弱,想办法去提高,什时候都一样,没有什么好说的。

2013-08-07 13:34 "@windshome
"的内容
那么为了让编程模型简单而减少状态的使用呢?我觉得这个不成为问题。分析和编程能力弱,想办法去提高,什时候都一样,没有什么好说的。 ...

speedVan应该是在思考超越应用层面的东西,这些思考有可能对现在的应用产生不了影响也动摇不了什么。

speedVan加油

前段时间脑袋发热,也想发明一种语言,思考到最后被某种阻力挡住了,但是又不能很清楚的表达这种阻力。
当结构化消灭了goto,那顺序,循环,分支这种模型也可以被消灭吗?

熟悉的for,while都是依赖状态的,分支应该不仅仅是if,switch这么简单,
[该贴被oojdon于2013-08-07 19:25修改过]

不知道各位大师们讨论的是哪个层次的高深问题了,崇拜ing.....

末学 感觉: 状态类似一个抽象概念,不是物质世界存在的东西,是一个思想认识上的概念。

如果从分层、分模块的角度上来讲,状态是一个各层、各模块之间交流的共同语言。

比如,经济决策层,根据统计部门得出的 是否通货膨胀、是否经济萎缩 等状态来 决策自己的经济政策该如何制定,它无需自己了解统计的细节和逻辑。

计算机中使用0,1 模拟 对象、模拟关系,归根到底,是在模拟现实世界,根据人类的认识思维去模拟世界。
[该贴被hbbbs于2013-08-08 08:48修改过]

数量本身就是一种状态,换句话说变量的值也是一种状态。
这个和if switch无关。

总不能所有的设计和编程中都不要变量了吧。

即便没有变量,常量是状态吗?所谓的常量,只是变量处于不能再变的一种状态而已。

绕回来说,你感知到了状态,是因为状态现实存在着。与其想办法消除状态,不能更清晰的把状态和状态的变化分析认识得更清楚。

所谓看山不是山,看海不是海。一个人从一个角度理解和看待世界总是有偏差的。这意味着,从某个角度,或者在特定时间和地点是对的。
一根铁棒被运入工厂,三个人分别从它旁边经过。甲说,这是根棒料。乙说,这是根连杆。丙说这是20元钱。
大家不难猜出他们三个分别是干什么的吧。甲是原料库管,乙是生产工人,丙是会计。
一个东西是什么显然是这个东西的状态。状态不是唯一和天生的,而是人这个主体判断出来的。因此,不能遇事先入为主。
并不是说不要状态,而是不要一开始就引入状态,状态需要在最后关头来确定。也就是最后那个输出函数来确定。

看到你们的回复后,我再说说我所想的:

在逻辑运算中,不存在状态概念。状态的存在,因变量而存在,因为可变,才有所谓的状态。

常量不是状态,常量的运用其实符合函数的不可变原则,属于指称范畴,指令式中谈到的常量,其实应如下理解:变量,是指称语,值或对象是指称对象。我们可以理解为在指定域内的专有用词。其实当我们声明一个名字=某东西的时候,其实就是说下文提到这名字就是这东西了,如果名字指定的东西不断改变,则会产生当挑出后文时,你不知道前文到底有没有改变该定义,在一个上下文中,所有的推断都无法单独确定。

只要没有变量,就没有状态。我们的固有思维是:一定有变量概念,所以我们才认为一定有状态。把变量去掉,一切用指称代替看看?

甲乙丙问题看似很对,但要回到编程问题上来。我们编程只允许同一概念,出现盲人摸象,或者一千个人一千个哈姆雷特,都只属于认知范畴。而在编程时,是必须一整套逻辑。

实际上状态是隐式的,当我们输入的是“状态”的时候,输出的就是“状态”,而不是在逻辑中存在状态概念。计算机不需要依赖状态,所有状态都是依赖IO的。

2013-08-12 08:16 "@SpeedVan
"的内容
实际上状态是隐式的,当我们输入的是“状态”的时候,输出的就是“状态”,而不是在逻辑中存在状态概念。计算机不需要依赖状态,所有状态都是依赖IO的 ...

能不能谈谈你对中国的古董工具--算盘的理解。从状态,计算,存储,指令的角度
[该贴被oojdon于2013-08-15 10:58修改过]

这是文化不同吧,
c出身unix,他们重视数据结构,算法是干粗活的。
haskell是重视算法的,是学院派的。

2013-08-15 10:56 "@oojdon
"的内容
能不能谈谈你对中国的古董工具--算盘的理解。从状态,计算,存储,指令的角度
[该贴被OOjdon于2013-08-15 10:58修改过] ...

还以为这贴结束了。

我这样觉得,你提出算盘,是因为其带有状态。

我这么说,算盘实际上,只是存储器,没错,“只是”而已。这样的说法是不是比较震撼?事实上,我们很多人都忽视了一个东西:人的脑袋。算盘的计算逻辑只存在人的脑袋,人通过计算后得到的算盘应有状态(在脑中的),映射到实物上。(计算逻辑就是各种口诀)

人用算盘计算,一直在计算的,其实是人,而不是算盘。

指令的角度,等等,我想想。

为什么要状态?这个问题我是这样思考的。

以聚合根为例,聚合根为什么需要状态?因为聚合根要封装不变性。那不变性如何实现?答案是,不变性本身就隐含着要基于当前状态为前提。举个例子,假设一个银行账号的余额不能小于零,这个是一个业务规则;那我们的BankAccount聚合根的取款方法Deposit方法内必须要知道当前的余额才能知道当前钱是否够扣!

所以,其实DDD中聚合设计的真正目的,看似为了聚合一些比较紧密的对象,本质上是为了捕获业务规则,要实现业务规则,本质上就需要依赖于这些业务规则所需要的状态,那状态如何表达?就是通过值对象了。

所以,可以看出,业务规则要实现,必须要依赖于对象当前的状态;

结论:业务规则的保证需要依赖于状态;业务逻辑的执行会导致状态转移;业务逻辑执行过程中要满足特定的业务规则;