所谓做工和品质

做工很多时候和“情怀”一样,是个说不清的事儿。大概由于习惯了软件行业,所以我从前一直有这样一个观念:差不多的原材料/元器件、差不多的设计、差不多的功能,最后弄出来的东西应该也差不到哪儿去。尤其是一些“简单”的产品。所以对于这些产品,不必盲目追求什么大牌、做工好,国产高性价比的也不错。

就在今天,我买了不到三个月的 VSonic VSD1S 耳机坏了,和上一副 VSonic GR02 坏掉的方式一样——耳机单元脱胶(上一副好歹还用了一年)。想起买之前在一些论坛和网店上看到的评论,不是这儿脱胶就是那里断线……这时候我才知道,为何 VSonic 要如此强调他们的售后保修(有问题一定修、一定换),不是因为对品质有信心,而是知道品质不稳定,为了留住顾客,才不得不推出大力度保修服务。就像现在的锤子和最初的小米一样……

现在想来,也许是和软件接触太久的缘故,总是容易把复杂的事情简单化。在工业社会,看起来再简单的东西背后都暗藏玄机,即使是一个塑料件,也需要选择塑料原料、铸模、倒模,即使是一颗螺丝,若是手工安装也很有可能少上半圈;而在资本主义的市场之下,很多“玄机”归根究底就是和钱有关系。有多少钱,决定你能采用什么工艺,是请普工手工胶合,还是机器人自动化作业,甚至干脆一体成型无需胶合;有多少钱,决定你能采取什么程度的品控,测试进行到什么程度、是否要淘汰掉略有瑕疵的产品;有多少钱,还决定了你能买得起什么样的原料,商业社会里,给多少钱办多少事,原料的良率、品质波动都直接由你的出价决定。

让我对这些生产过程的复杂度有一个直观体验的其实是这一年来和 FPGA 、 Arduino 打的交道,即使是这么“高端”的硬件开发套件,开发调试起来相比软件还是有诸多不便。程序里, a = 1 就是1;可是在硬件中,导线把两端连上可能并不能让两端信号一致,也许会遇上冲突,也许压根线松了、断了……不仅错误的可能性(及其所在的层次)大大增加,还缺乏可靠的调试工具。如此想想,那些更加底层的硬件设计生产更是困难重重了。

总而言之,单就这次的事件来说,即使有不少品牌溢价,国际大牌的品质的确还是要比国内的“玩家品牌”高出一个档次的……以及,购买国内这些号称“良心售后”的产品时,千万记得把发票多留几个月,很有可能是要用上的……

Git 认证凭证管理

尽管使用 SSH 真是相当方便,但总有些时候不得不使用 HTTP/HTTPS 之类的 git 后端——时常是由于网络环境限制导致。这时每次输入用户名密码真是相当烦心。从 1.7.9 版本开始, git 提供了 credential helper 来消除这一烦恼,且现在在各个平台下都有相当合用的 helper :

Platform independent

git 自带了两个平台无关的 helper : cache 和 store ,前者在内存中缓存凭据(可以设置有效时间),后者将凭据明文储存在硬盘上,除非文件系统有启用加密,否则不推荐使用。简单提一下前者的使用方式:

git config --global credential.helper cache
git config --global credential.helper "cache --timeout=3600"

以下平台相关的 helper 推荐使用 git 1.8.3 以上版本!

Read More

About Shadowsocks

我用 shadowsocks 很长时间了,最开始是从 V2EX 的这个帖子开始:发一个自用了一年多的翻墙工具 shadowsocks 。还记得那个时候这个小工具还只是一个900行左右的自用脚本,现在已经发展成功能齐备、拥有多种语言和平台 port 的社区项目、大家族了。虽然我认为它的发展在某种意义上偏离了一开始的理念——简单的架构,任何程序员都可以自己修改协议和加密部分,从而使得拦截变得困难——现在的 shadowsocks 毫无疑问已经形成了自己的一套协议,若要享受数量庞大的 ports ,自行修改协议变得不切实际了起来;然而更加丰富的功能、更稳定的程序、更快的速度也的确是为更广泛的群体提供了一个非常方便的工具。今天就简单说一下这么长时间以来的一些使用经验,以及其他一些废话。

