信息结构

在规则中提到了规则的三个部分:抓取,公式,存放。信息结构的作用就是为抓取提供一个数据规范,是对系统中的数据进行组织管理等功能的依据,明确了系统的信息结构才能更好的理解系统数据的存取方式。

1. 如何保障沟通精准

我们知道,信息系统就是处理信息的——而沟通是信息处理的一个主要场景。同时我们也知道,沟通经常会引发歧义,从而导致误会,那么,如何确保沟通的精准,无二义性呢?在回答这个问题之前,让我们先看一个引发哲学讨论的,沟通失误的实例:亚里士多德买面包的故事(中国也有类似的故事,叫白马非马,可以自行搜索)。

有一天,柏拉图写作到深夜,忽然肚子咕咕直叫——原来他还没有吃晚饭. 这时,亚里士多德来了:“老师,您还没吃饭吧?我去给您准备一下.” 柏拉图拿出一枚硬币递给亚里士多德说:“你去给我买个面包就行了.” 亚里士多德连忙跑了出去.不一会儿就回来了,可是他两手空空:“老师,外面有甜面包,有酸面包,没有光是面包的面包.” 柏拉图说:“就买酸面包.” 亚里士多德跑了出去,不一会儿又回来了,还是两手空空:“老师,外面有方的酸面包,有圆的酸面包,就是没有光是酸面包的面包.” 柏拉图笑着说:“那就买方的酸面包.” 亚里士多德又跑了出去,不一会儿又回来了,仍然是两手空空:“老师,外面有方的大的酸面包,有方的小的酸面包,没有光是方的酸面包.” 柏拉图说:“那就买方的大的酸面包!” 亚里士多德又连忙跑了出去,不一会儿又回来了,还是两手空空:“老师,外面有……” 柏拉图从亚里士多德手里一把夺过硬币,蹬蹬蹬地自己出去了.不一会儿就买回了面包,大口大口地吃了起来.

这个问题,实际上直到20世纪,才由美国的哲学家,语言学家,诺姆·乔姆斯基通过四类语言划分,形式化解答完毕。问题本质是由语境(context)引发的,任何名词都代表一类物品,可以有无限多的属性,语境决定了哪些属性是被关注的,哪些是不需要的。例如上面的故事中,柏拉图关注的是可以吃这个属性,因此,木头雕的面包是不行的,小麦做的还是稻米做的不重要,当然亚里士多德所说的口味、形状、颜色等属性更不被关注了。如果我们可以在沟通中消除语境,那么上述问题就会消失,如何消除语境呢?消除的工具您一定已经使用过了,那就是表格。采用表格做为通信时索引信息的唯一手段,也被称为语境无关语言(context-free language),是目前计算机可以处理的最高形式语言,也是C / C++ / Java / Javascript / Perl / Python等各种计算机语言(都属于语境无关语言)与自然语言的最主要区别。(语境无关也被翻译为上下文无关,信息结构也被称为数据结构)。

应用场合(由业务逻辑确定)决定了信息可以含有哪些属性,表格里的列(名词属性),如果在页面中不体现(CRUD),说明其在这个语境下是无用的,冗余的,可以安全去掉的部分——详情参考产品的完整性检查。这里实际应用场合决定的名词及其被关注属性的定义,就是软件中的名词定义及组织方式,称为信息结构。实际上,我们会意识到,信息结构就是我们日常生活中的名词,不过更形式化一些,需要由应用场合决定其拥有哪些属性。对应的,规则其实就是日常生活中的动词,不过被名词化(也就是依然采用表格的形式以名词方式描述动词)。所以我们精确指挥计算机行动,所需要的就是对表格的CRUD操作。下文关系一节里会继续讨论动词名词化的话题。

2. 现实世界的表格

现实中,为了解决自然语言描述不精准的问题,人类很早就学会了使用表格来精确定义特定应用场合下的名词,以让沟通在特定应用场合更加无缝。先让我们看一个现实的例子,我们都接触过的课程表:

我们注意到,上文的表头定义了一个新的名词: “课程”。然后,有了八个代词,第一节~第八节。“课程”这个名词指示了在我们的应用场合下,每个“课程”应该包含哪些属性,很明显,我们这里的“名词”包含了周一~周五的科目及教师这么十个属性。然后,有固定的八个代词具体描述了我们具体的“课程”对象,分别是第一节课程~第八节课程。这里第一节~第八节在WWARE中也称为_id。换言之,_id为XXX的课程就是一个代词了,指代了一个具体的课程对象。

如果我们一周只休一天,这个新应用场合下,“课程”的定义就会变化,反映到表格上,表头会变化。因此,信息结构图是由业务方根据具体的应用场合定义的,我们应该做的是去理解之,而不是试图重新定义之。

如果我们一天上6节课,那么代词数量会发生变化,也就是WWARE中_id的范围会变化。当然,现实的应用中,我们遭遇的大多是_id十分庞大的情况,例如学生信息表,拥有成千上万的学生——其实成千上万对WWARE不算啥,WWARE可以处理的数据上限,即便单集群也是百亿规模级的,而多数据中心可处理的规模更是无穷大的。

