news 2026/10/21 6:24:37

Alan Kay的面向对象:消息传递与系统设计实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Alan Kay的面向对象:消息传递与系统设计实践

1. 为什么“面向对象之父”这个头衔本身就值得聊一聊

很多人第一次听到“面向对象之父”这个称呼,脑子里浮现的可能是某个写了很多经典教材的教授,或者某个发明了某门语言的大佬。但真正被业内公认戴上这顶帽子的,是 Alan Kay。这个名字在编程圈里出现的频率不算高,远不如那些语言创始人的曝光度,但只要你往深了挖,就会发现一个很有意思的事实:今天绝大多数人嘴里说的“面向对象”,跟他当年脑子里想的那个东西,几乎不是一回事。

我自己刚入行那几年,对面向对象的理解就是“类、继承、多态”三件套,写代码的时候先想怎么抽象一个基类,再想怎么派生子类,觉得这就是 OOP 的全部。后来读了一些关于 Alan Kay 的访谈和早期资料,才发现自己一直在一个很窄的框里打转。他提出这个概念的时候,核心根本不是“怎么组织类”,而是“怎么让一堆独立的小东西互相发消息、协同完成一件事”。这个认知上的落差,直接改变了我后来做系统设计时的思考方式。

这篇文章想做的事情很具体:把 Alan Kay 关于面向对象的原始观点拆开,讲清楚他到底在说什么、为什么后来主流语言把它带偏了、以及我们今天写代码时能从中拿走什么真正有用的东西。适合已经写过一段时间代码、对 OOP 有一定实践但总觉得哪里不对劲的开发者,也适合刚开始学编程、想从源头理解这个概念的人。我不会堆一堆学术词汇,而是尽量用实际写代码的场景来解释,让你看完之后能直接在自己的项目里用上。

2. Alan Kay 眼中的面向对象到底在说什么

2.1 核心不是“对象”,而是“消息传递”

Alan Kay 多次在访谈里强调过一个观点:他后悔用了“面向对象”这个词,因为大家的注意力全被“对象”吸走了,而真正重要的是“消息”。这个说法第一次听到会觉得有点反直觉,毕竟我们学 OOP 的第一课就是“万物皆对象”。但如果你回到他当年所处的环境,就能理解他为什么这么说。

上世纪六十年代末七十年代初,计算机科学界正在摸索怎么处理越来越复杂的系统。当时的编程方式主要是写一大堆过程,按顺序执行,数据和处理逻辑是分开的。Alan Kay 受到生物学和早期分布式系统思想的启发,觉得应该换一种思路:把系统想象成一群独立的“细胞”,每个细胞有自己的状态和行为,细胞之间通过发送化学信号来协作。映射到软件里,就是每个对象是一个独立的计算单元,对象之间通过“消息”来通信,而不是直接去读写对方内部的数据。

这个区别非常关键。在“消息传递”的视角下,对象内部怎么实现、用什么数据结构,对外部来说完全不重要。外部只需要知道“我发一个什么消息给它,它会回我一个什么结果”。这其实就是今天我们在微服务、Actor 模型、甚至前端组件通信里反复强调的“封装”和“接口隔离”,只不过 Alan Kay 在五十多年前就已经把它作为核心理念提出来了。

我举个实际写代码的例子。假设你在做一个订单系统,有一个订单对象和一个库存对象。传统的 OOP 写法可能是订单对象直接调用库存对象的reduceStock方法,甚至直接访问库存对象的某个字段。但在消息传递的视角下,订单对象应该做的是“发送一条消息”给库存对象,比如“我要扣减某个商品的库存”,至于库存对象是直接改内存、写数据库、还是发给另一个服务去处理,订单对象不需要知道。这个思路在今天的分布式系统里已经是标配,但在单体应用里,很多人反而忘了这一点,把对象之间的耦合写得死死的。

2.2 他为什么对“类”和“继承”保持距离

Alan Kay 参与创造的 Smalltalk 语言里确实有类(class)的概念,但他对“继承”这件事的态度一直比较微妙。他更看重的是“原型”(prototype)式的对象创建方式,也就是通过复制一个已有对象来产生新对象,而不是通过类来实例化。这个思路后来在 JavaScript 的原型链里得到了体现,虽然 JavaScript 的早期设计跟 Smalltalk 的关系比较复杂,但核心理念是相通的。

