领域驱动设计
把值对象
视为不变
的.使无副作用
函数,不依赖可变状态
.
域事件一般不变
,不应修改
域代码操作
的数据,相反,总是返回新数据
.
大量使用UFCS
域链来限制使用内存
.
最好静态保证!
想用不变
,传统上:
但,基于模板:构建慢,内存使用率高
.脆弱
,对编译器更改敏感
,不可传递:需要array_
的潜在副本
想要:
但不能用不变
!
● 想使用不变
数据类型.
● 想使用区间
.
● 还使用了很多关联数组
.
● 但是不变
数据类型打破了许多区间
,并且不适合关联数组
!
错误,不能修改...
.不能用不变
.
为何?如下,很明显应工作:
不能用Unqual
!
Unqual
,只是去掉最外层
的限定符
.字段,仍然是不变
的.
如果覆盖不变,会怎样?
问题,是不能修改不变
字段.观察
不变引用
,改变了不变
的值
.用头可变
来放松
常系统?
因为是联
,所以不调用析构器
.
因为是结构体
,所以,即使T有不变
商店,也可用std.algorithm.mutation.moveEmplace()
.
可以控制生命期.故意的.
缺点是,未来可能会改变
.
如何写头可变
精确扫描
的GC
问题:始终按指针对待void[n]
.
想要DeepUnqual
.用DeepUnqual
来帮助.
rebindable.DeepUnqual
,为每个D数据类型
定义等效类型.可变
指针在一堆.不变
指针在另一堆
.其他,都不一样.
DeepUnqual!T
精确GC
,扫描扫描T的字段
.相同大小,相同对齐(中性
),同它工作,是深度不安全
!你要转换
一切.
置(T)==>重绑定(T)(神秘)==>T 取()
.
如何保存
T,如何取T
?
但,安全
吗?
是秘密
吗?安全
吗?
● 只要T是秘密
的,它就是安全
的.
● D不变
混合了内存不变性
和可观察性
.
● 只要未观察
到变化.就不在乎
值是否变化.
● Rebindable!T
是包装T
.
● 不能按T形式
取包含数据
的引用
,因为get
按值返回.
● 由于DeepUnqual
,存储的数据
是可变
的,因此可以改变Rebindable!T
.从不改变未声明
为可变
的内存
.
● 并且内存
自身未按不变
公开,而是返回不变
的值副本
.
虽然数据
存储在Rebindable
中,但它是可变化
的,但每次变化
都必须是从有效
状态到有效
状态,无法在变化过程
中抓到它
.
● 弱点:T
不能依赖由构造函数
或者复制构造
函数创建的每个地址
.
● 如果复制构造函数
到处搞乱字段地址
,就会中断
.
还有:Nullable, rebindable.Nullable
工具.
不变安全
的关联数组,rebindable.AssocArray
建议:可引用性
是万恶之源
.
● immutable
是不是太强大
了?应该可覆盖不变
字段吗?
● 否:不变
太弱了!
● 问题是可观察
到不变字段的变化
.
● 默认,可&i
并取得i
的永久视图:&i
是immutable(int)*
,但可能改变值!
● 什么比不变
更强大?右值
!
右值
:只能出现在右边
的,就叫右值
.
假设右值结构{}
可比不变
结构更强大,但仍可通过分配新值
来覆盖!
右值构
是纯数据结构:不取字段地址
,不引用
字段,不直接分配
字段.
为什么?这样,就不必害怕突变
,因为没有人能抓住
我们.
● 如果只赋值新构建
的T值
,则不会破坏不变性
.
● 纯右值
比不变
更强:它是不可引用
的,因此是不可观察
的.
● 事实上,它没有内存
:它仅是数据
,不保存在内存
中.
● 可读取它的值
,但不能远程观察
它的字段,因为它是旧数据
.
实际可行
建议:彻底删除
不变结构字段
.
为什么Unqual!T
不起作用?为什么Unqual!T
不应工作?
标准库
假定Unqual!T
造头可变
.
结构内部
可隐藏不变
字段,创建独立
的不变补丁
.
Unqual
已为构外
类型创建头可变
值.
字段
实际上总是头可变
的,immutable(T)
仅为T var
设置默认值.
实际上,不变
使每个字段为Unqual!(immutable T)
.
直接
访问可变(T.field)
字段,先隐式转为不变
,如果不能,则是错误.
这保留了常
,保留了不变
,不需要
访问器.
但允许在数据结构中,通过Unqual!T
使用任何T
.效果:Unqual!T==HeadMutable!T
,总是.但未完全解决类的头可变
问题.(immutable(Object)
不会隐式
转换到Object
.).但是在域代码
中,不会使用类.:-)
无论如何,存在std.typecons.Rebindable
.
代码位置