背景
Hello,大家好,我是Sunday。
今天咱们来看一本新的书《程序员超强大脑》
从这本书的名字中,其实咱们也可以看出来,这是一本关注【程序员大脑工作方式】的书籍。说白了就是:帮助程序员理解大脑如何加工代码的。
对于咱们程序员来说,我们需要经常去写代码、读代码,甚至是修改代码。但是代码本身是非常严谨的,可能多出一个空格,多出一个分号都会导致我们的程序出错。
而这些错误,很多时候都是由于认知问题所导致的。有可能是因为我们没有充分的掌握语法,有可能是对代码的假设认知有误,也有可能是因为对代码的阅读水平不够。
那么我们应该如何来提升这些能力呢?
书中通过四个维度,来为我们明确了能力提升的方式:
- 如何快速的阅读代码
- 如何深入理解代码
- 如何提高代码的编写能力
- 如何进行多人的代码协作
四个部分,一共分为了 13 个章节。
那么下面,就让我们进入到书中来看一看吧。
正文
01:代码阅读
第一部分包含了四个章节:
- 剖析程序设计之惑
- 快速阅读代码
- 快速学习编程语法
- 阅读复杂的代码
那么首先,咱们先来看第一块:剖析程序设计之惑。
第一章:剖析程序设计之惑
咱们先来看三段代码,这三段代码分别使用:APL、Java、BASIC 语言编写。大家可以看看是否可以看明白这三段代码的意思:
现在大家能不能告诉我,这三段代码分别都干了什么?
除了这个 java 之外,我相信另外两个大家都很难说出来他们的作用吧。
那么此时,我们可以来思考一下:为什么我们没有办法理解这几段代码呢?
其实这个原因,主要有三点:
- 缺乏知识: 什么是缺乏知识呢?很简单:我不会 APL 语言啊,所以我看不懂。
- 缺乏信息: 那么什么是缺乏信息呢?以第二段 java 为例。就算大家不了解 java 代码,相信大家也能看出来,它这是:声明了一个变量 n,然后打印了
Integer.toBinaryString(n)的执行结果。 但是这里的困惑在于:我们不知道Integer.toBinaryString(n)方法的作用。因为缺乏这个信息,所以我们很难明确这段代码干了什么。 - 缺乏加工能力: 而在第三段代码中,我们可以看出来:他首先声明了两个变量,然后执行了 for 循环,最后打印了一个变量。但是我们如果想要指导它的打印结果,那么就需要把整个程序的执行在自己大脑里面过一遍。 这种在自己大脑中加工代码执行的方式,绝对不是一件容易的事。大家可以想想面试中所遇到的 阅读代码,说结果的题目
而这三点,其实就是 大脑内部存在的三种认知过程,分别是:
- 长时记忆: 长时记忆顾名思义,就是 可以长期保存的记忆 ,类似于条件反射或者肌肉记忆的概念。第一段的 APL 代码其实并不复杂,如果我们知道 APL 中 T 代表的其实就是 二元编码函数,那么阅读这段代码就会非常容易。我们既不需要理解任何的单词,也不需要去读代码的作用
- 短时记忆: 当我们去读文档查询一个方法的作用时,我们只需要当时知道这个方法的作用即可,一般不会长期的记住它,特别是一个冷僻的方法。这样一种只在当时记忆的方式就被叫做 短时记忆。 针对第二段的 java 代码而言,我们只需要查询下这个方法的作用。就可以搞明白这段代码的含义。同时这个方法的作用我们可能很快就会忘掉。 所以,想要理解第二段代码,那么需要依靠的就是短时记忆。
- 工作记忆: 如果把长时记忆比作硬盘,短时记忆比作内存,那么工作记忆就相当于 CPU。 工作记忆的作用是在大脑中编译代码的执行。比如在面试时的 阅读代码题,这样的题目考验的就是你对代码的执行判断,说白了,考验的就是你的工作记忆。
这三种认知过程,具备基本的对应关系,咱们看下图:
箭头1 代表进入大脑的信息,箭头2 代表进入短时记忆的信息,箭头3 代表从短时记忆转移到工作记忆的信息,这些信息与来自长时记忆的信息(箭头4)相结合。工作记忆是大脑在进行思维活动时加工信息的机制。
第二章:快速阅读代码
想要记忆一段代码,并且把它默写下来。其实是一件非常困难的事情。其原因就出现在 短时记忆、长时记忆、工作记忆 三者的协作关系上。
咱们可以通过两段代码来进行测试。
首先是第一段代码:
// 插入排序
const array = [45, 12, 85, 32, 89, 39, 69, 44, 42, 1, 6, 8]
let temp
for (let i = 1; i < array.length; i++) {
for (let j = i; j > 0; j--) {
if (array[j] < array[j - 1]) {
temp = array[j]
array[j] = array[j - 1]
array[j - 1] = temp
}
}
}
for (let i = 0; i < array.length; i++) {
console.log(array[i])
}
这是一段插入排序的代码,书中原本是使用 java 编写的,我把它改成了 js 。
大家可以花三分钟的时间来尝试记忆这段代码,然后再把它默写出来,看看大家默写的结果和源代码的差距。
大家可以在这里暂停三分钟
然后是第二段代码:
function execute(x) {
let b = x.length
for (let v = b / 2 - 1; v >= 0; v--) func(x, b, v)
for (let l = b - 1; l > 0; l--) {
let temp = x[0]
x[0] = x[l]
x[l] = temp
func(x, l, 0)
}
}
同样,三分钟的时间记忆,然后尝试默写它
大家可以对比两次默写的结果,几乎可以肯定的说:第二次的默写结果,肯定不如第一次的好。
原因主要有两个:
- 你不清楚第二段代码的作用是什么
- 第二段代码的变量名更加模糊,这会增加你短时记忆的负担。
咱们来看下记忆这些代码时大脑的协作情况:
部分信息(例如变量名和变量值)存储在短时记忆中,部分信息(例如for 循环的语法)存储在长时记忆中。
那么根据这个协作图和我们默写的结果,其实就可以知道。我们之所以很难记住代码,其根本原因就在于 短时记忆很有限
那么如何弥补短时记忆不足的情况呢?
作者在这里给出了两种方式:
- 组块练习: 所谓组块练习指的是:把一个全新的知识点,拆分成多个熟悉的知识点进行学习。
- 增加长时记忆: 多写代码,尽量让代码能力变成长时记忆。
第三章:快速学习编程语法
有过开发经验的同学都知道,当我们去学习一个新的编程语言时,那么大量的 API 其实是阻挠我们学习的一个痛点。很多同学在学习 API 的时候,都会出现学完之后很快就忘了的情况。
之所以会出现这种情况其实也非常简单。
在 19 实际 70 年代,德国有一个哲学家叫做 赫尔曼、艾宾浩斯 他提出了人类的遗忘曲线:
根据图片可以看到。咱们在进行学习的时候,随着时间的推移,知识的留存就会变得越来越少。在两天之后,知识的留存率会只有 25% 。
而这个和美国学习专家 爱德加·戴尔 在 1946 年提出的 学习金字塔模型 其实是不谋而合的:
那么如何解决这种 知识留存率 不高的问题呢?在我做的前端训练营中有很多的学员,他们也都遇到了类似的问题,其实解决的方式非常的简单。就像学习金字塔模型中所提到的内容一样。 把你的知识教授给他人 。
有同学可能会很困惑,我没有学生,怎么教授给他人呢?其实是有办法的,两种方案:
- 写博客
- 录视频
通过博客或者视频的方式,把自己的知识输出出来,以输出来代替输入 而来完成 教授给他人 的知识留存率。
第四章:阅读复杂的代码
代码越复杂,越难以阅读,这是非常正常的一件事情。
但是,这里有一个问题,那就是:什么样的代码才是复杂的代码呢?为什么复杂的代码就难以阅读?
在前面我们提到过工作记忆的概念,我们知道所谓的工作记忆指的是:一种短时记忆,类似于 CPU 。而对于 CPU 来说就会存在一个 CPU负荷 的概念。负荷越大运转越慢,也就是所谓的 “难以阅读”。
那么什么情况下会导致负荷变大呢?说白了就是:陌生的代码:
- 当我们阅读别人写的代码时
- 当我们阅读不熟悉的语言写的代码时
当我们处于以上两种情况时,都会产生对应的认知负荷。
总结一下就是:当我们阅读别人写的代码,或者不熟悉的语言写的代码时,会产生更大的认知负荷。负荷越大,大脑运行越慢,也就是“难以阅读” 。
那么怎么解决这个问题呢?作者提出了三种方式(不过这三种方式也并不简单,大家作为参考即可):
- 重构: 调整代码的内部表现,但是不修改代码的外部行为。说白了就是咱们平常工作中所提到的 代码 review 。通过
review让整个代码的结构更加清晰,这样就可以降低我们的认知负荷 - 替换不熟悉的语言结构: 顾名思义,就是把不熟悉的语言结构变为熟悉的语言结构。咱们来看这一段内容
- 在抽认卡两面写上等价的代码: 这个的意思是说哪一张卡片,一面写 文字提示,一面写 对应的代码 。通过文字提示来对比代码。这其实是一种很好的方式。
02:代码思考
接下来咱们进入到整本书中的第二部分 代码思考 。 从阅读代码到思考代码,可以更好地理解程序,并避免出现思维方面的错误。
整个第二部分共分为三章的内容:
- 深入理解代码
- 更好的解决编程问题
- 迷思概念:错误的思维方式
那么接下来,让我们先看第一部分深入理解代码
第五章:深入理解代码
遇到一段不熟悉的代码时,程序员可能很难判断代码的作用。用第4章介绍的认知术语来说,阅读陌生的代码会显著增加大脑的认知负荷。而学习新的语法和编程概念并重构代码可以大幅减轻认知负荷。
所以这一章咱们就来看看,如何深入的理解代码。但是大家需要注意,这里作者的描述可能会比较 理想化。说白了,更好理解代码的前提是 有一个好代码
作者在这里提到了 5 点内容,帮助我们深入理解代码:
-
变量: 这里的变量主要指的是 具备语义化的变量名,作者提到变量的语义化非常重要,通过具备语义化的变量名,可以更好的帮助我们理解代码。但是这个主要考验的是 “上一任同事” 的能力,不以我们的个人意志为转移了。
-
角色和范式: 这里应该是一个翻译的错误。这里的角色指的是 一个主体 。比如:一个变量、一个函数、一个框架都可以称之为是一个角色。而范式指的是 行为习惯。作者在这里提到,依据不同的主体,使用大众可以接受的行为习惯,进行编码,是更好理解代码的前提。
-
加深对程序的理解: 这一块比较有意思,作者提到了 4 步方案,通过这 4 步来帮助我们更好的理解代码:
- 寻找焦点: 这是一个非常重要的概念。当我们去阅读代码时(无论是源码还是什么),我们一定要知道 你想要看代码中的哪一部分内容。因为整个项目的逻辑是非常复杂的,所以我们一定要找到其中的一个点,通过这个点进行突破。
- 以焦点为基础逐步了解代码: 找到了焦点之后,接下来就是以这个焦点进行扩散进行阅读。特别注意: 与焦点无关的事情,不需要了解。
- 通过一系列相关的实体来理解某个概念: 这里的实体可以理解为变量或者方法。根据上一步的描述,我们只需要关心焦点中的内容,那么与焦点无关的,比如在当前场景的执行逻辑下:没有执行的函数,没有使用到的变量都不需要关注
- 理解涉及多个实体的不同概念: 这一步相对来说更加负责一些。我们知道所有的函数都是有 “边界” 的。比如:当前的函数可以实现哪些功能?无法实现哪些功能?具体例子:构建二叉树。是否支持某个节点支持任意数量的子节点?是否可以随意添加节点而不报错?认清程序的 能力与约束(边界) 可以帮我们更好地深入理解代码。
-
阅读代码与阅读文本有相似之处:我之前一直会跟我的学员举个例子 写程序就像写作文一样,我们学习过的 API 就像具体的一个字,写的程序就是把这些字组成的文章。这个理论其实和作者在这里提到的是一样的。阅读代码和阅读文本其实有非常多相似的地方,所以就引出了最后一个内容
-
运用文本理解策略来阅读代码:简单来做一个固定的流程:先从一个验证的测试(最小的测试案例)开始,在测试的过程中观察变量的变化,确定不同代码行之间的执行关系,以此推断新变量的含义。把以上流程以图形的形式呈现在脑海中(或纸上),最后进行一些适当的提问。
第六章:更好地解决编程问题
如果我们要对程序员的工作进行一个定义,那么就是 如何更好地解决问题。专业程序员经常需要权衡不同的问题解决方案:应该将公司的所有客户抽象为一个简单的列表,还是一棵按默认分支组织的树?应该采用基于微服务的架构,还是集中处理所有逻辑的架构?
在评估不同的问题解决方案时,程序员往往发现这些方案各有所长。由于需要考虑的因素非常多,因此决定采用哪种方案颇费思量。例如,应该优先考虑易用性,还是把性能放在首位?是否有必要考虑今后可能对代码所做的修改,还是集中精力处理当前的任务?
作者在本章中提供了两种框架,通过这两种框架的形式,来帮助我们理解如何选择不同的软件设计方案。
-
借助模型来思考代码: 所谓模型指的是 对现实的简化表征 。主要的目的是:帮助人们思考问题并最终解决问题。 模型分为很多种,其中最重要的就是 心智模型。 想要解释清楚心智模型是一个很复杂的事情,作者在书中也只是做了一些简单的剖析,不过有一个例子非常有意思,在这里分享给大家:
如果给雪人穿上一件既好看又暖和的毛衣,那么与没有穿毛衣的雪人相比,穿毛衣的雪人融化得更快还是更慢?
有人一开始也许认为穿毛衣的雪人融化速度会更快,因为大脑会立即检索到“毛衣能保暖”这一心智模型。但是再想想就会知道,毛衣的作用不是保暖,而是减少热量散失,因此穿毛衣的雪人实际上融化得更慢而不是更快。
同样,对于我们这些程序员而言,可能会依靠简单的心智模型来阅读复杂的代码。如果代码中频繁出现指针,那么我们也许会混合使用变量和指针的心智模型,不再区分值和内存地址。在调试包含异步调用的复杂代码时,即使之前构建的同步调用的心智模型无法充分描述异步调用,我们也可能把这种模型作为参考。
-
概念机器: 概念机器也属于模型的一种,它的定义是:推理计算机如何执行代码时所用的模型。作者在这里通过一个例子比较形象的解释了什么是概念机器:
20世纪70年代,英国萨塞克斯大学教授Ben du Boulay在研究Logo语言时提出了概念机器的设想
他使用工厂工人来类比语言执行模型。工人能够执行命令和功能,有耳朵可以听到参数值,有嘴巴可以说出输出结果,有手可以执行代码描述的行为。这种编程概念的表征最初很简单,但随着时间的推移逐渐完善,最终能够解释包括内置命令、用户定义的过程和函数、子过程调用、递归在内的整个Logo语言。
通过以上类似抽象的方式,来帮我们更加的理解代码问题,作者在这里给出了一张图,大家可以作为参考
第七章:迷思概念-错误的思维方式
所谓迷思概念指的是:人们对某一问题或概念存在误解或错误的观念。这些迷思可能源自于错误的信息传播、个人偏见或文化传统等因素。
其实这种情况在各种圈子里面都是普遍存在的。
比如之前在面试一些同学的时候,我问他们 “vue3 目前的 ref 实现原理是什么?” 同学的普遍回答都是:“通过 Object.deinfeProperty 进行实现的” 并且说的掷地有声,振振有词的。 可是在 Vue 3.2 之后 Ref实现原理已经发生了巨大的变化了。这其实就是一个典型的迷思概念。
不过通常情况下,迷思概念有一个更加常见的表现,我相信在座的所有同学都有遇到过,那就是: 你坚信程序是正确的,是可以跑通的但是,现实却无法跑通。
那么明确好了什么是迷思概念之后,如何来消除迷思概念呢?
作者在这里提到了一种方式,但是这种方式都并不容易,因为这种迷思概念是来自于人类的 本能脑,你的 理智脑 和 情绪脑 一般是没有办法对抗它的。所以以下方案,仅供参考:
大家是否还记得刚才我们讨论过的“雪人问题”:与没有穿毛衣的雪人相比,穿毛衣的雪人融化得更快还是更慢?
有人一开始也许认为融化速度会加快,毕竟穿上毛衣更暖和,其实不然。毛衣可以减少热量散失,从而延缓雪人的融化过程,因此穿毛衣的雪人融化得更慢。
大脑可能在第一时间激活一个现有的概念:毛衣能保暖。这个概念适用于人类,但无法迁移给雪人,和你聪明不聪明没有关系。
人们长期以来一直认为,在探索事物规律的过程中,那些陈旧、错误的概念会从记忆中永远消失,代之以更合理、更准确的概念。但是实际情况不会这样,记忆既不会消失,也不会被新的记忆取代。确切地说,记忆提取将随着时间的推移而减少,但关于错误思维方式的记忆依旧存在。
明确了这样的道理之后,当我们再次思考毛衣是否会导致雪人的温度升高时,两种概念(毛衣能保暖、毛衣也能隔热)会相互“打架”,所以只有主动抑制“毛衣能保暖”的概念才能得到正确的结论。如果依靠推理而不是凭借直觉进行判断时出现“稍等片刻”的感觉,则表明大脑可能在努力抑制不正确的想法。
03:代码编写
如何写出来高质量的代码一直是一个长盛不衰的讨论话题。在本书的第三部分,主要讲解的就是代码编写的问题。
主要包含三大块:
- 提高命名质量
- 两种框架:避免低质量代码和认知负荷
- 提高解决复杂问题的能力
那么我们一个一个来看
第八章:提高命名质量
通过本章的名字,我们也能够看出来,本章讲解的主要就是 变量(函数)命名 问题。
一个好的命名,可以做到 见名知意。那么具体怎么做呢?作者在书中提到了一个叫做 三步模型 的方式。
- 第1步:选择标识符要体现的概念
- 第2步:挑选代表每个概念的单词
- 第3步:根据这些单词设计标识符
什么意思呢?咱们逐步来看:
第1步是选择标识符要体现的概念,这一步具有极强的领域特定性。在选择标识符所包含的内容时,应该重点考虑标识符的目的,即标识符能否体现出对象的信息及其用途。如果我们感觉有必要添加注释来解释标识符,或代码中存在与标识符相近的注释,那么建议将注释内容纳入标识符。某些情况下,在标识符中加入类型指示信息同样很重要,例如标明长度类型(水平长度还是垂直长度)、重量单位(千克还是磅)或缓冲区包含用户输入(因此存在安全隐患)。
第2步是挑选代表每个概念的单词。找到合适的单词通常并不难,显然应该选择一个在代码领域或整个代码库中使用的特定单词。但是如果我们不确定同义词代表相同的对象还是细微的差别,那么这种多样性就会带来问题。为提高命名的一致性,可以考虑建立专门的项目词库(project lexicon),把所有重要的定义记录在案,并给出同义词的替换词。
第3步是根据选定的单词来设计标识符,本质上是选择一个名称。举个例子,描述“最大点数”的惯用语是“maximum number of points”而不是“point maximum”,因此程序员可能更愿意使用max_points而不是points_max作为标识符。为使标识符听起来更自然,还可以考虑在其中加入介词,例如indexOf或elementAt。
第九章:两种框架:避免低质量代码和认知负荷
在前面咱们说过:阅读复杂的代码会导致认知负荷增大。所以想要减低认知负荷就需要降低代码的复杂度。那么哪些类型的代码会加重复杂度呢?从而增加认知负荷呢?
作者在这里提到了两个点:
- 结构性问题
- 标识符问题
关于结构性问题,作者在这里提到了一个词,叫做 代码异味。包括:过长的方法、提供了太多功能的类、过于复杂的 switch 判断都算是代码异味。
过多的代码异味就会导致代码的可阅读性变差,增加认知负荷。在这里作者推荐了另外一本书《重构》
有兴趣的同学可以去看一下。
而关于标识符的问题其实和第八章类似,这里就不再过多赘述了。
第十章:提高解决复杂问题的能力
如果我们把解决一个问题分成三个步骤的话,那么这三个步骤应该是:
- 明确目标状态(希望实现的目标)。一旦达到目标状态,就可以认为问题已经得到解决。
- 待解决问题的起始状态。
- 描述如何从起始状态达到目标状态的规则。
任何一个复杂的问题都可以按照这三步进行分析,从而明确出具体的解决方案。
而针对解决方案的话,作者在这里给出了两种方法:
第一种方法称为自动化(automatization),也就是能够不假思索地完成小任务。这种方法之所以有用,是因为解决小事所花的时间越少,解决难题就越容易。
第二种方法是借鉴其他人所写的代码并化为己用,以提高自己的问题解决能力。
那么首先我们先来看第一种,叫做 自动化。
所谓自动化指的是:一旦某项技能经过反复练习后成为本能,就可以认为这项技能已经实现自动化,例如走路、阅读或系鞋带。
由这个定义我们就可以知道,想要实现所谓的自动化,其核心就在四个字:熟能生巧 。这个概念在《刻意练习》这本书中进行了详细的介绍
用一句话概括就是:把一件事情,进行反复的、刻意的训练。 并且这个时间通常不会很长,根据我的经验,一般只需要 几十 到 几百个小时即可。
下面这张图描述了刻意练习的作用
然后我们来看第二种方式:借鉴他们的代码为己用。
这其实是一种非常常见的方式,比如:大家应该都有过百度直接复制代码的经历吧。这其实就是借鉴他人的代码为己用的一种体现。但是除了这种方式之外,还有很多其他的方式。
比如:
- 与同事合作,研究代码
- 用好 Github,寻找现成的源代码
- 阅读讨论源代码的文章
类似的方案有很多,但是核心就是 “借鉴” 别人已有的代码逻辑。就像我们之前别的视频中说到过的一样:你所遇到的绝大多数的问题,别人可能都已经有了现成的解决方案。
04:代码协作
所谓协作指的就是团队合作的意思。在前面的三部分中,书中主要讲解的都是个人开发的能力。所以在这最后一部分里面,作者主要会讲解团队协作相关的内容。
不过这里大家需要注意,以下内容是 挂在墙上 的。实际操作的时候,仅供参考。
整个第四部分分成三章:
- 编程活动与任务
- 设计和改进大型系统
- 对新程序员进行试岗培训
第十一章:编程活动与任务
当我们在去进行开发工作的时候,我们的大脑会产生一种认知惯性。这种认知惯性,作者把它叫做 “预热”。一旦有了这种惯性之后,那么就可以大大的减少我们的认知负担。也就是很多同学所说的:“唉,有感觉啦~~”
不知道大家有没有在进行编码过程中被人打断的经历?大家是不是非常讨厌这种情况。那么这是因为什么原因呢?作者专门对这一块进行了解释:
经过研究发现:程序员经常受到干扰,每次持续15~20分钟。工作期间,程序员要用差不多20%的时间来应付各种干扰。随着Slack以及其他即时通信应用程序的使用日益广泛,程序员受到干扰的情况如今可能更加普遍。
数据显示,程序员平均每天只有两小时能排除干扰、专心工作。程序员也承认,干扰对自己的影响很大。微软公司的一项研究表明,62%的程序员认为思路被打断后再找回工作状态相当不易。
那么如何解决这个问题呢?
作者提到可以通过以下三步来尽量减轻干扰的影响
- 保存心智模型: 这一块作者说的并不清楚。当然也可能和翻译有关系。不过在这一块最后,作者提到了一个也算是有用的方法吧,那就是:“如果打断你的不是立刻就要回复的消息,那么可以先不进行回复”。不过总感觉说了和没说一样。
- 改善前瞻性记忆: 前瞻性记忆指的是 关系到将来而不是过去的记忆。比如我们常说的
TODO,依靠TODO来明确我们以后要做的事情,以达到有条不紊的目的。这个我是深有体会的,我在做 前端私教训练营 的时候,都会为未来的工作设置“微信提醒”。这样的提醒,总可以明确的告诉我,我要在什么时间跟哪位同学交流哪些问题。 - 标记子目标: 把一个大目标拆解成多个小目标。每个小目标的时间就会被缩短,这样可以最大程度的减少被打断时引起的心智负担。
第十二章:设计和改进大型系统
无论是使用了再多的设计方案,当项目升级、迭代的越来越多时,那么代码都会“屎山”代码。这是一个必然的过程。设计方案和规范起到的作用是延缓这个问题出现的时间。
第十三章:对程序员进行试岗培训
人人都知培训好,但是在目前的这个大行情之下,很多的企业已经不再关注试岗培训了。企业更需要其实是一个进来就能直接干活的人。所以目前国内的 试岗培训越来越少,试岗却越来越多 。
最后两种没有进行太多的介绍,是因为最后两章的内容,确实不太适合国内的情况。所以没有必要在这里浪费大家的时间。
总结
那么到这里咱们这本【程序员超强大脑】就算是看完了。没记错的话,我是在 23年8月立的 flag,这都 24 年了才给大家兑现。这个故事告诉我们 flag 真的不能随便立。
有很多同学问题:“Sunday 老师,讲书的这个事情你会继续做下去吗?”
我在这里给大家一个肯定的回答:“讲书系列的视频,我 会 继续录制下去的。”
23 年对于很多同学而言,并不容易。愿大家 24 年可以都可以一帆风顺,砥砺前行。
我是 Sunday,咱们下一次再见咯~