为什么他对继承这么谨慎?因为继承很容易导致一种问题:子类被迫继承父类的一堆它根本不需要的东西,而且父类的任何改动都可能影响到所有子类。这在大型项目里会变成一场噩梦。我自己就踩过这个坑。早年做一个后台管理系统,设计了一个“基础实体类”,里面放了创建时间、更新时间、创建人这些字段,然后所有业务实体都继承它。一开始很爽,代码复用率很高。但后来有一个实体不需要“创建人”这个字段,另一个实体的“更新时间”逻辑跟其他实体完全不一样,继承链就开始变得别扭。最后不得不把基础类拆成好几个接口,用组合的方式重新组织,才把问题解决掉。

Alan Kay 更推崇的方式是“组合”和“委托”。一个对象需要什么能力,就持有一个具备那个能力的对象,把消息转发给它,而不是通过继承去获得。这个思路在今天已经是设计模式里的常识,但很多人写代码时还是会下意识地先想“我该继承谁”,而不是“我该组合谁”。这个思维习惯的转变,其实比学几个设计模式更重要。

2.3 他真正关心的是“系统怎么长出来”

如果把 Alan Kay 关于面向对象的所有论述浓缩成一句话,我觉得是:他关心的不是单个对象怎么写,而是一整个系统怎么由大量独立单元组合而成,并且能够灵活应对变化。这个视角在今天看来特别有现实意义,因为我们现在面对的系统规模比当年大了几个数量级,微服务、事件驱动、响应式编程这些概念本质上都在解决同一个问题:怎么让一堆独立的部分协同工作,同时保持各自的独立性和可替换性。

他在访谈里提到过一个比喻,大意是说一个好的系统应该像生物体一样,每个细胞都知道自己该做什么,细胞之间通过信号交流,整个系统对外表现出稳定的行为,但内部一直在更新换代。这个比喻放到今天的云原生架构里,简直就是在说容器和服务的编排。你不需要知道某个服务内部是怎么实现的,只需要知道它能响应什么请求、返回什么结果,然后就可以把它替换掉、扩容、缩容,整个系统依然正常运转。

这个视角对我最大的启发是:写代码的时候不要只盯着当前这个类怎么写,要多想一步——这个类在整个系统里扮演什么角色,它跟其他部分通过什么方式交互,如果将来它的实现要换掉,会不会影响到别人。这种思考方式比单纯追求“代码复用”要有价值得多。

3. 主流语言把面向对象带偏了吗

3.1 “类、继承、多态”三件套是怎么变成标准的

如果你去翻任何一本讲面向对象的教材,目录里大概率会出现这几个词:类、对象、封装、继承、多态。这套话语体系主要是从 C++ 和 Java 这些语言的教学里沉淀下来的。C++ 早期为了兼容 C 并且提供高性能的抽象能力,把类作为核心机制,继承作为代码复用的主要手段。Java 更进一步,几乎把所有东西都塞进了类里,连一个简单的工具方法都要放在某个类下面。

这套体系有它的历史合理性。在大型企业级应用里,用类来组织代码、用继承来复用逻辑,确实能解决一部分问题。但问题在于,当这套东西变成“面向对象”的代名词之后,很多人就以为 OOP 就等于写类、写继承。结果就是大量过度设计的代码出现:为了继承而继承,为了抽象而抽象,一个简单的功能被拆成七八个类,每个类里只有几行代码,调用链长得让人头晕。

我自己在维护一些老项目的时候,经常看到这种代码。一个业务逻辑,从入口到真正干活的地方,要经过三四层继承,每层都覆写了一点东西,最后你根本不知道实际执行的是哪个版本的方法。这种代码的维护成本极高,改一个小地方要翻遍整个继承树。Alan Kay 当年设想的“独立单元通过消息协作”完全不是这个样子,反而更接近今天函数式编程里“组合小函数”的做法。

3.2 被忽略的“消息”和“自治”

主流 OOP 语言里,“消息”这个概念其实是被弱化的。在 Java 里,你调用一个对象的方法,本质上就是直接调用,编译器在编译期就确定了要执行哪段代码。这跟 Alan Kay 说的“发送消息”有本质区别。真正的消息传递应该是:发送方把消息发出去,接收方自己决定怎么处理,甚至可以把消息转发给别的对象,或者直接忽略。这种灵活性在 Smalltalk 和后来的 Erlang、Akka 这些系统里体现得更充分。