Read More

MySQL 的大小写敏感问题

昨晚刚刚被一个课程大作业坑了,特地写一篇博客来记录一下。提问: MySQL 是大小写敏感的么(包括关键字和标识符)?刚上过数据库系统原理课的好学生们一定会记得这句话:“ SQL 是大小写不敏感的”。而有过一些实际开发经验的人可能会说:“表名是大小写敏感的,其他不是。”很遗憾,两个答案都是错的。

Short version: it is implementation dependent.

对于 MySQL 来说,所有的关键字都遵循 SQL 标准,大小写不敏感,而表名是否敏感则依赖于一个叫做 lower_case_table_names 的设置项,它的默认值根据操作系统而不同,具体如下(文档):

  • Windows: 该值默认为1,表名在存储、查找过程中都被转化为小写,因而是完全大小写不敏感的。这与 Windows 的文件系统有关,事实上,你无法在一个大小写无关的文件系统上强制 MySQL 大小写敏感。
  • *nix: 该值默认为0,表名在存储、查找过程都严格遵照给定的大小写,即是完全敏感的。
  • Mac OSX: 该值默认为2,表名在存储时保留大小写,但在比对时全部转化为小写。这和 Mac OSX 的文件系统惯例一致。

所以,当我昨晚从(使用 Windows 的)队友手中接过一个数据库操作不在意大小写的代码时,虽然浑身不舒服,但回想起课上说过的“ SQL 大小写不敏感”(虽然我从没有试过非关键字究竟是不是大小写敏感的),就也没多想。可一跑起来却全是数据库错误,愣是过了好一会才终于怀疑起大小写的问题来……

Arduino IDE 编译生成过程

最近因为一门实训课程的缘故接触了 Arduino 开发。由于有一定的 C++ 基础,所以还是很快上手了 Arduino 提供的开发环境,简单说来就是一个 C++ 工程,所谓的“Sketch”(.ino文件)其实就是 C++ 源代码。然而其中有一点令我很困惑,并最终导致了问题的产生: Arduino IDE 是如何处理源代码中的头文件引用并最终链接整个程序的?

这个问题听上去根本不是问题:不就是和一般的 C++ 一样使用 #include 预编译指令么?顶多最终链接的时候 IDE 做一些自动处理,把用到的模块都链接起来。但如果你用过 Arduino 的 library ,你就会发现它的使用方法不符合 C++ 的规则:库是存放在 library 目录下的一个个子文件夹中的,而使用的时候却是直接 #include 某个头文件,没有指明库文件夹的名字( C++ 的头文件引用是不会递归搜索的)。

Read More

解决 systemd 休眠时无法切断电源的问题

systemd 作为一个功能强大的新一代 init 系统,功能不仅仅限于启动一系列 daemon ,还接管了日志、电源管理甚至部分的用户登录功能。在切换至 systemd 来管理电源后(卸掉了 pm-utils ,改用专为 Thinkpad 开发的 tlp ),我的 Thinkpad T430s 遇到了休眠后无法关机(使用的命令是 systemctl hibernate ,或者是通过 GNOME 来触发)的问题。经过一番搜索,找到了 /etc/systemd/sleep.conf 这个配置文件,简单设置即可 fix 。

这个文件默认是不存在的,需要自行建立,然后在文件中加入以下配置:

[Sleep]
# A fix for unable to poweroff after hibernation
HibernateMode=shutdown

原理是让内核在休眠后使用普通的关机流程(默认是“platform”,即通过 ACPI 进入 S4 之类的模式,在某些笔记本上可能无法正常工作)。具体详情可以 man systemd-sleep.conf 查看。

