01 理解面向对象

和机器语言一样,面向过程的语言依然还是图灵模型解决问题的思路:有限的有序指令序列。只不过这里的指令从机器语言、汇编代码换成了容易理解的表达式而已,面向过程的编程语言和机器代码在认知上没有本质区别。

组织面向过程的程序,这部分工作的心智负担需要高水平的程序员来承受,将现实中的业务分解成有限的有序指令序列。分解任务成为指令序列的过程就是编程,它要求程序员既要像人一样思考现实又要像机器一样思考。只有最聪明的人才能像机器一样思考,好的程序员可不好找。

能不能想办法利用推理机,再进一步,让程序员按照人类一样思考事物,写出符合人类语义的代码,然后再翻译成目标代码呢?回答这个问题就需要先回答另外一个问题,符合人类认知的思考方式的语言是怎么回事。

人类需要通过概念来进行交流,给一撮物质一个标签,这个标签就是概念。将一堆标签组合起来再打上标签,就是抽象概念。不同的语言、不同文化背景的人无法交流就是因为使用了不同的标签系统,甚至也有可能贴错了标签的情况,导致认知无法对齐。

理解面向对象需要到生活中去,观察玩泥巴的小孩。他们用泥巴创造出一个城堡前,泥土就好像计算机世界中的数据,将泥土组织成有清晰边界的物品就是对象。我们为了描述这类对象,就需要给它起个名字才能交流。类可以对应现实中的一个概念,很多面向对象的书籍并没有点破这一点。

可以把现实和面向对象中的元素对比一下,建立一个理解面向对象的模型。

所以面向对象编程是建立在非常好的心智模型上的,只不过这个模型对于不熟悉西方哲学的人来说过于抽象。对象、实体、类、行为,这些面向对象中的内容和概念早已经被哲学家讨论过数千年,但是在中文的语境中并不新鲜。

02 面向对象的哲学意义

人是通过语言思考的,我们不遗余力的使用自然语言描述事物,面向对象是计算机语言和自然语言的一座桥梁,这座桥梁由哲学链接。对象这个词在不同的领域都被用到,这并不是巧合:

  • 哲学中的对象
  • 数学(范畴学)中的对象
  • 语言中的宾语

维特根斯坦的《逻辑哲学论》中对对象、类的阐述和面向对象极为相似,不过这本书非常晦涩。通俗来说:

对象是人认识世界的基本单位,对象由实体和正在发生的事构成。

也就是说对象不是一成不变的,可以由"造物主"自由的设计和组合。当我们在开发一款 XXX 管理系统时,被管理的"物品"被模拟为一个静态的物品,就能看做一个对象。假设我们正在开发仓储管理系统,极端的面向对象者会告诉你将行为放到"货物"这类实体中,这样看起来更加像面向对象的风格,但是他们背离了面向对象的初衷。

虚拟的世界里,静态的对象需要由动态的对象处理,这构成了一组主客体关系。而对于"上帝"来说,它们都是对象。熟悉 Java 的程序员可以这样理解,Spring 中的 Bean 是一种对象,在应用启动时就被初始化了,就像上帝造出亚当开始干活儿。而从数据库中提取出来的实体,就像是从仓库中提取出来的"物品"。

如果开发一款游戏,对象貌似都是有生命的。但是对于普通的管理系统来说,真正需要设计的是"货物管理者","收银员"这类对象,而"货物"这类实体就应该让它们安安静静的躺在那里。

使用面向对象越久,越会下意识的使用面向对象思考现实,面向对象是程序员进入哲学世界的启蒙课。

03 理解面向对象中的困难概念

有了上面的一些思维,就很容易理解面向对象的困难概念。

接口

接口是一个契约,例如瓶盖和瓶身之间的关系,换句话说就是一个标准,这个标准要求接入的对象有哪些功能(方法)。

所以定义接口的一方就能实现让实现的一方来兼容自己,这样就能做到组件可替换了。

所以在没有必要可替换的地方,可以不用定义接口。

抽象类

类是一个概念,抽象类就是一个抽象概念。

概念包含了属性,所以抽象概念定义的就是继承过来的属性。

这就是抽象类和接口本质不同。

接口是契约,含义是"能做什么";抽象类是抽象概念,含义是我有什么。

工厂

工厂就是一个比喻,就是把类变成对象的时候做了一个包装。

同样的比喻其实还有 Repository、Service、Controller,所以在 Spring 中,这类对象都被叫做 Stereotype,只是一种版型。

继承和组合

继承是从子类系统上区分不同事物;组合是通过对象属性上灵活组合区分不同的事物。

其实这两种处理方式并没有优劣,只是设计上的不同。

比如做一个宠物游戏,宠物种类就应该用继承,但是宠物用的物品就应该用组合。

柴犬继承于犬类,在是在狗窝中需要组合柴犬和狗粮。

这取决于我们怎么认识世界和设计世界。

DDD

DDD 的意思是领域驱动设计。领域就是业务对象,也就是业务概念驱动设计。

充分利用 OOP,对现实业务建模,给一堆数据取好名字,定义好关系、属性,这就是领域驱动设计。

其实 DDD 就这么简单,只不过在实践上大家搞出来很多概念。

04 总结

用英语去理解计算机概念其实非常容易,因为计算机概念都是来自现实的比喻,只是翻译的时候翻译的不好。

像什么 handler 翻译成句柄,其实更应该翻译成抓手(笑)。

比如方法,英文是 function,这就是功能的意思。

Object 中文是对象,其实这个词也是目标、客体,意思是被操作的东西。

编程其实是扮演上帝,而我们哲学上通过主体-动作-客体来描述构建世界的过程。

比如 OrderServcie 和 Order 这两个对象。

在系统启动的过程中,这两个都是客体,虚拟机是主体初始化这两个对象。

在处理业务的过程中,OrderServcie 操作 Order,于是 OrderServcie 就是主体,而 Order 就是客体,虽然这两个对于虚拟机这个上帝来说都是客体。

我把对认识世界和计算机软件画了一个图,有兴趣可以参考:

(这张图来自我的小报童专栏《人生十问:自我认知的困难问题》)

Last Updated:
Contributors: shaogefenhao