“自治”也是被忽略的一点。Alan Kay 希望每个对象是一个独立的、有自己行为逻辑的单元,而不是一个被动等待别人调用方法的数据容器。但在很多 Java 代码里,对象就是一堆 getter 和 setter,业务逻辑全在 Service 层里,对象本身没有任何行为。这种写法被称为“贫血模型”,在领域驱动设计里是被明确批评的。贫血模型的问题在于,数据和行为分离之后,任何一段逻辑都可能被散落在多个地方,改一个规则要改好几个文件,而且很容易漏掉。

我并不是说所有项目都要用富领域模型,有些简单的增删改查用贫血模型反而更直接。但如果你在做一个业务逻辑比较复杂的系统,把行为放到对象内部、让对象自己管理自己的状态,确实能减少很多不必要的耦合。这个思路跟 Alan Kay 说的“对象应该像一个独立的生物体”是一致的。

3.3 从“是什么”到“能做什么”的转变

Alan Kay 的观点里还有一个很实用的启发:不要纠结于“这个对象是什么类型”,而要关注“它能响应什么消息”。这个思路在今天的前端组件设计里特别有用。比如你设计一个按钮组件,不要去想“它是一个 Button 类的实例”,而要想“它能响应点击、能显示文字、能改变状态”。只要一个组件能响应这些消息,它就可以被当作按钮来用,至于它内部是用 div 还是用原生 button 实现的,调用方不需要关心。

这种“面向接口”而不是“面向实现”的思路,在 TypeScript 里体现得很明显。你可以定义一个接口,描述一个对象应该具备哪些方法,然后任何实现了这些方法的对象都可以被当作这个接口来使用,不需要显式地声明继承关系。这就是所谓的“结构化类型”,跟 Alan Kay 强调的“消息决定一切”在精神上是一致的。

我在做组件库的时候,会刻意避免让组件之间产生继承关系,而是通过 props 和事件来通信。一个组件需要什么数据,就通过 props 传进去;需要通知外部发生了什么,就通过事件发出去。这样每个组件都是独立的,可以单独测试、单独替换,整个系统的灵活性会高很多。

4. 把 Alan Kay 的思路落到实际项目里

4.1 从“先设计类”改成“先设计消息”

很多人的开发习惯是:拿到需求之后,先想有哪些实体,每个实体有哪些属性,然后画出类图,再开始写代码。这个流程本身没问题,但如果只停留在这一步,很容易设计出一堆互相耦合的类。我的做法是,在画类图之前,先列一张“消息表”:系统里有哪些角色,每个角色会发出什么消息,谁会接收这些消息,收到之后会做什么反应。

举个例子,假设你在做一个简单的博客系统。传统的做法可能是设计 User、Post、Comment 三个类,然后 User 有发布 Post 的方法,Post 有添加 Comment 的方法。但用消息的视角来看,应该是:用户发出“发布文章”的消息,文章服务接收后创建一篇文章;读者发出“发表评论”的消息,评论服务接收后创建一条评论并通知文章服务更新评论数。每个服务只关心自己接收什么消息、发出什么消息,不关心其他服务内部怎么实现。

这个思路的好处是,当系统规模变大、需要拆分服务的时候,你已经有了一张现成的消息流转图,拆分起来会顺畅很多。而且每个服务的边界很清晰,测试的时候也更容易模拟。

4.2 用组合代替继承的实际操作

如果你现在手上有一个继承层次比较深的代码,想改成组合的方式,可以按下面这个步骤来操作。第一步,找出继承树里每个子类真正需要的方法,把那些子类不需要但父类提供的方法标记出来。第二步,把父类里那些通用的逻辑抽成一个独立的辅助类或者工具类。第三步,让原来的子类持有一个辅助类的实例,需要用到那些通用逻辑的时候,通过调用辅助类的方法来实现,而不是通过继承获得。

这个过程听起来简单,但实际操作的时候要注意一点:如果父类的方法里用到了子类覆写的其他方法,直接抽出来可能会改变行为。这种情况下,需要把父类里那些会被覆写的方法也一起抽出来,通过参数或者回调的方式传入。这个重构过程可能会比较繁琐,但做完之后代码的灵活性会明显提升。

