Bob 大叔前天更新了博客 Classes vs. Data Structures , 对 面向对象中的 Object 与面向过程中的 Data Structure 作了一番比较,很有意思。
在文章中,Bob 大叔通过问答的形式,从 Class 与 DataStructure 的定义中推导出Class 与 Data Structure 是一对相对的存在。两者在三方面存在相对关系:
- Classes make functions visible while keeping data implied. Data structures make data visible while keeping functions implied.(Classes 中函数是显性的而数据是隐含的,Data Structure 中数据是显性的而函数是隐含的)
- Classes make it easy to add types but hard to add functions. Data structures make it easy to add functions but hard to add types.(Classes 易增加类型,不易增加函数; Data Structure 易增加函数而不易增加类型)
- Data Structures expose callers to recompilation and redeployment. Classes isolate callers from recompilation and redeployment.(Data Structure 直接暴露给调用方,改变后需要重新编译和部署,Classes 改变后无需重新编译和部署)
注意,这里讨论的 Class 与 Data Structure 是 C,Java 等类 C 语言中的概念,而不是 Lisp,Haskell 等函数式语言中的概念。
从第一条来看,我们需要重新审视以前在语言中被认为是数据结构的对象。List
Map
等容器在平常的观点中是属于数据结构的,但它们其实只是暴露了可操作的函数而已,数据结构是隐藏在具体实现中的,因此其属于类而不是数据结构。开发中使用的 DTO
由于只含有数据,虽然是表面是类,本质却是数据结构的。
类是对具体世界的建模,对外暴露的是 API,也就是它能做什么,这是我们了解一个类的途径。如果我们认同类对具体世界的建模是合理的话,我们对具体世界的认识也是从世界展示给我们的行为开始的。子曰:“察其言而观其行”,这应该是我们认识一个人的第一步。
从第二条来看,类增加类型容易而增加行为困难,数据结构相反。人若要长出第三只胳膊来,不知道需要多少万年的进化,造个人就容易多了。
第三条是从依赖方向上说的,所有依赖数据结构的源文件在数据结构有修改时都需要重新编译,耗时比较长;类将行为和实现分离,使用方只需要依赖接口就可以了,对实现不用关心,当实现有变化时,只需要编译变化的类,二者的关联是在运行时关联起来的。当你需要分配任务时,你只需指定谁谁干什么,不需要操心怎么做,各人有各人的实现方式,但最终你知道的就是活做完了。
类和数据结构其实就是面向对象和面向过程不同设计哲学的体现,从分析来看,面向对象更符合我们平时对世界的认知。面向过程的编程方法将数据完全暴露出来,更符合计算机的认知,计算机就是 CPU 围绕着寄存器、内存来运算。从设计上看,面向对象比面向过程抽象层级更高,更适合大规模的业务,小巧的业务使用面向过程会更轻便一些。