程序是人类对世界的解构,在面向对象编程中,其核心就是「对象」(Object),围绕着对象建立起属性和方法。所谓属性是用于描述对象特征的,属性通常也是名词,同时属性通常也都有固定的可选值(有一定的校验规则),属性这个名词可能本身也是一个对象,这个时候的属性实际上也是描述一个对象与另外一个对象的关联关系;对象同时还有方法,方法是一个动作,通常是说谁可以对这个对象执行什么操作,操作的过程中需要哪些必要的参数,有时候也描述了它与另外一个对象之间的关系是如何建立的。

例如「文章」是一个对象,它并不是某一篇具体的文章,而是指「文章」这个人们约定俗成的概念。文章有标题,有内容,有摘要,这些就是属性,它属于文章的一部分。同样「文章」也有「作者」,而「作者」本身也是一个概念,它同样不是指某个具体的作者。那么文章和作者之间就产生了一种关系,我们可以通过很多种的方式来描述他们的关系,例如一篇文章的作者,意思就是看这篇文章的所有作者,可能是一个也可能是多个;我们也可以说一个作者的文章,那么就是去看这个作者写的做所有的文章。

属性

通过属性我们可以将对象进行分类,例如文章有一个属性可以是「发布状态」,可选值包括[未发布,已发布] 两个。那么我们将所有的文章都根据此分为两类:一类是未发布的文章,一类是已发布的文章。对象的每个属性都可以用来分类,属性越多,每个属性的可选值越多,对象的分类就越多。

对象的分类实际上通过这样的格式来描述具有某种属性的对象:{{属性值}} 的 {{对象}}。每一个「属性值」的「对象」我们可以理解为该对象的一个「子对象」。它继承了对象中共用的属性和方法,但同时也有着自己的特有属性和方法,所以它本身也还是一个「对象」,还可以继续包含更特殊的子对象。

分类的意义在于更清楚的描述这个对象。因为有些方法只有在特定的分类中才有意义。例如我们说文章有一个操作是「发布」,但是这个操作对于「已发布的文章」是没有意义的,所以「发布」这个操作实际上对象应该是「未发布的文章」。在比如文章和作者之间的关系,是透过「写」这个动作关联起来的,我们说某个作者写了某一篇文章,反过来则不行,文章不可能添加作者。而作者也只能写「未发布」的文章,不可能写出来已发布的文章。也就是说,方法实际上是对对象属性的更改,不同的方法更改的属性不同。

方法

方法是对对象的操作,每个对象都会有几个固定的方法,简称为 CRUD:

  • Create (C):创造
  • Read (R):获取
  • Update (U):改变
  • Delete (D):删除

虽然我们说这是某个对象的操作,但是对象毕竟是一个虚构的概念,它只存在于我们的脑海中。实际上这些操作是针对于「实例」的。「实例」就是具象化的对象。例如我们说「文章」是一个抽象的概念(对象),而你此时此刻正在看的这一篇文章《从程序的角度来理解世界》就是一个具象化之后的实例。所有的方法都是基于实例的,而非对象。

创造

创造,实际上是在基于该对象在创造实例。当我们去理解某个事物的时候,首先要去思考它从哪里来?

获取

获取,我们能够从哪里获取到这些对象?同一个对象,其子对象的获取方法可能不同。

改变

改变是一个非常含糊的操作,它里面包罗万象。改变实际上是概念「实例」当中的某个「属性值」。有些改变可能一次概念多个属性值,但大多数都是通过直接修改其中的一个属性值,而该属性值的变化可能会触发其他的方法,从而修改其他的属性值。例如改变一篇文章的发布状态,发布文章是将发布状态从「未发布」修改为「已发布」,而从「已发布」修改为「未发布」我们可以称之为「撤稿」或者「下架」,这两个操作都会将文章的状态修改,但是还有后续的操作可能不同。例如撤稿可能是因为作者自己不想发表了,而下架更多是表示平台直接撤掉了文章,可能是出于监管压力,也可能是舆论压力等等。

删除

能够被创建的实例通常也都是可以删除的,删除可以有几种不同的理解,例如对于个人来说,我们可以把赚钱当作是「创造钱」,可以把花钱理解为「删除钱」,当然你也可以把钱撕碎当作删除钱。产出的意思是原本的那个实例已经无法发挥做了,有可能是不存在了,有可能是转移了。