我自己做过一次这样的重构,把一个有五个子类的基类拆成了三个独立的辅助类,子类通过组合的方式使用它们。重构之后,新增一个子类只需要组合它需要的辅助类,不需要再考虑继承树的结构。而且原来那些子类之间互相影响的问题也消失了,因为每个子类都是独立的。

4.3 消息传递在前后端通信里的应用

Alan Kay 的消息传递思想,在今天的前后端分离架构里其实已经得到了很好的体现。前端发送一个 HTTP 请求,后端返回一个响应,这就是一次典型的消息传递。前端不需要知道后端是用什么语言写的、数据库是什么,只需要知道发什么请求、会得到什么响应。后端也不需要知道前端是用什么框架渲染的,只需要按照约定的格式返回数据。

但很多人在设计 API 的时候,还是会不自觉地把后端的内部结构暴露出去。比如返回的数据里包含了数据库表的主键、外键关系,或者 API 的路径直接对应后端的 Controller 方法名。这些做法都会让前后端产生不必要的耦合。更好的做法是,把 API 设计成一组“消息”,每个消息描述一个业务动作,而不是一个数据库操作。比如用POST /orders而不是POST /createOrderFromCart,用GET /users/{id}/profile而不是GET /getUserById。

这个思路在 GraphQL 里体现得更彻底,客户端可以精确地描述自己需要什么数据,服务端按照这个描述返回结果,双方通过一个 schema 来约定消息的格式。虽然 GraphQL 不是所有项目都适合用,但它背后的“按需获取、消息驱动”的思路是值得借鉴的。

5. 常见误解与实操中的坑

5.1 “万物皆对象”不等于“万物皆类”

很多人把“万物皆对象”理解成“万物皆类”,觉得任何东西都应该先定义一个类,然后再实例化。但在 Alan Kay 的原始设想里,对象是运行时的实体,类只是创建对象的一种方式,而且不是唯一的方式。原型式编程里,你直接复制一个已有对象,修改它的几个属性,就得到了一个新对象,不需要先定义一个类。

这个区别在实际开发里是有影响的。比如你在做一个配置系统,需要根据不同的环境生成不同的配置对象。用类的方式,你可能要定义 Config 类,然后定义 DevConfig、ProdConfig 等子类。用原型的方式,你可以先创建一个基础配置对象,然后根据环境复制它并覆盖几个字段。后者在配置项很多但差异很小的情况下会更简洁。

JavaScript 的对象字面量和展开运算符就是典型的原型式思路。你不需要定义一个类,直接写一个对象,需要变体的时候用展开运算符复制一份再改几个字段。这种方式在写配置、写测试数据、写临时对象的时候特别方便。当然,对于需要复用行为、需要明确类型的情况,类还是有它的价值。关键是不要被“必须用类”这个思维定式绑住。

5.2 过度抽象比不抽象更可怕

Alan Kay 强调消息和自治,但有些人会把这个理解成“要把每个小功能都抽象成一个独立的对象”。结果就是系统里充满了各种细碎的对象,每个对象只做一件极小的事情,对象之间的消息传递链条长得离谱。这种过度抽象的问题在很多“设计模式驱动”的代码里都能看到。

我见过一个项目,一个简单的“用户登录”功能,被拆成了 Authenticator、CredentialValidator、TokenGenerator、SessionManager 等六七个类,每个类都只做一小步,类之间通过接口和事件来通信。代码看起来很“优雅”,但调试的时候非常痛苦,因为你要在六七个文件之间跳来跳去才能搞清楚一个登录请求到底经过了哪些步骤。而且新增一个登录方式的时候,要改好几个地方,因为每个类都只负责一小块逻辑。

抽象的目的是降低复杂度,而不是增加复杂度。如果一个抽象没有让代码更好理解、更好修改,那它就是一个失败的抽象。我在做设计的时候,会问自己一个问题:如果我把这个抽象去掉,代码会变得更难懂吗?如果答案是不会,那我就不加这个抽象。这个判断标准虽然简单,但能避免很多过度设计。

5.3 消息传递不等于异步

有些人一听到“消息传递”,就想到消息队列、异步处理、事件驱动。但 Alan Kay 说的消息传递,核心是“发送方不需要知道接收方怎么处理”,而不是“发送方不需要等待接收方处理完”。同步调用也可以是一种消息传递,只要调用方不依赖被调用方的内部实现。

