面向数据开发
数据驱动编程的核心:数据驱动编程的核心出发点是相对于程序逻辑,人类更擅长于处理数据。数据比程序逻辑更容易驾驭,所以我们应该尽可能的将设计的复杂度从程序代码转移至数据。
数据驱动是一种思想,数据驱动型编程是一种编程范式。基于数据驱动的编程,基于事件的编程,以及近几年业界关注的响应式编程, 本质其实都是观察者模型。数据驱动定义了data和acton之间的关系,传统的思维方式是从action开始, 一个action到新的action,不同的action里面可能会触发data的修改。数据驱动则是反其道而行之,以data的变化为起点,data的变化触发新的action,action改变data之后再触发另一个action。如果data触发action的逻辑够健壮, 编程的时候就只需要更多的去关注data的变化。思考问题的起点不同,效率和产出也不同。 把知识叠入数据以求逻辑质朴而健壮
开发后台的同学应该更加有体会,对数据更加亲切,大多的时间都是在处理数据,能从Mysql里很好的读出来,就完成一半功能了,处理之后再写会数据库或者通知用户、展示等。
其实开发游戏也是一样,需要处理的数据就是,玩家、装备、各种数值。ECS框架的出发点也是一样的。有人说ECS的编程方法,有点反人类。其实真好相反,只不过大家是习惯了从逻辑出发,因为我们最开始使用的开发语言是就是面向逻辑的,面向过程的。
视图
类似Mysql视图的概念
视图是对若干张基本表的引用,一张虚表,查询语句执行的结果,不存储具体的数据(基本表数据发生了改变,视图也会跟着改变);可以跟基本表一样,进行增删改查操作(ps:增删改操作有条件限制);
从面向中数据开发的角度出发,视图就是数据源的进行不同层次的映射、汇总、抽象,每一层次为不同业务进行服务,方便逻辑处理,提升开发效率。对视图、数据的设计很重要,它是上层设计的基石。基础打不好,后面早晚会出现问题。也可以把其理解为观察者模式。
ZProperty框架引入Select/Where/Merge/Count/Sum等方法,对源数据进行处理,生成不同的视图。它与Linq很想,用过的一定会很喜欢Linq的强大,其实作用是一样的,其核心还是面向数据的。不过Linq生成的还不能叫视图,因为如果源变化时,视图不会进行更新,这是因为Linq是基础框架,面向的List这些基础类,但在ZProperty的基础上,我们就能做的真正的视图,视图会根据源进行动态变更。其实原理很简单就是注册相应的事件。
Select:对数据源进行变换,数据量是一致的,数据内容进行变换
Where: 对数据源进行有条件的映射,数据量会变为满足条件的数据量,数据内容不变。
Merge:对多个数据源进行合并。数据量是总和,数据内容保持不变。
Count: 数据源的数量,映射到一个变量中。
Sum:数据源的各项和,可以根据条件对项目进行选择,同时也支持对求和的方式进行配置。
public void Where(IZPropertyRefList<T> source, Func<ZPropertyInterfaceRef<T>, bool> selector)
public void Select<ZT>(IZPropertyRefList<ZT> source, Func<ZPropertyInterfaceRef<ZT>, T> selector)
public IDisposable Count<ZT>(IZPropertyList<ZT> list)
以上还有很多方便好用的重载哟
注意内容:
与Mysql一样,Zproperty的视图也是不支持增加、删除的。当然数据内容因为C#是引用,所以可以进行同步的。但对Count、Sum这样的视图的修改是没有意义的。
目前只有ZPropertyRefList,才能支持Select等视图方法,因为要根据RefID为基础进行一个关联。
Zproperty还不支持,Linq那样实现多级的连续调用。
注意注意,以上最后一个返回的IDisposable接口,这个很重要,作用大家猜猜
后面还有对UniRX的支持,未完待续。。。
关联
视图之后,引入另一个概念“关联”,也就是把两个Property(数据)进行关联。
视图也是一种特殊的关联。
其实各数据、普通的Property组成的只是一个树形/森林的结构,
正常的Property框架,一个对象可以向下访问其结构中的Property。
而我们希望的Property组合成了一个大的 Mesh,需要具有横向、向上或者任意的联结,以保证逻辑需要。
比如一子弹打中物体后,需要知道其发射者的信息,完成记录功能。
注意与视图的区别:
Select只是观察者,是单向的,而Link有双向的同步功能。
Link同步可支持进行设置,同时内部也是实现的是Select
注意问题:
目前Link的时机还是比较早的。会被接口隔断。除非是接收其对应的OnvalueChange
其它关联
追加Cursor的支持,用于Loop遍历List。