1.3 语言的抽象性
关于抽象思维,其定义如下:
抽象思维,又称词(概念)的思维,是指用词(概念)进行判断、推理并得出结论的过程。抽象思维以词(概念)为中介来反映现实。这是思维的最本质特征,也是人的思维和动物心理的根本区别。
之所以把抽象思维称为词思维或概念思维,是因为语言和抽象是一体的。我们只能通过语言表达抽象的概念,并进行逻辑判断和推理。
当我们说牛的时候,说的就是牛的抽象,它代表了所有牛共有的特征。我在演讲中分享抽象思维的时候,会经常给同学们下套。
我问:“你见过牛吗?”
同学说:“见过啊。”
我继续问:“你确定你真的见过?!”
同学说:“好像——见过——吧——”
我继续问:“在哪里见的?”
同学说:“在老家的山头上。”
我说:“你没有见过牛,你能看到的是那头在老家山头上正在吃草的老黄牛。而牛作为一个抽象概念,你既看不见也摸不着,它只存在于你的思维之中。”
当你在程序中创建牛(Cow)这个类(Class)的时候,道理也是一样的,它代表了对一类牛的抽象。而每一个实例(instance)代表了一头一头具象的牛,比如那头在山上吃草的老黄牛。
因为语言的抽象性,我在团队中会要求大家使用通用语言(Ubiquitous Language)进行沟通交流,因为只有大家对概念的认知达成一致,沟通交流起来才会顺畅,而程序只是我们程序员之间的一种交流方式。
这也是我在做设计和代码审查(Code Review)的时候,会特别关注命名是否合理的原因。因为命名的好坏在很大程度上反映了我们对一个概念的思考是否清晰、抽象是否合理,反映在代码上就是代码的可读性、可理解性是否良好,以及我们的设计是否到位。
有人做过一个调查,问程序员最头疼的事情是什么。Quora和Ubuntu Forum的调查结果显示,程序员最头疼的事情是命名。如果你曾经为了一个命名而绞尽脑汁,就不会对这个结果感到意外。
正如Stack Overflow的创始人Joel Spolsky所说:
“Creating good names is hard,but it should be hard,because a great name captures essential meaning in just one or two words.”(起一个好名字应该很难,因为,一个好名字需要把要义浓缩在一到两个词中。)
这个浓缩的过程就是抽象的过程。我不止一次发现,当我觉得一个地方的命名有些别扭的时候,往往就意味着要么这个地方我没有思考清楚,要么是我抽象错了。
关于如何命名,我在《代码精进之路:从码农到工匠》[1]一书里已给出了比较详尽的阐述,这里就不赘述了。
我想强调的是:语言是明晰概念的基础,也是抽象思维的基础,在构建一个系统时,值得我们花很多时间去斟酌和推敲语言。我曾经做过一个项目,在过程中针对一个关键实体讨论了两天,因为那是一个新概念,我们尝试了很多名字,却始终感觉别扭、不好理解。随着讨论和对问题域理解的深入,我们最终找到了一个相对比较合适的名字,才算罢休。
这样的斟酌是有意义的,因为明晰关键概念是我们设计中的重要工作。虽然不合理的命名和不合理的抽象也能实现业务功能,但代价就是维护系统时的极高的认知负荷。随着时间的推移,也许就没人能搞懂系统为何这样设计了。