这个区分很重要,因为很多人为了追求“消息传递”而强行把同步逻辑改成异步,结果引入了不必要的复杂度。比如一个查询操作,本来就是需要立即拿到结果的,改成异步之后,调用方要处理回调、要管理状态、要处理超时,代码量翻了好几倍,但并没有带来任何实际好处。

我的建议是:先判断这个交互是不是真的需要异步。如果调用方需要立即拿到结果才能继续,那就用同步的方式,但保持接口的清晰和独立。如果调用方不需要立即拿到结果,或者需要同时触发多个操作,那再考虑异步。不要为了“架构好看”而牺牲代码的简单性。

6. 从 Alan Kay 的观点里能拿走什么

6.1 设计时先想交互,再想结构

Alan Kay 的观点给我最大的启发是:设计一个系统的时候,先想清楚各个部分之间怎么交互,再想每个部分内部怎么实现。这个顺序很重要,因为交互方式决定了系统的灵活性和可扩展性,而内部实现是可以随时替换的。

具体到日常开发,我现在的习惯是:拿到一个需求,先画一张草图,标出有哪些角色、每个角色会发出什么请求、谁会响应这些请求。这张草图不需要很正式,用纸笔或者白板画几个框和箭头就行。画完之后,再考虑每个角色内部需要什么数据、什么逻辑。这样做的好处是,系统的边界在一开始就比较清晰,后面写代码的时候不容易出现“这个逻辑该放哪里”的纠结。

这个习惯也影响了我做技术选型的方式。以前选框架的时候,我会比较关注“这个框架提供了哪些类、哪些继承体系”。现在我会更关注“这个框架里各个部分怎么通信、消息格式是什么、能不能方便地替换某个部分”。后者才是决定一个框架能不能长期用的关键因素。

6.2 保持对象的独立性和可替换性

Alan Kay 说的“自治”,落到实际代码里,就是每个模块应该能够独立测试、独立替换。我在写代码的时候,会刻意避免让一个模块直接依赖另一个模块的具体实现。如果两个模块需要通信,我会定义一个清晰的接口,让它们通过接口来交互。这样,只要接口不变,任何一个模块的内部实现都可以随时替换。

这个做法在写单元测试的时候特别有用。如果每个模块都依赖接口而不是具体实现,测试的时候就可以很方便地创建模拟对象,不需要启动整个系统。我见过很多项目,因为模块之间耦合太紧,写一个单元测试要启动数据库、启动消息队列、启动一堆外部服务,测试跑一次要几分钟。这种项目的问题不在于测试写得不好,而在于模块的独立性太差。

保持独立性还有一个好处是,当某个模块需要重写的时候,你可以放心地重写,只要接口不变,其他模块完全不受影响。这在长期维护的项目里价值巨大,因为技术栈会变、需求会变,能够局部替换而不影响全局,是一种非常重要的能力。

6.3 对“最佳实践”保持警惕

Alan Kay 当年提出面向对象的时候,并没有一套现成的“最佳实践”可以遵循。他是在探索一种新的思路,而不是在执行一套固定的规则。这个态度本身就值得学习。今天我们在网上能看到大量的“最佳实践”、“设计模式”、“架构规范”,这些东西有参考价值,但不能盲目照搬。

我自己的经验是,任何一条“最佳实践”都有它的适用场景和前提条件。比如“面向接口编程”在需要灵活替换实现的场景下是对的,但在一个简单的脚本里,为了一个只用一次的功能定义一个接口,就是多余的。“不要重复自己”在大多数情况下是对的,但有时候两段看起来相似的代码,背后的业务逻辑完全不同,强行合并反而会导致耦合。

我的做法是,看到一条“最佳实践”的时候,先问自己:它解决的是什么问题?我现在的项目有这个问题吗?如果没有,那我就不需要遵循它。如果有,那我要理解它为什么能解决这个问题,然后再决定怎么用。这种“先理解再使用”的态度,比死记硬背规则要有效得多。

7. 我个人的一些实操体会

写了这么多,最后分享几个我自己在实际项目里总结出来的小经验,都是跟 Alan Kay 的思路相关的,但更偏实操层面。

