Latest stories

十年回顾

我在两个月前的某测评网站上做了一次 mbti 测试,测试结果是 INTJ 型人格,「内向,直觉,思考,判断」。所以在大多数的跨年夜,或是某些重要的节日,都是一个人度过的。从 14 年开始每次跨年夜要一个人看一部电影,那一年看的是「蝙蝠侠:黑暗骑士」,今年被好友叫去,说是那边组织的有个 party,于是过去,和一群陌生人完成了跨年,期间的大部分时间都在进行着「聚会游戏」,我极少有机会参加这样的聚会活动,但就这样,稀里糊涂的告别了 2019。

从 2010 到 2019 的这个十年,自己个人经历了巨大的变化,往后不知道是否还会经历相似的十年,但在这个时间节点,我有必要通过某种形式,把我的回忆记录下来。

多个项目共享 Webpack

最近在看 @keyframer 的一系列视频,需要用到 webpack 来配置 scss 环境,这就导致了每一个项目都要重复下载一遍 webpack 和相关的所有 node modules,这样很浪费空间。

因此要想办法把 webpack 独立出来,让每一个项目都可以访问到 webpack,一个方法是全局安装 webpack。这里提供另一种方法,想到我们通常使用 webpack 的情景是,在 package.json 里预先定义好

"scripts": {
    "dev": "webpack-dev-server",
    "build": "webpack"
}

然后 npm run dev。我们需要把这里修改一下,让每个项目都统一调用同一个 webpack。

阅读摘要 | issue #3

Program analysis

GitHub 开源程序分析库 semantics,这里的一篇文章科普什么是程序分析 Program Analysis,以及它能用来做什么?

程序静态分析,program static analysis,意味着在不运行程序的情况下,我们可以知道:

  1. 程序运行时所需要多少内存;
  2. 得到所有的 dependencies 并生成相应的 graph;
  3. call graph,所有的函数调用关系;
  4. control flow graph,字面意思,程序运行时的 control flow,比如 if,for 循环这些;

The Designer’s Growth Model

https://css-tricks.com/the-developers-growth-model/

模仿 Grenier groth model, Dennis Hambeukers 提出他的「设计师成长模型」,分为五个阶段:

  1. 第一阶段是 Producers,生产者,仅仅是作为个体,通过不断学习,设计创造好的 artifacts;
  2. 第二阶段是 Architects,对于稍微复杂的项目,进入多人协作领域;
  3. 第三阶段是 Connectors,不仅仅是多人「协」作,而能够真正做到多人「创」作;
  4. 第四阶段是 Scientists,能够应对系统级别的复杂性 complexity,在更高一层级上进行思考,统筹,降低风险,指明方向;
  5. 第五阶段是 Visionaries,skill, mind, toolset,所有一切集大成者,对于策略,组织,领导力又有着自己独到的见解,对于更远的未来有着自己清晰的解读,清晰的 roadmap;

Lazy Evaluation, foldr | 5kyu

关于 lazy evaluation,首先要明白两个概念:call by name 和 call by value:

// Evaluates with call-by-name strategy
1 function callByName (a, b) {
2  if (a === 1) {
3    return 10
4  }
5  return a + b
6 }
// Evaluates with call-by-value strategy
1 function callByValue (a, b) {
2  if (a === 1) {
3    return 10
4  }
5  return a + b
6 }

两个函数在形式上没有什么区别,只是在运行时采取了不同的策略或态度,前者是 lazy,后者是 eager;

> callByName (1, 2 + 3)
> a === 1
> return 10

> callByValue(1, 2 + 3)
> callByValue(1, 5)
> a === 1
> return 10

使用 lazy evaluation,只用当真正需要读取这个变量或 expression 的时候,才会对其进行运算或 evaluate,也就是字面意义上的 call by need。

实现 lazy evaluation 有很多方法,但其核心概念则是 functional programming。即我们把所有的 variable 写成函数的形式,这样的函数通常被称为 thunk:

JavaScript: Semicolon 二三事

由于 JavaScript 拥有 Automatic Semicolon Insertion 这样的机制,我已经很长时间在写 js 的时候不加分号了。但今天碰到了这样的一个情况:

let i = 0

(function test () {
  console.log('hello')
})()

这里会提示报错:

TypeError: 0 is not a function

观察了一会儿,才发现,JavaScript 引擎一定是把第一行和第三行看成一行代码,按道理,第一行末尾应该是要自动加一个分号的。这里如果我们手动加上分号,程序就不会报错了。

let i = 0;

(function test () {
  console.log('hello')
})()

关于 JavaScript 的 Automatic Semicolon Insertion,规则是这样的:

阅读摘要 | issue #2

The #1 Way to Spice Up Your Designs (And Create a More Cohesive Brand)

在 UI 设计中如何更好的使用 motifs (小的视觉元素),既不喧宾夺主,又能体现 UI 设计的 consistency 一致性。在 foundationmedicine.com 网站看到它们将 hexagon 作为它们 UI 设计的 motif,这分别体现在:

  • Logo
  • 空白处的填充,space filling;
  • 字体,GT Sectra,本身就具有六边形结构;
  • 分割线;
  • 诸如 qutation marks 这些小的 文字元素

同样的视觉设计,分析也可用在 The Intercept ,它们选取 command line 的下划线光标作为它们的 motif,在 Logo,字体,分割线等都有体现。同样在 CSS Tricks,则是把「橙黄渐变」作为一种 motif。

Level up your .sort game