3. 名词之间的关系

我们已经知道,名词之间是有各种关系的,假如我们按照上面的方法定义了多个名词,并且这些名词之间有关系,我们应该如何描述这些关系呢? 您一定会想,不同的关系要用不同的方式描述啊,其实不然,英国的埃德加·弗兰克·科德发现并证明了关系模式(类似名词)是静态的、稳定的,而关系(类似代词)是动态的、随时间不断变化的。这句话揭示了一个动词名词化的方法,关系模式的处理方式与名词相同,而关系的处理方式与代词相同。换言之,描述动词,可以使用像名词一样的表格,其属性都是索引其它名词的id,用于描述涉及名词之间的某个关系(动词)。我们描述名词之间的关系,通过给定一张表格,然后表格中的列都指向了其它名词。由于我们使用了名词化的方式处理动词,我们可以认为,计算机语言全部是由“名词”构成的,我们使用计算机语言来描述事情,就是将其翻译为针对“名词”CRUD的一个过程。

动词绝大多数时候是可以归约到名词表中的,人们已经总结出了6个基本范式来将动词归约到名词表中。一开始,您可以不去归约,而是直接使用动词表,但是请记住,现实应用中,动词表都是被归约到名词表中的。通常我们的归约方式:

1、1-1映射,直接按照方向归约到名词表上(两个方向两种处理)。

2、1-n映射,直接按照方向对于到n表上(两个方向两种处理)。

3、n-m映射,在n表上添加m对应的列,而在m表上添加n对应的列(两个方向两种处理)。

如果系统中全部使用动词表,只需要支持1-1映射即可完成设计。

举个例子,在上文的课程表基础上,我们再定义一个名词,“老师”表以及一个动词“授课表”,然后,根据上文,我们很自然的可以发现,“授课表”可以被省略掉,我们只需要说明,“老师”表中的姓名属性与“课程”表中的教师属性相等,就说明了“老师”与“课程”这两个名词之间的关系。这个关系有什么用呢?很自然的,拿到一个代词,例如如第一节课程,通过这个关系定义,我们就可以在“老师”表中检索,从而得到与这个课程对象(代词)相关的老师对象(代词)。使用这种方法,我们就可以形式化回答任意的涉及多个名词关系的问题了。

进一步思考下,其实动词可以名词化处理,也说明这样一个事实:动词可以看作将名词的某些属性值变化为新值的一个过程——请牢记这句话,你需要形成以状态变迁描述世界的习惯(动词可以看作改变动作结果状态的自然语言描述,基于这点,我们可以以名词/代词及其变化来描述整个世界)。例如,我们说,小王打了小明,可以说小王让小明的肉体痛觉上升了。这样描述虽然罗嗦,但是更精确,适合于无二义传递信息,配合上文由应用场合决定的“名词定义”方法,我们只需要拥有对名词及属性的CRUD(创建,读取,更新,删除)能力,就可以完整的模拟自然语言了——而且是精确模拟。其实我们绕了这么一大圈,就是为了寻找到一种比自然语言更精确的描述体系,以让计算机可以清晰明白我们的意图而不会有偏差。再举个例子,小王爱小明,这里爱是动词,该如何用状态变化法描述呢?小王希望小明心情上升?或者小王希望小明能帮助自己心情上升?这就有歧义了,如果选择基于名词的CRUD方式描述,这个歧义就会消除。

请记住,名词之间的关系也是由应用场合决定的,换言之,也是由业务方确定的,程序员只需要去了解就可以了。WIDE通过在信息结构图的属性定义上,指明本属性关联到其它哪个表上,从而描述了表格之间的关系——这种描述方式,如果使用动词表,即可描述全部关系,请自行根据实践需要,是否启用WIDE中的这一特性。

最后,我们来思考下我们常用的两个关系,派生与聚合。派生的例子,人是一个生物,做成两个表格,人的表格拥有生物表格的全部属性,并且会多几个属性。换一种方式,人的表格可以有一个生物属性,保存了一个_id,这个_id就指明了这个人的生物属性。这种存储方式其实是将派生当作聚合处理了。而聚合的例子,汽车包含四个轮子,表现在表格上,汽车会有四个属性,左、右前轮,左、右后轮,保存了四个_id指明其在轮子中的对应物体,同时轮子又是一个表格,其中会有四个代词(_id)指明的四个具体轮子,会属于同一辆车。派生与聚合是常用的手段,并且WIDE中对其有特殊支持,这些随着具体会逐步清晰,现在的目标是理解:如何描述名词之间的关系。

最后,我们来总结下,自然语言和计算机语言的对应关系:

  • 名词==》名词表头、代词==》行、形容词=》列
  • 动词==》动词表头、                      副词=》列
4. 信息结构图是什么