这四种方法其实是 REST 规范中经常提到,其实是非常高层级的抽象,现实中方法或许也都是基于这四个方法。另外,这四个方法在不同的场景,面对不同的人来说可能是不同的,也正如前面所说的,这里的不同场景下的对象,实际上就是有条件限定的对象,就是某种子对象。

对象

在用户体验设计中也存在这样一个过程叫做「信息架构设计」,信息架构所解决的问题是可寻性的问题,所谓「可寻性」意味着用户能否找到他所需要的信息,这当中包含几个方面:

  1. 用户是否知道他所寻找的事物的名字;
  2. 用户是否知道他所寻找的事物的分类方式;
  3. 用户如何描述他要寻找信息;

第一点意味着用户是否知道这个对象的名字,几乎这个世界上人类已知的和想象的事物都会存在一个名字或多个名字,一个名字是最容易解决的,但现实中偏偏同样的事物会存在很多个名字,最简单的例子就是不同的语言和文化中对事物的称呼不同,例如 Apple 和苹果,Jobs 和 乔布斯、贾伯斯等。对于系统来说名字没有对错,但是需要理解现实中的事物就是这样的存在的,因此在信息架构中的搜索系统中,这些名字都是用户描述事物的方式。

计算机程序是以现实中事物存在的方式,将其虚拟化变成信息在计算机这个虚拟化的世界中运行,当我越来越理解计算机时,也越来越多的理解这个世界,我们不断的解决计算机世界中存在的问题,实际上就是在复制现实中「进化」或者是「神」是如何解决这个世界中的问题的。例如开发者们最头疼的问题「命名」,现实中也是如此,每个地方的对同样的事物会有不同的叫法,例如卷心菜在 Wikipedia 中第一段的描述:

卷心菜(学名:Brassica oleracea var. capitata,香港称椰菜,台湾称高丽菜)为甘蓝的变种,植物学上称结球甘蓝;俗名又称洋白菜、圆白菜、球白菜、大头菜、莲花菜、疙瘩白,是一种常见蔬菜。山西、陕西等地区多称莲花白、花白或茴子白,广东部分地区亦称椰菜或包菜,云南地区称莲花白或包白菜。在闽南地区及台湾习称高丽菜(闽南语:ko-lê-tshài)或甘蓝菜,也有人称包心菜或玻璃菜。

我们都是通过自己的语言来描述这个世界,以及自己对概念之间的关系来构思这个世界,所以开发者在阅读别人的代码的时候通常就是要从原作者的角度去理解他所认知的世界,而这通常是很头疼的。所有的事物都有他对应的「概念」(名称),我们也总会通过很多方法来描述这个概念(属性),概念与概念之间总是有着千丝万缕的关系。我们在学习新的知识其实也是如此,理解各种名词(概念)、属性以及概念之间的关系,所谓学习就是不断的拓展自己对新概念的理解和对已有概念新属性和新关系的理解。在《如何阅读一本书》中,作者有提到在阅读过中的几个规则,其中包括:

规则五:诠释作者的关键字,与他达成共识。

规则五的意思实际上是理解书中所出现的名词(概念)。对读者来说,这些名词或许是新事物,或许是你已知的事物的新名字,亦或者是这个名词你很熟悉,但是作者的意思却是另外一个东西。因此这个规则实际上就是「翻译」书中出现的名字,将其翻译成自己的语言,也就是与自己认知中名字做关联。

规则六:找出书中的关键句,抓住作者的重要主旨。

规则六的意思实际上就是寻找概念与概念之间的关系,以及这种关系是如何构建起来的。关系通常都只是一个动词,有时候会包括各种各样的条件以及各种参数,这些其实都相对其次,关键是找到概念之间的东西。这些关键句我简单分类为:作者对名词的解释;描述名词的属性;名词之间的关系。

所以我阅读工具书的方式通常是利用 OneNote,因为其无限大的画板非常好用。先记录下书中出现每一个我认为比较重要的概念,然后在阅读的过程中逐渐将这些概念之间的关系连接起来。有时候你会发现作者自身的矛盾,他可能自己都没有很清晰的描述出概念之间的关系,或者是对概念的定义不清晰,那么此时你就可以指出作者的不足。

正如美国的设计师 Charles Eames 所说的「Eventually everything connects - people, ideas, objects. The quality of the connections is the key to quality per se.」