关于 JavaScript 中 .sort() 方法的使用。其中提到的几点关键:

  • While many of the ES5 array methods such as .filter, .map, and .reduce will return a new array and leave the original untouched, .sort will sort the array in place.
  • 要想不让 original variable 发生改变,使用 ...
  • Running functions before comparing values,这里存在一个小的 design pattern;
  • 如何添加 tierbeaker,也就是当出现同样值是有没有第二比较规则,这里用到的 reduce 方法。
  • 如何写一个随机排序;

JSON Web Token 的产生和认证

有两种认证方式,一种是基于 cookie 的认证,另一种是基于 token 的认证。后者实现往往是通过 JSON Web Token (以下简称 JWT)实现的。首先要说明一下两种认证方式的区别:

cookie-based authentication 的认证流程是:

  1. 用户填写 credentials,包括用户名,邮箱,密码这些内容;
  2. Server 服务器验证这些 credentials 是否正确,如果正确,则认证成功,创建一个 session 存储在数据库中;
  3. 将这个 session 的 session id 存储在浏览器端的 cookie 里;
  4. 接下来的每一个请求,都会带着这个 session id,Server 在接收请求后也会验证 session id 与 session 是否匹配;
  5. 一旦用户登出,client 端和 server 端的 session 均被摧毁;

token-based authentication:

  1. 用户填写 credentials,包括用户名,邮箱,密码;
  2. Server 服务器验证这些 credentials 是否正确,如果认证成功,则返回一个 signed token;
  3. 这个 token 会被存储在 client 端,大部分是在 localStorage,但也会存储在 session storage 或是 cookie 里;
  4. 接下来的每一个请求,都会带着 token 作为额外的 authentication 信息。
  5. Server 收到请求后,首先 decode 这个 token 并对 token 里的 signature 进行验证;

auto01

为什么会说 token-based 更好:

  1. stateless,也就是不需要再在 server 端保存一份纪录,但 server 端要保存用于签名时用的「secret key」;
  2. cookie 对跨域 CORS 操作不友好,token 则没有这个问题;

iPadOS 使用体验

今早安装了 iPadOS Development Beta 版本,体验了一会儿。因为不太敢拿 mac 升级 Catalina,据说文件系统改掉了。目前 mac 不太敢升,所以 Sidecar 功能暂时还没办法体验。iPhone 变化其实没那么大,也就只有 iPad 可以尝试了。提前做好备份,在苹果的开发者官网 Installing Apple Beta Software 下载安装 Xcode beta,安装完毕要打开运行,这样做的目的是帮助 iTunes 能够识别 iOS13。下载你所使用设备的 ipsw 文件。我是在这里下载的。然后在 iTunes 里更新就行了,注意要提前做好备份。

具体的安装教程也可以参考这个 YouTube 视频

下面按照给我带来惊喜的顺序,来简单谈一下这次的 iPadOS / iOS13。

阅读摘要 | issues #1

Complex life may only exist because of millions of years of groundwork by ancient fungi

在 hacker news 看到这样一则评论:对于 Fermi paradox 费米悖论的一个解释,死去的有机物通过数百万年,在这个星球上形成了丰富的化石燃料。因为这些石油化石资源的丰富,我们才能进入工业时代,才能进入电气时代。但有人反驳,即使没有这些化石,但只要存在了生命,就会有能量源,不管那是什么,就能帮助机器运转。

Why specialization can be a downside in our ever-changing world

作者认为专业化, 10000 小时理论,更倾向于在一个 kind or simple 的环境里发生。而事实大多数人所面临的环境都是极其复杂的, wicked 。重申了行动要优先于思考,并引用了 Herminia Ibarra 的话「We learn who we are in practice, not in theory」。最后,他认为让我们避免陷入自我的 cognitive biases 认知偏见的,是「science curiosity」。

JavaScript async and Promise

非常推荐先看一下参考链接里两个 youtube 视频,分别介绍了 event loop 和 setTimeout 的实现原理,这对于理解 JavaScript 里异步操作实现非常有帮助。其次是关于 Promise object 的手动实现,有一些抽象,因为包含了大量的 callback 函数。这里一定要分清楚,哪些是函数的声明,哪些是函数的调用。

Event loop

JavaScript 是一种 single thread 的语言。既然单一线程,那么在某个时间点,只能完成一项任务。于是

$.get('http://twitter.com')
$.get('http://youtube.com')
$.get('http://google.com')

在单线程下,如果某一行执行所需要的时间太久了,那么余下的的 command 也无法执行,程序就在那一行停滞下来了。我们把这个叫做 blocking。然而事实上,当我们在使用 setTimeout() 函数时,程序似乎不会出现 blocking。

console.log('hi')
setTimeout(() => console.log('there'), 0)
console.log('Welcome!')

// output:
// hi
// Welcome
// there

这里哪怕是设置 delay 为 0s, setTimeout() 里的函数也是在最后才执行,是怎么回事呢?

在 JavaScript 的执行环境中,所有的需要运行的函数是单线程的,按照次序会出现在 call stack 里。而通常,JavaScript 要么在 Browser 里运行,要么在 Node 环境运行,在 Browser 里运行时,会有一整套来自 Browser 提供的 web API,同理在 node 环境里也有相应的 API。 setTimeout() 函数就来自这些提供的 API 中。当我们 declare and call 一个 setTimeout() 函数时,Browser 会生成一个 timer 计时器,计时器的时间达到时, setTimeout() 里定义的 callback 函数会进入到一个叫 task queue 的容器中,此时程序会去检测 call stack 是否为空,当 call stack 为空时,会将 task queue 中最上层的函数移入 call stack 中进行执行。因此本质上来讲,由于有 web API 的加持,最终类似 setTimeout() 函数还是使用了多线程。只不过对于 JavaScript 来讲,一直是执行的是 call stack 里的内容,可以认为一直是单线程操作。

分类

标签