《DDD with TLA+》(2) 系统行为
DDD 是对 naïve Agile 的补偿
迭代开发,到后期就顶不住了。因为没有系统蓝图,我也不知道系统要干啥,一步一步叠加。
我们的系统行为并不是独立的,而是有关联的。如果一开始的时候没有把这些关联识别出来,搞清楚的话,到迭代后期就非常困难了。所以说并不是一开始什么都不管只管编程就好了。后期更改的成本是很高的。
例子
domain
这是什么领域?什么问题?
在几何领域里面,有很多可以提炼的,比如角度,长度。但是这个问题和角度和长度没有关系,所以我们要考虑和领域里面哪些概念有关系。
和两个点是否关联,是否共线等概念有关系。
解(TLA+)
识别领域概念-》定义语义
这个例子是一个静态系统,但我们的系统一般都是行为系统。
领域特点
一般企业应用
有现实业务活动做参考
业务行为少,种类多,繁杂不规范,容易有歧义
可靠性要求中
游戏
无现实对照物,自创规则
行为可简单,可丰富,规则确定
可靠性要求中
电信系统
无现实对照物,开放协议规范
行为极其丰富,规则明确
可靠性要求高
云基础/设施(操作系统、数据库、集群管理调度等)
无现实对照物,自定义规则
行为极其丰富,规则明确
可靠性要求高
模型表达与检查
行为简单类模型
文本、图示、类、对象、ADT、DSL、代码等
人肉检查、测试
行为丰富类模型
规范精确的表达
虽然有可能需求会变,但是实现的时候一定是确定的。所以对于行为一定是要精确的表达。
模型显示化
自动化、穷尽式检查
《Domain Modeling Made Functional》
这本书很薄,但是讲的最清楚。
其他领域
其他领域的科学家、工程师是如何建模的?
桥梁设计,硬件,航空航天。。。
动态连续系统建模
大部分系统都是动态连续系统。
提取问题相关变量,用微分方程描述变量随时间变化关系
提出并验证变化满足要求的约束属性
然后基于模型进行低层设计、构建实际系统
地球围绕太阳转是个系统,微分方程是个模型。
源代码就是设计
美国的一个航天专家经过调查,发现满足模型定义的只有源代码。
高层设计的缺陷
不完整、不精确、不规范
无法验证
代码完整、精确、规范?
但是太多实现细节、掩盖系统真正要表达的行为和约束
不利于领域核心知识的学习、传播
不利于软件的演化更改
代码能测试?
但是代码运行只能展现出部分行为,没有展现的行为可能隐藏 bug
代码修改起来容易?
但是如果考虑了正确性,代码改起来一点也不容易
不理解行为、约束,也就没法预测更改后的行为
语录
It is easier to write an incorrect program than understand a correct one.
Alan J. Perlis, Epigrams, 1970s
Testing can show the presence of errors, but not their absence.
E. Dijkstra
系统行为
我只有知道我想要什么,才能设计的好。当然这也是个迭代的过程。
如果不是子集,那就是 BUG。
期望的系统行为
是个集合:
{期望的系统行为}
这两种表达有什么区别?
第一个是具体的元素是啥
一个是刻画元素的属性。
我们编程的时候,经常是考虑第一种。我们期望是在第二种的层次上思考。
什么是系统行为?
什么叫系统达成目标?就是领域里某些状态变化满足你的预期了。后面系统是个什么程序,还是个人都不用关心。
状态序列
行为是系统的一条可能执行路径,行为是一个状态序列,状态是对变量的赋值
行为是个序列,但是我对行为有要求。
例子
行为是个序列,但是我对行为有要求。
绿框里是系统需要满足的属性。实际的行为我并不关心如何产生的,只要满足我定义的关系即可。
我表达属性约束,而不是产生序列。
行为理解练习
“倒计时”界面,模拟火箭发射。
10,9,8,7...0 launch
先尝试描述一下行为。如果能把行为描述清楚的话,程序一编就编对。否则会来来回回修改。
先不要考虑这些行为是一类的,不要过早抽象。我们需要把系统的行为都先展现出来。
一共有 11 种行为。
这个才是最关键的,软件编程序无非也就是产生这些。
如何表达?
Start, Count,Launch,Abort 是系统允许的行为。
等号表示等式。相当于一个条件。
我们可以比对一下,拿任何一个行为去套都是满足的。
动态离散系统建模
大部分软件系统都是动态离散系统。系统的正确性和变化发生的时间是没有关系的。
提取问题相关变量,用 TLA+描述变量每一步的变化关系
提出并验证变化满足要求的约束属性
然后基于模型进行低层设计、构建实际系统
评论