MoreRSS

site iconkily zhou修改

博客名:臨池不輟。爱思考哲学的前端。
请复制 RSS 到你的阅读器,或快速订阅到 :

Inoreader Feedly Follow Feedbin Local Reader

kily zhou的 RSS 预览

Node.JS 作者 Ryan Dahl 的故事

2025-10-02 08:30:00

今天我想来聊聊 Node.js 的作者 Ryan Dahl(ry),前不久在它的一个演讲主题上了解到了一些关于他的故事,结合我自己的一些认知,我想 ry 的故事对于我们是有所启发的,无论是编程、工作还是生活方式。

像 ry 这样的程序员,我觉得工程师更符合他的 title,Node.js 是在2009年5月28日 发布 0.0.1 版本的,已经有 16 年的历史了。在这期间除了一些对外的技术类型的分享和演讲之外,很难找到和他相关的资料。但是这并不妨碍我们从他的作品和这 16 年间做的事情去了解他。

这篇文章会顺着 Node.js: The Documentary | An origin story 的时间线总结和归纳下 ry 的经历。

早些年 ry 是纽约北部的一名数学研究生,并且准备攻读博士学。它在视频中讲到,他虽然喜欢数学这个领域,但是实际上他并没有做更多看得见的、能实践的事情。这和我们认知的数学这门学科是一致的。他说他想做一些事情是与人类正在发生的东西相关,然后他就退学了。

ry-gf.png

退学后他在 Craigslist(类似当年中国的黄页网站,百姓网之类的) 上找到了他的编程之路,当时他应聘了一家滑雪板公司,做一些营销网站,当然这并不是一些看起来很有意思的事情。他把注意力转向了更抽象的事情上,他使用 Ruby on Rails 实现了整个网站,发现它很慢,然后他就研究 nginx 模块,比较底层的 web 技术栈。

接着他遇到了自己自己的女朋友,并随她女朋友一起去了德国,在科隆生活了大约两年,因为科隆消费比较低,租房每月只要 400 刀,这让他有足够的空间和时间去思考一些事情,去做一些自己想做的项目。并且他认为这是一段20多岁时的愉快的时光。

V8 发布的时候他就在考虑一个问题:JavaScript 与非阻塞。他在视频中也说到:这是一个在正确的时间思考正确的事情。

ry 呆在科隆的那段时间大概从 2月~10月的时候全职开发构建了第一个版本的 Node.js

Isaac Schlueter(izs) 在 Node.js 首次发布的时候是 yahoo 的工程师,还因为当时的工作总是要在 PHP 和 JavaScript 之间切换而感到沮丧,所以他会考虑为什么不使用 JavaScript 来做服务端的编程语言。当时也有一小部分人在试图将 JavaScript 实现成服务端编程语言,比如:Server.js,Jaxer,RingoJS。在当时 JavaScript 服务端能力已经有一些端倪了。Node.js 的出现有点出乎意料。Isaac Schlueter 说他认为 ry 选择 JavaScript 并不是因为他喜欢 JavaScript,而是因为 JavaScript 很合适

ry 说在选择 JavaScript 之前也研究了像 Python,Lua, Haskell 这样的编程语言。但是有一天和朋友坐在一起,突然之间就有了一个想法:“我靠 JavaScript,就应该是 JavaScript”。就在那一刻他非常清楚的确定了是 JavaScript。

当时在其它编辑语言中基本上都有了一定的范式。但 JavaScript 还是空白。

非阻塞IO的实现在其它的编程语言实现都会有很大的阻力,比如在 Python 中打开一个文件,大家已经习惯了使用下面的同步IO范式来实现:

with open("filename.txt", "r) as file:
	content = file.read()

所以使用 Python 来实现显然不是一个好的选择,因为这意味着 Python 开发者需要转换编程习惯。

后来越来越多的人知道了 Node.js,但是当时还没有包管理系统,izs 就创建了 NPM,最开始 NPM 的源代码是一些 shell 脚本,很多代码来自于 Yinst - yahoo 内部用的的包管理器。

ry 在 JSConf EU 上的主题演 Ryan Dahl: Original Node.js presentation 首次对外公开 Node.js,可以看出来当时的他还是很青涩、很紧张的。

ry.png

ry 说他只是 JSConf 上的一个普通演讲者,但是他已经为了这个演讲提前几周做了充分的准备。每个人都在演示自己的 玩具 项目,而只有他写的 Node.js 是真正严肃的项目。它在现场展示了一个使用 Node.js 构建的 IRC 频道服务器,当场在同一个网络的观众也可以链接进去发消息。

在 Node.js 创建的初期,程序员还没有一些很好的沟通工具,没有 slack, discord, github 的功能还非常的原始,也没有任何持续集成的工具。大家都通过电子邮件将补丁发给 ry,然后手动合并到代码仓库中,ry 就像是个人工的 CI 工具一样,手动打补丁,手动测试。

JSConf 演讲之后 ry 还在科隆,当时已经有很多公司联系他说对他的项目感兴趣。他就飞到旧金山去和对方聊,也是为了这个项目能继续下去找一些资金支持。最后 joyent 提出了好的方案。joyent 是一个云服务提供商,他们想在自己的服务上运行 node 应用程序。

然后 ry 就搬到了旧金山,全职从事 Node 工作。他在 joyent 时除了 Node 没有任何其它工作。

Bert Belder 在一家初创公司,为建筑公司做自动化,他们必须进行一些复杂的计算,他们为前端实现这些计算功能。使用 Node.js 在一夜之间完成了他们的数据迁移工作。他为解决了 node 在 window 平台上运行的问题。Bert Belder 是 libuv 的作者,libuv 是 libev 的集成者,它解决了不同平台异步 IO 模型的封装和实现。node 0.4 之前 libev,一个 select 的包装,很老而且速度一般,只支持 macOS 和 Linux,还不支持 window。

在早期的开发过程中 ry 通常会引入了破坏性变更,比如:v0.0.3中把 sys 模块更名为 util。然后大家都惊慌失措了。

npm 是随着 node 0.0.8 版本同时发布的,但是下一个 node 版本上就没法用了。所以社区都想要知道 node 第一个稳定版本什么时候发布的时候。ry 说 1.0 版本还没有完整的路线图,因为这是一个很遥远的版本,目前还是专注于 0.0.6 版本,需要重新设计管道,然后再重新审视这个问题。

工作了 1 年后,joyent 想从 ry 手里买下 Node.js 这个项目。ry 说他还不确定 joyent 从他手中买下一个开源项目是好事还是坏事。当然 ry 知道 joyent 的目的的:joyent 是想管理这个项目,拥有商标、网站并且利用这个来推广他们的公司。ry 同意了这笔交易,因为他当时并没有因此失去些什么,所以他感觉很好。社区当然会有很多质疑,大家会觉得这对 Node 意味着,如果 joyent 变坏会怎么样?但是因为 ry 和 joyent 达成的协议是 node.js 还是会以 MIT 许可来发布源代码,实际上 joyent 买的只是一个名字。

后来 Node.js 的运营和一些管理上的工作 joyent 会决定,ry 把管理上的一些事务交给了 Isaac 并逐渐退出了 Node.js,后来 Isaac 对于运营 Node.js 的工作感觉到无聊和厌倦,工作交给 TJ 后退出。

最后 joyent 也不怎么把精力投入到 node.js 中,node 代码仓库的迭代明显减少。更新明显放缓,社区觉得 Joyent 对新功能(比如 ES6 特性、模块系统、协程方案)的推进过于保守,维护效率不高。

Node Forward, 讨论 node 未来的发展,核心维护者向 joyent 提出开放式的管理。

mikreal 分叉 node.js 起名 iojs。

joyent 换 CEO Scott Hammond 与核心开发者沟通。

三个月后

双方就 Node.js 项目治理模式达成一致:技术方向和技术决策真正由社区驱动的,从而确保项目在真正的共识模式下运行,而不代表任何组织特殊利益的模式。io.js 成了一个重大的警告,让 joyent 意识到他们在node 中拥有的东西实际上危险之中。

同时建立 Node.js Foundion。joyent 说为了我们的利益,我们不需要成为 Node 的管理者,但是我们需要 Node 作为一个统一的项目

node 4.0 发布合并了 io.js

2019 年 Node.js Foundation 和 JS Foundation 合并成 OpenJS Foundation。

在这之后 ry 淡出 Node.js,他花了几年时间在其它兴趣上:机器学习,分布式系统,几何,摄影等。

2018 年 JSConf EU 回归,发表演讲 10 Things I Regret About Node.js,此时的 ry 看起来更潇洒、时尚。甚至不像是一个上技术分享会的程序员的形象,虽然还是很紧张。

ry-deno.png

在他淡出的这段时间,前端或者说 Node.js 社区已经有很大变化了。Node.js 似乎也有一些瓶颈和问题。

但在这个视频中他坦率地讲出了自己在 Node.js 中的一些设计「缺陷」:

  • 没有使用 Promise
  • 安全性
  • 构建系统(gyp)
  • node_modules
  • require("module") 时不写 .js 扩展名

可以看到 ry 总结的这些问题非常精准的戳到了当时 Node.js 的一些核心问题。我想经历过那个时代的程序员一定会记得:callback hell, node_modules, node-sass, gyp, fsevent...

有意思的是实际上在 Node.js 出现之间 JavaScript 回调地狱并没有那么臭名昭著,因为 Node.js 出现后使用了异步 IO 的模型,刚好回调函数的模式可以和异步 IO 很好的融合,写起来很自然。但是使用的太多了就会另人感到不适:

callback hell

doSomething(function(result1) {
    doSomethingElse(result1, function(result2) {
        doAnotherThing(result2, function(result3) {
            doFinalThing(result3, function(result4) {
                console.log('Done:', result4);
            });
        });
    });
});

Promise

doSomething()
  .then(result1 => doSomethingElse(result1))
  .then(result2 => doAnotherThing(result2))
  .then(result3 => doFinalThing(result3))
  .then(result4 => console.log('Done:', result4))
  .catch(err => console.error(err));

async/await

async function main() {
    try {
        const result1 = await doSomething();
        const result2 = await doSomethingElse(result1);
        const result3 = await doAnotherThing(result2);
        const result4 = await doFinalThing(result3);
        console.log('Done:', result4);
    } catch (err) {
        console.error(err);
    }
}
main();

为了解决这些问题,他又发明了一个新东西:Deno - 一个基于 V8 的安全 TypeScript 运行时。

ry-deno-intro.png

deno 的出现可以说解决了 Node.js 所有设计上的重大缺陷问题,并且引用了 TypeScript,这使得使用 JavaScript 编写严肃的程序、系统成为可能。

值得注意的是,早期的 deno 底层是 Go 实现的,在后来的迭代中换成了 Rust,其中一个重要的原因是:JavaScript 是一门高级程序语言,是有垃圾回收的。而 Go 也一样,如果用 Go 实现那 deno 的运行时就会有两个垃圾回收器。ry 在后来的演讲中说:有两个垃圾回收器那样不对。虽然不是不可以,但是出于程序员的直觉两个垃圾回收器是不对的。

2021-4 成立 deno 公司

2022-6 Deno 完成了红杉资本领投的2100 万美元A 轮融资,总融资额达到2600 万美元,目标是开发一款商业产品 Deno Deploy

我的博客也托管在 deno deploy 上,以前用过 github pages, hugo, hexo 等,但是多少还是有点问题,刚好因为自己对 JavaScript 熟悉所以一直用免费版的 deno deploy。

——

这就是 ry 到目前为止做到的事情,当然故事还在继续。毫无疑问 ry 是一个成功的程序员、工程师、老板、Node.js 社区的精神领袖。我想从我自己的视角总结几个关于他的问题,这会对我们的工作、生活有所启发。

在这之前我想有几个时间点在技术领域是非常重要的:

  1. Linux 2.5.44 内核发布于 2003年6月26日,引入 epoll 大概 22 年前
  2. Nginx 发布于 2004年10月4日,大概21年前
  3. V8 JavaScript 引擎发布于 2008年9月2日,大概 17 年前
  4. Node.js 首次发布于 2009年5月28日, 大概 16 年

epoll 在 Linux 内核中之前,大部分网站使用的服务器还是 apache。apache 服务器的模型是多线程的,一请求一线程,显然这是无法应对大量并发访问的。因为启动一个线程会有很多开销,假如:启动一个线程需要5MB的内存,那么 1G 内存的机器上就最多只能开 200 多个线程,也就意味着一台 1G 内存的电脑只能服务 200 个 HTTP 连接(用户)。

但是随着互联网的发展,大家在网上的活动越来越频繁,这才出现了大量的高流量网站,社交媒体、BBS、搜索引擎、博客、个人网站等等。一时之间网络流行起来,大家在上网的时候越来越多。

Nginx 就应运而生了,他抛弃了 apache 线程驱动模式,使用事件驱动,异步非阻塞模式。Linux 下使用 epoll 实现异步 IO。Nginx 设计之初就解决了 C10K 问题。对于 静态文件服务、反向代理、负载均衡应用场景展示出了极高的性能。

我第一次使用 Nginx 的反向代理的时候,感觉就是:哇,这是什么魔法,太神奇了。只需要一行配置就可以让 A 网站展示 B 网站的内容。

注意在这个时间节点,大概 2004 年的时候不没有任何编程语具备异步编程模型的默认范式。当时异步编程概念是很早就有了。我这里讲的默认范式可以理解成指定编程语言中的编程风格或者说语言内核。比如:Java 的 OOP,Haskell 的 FP,现在 JavaScript 中的 Promise/async/await。

显然 ry 知道 Nginx 的核心原理,他是想把异步 IO 这种模型植入到某个编程语言中去,你可以想象的到这个想法的威力有多大吗?Nginx 是一个应用层软件引入异步 IO 后有这么大的性能提升,如果把这个模型引入到一个编程语言中,那整个编程语言都是基于异步 IO 的,性能会比同步的高出很多倍,人们可以轻易的编写出高效的程序。

就像前文中讲到的, ry 也研究过其它编程语言,没有合适的。但是无意中发现 JavaScript 很合适。

V8 的出现让 chrome 浏览器在 2008–2015 年期间,市场占用率从 0 到了 53%,让整个 WEB 加速,也让 PC 时代到达了发展的顶峰。那段时间每年都会出现新的流行的东西。网络聊天,论坛BBS,个人博客,微博,团购,电商。整个互联网是一片朝气蓬勃的样子。

我自己写博客也是当时受到了韩寒、徐静蕾新浪博客的排名的热度影响。

可以想象当时大家对浏览器一种什么样的需求,大家似乎感觉不太到浏览器有多重要,但是对于 JavaScript 来讲却是暗流涌动。彼时的浏览器可以说是万花齐放:

  • 遨游Maxthon - 用户用的最多的是它的书签功能,登录完书签永远可以保留
  • 世界之窗-轻量级,号称“小巧、快速”,核心是 IE 内核,完美的兼容性
  • 搜狗-主打双核
  • UC-主打移动端
  • 火狐
  • Opera
  • ...

最终,技术上异步IO模型被验证了正确性,V8的出现也逐步把 JavaScript 拉向了正经严肃的编程语言行列(当然目前看来很多地方还不够严肃)。然后 Node.js 的出现就显得很水到渠成。

当然如果只看到这些泛泛的趋势、苗头其实并不能很客观的解释最终为什么是 JavaScript 而不是其它语言,因为在我的职业生涯中从事 JavaScript 编程占大部分时间,所以我还是想从编程语言的角度来总结下为什么 JavaScript 比较合适的原因。

主要原因有三个:

第一:JavaScript 还很年轻(很初级)

选择 JavaScript 不是因为 JavaScript 这门语言好,而是因为 JavaScript 这门编程语言还很初级,当时的 JS 还处于脚本语言的范畴,人们用它来编程基本上很多时候是调用浏览器这个宿主环境提供的一些 API,比如:DOM/BOM/XHR 等。但是严肃的讲当时的 JavaScript 还只是一个玩具脚本语言。

第二:JavaScript 语言特性丰富

JavaScript 语言是一门看起来啥功能都有的语言。我们可以看看《JavaScript 权威指南》中的一段关于 JavaScript 的介绍

JavaScript 是面向 web 的编程语言,是一门 高阶的(high-level)、动态的(dynamic)、弱类型的(untyped)解释型(interpreted)编程语言,适合面向对象(oop)和函数式的(functional)编程风格。JavaScript 语法源自 Java 和 C,一等函数(first-class function)来自于 Scheme,它的基于原型继承来自于 Self

可以看出来 JavaScript 啥特性都有,但实际上啥特性都不好用。这就给 ry 一个选择 JavaScript 的理由,这门编程语言上没有什么特别好的东西,才不至于它有一些默认的范式而导致语言层面引入异步 IO 会产生很大的阻力。

第三:JavaScript 的核心,单线程事件驱动

这个是 JavaScript 这种脚本语言被设计之初就确定好的,因为脚本语言就是用来屏蔽底层复杂性的。你很难想象如果 JavaScript 实现上提供多线程,同时又跑在浏览器里面它会把浏览器搞成什么鬼样子。

事件驱动这个好理解,因为 JavaScript 被设计出来就是要处理用户 UI 界面上的事件的。比如:用户点击按钮,提交表单。

单线程事件驱动这一点可以说是技术上最合适的一点,因为当 ry 把这个理念和编码方式与异步 IO 集成后,编写出来的代码非常简单而且容易理解。

我们可以看看 Node.js 官网上一直存在的代码片段,实现一个简单的 HTTP 服务器:

import { createServer } from 'node:http';

const server = createServer((req, res) => {
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.end('Hello World!\n');
});

server.listen(3000, '127.0.0.1', () => {
  console.log('Listening on 127.0.0.1:3000');
});

这个实现就是 Node.js 的精髓:异步非阻塞 IO。8 行代码实现一个 HTTP Server,性能可以和 Nginx 媲美,这已经足以惊艳所有人。

异步编程的这种范式正在植入到 JavaScript 这门语言中。自从 JavaScript 有了这种最佳实践,异步编程的标准模型:async/await 也慢慢渗透到了其它编程语言中,Python/Rust 都有所借鉴。当然异步编程在其它编程语言里面也有实现,但是都没有在 JavaScript 中那么自然。

技术界总有一些人靠自己的本领过上了衣食无忧的生活,但是过上衣食无忧的生活这并没有什么意义,因为人生的意义总是在于创造一些东西而非享受一些结果。我想 ry 是这样的人,要不然他也不会在卖了 Node.js 得到钱之后走上一条结束自己人生的路。也正如他在自己人生关键时刻做出的选择一样:做看得见的、能实践的事情

我一直认为任何事情,方向对了+人对了,那结果就是自然而然的成功。就算不成功也没有什么遗憾。

所以 Node.js 成功了,Node.js 的成功在于它开创了一个新的纪元,他为原来在前端的开发者打开了一扇门,这里大家才意识到:原来前端也可以写后端,也可以写服务端,前端也可以在更多领域实践,可以和更多的领域一起竞争。

参考资料:

React 随想

2025-09-28 08:30:00

看到 HN 上关于 React 的一些讨论,也想说点我的看法。


那么让我来总结下React的优缺点:

首先谈到 React 的优缺点就不可避免的涉及到 JavaScript 这们语言的优缺点,再扩大一点讲就是前端的优缺点。

React 出现的原因是要解决 UI 的复杂度问题,简单理解成 HTML 和 JS 的复杂度问题。为什么?HTML 不是很简单么,有什么复杂度?

HTML 是用户界面的复杂度,JavaScript 是工程层面的复杂度。前端程序员的使命就是解决这两者之间存在的复杂度,从而构建高效的 GUI 软件。

而在所有的 GUI 软件中,HTML 界面是最变化多端的,它代表着可以给用户提供各式各样的花哨吸引眼球的功能和视觉冲击,从而解决某些心理诉求而不是功能需求。然而工程层面从来不关心这些东西,工程层面只关心效率、稳定、成本。

其次 JavaScript 这门语言本来是有很多缺点的,最大的缺点我认为是设计和实现上的不一致性,设计是 tc39,但实现却是各个主宰浏览器的大公司组织。一个很简单的问题是:ECMA-262 规定所有 JavaScript 的数字类型都是 double 双精度浮点,而实现上根本不可能这么做,因为如果那样的话在 JavaScript 中数字类型占用的内存将会翻倍。有人可能说性能不重要,但是真的不重要吗?

最后,让我来讲讲 React 的优缺点:

React 最好的设计在于解决了 HTML/JavaScript 之间的复杂度,它使得 JavaScript 在构建大型前端工程中时,分散的复杂度的治理集中到了 JavaScript 层面,这就很有意思了,因为我们总是想让 HTML/CSS 这类看起来像是程序语言的东西真正的具备“编程能力”,因为只有这样,通过 JavaScript 去构建工程时,代码层面才会是一致的。

React 最大的缺点在于它的定义和它被使用的场景出现了偏差,React 从来就说它是一个 library 而不是 framework,但是当我们用它来构建前端应用的时候,我们总是想要一个 framework 而不仅仅是一个 library。一个 library 的内核是函数式的思想这没有问题,但是人们会受到影响,当 React 的用户越来越多,而 React 本身又推崇函数式的范式,那社区就会有不正的风气。这种风气可能对语言生态产生间接影响,比如 tc39 decorators proposal,天知道这个提案什么时候才会被通过,大家觉得不需要 class 了,所以这个提案就不会有继续下去的动力了。

然而实事上讲 React 它对自己的定义一点都没变,它的设计方向也很一致。问题是它承担了很大量级的受众优势,但它从没考虑过这其中的责任。当然这个责任也不是 React 一个 library 能承担的。

相信数字还是相信直觉

2025-08-16 18:59:45

想必很多人都有这个体验:上学的时候写作文,要求 800 字。结果是写到 750 字的时候就已经词穷了,所以为了达成目标,就要东拼西凑,最终把这个数字凑到 800 个。支撑你这么做的理由只有一个 —— 就是要交作业

如果你刚好在一家商业公司上班,应该会更有体会。领导要做决策,数字是一个很好的决策理由。数字往往是“事后诸葛”,我们试图通过分析大量的数据,去总结成功的因素,总结方法论。最终应用到我们的实践中。但是分析数据,得出数字,往往只能证明一些事情,并不能创造新的事物

长此以往,当你做任何事情前会先习惯性的问自己:有什么价值,要花多少成本,最终有多少收益。因为当你开始对比、开始计算时结果可能已经有了答案。计算的过程只是无限的趋近于你心里想要的那个结果而已。极端的时候,甚至可能为了结果去凑数、造假掩盖一些东西。但是台面上还是要讲数字,因为数字很有说服力。1比0大,2比1大,这么简单的道理谁能不知道呢

这个道理可太简单了,简单到不用你去思考,你也无法反驳和批判。甚至容不得你去质疑,哪怕一点点的质疑都会变成对事实的不尊重。最终剩下的只有冷冰冰的数字和事实

相反的,直觉往往没有那么多的副作用。我们可以看看一些大人物,成功人士。他们在做决定的时候往往都是靠直觉而非数字

乔布斯在创造 iPhone 的时候不会提前的算好,iPhone有出货量,能带来多少收入。他只是觉得手机那么小的东西上面放个键盘不对,也不能说放个键盘到底哪里错了,只是觉得不对而已。

马化腾在创建 QQ 的时候,他只觉得在网上聊天很有意思,人和人不用见面就可以交流。并不是非要见面才能聊天

...

直觉是人类与生俱来的一种能力。直觉是个人的,是不会自我欺骗的。如果直觉不对是可以被纠正的。当一个新的词语第一次被你听到,你会觉得:我以前从来没有听说过。然而在接下来的日子里面这个词又频繁的出现,这时你才意识到,其实你认为的第一次可能已经是第N次了,只是那一次被你发现、关注到了

数字却是大众的,是可以被编造的。如果说 60 分是及格分,那 59 分和 60 分的区别是什么?及格和不及格、对和错,这应该是天壤之别。但是直觉上讲差别并没有那么大,所以1分之差真的有那么重要吗?这反问句似乎也会让人产生一种错觉就是1分之差不并没有那么重要。直觉就是这么神奇,当你开始思考时,直觉就出现了

我想有一天,计算机能算出任何我们想要的数据,可以计算出来所有的成本和受益。那我们是不是就可以躺在床上,手里拿上一个只有两个键的键盘:。我们只做决定好像就可以了。但是如果做出一个决定是如此的机械和简单,那我们似乎就真的可以被机器替代了吧。

小时候总觉得 800 字很多,写完这篇文章的时候习惯性的算了下。1158 ^_^

我做程序员这十年

2022-05-19 18:59:45

今天是个特殊的日子,十年前的这个时候我根本无法想像我可以在一家公司呆十年,坚持做一样工作十年之久。于是我就想要写点儿东西来回顾一下这十年的发生在我身上的事情。工作、学习、编程、生活。

起因

我接触电脑的时间比较早,大约在小学五、六年级的时候就有了微机课。似乎是邓小平爷爷的一句「计算机要从娃娃抓起」的原因,学校采购了一批微机。每周都有一节课,大家都很期待。课堂上老师会教我们打字,在漆黑的屏幕上敲击 DOS 命令。

那个时候只感觉电脑很神奇,似乎就是电视机和游戏机的合体。

直到后来上了初中,有了互联网,有了网上聊天,有了局域网对战游戏。似乎电脑的用处又多了很多。

我人生中的第一台电脑是上高中时我三伯从深圳带回来的。上面装的是 Windows 98,后来有了 XP。但是我发现那台电脑太旧了硬件根本不支持安装 XP。这让我很失望,因为当时的 XP 看起来非常赏心悦目,比起 98 那种棱角分明的黑白灰风格漂亮多了。

直到现在我还记得,当时我专门进了一趟城,买了两张 3.5 英寸软盘。打算去网吧下载几首歌曲用软盘复制回家里的电脑上面。因为那时候家里面的电脑还没联网。因为3.5寸软盘容量只有 1.44MB,一首 mp3 格式的歌至少 3M 起,完全放不下。后来专门下载了另外一种音乐文件格式叫 wma,比 mp3 有更高的压缩率。一张软盘可以复制差不多两首歌曲。虽然那时候已经有能放 mp3 的随身听了但是折腾这个还挺有意思的。

接着就是玩 QQ 空间,那时候比较流行空间装扮。网上有很多看不懂的代码,复制到 QQ 空间的自定义模块里面去就会有很多神奇的效果。Flash 动画,一首动听的音乐,一张漂亮的图片。每当我去看别人的空间时总感觉:人家的空间怎么装扮的这么漂亮。

高中毕业后我就从城里买了一本年度版本的《电脑报》,用来排解那段无聊的夏日。当然我看完后,其实真正懂的只有一半不到,很多专业的用词,根本不知道是什么意思。当时就觉得会安装操作系统就已经非常利害了。

也就是由于这本电脑报的启蒙,让我在放假期间报志愿时选择了计算机软件这个领域。我几乎是很轻易的就做出了这个选择,选什么专业这个问题上家人们并没有强行给我建议。我当时只知道一点:世界首富比尔盖茨是干这个的,所以我觉得我要是做这个应该也不会太差。

上了大学就开始学软件专业相关的知识,实际上真正学起来的时候也是很枯燥,理论上的东西对于我来说总是让我感到望而生畏。但是好在我因为我是这个专业的,所以还保持了这个专业的一些基本操守。比如:我喜欢写博客、搭网站、倒腾服务器什么的。写博客是因为当时也流行这个,当年韩寒和徐静蕾博客就很出名。我觉得自己也可以写写,但是毕竟咱是搞计算机的,怎么着也得弄个专业一点的,完全是自己设计的网站那种。而不是用新浪博客这种托管的博客站点。最重要的一点是:托管的博客站点他们提供的控制博客主题样式的功能限制太大,而且也没法自定义域名。这就让我觉得没意思,因为我就想做一点和别人不一样的事情。

然后专业课上也学习了网页制作相关的技术。用 Dreamweaver 拖图片到表格布局中去,拼成一个网页,这是当时书上教的。但是我上网上查过之后发现这种模式已经过时了,当时流行一个网站重构的概念,使用 CSS 来进行页面设计,会让你的页面更加炫酷。

当时我就知道有一个网站叫做 CSS Zen Garden,它的主题思想就是提供一套 HTML 代码,然后只允许你使用 CSS 对页面的元素进行布局、设计。上面有很多非常棒的设计作品,只是你很难想像这是基于同一个 HTML 设计出来的。这也是 CSS 的魅力所在,限制你的并不是技术,而是你的创意和想法。

我大概就是这样进入到前端这个领域的。

经过

大学还没毕业,就赶上了当时互联网的一股浪潮 —— 电子商务,其实就是网上卖东西。那些年几乎每年都有一样新的互联网概念出世:论坛、聊天室、博客、微博、团购、电商。似乎是中国互联网百花齐放的时代。哦,对了。那时候社交网络是 MySpace,Twitter 还没流行起来。不一样的是当时这些网站都可以访问。

通过写博客、逛论坛。我被一些创业的老板盯上了,还没毕业就联系我想让我去北京上班。我当时想的是先毕业再说。只是当时其它同学好像都很着急找工作了,但是我一点都不急,最后一个学期了我还常常自己玩自己的游戏,自己学自己的东西。好像在我的意识里从来就没有找不到工作这种设定。后来我才知道当时一些同学早早的去找工作,在西安一个月七八百块钱就不错了,还不管吃住的那种。

后来毕业后我就来到了北京,这个让人充满向往的城市。先后呆了两家公司后,来到了现在的公司。基本上我换工作的原因只有一个,就是我做的事情限制了我的成长。我感觉学不到什么新东西了我就会离职。

刚开始都是只写 HTML/CSS,小公司一般会这个就够了。但是稍大一点的公司,就需要我会写 JavaScript,那时候才感觉至少水平到了 JS 这一层才有了编程的概念。会 JS 就能去大公司、正规公司,也能学到很多未知的技术。

后来在公司一直做了大概有4年的前端工程师,那段时间里是我写代码频率最高的一段时间,因为业务需求多,前端要做的事情也很多。那时候流行模块化、组件化、工具自动化这些概念。慢慢的 Node.JS 也出现了,前端有了要开始要跨越和后端之间的那条界线的趋势。整个行业中前端工程师的整体素质也有了很大的提升。再后来你会发现很多做后端的同学转做前端,反而做的更好了。因为大家认识到了前端的重要性,前端不再是一些表层的东西。前端变成了一种和用户沟通的形式。

此时我也发现了自身的一些瓶颈,很多东西无法深入下去。有的概念几乎全是空白,于是我就去看一些更专业领域的书箱资料。学习了 Python, 了解了 Ruby,补上了操作系统相关知识点。后端可以说也入门了,此时我只需要一个实践的机会。

也是机缘巧合,由于公司变动调整,我转做了一年的 Java 工程师。这让我对于无论是编程语言层面,还是系统框架层面都有了新的认知,把我之前学习的零散的东西都建立成了一种体系。并且当我维护过十万行级别的代码的时候,我才对技术有了更加深刻的认识,对技术才产生了敬畏之心。

我在考虑问题的时候不再只看到我自己的那一面。而是技术上从系统层面看,功能上从产品层面看,管理上从项目的层面多角度的去理解一个软件产品生命周期。因此,我似乎具有了一种跨跃式的思维模式,从技术层面看清产品的本质,从产品层面理清楚技术的突破点。

直到现在,虽然我冠有前端工程的虚名。但事实上这并没有限制我做的事情。因为我从来不给我自己打标签。相对于这些名义上的东西来讲我更关心我正在做的具体的事情,是我做的这些事情定义了我是一个怎么样的人,而不是那些标签。

结果

现在回看这十年间的我。北漂、地下室、租房、买房、成家、养育,这些关键词都成为了我经历中的一部分。我从来都没有想像过我能在北京这座城市实现这一切。

从感情上讲我是很讨厌北京这个城市的,因为他没有生活,只有拼搏。但是从理性上讲,我现在拥有的几乎所有世俗意义上的成就都是北京这个城市给我的。因为她公平,所以我才有机会。

我在公司这十年里面,几乎每年都会晋升。我和公司的关系已经不是简单的雇佣和被雇佣关系。而是相互成就、相互欣赏。

虽然不知道未来的路还能走多长,但是有句话说得好:

但行好事,莫问前程。

顿悟

许多人都会因为自己工作或者职位的原因而给自己画个圈圈。我是一个程序员,程序员就是怎样、怎样的。

我在刚开始的时候,出于一种自恋式的骄傲我自己也这么认为。我觉得程序员是不善言辞的、有思想的、专注的一个群体。当我尝试用一些美好的词语去描绘他们的时候,我发现这并不完整,之于我自己更是如此。

但事实上程序员也是普通人。

他们有细腻、感性的一面
他们也有果敢、理性的一面
他们有或专业或普通的能力
他们有或高雅或低俗的需求
他们豪放、他们矜持
他们独一无二

不为别的,只因为他们是芸芸众生中所有普通人中的某一个完整的人而已。

如果说非要我总结几句身为程序员的行事格律,那我觉得应该是以下几句话:

  1. 关注问题的本质,但不只关注本质
  2. 给出方案前务必要讲清楚问题是什么
  3. 不要给自己打标签,别人行,你不行
  4. 不要使用一样你不了解的技术
  5. 从高层理解设计,从底层研究原理
  6. 问题和结论不在一个维度上时没有讨论的意义
  7. 分清楚什么是事实认知什么是情感认知
  8. 生活不是诗,但你是一个诗人

ten-years

从《如梦令·昨夜雨疏风骤》读出人生三重境界

2022-05-15 17:59:45

昨夜雨疏风骤,浓睡不消残酒。试问卷帘人,却道海棠依旧。知否,知否?应是绿肥红瘦。
—— 李清照〔宋〕

看山原是山 —— 一切景语皆情语

开头两句「昨夜雨疏风骤,浓睡不消残酒」是交代场景。昨天晚上下着稀疏小雨,伴着大风。睡了一觉醉意仍然没有消退。浓睡不消残酒,此处用「浓」字形容沉睡,浓本来是形容液体的,「浓睡」,「残酒」等字眼这就已经奠定了一大早她本身内心还未化解开的某种忧怨。她这才意识到院子里面的海棠花经历了风雨交加的夜晚,不知道情况如何了。

于是有了对话「试问卷帘人,却道海棠依旧」。这两句中的「试」、「却」被认为是最为精妙的内心情景描写。

「试」是因为李清照还不确定海棠花全部凋谢了,她内心还暂存了一点希望,哪怕只是一点点,就是这一点点支撑着她一大早醒来就急切地想知道院子里的情况。

「却」是因为「海棠依旧」肯定是不可能的,李清照读了很多书,经历了多少春夏秋冬,她不可能不知道春去夏来之时,下雨会带走海棠花。

虽然李清照不情愿承认海棠花凋零的事实,但是理智让她发出了对卷帘人的嗔叹:

「知否,知否?应是绿肥红瘦」。知道吗,知道吗?这个时节,现在的院子里应该是绿叶茂盛,红花凋零的时候。「绿肥红瘦」是全词最为绝妙的四个字,绿代表着夏天、树叶,红代表着春天、花开。「绿肥红瘦」则表达的是春去夏来海棠花凋零,青春、时光即逝的伤感。

看山不是山 —— 最懂她的卷帘人

通常多数人认为在这首词中,卷帘人只是不走心的说了一句「海棠依旧」。但是恰恰相反,我觉得在这首词里面「卷帘人」才是点睛之笔。

卷帘人的回答「海棠依旧」充满了智慧,卷帘人有着极高的情商,或许只有她懂李清照。

我们从「试问卷帘人」这句开始分析,此刻李清照很想知道风雨过后院子里面的情况。

卷帘人回答「海棠依旧」有两种可能:

其一,李清照当时问的就是「院子里面的海棠花怎么样了?」,卷帘人说:「海棠依旧」 其二,李清照的院子里面几乎全是海棠花,她问院子里的情况,卷帘人自然知道她问的是海棠花,于是说:「海棠依旧」

这两种可能,无论是哪种都至少说明了李清照非常关心海棠花如何了,她关心海棠花是因为她不想看见海棠花凋零而因此伤感,但是理智又告诉他时间(海棠花凋零的)到了,再美的东西都熬不过时间。只是她心里面还有那么一点点念想,或许还有那么几支还未凋零呢?

可以想象,此时如果卷帘人告诉他院子里的真实情景,那该有多残酷。难道卷帘人要告诉她:你那些心爱的海棠花都被昨天夜里的大雨打的凋零不堪、破败不堪、全部死掉了。那李清照岂不要哭死?

所以说卷帘人很懂李清照为何尽兴、为何伤感。卷帘人天天和李清照在一起,她的一个表情、一个神态、一颦一笑一忧愁都在卷帘人的眼里...

如果我是那个卷帘人,我是段不忍心告诉李清照真实情况的,那将是无比残忍、无比无情的人才说的出来的。

试问没有卷帘人「知否」何在?

试问没有卷帘人「绿肥红瘦」又将何在?

看山还是山 —— 何谓海棠依旧

事实上如果没有卷帘人的存在,这首词似乎也能讲得通。我们理解的「试」和「却」两个字之间存在一种矛盾感。「试」表示不确定,心存的期许。「却」表示确定的转折对比,事实的无奈。

此语境更像是一位说梦的痴人被「海棠依旧」点醒了一般,又好像是一种痴人说梦般的暗自言语。

这首词音律是那么的完美,没有一个多余的字。节奏时急时缓、时快时慢、时抑时扬、时而押韵、时而叙述,如绵绵细流一般任意思绪流淌。如此只可能是一个人的自言自语,才能一气呵成。

所以其实根本没有卷帘人,只是李清照自言自语罢了。因为孤独的人都喜欢旁若有人般的暗自言语~

那么「海棠依旧」究竟意味着什么?

你难道不觉得「海棠依旧」这四个字充满了智慧吗?智慧到根本不像是由卷帘人口中说出来的。要么是李清照自己杜撰的,要么就是上面分析的那种可能——卷帘人有着超人的智慧。

或许李清照只想到了当下的绿肥红瘦,伤感于青春、时光的即逝。还在伤感困惑的她被卷帘人口中的「海棠依旧」所点化。

卷帘人淡淡地说道:「明年海棠花依旧会开,你又何必如此的感伤。春去春会回来,又有谁人绕过了时光?」

「海棠依旧」的真正意思不就是所谓的天之道吗?客观规律,不以人的意志为转移的道。

不管你信不信,海棠花每年都会开,不会因为你的怜惜海棠花就晚几日凋谢,也不会因为你的期许海棠花就提前开放。

此时,「海棠依旧」到底是出自谁口已经不重要了。

因为明天太阳照常升起,因为明年海棠依旧。



悟道休言天命,
修行勿取真经。
一悲一喜一枯荣,
哪个前生注定?

袈裟本无清净,
红尘不染性空。
幽幽古刹千年钟,
都是痴人说梦。

所谓的设计系统

2021-10-25 10:20:04

是的,我今天就想批判一下那些披着「设计(系统/语言)」外衣的研发工程师。

设计系统(Design system)这个概念应该是从国外最先有的。它的定义是:

A Design System is a set of interconnected patterns and shared practices coherently organized
设计系统是被统一组织起来的一系列紧密关联的模式和可重用的实践。

国内的组件库只有 Antd 在推出的时候声称自己是 一个 UI 设计语言,虽然当时我还不知道什么叫做设计语言,什么是设计系统。但是从工程师的角度我知道它就是 一套组件库

一直到近两年,越来越多的前端团队以设计系统为排面推出自己的组件库的时候,我就觉得有些不对劲儿了。

哪里不对劲儿了?我在想我们实际上做的事情不就是设计了一套组件库吗,为什么要把设计放在前面。这似乎传达给我们一种信号:

我们应该是设计先行?我们应该优先做设计角度取舍。
相反的,工程层面实现那就应该向设计方向妥协?

我想并不是这样的,或者说不应该是这样的。

设计 永远是最上层的,它们关注的用户的外在、外观感受,它是感性的、多变的,没有唯一标准的。你很难想象用一套设计系统满足所有人的需求对吧?因为我喜欢蓝色,你喜欢红色这是不需要解释的。

工程 永远是最底层的,它关注事物内在的东西、自身属性,它是理性的、不变的,有迹可循的。所以工程层面追求的是一致、复用和效率。没人喜欢一个相同的组件在不同的实现上有不一样的 API。

在「前端工程师」这个职位名字中,「前端」是个形容词,「工程师」才是名词。

我们得先是工程师再是前端对吧。当我们不由自主地和设计靠拢时,思维模式也受到了影响,似乎只有设计思维才会关注到那些形容词。

当我们在设计一套组件库的时候会遇到很多不一致的情况,在我的经验里面:

来自与设计和实现的不一致要多于纯粹实现层面的不一致。

当我们设计的组件库需要考虑到跨端情况的时候,我们的组件库应该有一套一致的 API、一致的命名规则。但是从设计角度去决策的时候这件事情变得非常困难。

比如说:日期选择 这个组件,移动端通常叫做 DatePicker,这个词强调的是用户的动作(pick),在 PC 端通常叫做 Calendar,这个词强调的是组件本身的特征。

但是我们在工程实现层面真他妈不需要这种差别,它就是一个日期选择组件而已。

还有:按钮 组件的类型属性,有的是表形的:default/info/warning/error,有的是表义的:primary/secondary/danger

再一次,我们在工程实现层面真他妈不需要这种差别。它就是一个简单的按钮而已。

造组件库的人没有想清楚这件事情,用组件库的人却得承受这种不一致。那什么组件库的设计者们没想清楚这件事情?

因为他们的思维也被设计系统带偏了。一味的追求设计上的形式化的一致,却忽略了工程上逻辑的一致。

当这股邪风吹来,没人会在意组件库的工程化设计,没人在意它好不好用,每个人都想复制粘贴快速实现一套组件库,然后再披上设计系统的外衣,为自己的似锦前程添砖加瓦...