抱歉由于 Akismet 抽风导致评论困难

不知为何最近 Akismet 抽风,几乎把所有中文评论都当做了垃圾评论,以前没有发生过这样的状况。经过提醒才发现垃圾评论里躺着好几条明显是正常的回复,赶忙拉了出来。这样想来大概已经有正常回复被删除了(扔进垃圾评论1个月救会自动删除,而我之前没有查看垃圾评论的习惯)。最近会稍微多留意一下垃圾评论队列,如果有朋友发现回复以后没有显示出来(我没有设置审核,正常情况下评论后应该会立刻显示的),方便的话请直接邮件联系我或推上给我发 DM (链接见页面顶端)。谢谢!

再次向被误判作垃圾评论的朋友表示抱歉。

华为P6(电信版)简评

春节后想给老妈换一部手机,她之前用的那台 MOTO 实在是太老了,安卓2.2,有很多应用已经用不了了。由于必须要电信和移动双卡双待这样的特殊需求,可选范围小了很多,基本上最近那些热门机型都没戏了。由于预算限制,三星 S4 电信版也被淘汰了。看来看去,就看中了这款争议不小的“国产旗舰”华为 P6 (电信版)。机子已经拿到几天了,这里简单说一下感受。

Read More

Content Security Policy 导致 bookmarklet 失效

近来发现在知乎、 Github 上我最常用的 bookmarklet (书签小工具,就是那种一句话 Javascript 书签)——饭否分享失效了。打开 Console 一看,有这样的提示:“Content Security Policy: 页面设置阻止读取一项资源:已经阻止执行内联脚本。”大概是孤陋寡闻,之前还没听说过 Content Security Policy 这玩意儿,猜测又是和 Cross-Origin Resource Sharing 有关系的什么东西,就做了一番搜索。

CSP 是一个可以限制页面中哪些 src (包括脚本、图片等等)可以被允许的实验性 HTTP Header 。这是 W3C Candidate Recommendation ,而这个是 MDN 上的相关资料。简而言之又是一个 defend by depth 的产物,可以给 XSS 防范再加上一层保险:直接禁止掉 inline script 和 inline eval ,然后给出一个允许加载的资源域的白名单,这样即使有 XSS 过滤漏洞,也无法注入站外的脚本。

但是问题就来了:用户直接在地址栏里输入的 Javascript 应该被允许么? Bookmarklet 应该被允许么? W3 文档这么说:

Enforcing a CSP policy should not interfere with the operation of user-supplied scripts such as third-party user-agent add-ons and JavaScript bookmarklets.

可事实是 Firefox ( Chrome 估计也是)没有正确实现,把 bookmarklet 也给拦截了,同时拦截掉了的还有 Lastpass 这样的插件的 JS 脚本,这也顺便解释了为什么 Lastpass 在知乎首页上无法自动填充的问题。

Github 博客上介绍这个新措施的文章里也提到了这个问题,并且给出了一个“解决方案”——直接把浏览器的 CSP 支持给禁用就好了……

我们是否需要使用框架?

几乎所有领域的编程中,都有“框架”(framework)的出现,在编程语言之上提供了又一层的抽象,实现了一些基础设施,来辅助某些开发过程。就算不是程序员,只要经常安装软件的有心人都会注意到一个叫做 .Net Framework 的重量级框架。现在估计有一半的常用 Windows 软件使用了 .Net 框架,的确大大方便了桌面软件的开发。可能是因为它的确太有用,简化了很多原来很麻烦、不优雅的工作,并且本身体量较大,不容易实现,鲜见有人重复发明轮子。但 Web 领域就不一样了,不管是前端还是后端,都有多如牛毛的各式框架供选,并且还不断有人不满意已有的框架而自己从头来过,甚至最后剥离出一个新框架。也不断有人质疑, Web (或其中某一个方面)这样“简单”的事情,需要用上框架么?或者,需要用上现成的框架么?

Read More