Weekly#14
Hi, 欢迎来到第 14 期的周刊 ヾ(´∀ ˋ)ノ
不知道你是否喜欢这样的周刊内容?如果有什么想法欢迎留言或者 email 给我。
随着 订阅的 RSS 增多,每周需要处理信息的时间也变多了,渐渐地感觉时间不太够。
平时工作日下班回到家就挺晚的,没有太多大片的时间。
到了周末,也有不少的事情需要处理,补觉,打扫房间,做饭…有时还会外出一趟,剩下用来写东西的时间就不多了。
上周尝试把电脑带去公司,利用午休时间写写博客,但是半小时左右的时间,也不够用,而且不午休,下午精神也不太好。
以前处理信息,是先将一堆想看的链接记录在一个文件,然后抽空看(或者没空干脆就不看),觉得感兴趣的,或者有用的,就将链接简单记录到对应的笔记中。
但是作为周刊,如果简单记录一下链接,随便写几句话,感觉有点敷衍。
对于周刊,我会先完整阅读文章,然后发现有趣的部分整理出来,也许还会添加一些自己的想法。
相比直接放在笔记中什么时候有空再看,整理周刊的形式倒是强迫我去消化文章内容,收获会比直接整理笔记更多,但是写完周刊,我还得整理到笔记中。
或许我需要调整一下自己的信息处理流程。
我希望先记录在笔记中,相比给别人看,更重要的是方便自己查找,在我需要的时候,或者在我突然想到曾经看过的内容时,能找到相关的资料。
整理笔记的时候,也按照周刊的做法,先去消化好文章,然后整理自己的想法。
笔记记录完成后,每周再拉取一周的变更,将有意思的再整理到周刊中。
后面尝试一下吧(´・ω・`)
News | Article
State Of CSS 2024
可以了解一下当前 CSS 的趋势,新的语法,学习资源。
对 CSS 改变比较大的功能主要是:
不过我用的很少,主要是浏览器兼容性不是很好,或许可以在一些个人项目中试试。
mac programming for dummies (1999)
作者重读了一遍很早以前买的《Mac 编程傻瓜》,多年回头看,发现里面依然有各种问题,但是最终他还是按照书里的内容完成了一个程序。
因此,我把 Mac编程傻瓜 放在书架上,以提醒自己。挫折、困惑和坚持。兴奋、创造、个人计算。
这也提醒我,永远不要把自己看得太重,因为无论我在过去 25 年里学到了多少东西,这句话永远都是真理:我第一次学习编程是从一本傻瓜的书中。
Writing system software: code comments.
作者认为注释是重要的,并且对注释进行了分类。
之前在 Weekly#11 中分享的 文学编程 也是类似的观点,要反转代码和文档/注释的关系,让文档变成主角。
Weekly#12 中也分享过类似的话: we can say that writing code is sharing the experience of understanding the requirements/implementation.
总而言之就是要提高代码的可读性,为以后读代码的人着想(这个人很可能也是自己),提供多一些信息,减少别人阅读代码的认知负担。
编写注释对于生成良好的代码至关重要,因为这样的代码从长远来看是可维护的,而且在修改和调试过程中,其他人和作者都可以理解。
并非每个人都这么认为。许多人认为,如果代码足够扎实,注释是没有用的。
他们的想法是,如果一切都设计得很好,代码本身就能记录代码在做什么,因此代码注释是多余的。
我不同意这种观点,主要有两个原因:
1.许多注释并不解释代码在做什么。它们解释的是你无法从代码所做的事情中理解的东西。
通常,这些缺失的信息是代码为什么要做某个动作,或者为什么要做一些显而易见的事情,而不是其他感觉更自然的事情。
2.虽然逐行记录代码在做什么一般不会有什么用处,因为只要读一读就能理解, 但编写可读代码的一个关键目标是降低读者在阅读代码时的工作量和需要考虑的细节数量。
因此,对我来说,注释可以成为降低读者认知负荷的工具。
- FUNCTION COMMENTS
- 函数注释的目的首先是防止读者阅读代码。相反,在阅读注释后,应该可以将某些代码视为一个黑盒子,应该遵守某些规则。
- DESIGN COMMENTS
- 函数注释 "通常位于函数的开头,而 "设计注释 "通常位于文件的开头。设计注释基本上说明了某段代码如何以及为何使用某些算法、技术、技巧和实现方式。它是对代码中实现内容的高层次概述。
- WHY COMMENTS
- 为什么注释要解释代码做某些事情的原因,即使代码正在做的事情非常清楚。
- TEACHER COMMENTS
- 教师评论并不试图解释代码本身或我们应该注意的某些副作用。相反,他们教授的是代码运行的领域(例如数学、计算机图形学、网络、统计学、复杂数据结构),这可能是读者技能范围之外的领域,或者只是因为细节太多而无法从记忆中回忆起所有细节。
- CHECKLIST COMMENTS
- 有时由于语言限制、设计问题,或者仅仅是由于系统中自然产生的复杂性,不可能将某个概念或界面集中在一块,因此代码中有些地方会告诉你要记住在代码的其他地方做事情。
- GUIDE COMMENT
- 引导注释的作用只有一个:照看读者,帮助读者处理源代码中的内容,提供明确的分工、节奏,并介绍您将要阅读的内容。指南注释存在的唯一理由就是降低程序员阅读代码时的认知负荷。
- TRIVIAL COMMENTS
- 琐碎注释是指阅读注释的认知负荷与阅读相关代码的认知负荷相同或更高的指导性注释。
- DEBT COMMENTS
- 债务注释是硬编码在源代码本身中的技术债务声明。FIXME、TODO、XXX、"This is a hack" 等都是债务注释。一般来说,这些注释并不是很好,我尽量避免使用它们,但这并不总是可能的,有时与其永远忘记某个问题,我更愿意在源代码中加入一个节点。
- BACKUP COMMENTS
- 备份注释是指开发人员对某些代码块甚至整个函数的旧版本进行注释,因为她或他对新版本中操作的变更缺乏安全感。
注释就像是橡皮鸭调试,只不过你不是在和橡皮鸭对话,而是在和代码的未来读者对话,他们比橡皮鸭更可怕,而且会使用 Twitter。
你可能认为写注释是一种不太高尚的工作形式。毕竟你会编码!
但是,请考虑一下:代码是一组语句和函数调用,或者不管你的编程范式是什么。
老实说,如果代码不好,这些语句有时并没有什么意义。
注释要求始终有一定的设计过程,并从更深的意义上理解你正在编写的代码。
此外,为了写出好的注释,你必须提高自己的写作技巧。同样的写作技巧也有助于你撰写电子邮件、文档、设计文件、博文和提交信息。
我之所以写代码,是因为我有一种分享和交流的迫切感。我喜欢写注释,就像我喜欢写代码一样。
Naming Conventions That Need to Die
作者例举了一些应该摒弃的命名,像是普朗克常数,这种以发现者的名字命名的,如果对于相关领域不熟悉,就不知道是什么。
更好的是用几个名词和形容词描述清楚,通过名字就让人知道大概是什么东西。
一个好的名称应能传达一个基本概念的精髓,通常是通过几个精心挑选的名词和形容词。
例如,广度优先搜索和深度优先搜索的信息量非常大。
如果我们称它们为 "Zuse's method" 和 "Tremaux approch",除非我已经是一名科学历史学家,对每位发明者的各自领域了如指掌,否则根本无法表达出这两种方法的任何信息。
编程中也需要注意良好的命名,还是那句经典名言:
There are only two hard things in Computer Science: cache invalidation and naming things.
Use data that looks like data
在自测的时候,往往需要造数据,无论是接口的,还是页面上输入的。
但是为了偷懒,我测试时,输入的更多的一些无意义的内容,例如名字我会图方便,输入 1111 等。
问题是,这些随便输入的数据,当需要去调试的时候,容易让你分不清是什么,那么多个 1111,什么是名字,什么是地址,什么是备注?
所以,对待测试数据,也应该像代码一样认真对待,注释,文档也是如此。
什么是代码,什么是数据,是用户输入的数据?是运行时生成的数据?应该一目了然。
你在测试,你在调试。你最不希望的就是在查看日志、错误信息或正在试用的用户界面时分不清什么是什么。
数据应该在你看第一眼就能告诉你,你看到的是自己输入的数据,还是默认值,或是系统中漂浮的其他东西。
That's Not an Abstraction, That's Just a Layer of Indirection
一个抽象概念的好坏,取决于它能否掩盖其背后的复杂性。想想真正伟大的抽象,比如 TCP。
尽管 TCP 建立在不可靠的 IP 协议之上,但它能帮助我们假装拥有可靠的通信渠道。
它承担了纠错、重传和数据包排序的复杂性,使我们不必如此。
这就是伟大抽象的标志。它让我们在操作时,仿佛底层的复杂性根本不存在。
我们利用它的好处,而抽象则让我们看不到、想不到那些困难的东西。
但是,那些糟糕的抽象呢–或许更准确地说,那些伪装成抽象的间接层呢?
这些“抽象”并没有隐藏任何复杂性:它们往往只是增加了一层,而这一层的意义完全来自于它应该抽象的东西。
想一想函数上的一层薄薄的包装,它没有增加任何行为,却增加了一层额外的导航层。
有句名言:"所有的抽象概念都会泄露"这是真的。无论多好的抽象,最终都会遇到需要了解底层实现细节的情况。
下一次当你使用抽象概念时,请扪心自问:这样做真的能简化系统吗?还是只是多了一层间接?
明智地使用抽象,记住–如果你没有真正隐藏复杂性,你只是在增加复杂性。
Where web components shine
一篇分析 WebComponent 的优缺点的文章。
顺便这里有一篇 WebComponent 的实践:Hyper-responsive web components
Please support “skip to main content”#
通过在页面最开始(尽可能靠近开头 <body> 元素的位置)添加 Skip Links,可以帮助那些使用键盘操作的人,是一个好的无障碍实践。
我也在博客添加了 Skip Links,如果你按 Tab 键,当 focus 到 Skip Links 时,就可以方便地跳转。
Help us choose the final syntax for Masonry in CSS
不久的将来,就能用上 Masonry 布局了,一种像是砖块一样参差不齐的布局,很适合图片墙,文章墙之类的场景。
现在对于语法应该怎么定义还不确定,回想自己在组件开发时,也会纠结提供什么样的选项,数据结构是什么,怎么样才是比较好用的,也是挺纠结。
W3C (World Wide Web Consortium) 工作组如何决定的呢,他们有自己的设计原则,然后基于设计原则做判断。
文章中他们基于设计原则,详细讨论了采用什么语法会更好。
每当出现类似这样的严重分歧时,向前迈进的最佳方式就是站在 30,000 英尺的高度来看待问题–讨论现有选择的更大影响。
换句话说,就是尽可能多地重复使用已有的语言,并在使用过程中进行再利用。尽量简单。简单易学。不要多此一举,创造出不止一种做事方法。
文章看下来,感觉复用 Grid 布局的语法,添加一些关于 Masonry 的语法会更好,你觉得呢?
Why I’m skeptical of rewriting JavaScript tools in “faster” languages
现在很多前端库都在用 Rust,Zig,Go 等其他语言去重写,因为重写往往都得到了比较好的性能表现。
作者提出了不同的看法,他觉得重写性能好,可能是因为这些坑已经踩过了:
然而,这些工具并不一定因为使用了更快的语言而更快。
它们之所以更快,可能只是因为:1)它们在编写时考虑到了性能;2)API 表面已经确定,因此作者不必再花开发时间修补整体设计。
你甚至不需要编写测试!只需使用以前工具中的现有测试套件即可。
他认为 JS 之所以性能没有其他语言好,是因为 JS 没有很好地利用 Bytecode 和 JIT(Just-In-Time compiler)。
- Bytecode
- 是 JS 编译后的字节码,如果缓存命中了,直接读取字节码,就不需要重新编译,这样性能就会提升。
- JIT
- 通过在运行过程中监控代码并发送需要优化的热代码(重复频繁运行的代码),编译成机器码,也会让函数执行更快。
作者还有一个担心,如果 JS 生态都用 Rust,Zig 等替换,到时一个 JS 开发者碰到 Rust 的错误,就可能没辙了。
前阵子看到的 JS0/JSSugar: the tooling will continue until morale improves 也是类似的观点,
Google 提议将 JS 分成 JS0 和 JSSugar,JS0 由引擎实现,JSSugar 让 Webpack 等构建工具转换成 JS0,
这可能会导致以后写 JS 必须得用构建工具,对于那些不熟悉构建工具或不想依赖构建工具的人而言就会比较无力。
我想如果你在谷歌工作,那是对的。
但我怀疑大多数开发者并不是在科技巨头工作的专业人士,而是尽力在一个令人困惑的工具生态系统中进行爱好者。
如果我们放弃将他们简单的代码直接发送到浏览器,他们将来还有什么希望放下那些工具呢?
Accountability sinks
在《无责任机器》中,丹·戴维斯认为,组织形成了“责任沉没”,这些组织吸收或模糊决策的后果,以至于没有人能对此直接负责。
举个例子:
一家酒店公司的高层决定减少清洁人员的数量,因为这能改善某个资产负债表上的数字。
后来,当你试图办理入住时,房间还没准备好,接待员也无法告诉你何时能入住;
他们可以提供一张代金券,但你需要的是一个房间。
没有人可以投诉,也无法与那个遥远的领导沟通,告诉他们你的计划被搁置了。
责任被吞没在一个空洞中,永远消失。
如果把这两个框架结合起来,就可以得出这样的结论:要对某件事负责,你就必须拥有改变它的权力和理解你这样做的目的是什么。
如果以后都是人工智能做的决定,那出了问题,找谁去问责呢?
为什么善良可以解决一切事情?
保持善良是内心的一种看世界的状态或角度。
保持善良是一种看世界的心态吧,友好待人,多些宽容,多些换位思考,多些理解。
但保持善良也不是任人欺负,想起王尔德《忠实的朋友》的故事,汉斯老实得被磨面师害死了,太不值得了。
之前看得一篇关于开源的文章 (Setting expectations for open source participation) 也有类似的观点,就是保持善意:
当你把应该被视为善举的行为扩大到所有行为时,就会产生一个有趣的效果,那就是当事情没有发生时,没有人再有理由生气或沮丧。
虽然您仍然有权期望受到善待(这是您对他人的善意所应作出的反应),但一旦您放弃了对即将发生的事情的任何预设,事情对每个人的压力都会大大降低。
而当压力减少时,人们往往会有更多的动力去帮助别人,因为整个局面对所有参与者来说都会变得更加愉快。
The weird history of the barcode
关于条形码的历史。目前的一种趋势似乎是要将条形码替换成二维码。
然而,尽管条形码无处不在,大多数人却不屑一顾。
弗里斯说:“条形码成功的最大证明就是,我们从未想过它们。”
What We Do Filmmaking Process
迪士尼动画电影的制作流程。
这个微妙的“••• ”图标或许比你想象的更重要
“更多”图标意味着选项更多,但又不会占用额外空间。
它们充当导航指南,让用户放心的轻点一下,即可获得更多功能。
...
有横向的和纵向的。
- 横向排列相对于纵向,给人的感觉更积极
- 横向占据空间比纵向多,有的时候空间比较少的时候,可以考虑用纵向
- 横向可以用于主要页面的更多,纵向可以用于次要页面的更多,形成主次
- 考虑页面的清晰/简介,是否和其他类似元素存在重叠,决定使用什么元素
设计师必看|大屏里的指尖奥秘
手机上的一些单手操作例子。
现在手机上的单手操作都是类似的,用户已经形成了习惯,如果自己实现的时候,要注意保持用户交互的一致性,避免增加用户的认知成本。
Tutorial
What Makes a Font Accessible? A Designer’s Guide
关于如何设计无障碍字体的教程。
JavaScript Guidebook
又一个 JavaScript 教程,先收藏着,以后有需要再翻翻。
Code
Fun with Custom Cursors
一些自定义指针的实践。
Solving Background Overflow With Inherited Border Radii
一个实用技巧,设置 border-radius: inherit;
让内部元素继承圆角,这样 background 就不会溢出了。
比在父元素使用 overflow: hidden;
要好,能避免一些 overflow 裁切的问题。
<style> .Card { max-width: 20rem; border: 2px solid black; border-radius: 2rem; } .Inner { padding: 1rem; background-color: pink; } </style> <div class="Card"> <div class="Inner">Some content</div> </div
<style> .Card { max-width: 20rem; border: 2px solid black; border-radius: 2rem; } .Inner { padding: 1rem; background-color: pink; /** 设置内部元素,继承圆角 */ border-radius: inherit; } </style> <div class="Card"> <div class="Inner">Some content</div> </div
Responsive TOC leader lines with CSS
书里的目录包括章节和页码,章节和页码之间一般会用 "…." 去填充空白,方便读者对应章节和页码。
文章讲述了如何实现这样的目录,同时考虑页面的响应性。
| <-- max available width --> | .page ↴ ┌─[ .chapter ]────────────────────────────────────────────┐ ┌─────┐ │ ┌─[ text ]───────────────────────────────────────────── │ │ │ │ │ "The first line of my very very verrrrry long chapter │ │ │ │ └────────────────────────────────────────────────────── │ │ │ │ ──────────────────┐ ┌─[ .chapter::after ]───────────────┐ │ │ │ title overflows" │ │ free space for the dot leaders │ │ 123 │ │ ──────────────────┘ │ (overflow limits to .chapter box) │ │ │ └─────────────────────┊───────────────────────────────────┊ └─────┘ ┊ »invisible dots land« ┊ └┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┘
Cool Bit
Smarter than 'Ctrl+F': Linking Directly to Web Page Content
你可以在页面选中一段文字,然后右键选择 Copy Link To Highlight ,将链接分享出去。
对方打开链接,就能看到你高亮的部分,这样对方就能很直观看到你想他看的部分。
一个很有用的技巧,Chrome 支持比较好,Firefox 最新的版本也支持了。
这周的周报里一些 Source 我都是这么引用的,你可以点开看看ლ(´ڡ`ლ)。
(引用英文的链接都不长,但是引用中文的链接都会很长,应该是中文被转义了。)
[YouTube]How is this Website so fast!?
作者分析了 McMaster-Carr 为什么用起来那么流畅,尽管网站用的技术比较老旧,但是开发者还是在背后做了很多优化。
他们的网站看起来很旧了,但一旦你用过几次,为你的特殊应用找到一些特定的零件,你就会发现他们的网站绝对是用户体验设计的黄金标准,你可以如此快速地进入并找到你需要的确切零件。
Morse Transmitter
用耳机发送 Morse Code。
如果你想学习 Morse Code,这里还有一个练习网站: Welcome to the daily Morse code challenge。
World's most performant DOM-based table
自称是世界性能最好的基于 DOM 的表格,不过确实挺流畅的。
Tool | Library
图片分割器:智能切割,创意无限
em..分割成 9 宫格,或许发朋友圈的时候有用?
Frame0
一个用来制作原型的应用,组件都是手绘风格的,它的理念是:
Focus on the idea. Don't waste time on style and layout.
因为是手绘风格,所以你可以不用那么注重低保真,而是把注意力放在想法表达上。
Pure Landing Page
可以用来找找 Landing Page 的灵感,看看别人是怎么做的。
以前还看过一个教程:如何制作落地页:保姆级实操指南。
jj (Jujutsu)
A Git-compatible VCS that is both simple and powerful
一个版本管理工具,兼容 Git,不过还处于开发阶段,可能存在一些不稳定的功能。
有人分享了它的使用体验: Jujutsu (jj), a git compatible VCS。
Emoji-Fallback.js
Provide support for emojis on ALL web browsers!
一些话
但是,高级工程师不能仅仅依靠技术技能。
他们也是具有远见卓识的建筑师,能够超越眼前的任务,设计出可扩展、可维护的系统。
他们的决策会对多年后的项目产生积极影响,展现出只有丰富经验才能具备的远见卓识。
他们已经掌握了成为有效导师和领导者的软技能,不仅能指导初级开发人员编码,还能指导他们驾驭复杂的软件开发环境。
Software Engineer Titles Have (Almost) Lost All Their Meaning
很多人害怕写作,认为写作有门槛,但我不这么认为。
我认为只要会思考,就会写作;只要能和人正常沟通,就会写作。
写作只有把文字变成作品被品味被评价才是一种有门槛的艺术。
我们受学校教育的影响,把写作完全视作一种文学艺术,才让人对写作感到害怕。
却没有人教育我们,写作是一种思维的工具,写作可以帮助我们思考。
我们其实可以只为自己写作,它是没有门槛的。
把写作视作和自己对话,你就会发现写作也就是那么一回事儿。
和自己对话需要遣詞造句吗?不需要。
需要遵循什么文章结构吗?不需要。
When you’re starting something new, the most important thing is knowing what to learn.
需求只来自你对用户的了解, 但是需求不来自: 1. 需求不来自调研; 2. 需求不来自分析; 3. 需求不来自讨论; 4. 需求不来自竞争对手。
When you read, you are reading the writer’s words
But when you write, you are reading your soul
我不知道最终会有谁读到这篇文章,但这就是博客的全部理念,不是吗?
在不过分超出能力范畴的情况下,先做出承诺,再逼自己完成这件事。即使一开始感到不安,也不要轻易拒绝新的机会。
2023 年,来自 the University of Texas and Riverside 的研究人员估计, 在微软数据中心训练 OpenAI 的 ChatGPT3 大型语言模型耗费了约 70 万升新鲜饮用水。
此外,在一个典型的聊天会话中,每 10-50 个回复会消耗约 500 毫升水。
…努力只能算得上愿望实现的充分条件…
Music
这周依然推荐方大同的歌,推荐你听听 2011 年香港演唱会的 Love Song,或许你也会被现场感动。
演唱会后面的几首歌我都挺喜欢,从《Rosy》一直 《Wonderful Tonight》,都挺温柔动听的。