第一个经验是:当你觉得一个类的代码越来越长、越来越难改的时候,不要急着去拆分类,先看看这个类跟其他类的交互方式是不是有问题。很多时候,问题不在于这个类本身太大,而在于它承担了太多跟其他类通信的职责。把通信的部分抽出来,让这个类专注于自己的核心逻辑,代码自然就清晰了。

第二个经验是:在设计接口的时候,尽量用“做什么”来命名,而不是“怎么做”。比如calculateTotalPrice比sumItemPricesAndApplyDiscount要好,因为前者描述的是目标,后者描述的是步骤。用“做什么”来命名,实现方式可以随时改;用“怎么做”来命名,实现方式就被固定下来了。

第三个经验是:不要害怕在项目初期把一些东西写“死”。Alan Kay 强调灵活性,但灵活性是有成本的。在需求还不明确的时候,过度追求灵活性会导致大量无用的抽象。更好的做法是,先把功能实现出来,等到确实需要灵活性的地方再引入抽象。这种“延迟抽象”的策略,能避免很多前期过度设计的问题。

第四个经验是:多读一些老代码,尤其是那些存活了十年以上的开源项目。你会发现,这些项目里很少有一开始就设计得很完美的架构,大多数都是经过多次重构、逐步演化出来的。Alan Kay 的思想在这些项目里往往体现得很明显:模块之间通过清晰的接口通信,每个模块内部可以独立演化。这种“演化式”的设计思路,比“一次性设计完美架构”要现实得多。

面向对象这个概念被讨论了五十多年,各种解释和延伸层出不穷。但回到 Alan Kay 的原话,核心其实很简单:让一堆独立的小东西通过消息互相协作,每个小东西自己管好自己的事情。这个思路在今天这个系统越来越复杂、变化越来越快的环境里,反而比以往任何时候都更有价值。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/21 6:24:36

C++项目.sln文件完全指南:从结构解析到构建排错实践

做Windows原生C开发的老哥们,几乎每天都会跟一个不起眼的文件打交道:Microsoft Visual C项目里的.sln解决方案文件。这东西平时安安静静躺在仓库根目录,可一旦多项目协同、配置切换、版本迁移、命令行批量构建出问题,大家不约而同…

作者头像 李华
网站建设 2026/10/21 6:23:41

基于北方苍鹰算法优化BP神经网络的多变量时序预测Matlab实现

先交代一下背景:我之前拿到一批多变量时间序列数据,要做预测建模,顺手把“基于北方苍鹰优化算法优化BP神经网络(NGO-BP)的多变量时间序列预测Matlab实现”整个流程跑了一遍。这篇文章就是复盘整个思路和代码细节&#…

作者头像 李华
网站建设 2026/10/21 6:22:59

矩阵计算中哪些数学证明值得写?实践指南与替代方法

最近又有人问我矩阵计算的数学证明该怎么写,我的第一反应不是讲怎么证,而是反问一句:你确定真的要写这个证明吗?这套矩阵计算框架做了三年多,从最初的矩阵分解、特征值计算到现在的分布式矩阵运算,我踩过最…

作者头像 李华
网站建设 2026/10/21 6:22:41

可插拔架构下的知识管理:自建知识工作插件系统全解析

我过去很长一段时间在写东西这件事上非常痛苦——不是没有素材,而是素材太散。某天要写一篇关于“分布式存储”的文章,我需要在至少五个工具里翻找:浏览器书签里的链接、手机备忘录里的片段、电子书划的笔记、聊天记录里同事发的一张架构图、…

作者头像 李华
网站建设 2026/10/21 6:21:25

不确定性感知轨迹规划:行星探测车可通行性预测与高斯过程量化传播

1. 项目概述与核心动机做行星探测车轨迹规划这个方向的人,应该对“不确定性”三个字有切肤之痛。我们在会议室里看到的火星车照片都是阳光明媚、地形平缓,好像随便一条路都能走。但真实情况是:探测车前方是一大片只靠轨道相机和双目立体视觉粗…

作者头像 李华
网站建设 2026/10/21 6:21:06

30天打卡实战:如何用系统设计告别意志力内耗

3月9日,我在打卡表格上写下第30天的记录。说“没想到”其实有点假,因为前20天撑过去之后,第30天基本是顺理成章的。但走到这一天,回头看整个过程,我是真切地感受到:打卡这件事,关键不是那张慢慢…

作者头像 李华