上文已经描述了,一个信息结构就是在特定应用场合下,定义一个语言,其中名词部分定义一张表,指明了这个名词包含了哪些属性需要被关注;动词部分也是定义一张表,通过指明哪个属性与其它名词有关来形式化精准定义动词。信息结构图就是把某个应用所涉及的自然语言全部重新定义一次,并提供了快速切换到现实二维表的形式来思考。这些内容在后文的信息结构图操作一章里会有详细的操作描述。

为了体会概念层ER,我们推荐您使用TerraER来描述概念层实体关系。我们为您打包并放在了WWARE服务器上。可以下载Linux版或者Windows版。

5. 以信息结构的视角看规则

我们切换一个主体,站在信息结构的角度来看规则, Roy Fielding博士在2000年提出的Restful架构,使用WWARE的语言来解释,就是描述了这样一个现实:在信息结构图的基础上,计算机语言的描述方式,就是针对信息实例的CRUD(创建、读取/搜索、更新、删除)。

因此,到这里,我们需要意识到,程序员的目标,可以用另外的概念来描述了,在了解信息结构图定义的语言基础上,把用户的自然语言描述过程,翻译为针对一對表格的CRUD操作。这才是我们程序员真正思考问题的方式,规则只是理解到这里的必经之路,虽然也可以处理问题,但是复杂度会高。您可以尝试把任意自然语言描述的规则翻译下,看是否可以翻译为针对一组表格的CRUD操作。实际上,我们提供的基础规则的背后,也隐含定义了一些“专有名词”,不过通常这些名词与自然语言保持一致,很多时候无需刻意解释即可理解。

从这个角度来思考,我们会发现事情一下简单了很多。总结下,实际工作中,我们这样执行:

1)先听取一次自然语言描述的“私人教师”操作说明。

2)然后寻找中间的“名词”,对应到信息结构图上的名词定义(表格定义)。

3)然后查看句子中,与这个名词对应的动词,将动词设置为表格。

4)按照6个基本范式,将动词表归约,以简化后续操作。

4)最后,将这些CRUD操作使用已知规则(基础规则或其他module提供的规则,或同项目其他同事完成的规则)来描述。

实际上,现实中绝大多数的“私人教师”十分简单,通过查阅目标流程图以及诉求树,结合信息结构图就可以自行得出,只不过我们还是建议一开始,机械按照上面步骤执行,并细节体会涉及的概念。这对于简单应用没有帮助,但是参与复杂的智能型应用(例如下败世界围棋冠军的AlphaGo),清晰的概念就十分重要——因为这些应用的一个特点就是,规则本身不是预设的,而是按照另外一些规则学习总结出来的。

前面在讲到规则的时候,其实也涉及了信息结构。每个规则实际上都蕴含了一组信息结构,抓取的“名词”是一个信息结构,存放的“名词”也是一个信息结构。所以每个代码段在抓取的时候,就要注意“名词”的格式了,免不了也会进行信息结构的格式转换。我们使用自定义规则(标准Javascript语法)进行格式转化,这些语法十分简单自然:名词1.属性1=名词2.属性2。无需刻意去了解,工作中遇到之后很快就会理解。

6. 工作思路:以产品定义的专有名词为核心,规则是作针对名词属性的CRUD

经过上面的描述,我们会理解到,虽然“私人教师”的本质是规则,但是程序员并不是按照规则去思考的,而是以信息结构图(产品定义的专有名词)为中心思考的。例如,检查用户是否已经登陆,我们的思维应该是,读取用户信息(_id/用户名指代的一个具体“用户”),并检查登陆状态属性的值。实际上,由于用户这个名词会经常用到,登陆这个动词已经非常清楚,因此,我们不需要理会中间细节区别,而是直觉告诉我们,可以直接拖拽一个登陆检查规则放上去。只不过,在这个动作的背后,我们应该牢记:程序员是以信息结构(名词)为中心思考的,规则(动词)是针对名词属性的CRUD(创建,读取/搜索,更新,删除)

因此,为了培养自己的程序员素养,您应该养成一个习惯,日常生活中的对话,脑海中有意将其映射为一些名词属性的变化,包括借助名词之间关系来回答现实的问题——现实的问题也可以转化为对名词属性的状态询问。养成以名词为中心的思维习惯,有助于精确描述事情,最终帮助你快捷的与计算机沟通

7. 模块(module)提供了常用名词支持

module本质上就是维护了一组信息结构,这组信息结构通常是非常稳定的,而且复用度极高,所以通常优先考虑使用module来处理信息。例如用户,交易,日志,商品,邮件,视频,短信等名词都有Module支持。并且随着进展,WWARE会支持越来越多的Module来支持不同场合下的名词定义。

8. 如果信息结构变化,如何复用模块中类似的信息结构?

module中的信息结构不会随意变动,实际需求中通常都是在module的信息结构上扩展额外的信息,手段就是派生,即增加一个新的二维表,通过属性关联的方式,与module中的信息结构建立关联关系,然后利用标准第三方API调用的方式,首先获取module的信息,然后再在新的二维表中增加额外信息。