面试题:如何理解加班

前阵子参加 SF 的征文活动 一起分享你的故事,我的文章 我的编程职业生涯 有幸得到大家的支持,最终得奖:汤青松老师的《PHP Web 安全开发实战》。书前两天寄到了,还没来得及细看,也没法写书评,所以想了想,再分享一段职场经验吧。

继续阅读“面试题:如何理解加班”

使用 Webpack 动态打包文件夹

各式各样功能强大的小语言是我厂机器编程的特色,为了让更多的同学提前感受到 DSL 的威力,我们开发了 demo 应用:https://demo.openresty.com.cn/

Demo 里面,需要添加一些范例代码,方便用户直接体验。这些代码,可以通过后端 API 获取,也可以直接编译到前端代码里。目前范例很少,直接打包到一起应该是最简单的做法。

但是如何打包是个问题。经过一些研究,我觉得这样做好:

  1. 负责小语言的同事直接把范例写在项目仓库里,Edgelang 就用 .edge 扩展名,Navlang 就用 .nav 扩展名
  2. 前端在 webpack 里实现一个 requireAll 的功能,把所有代码当成纯文本用 raw-loader 加载进来
  3. 这样添加了代码后,重新 build 一下就好。范例文件可以用 lazy-load 的方式加载

Webpack 提供了一个方法叫 require.context,可以深度遍历一个目录,返回一个 context module,用这个 API 我们就可以动态的加载这个目录下的文件——具体的讲解和参数说明大家看下文档吧,这个部分中文资料不太多,我不太确定译名。我们可以在范例代码的目录下放一个 index.js,负责加载所有代码范例:

function requireAll(r) {
  r.keys().forEach(r);
}

const Languages = [
  'edgelang',
  'navlang',
];

let context = require.context('./edgelang', true, /\.(edge|css)$/);
requireAll(context);
context = require.context('./navlang', true, /\.(nav|css)$/);
requireAll(context);

export default Languages;

然后我们改一下 webpack.config.js 就可以了。

module.exports = {
  module: {
    rules: [
      {
        test: /\.(nav|edge|fan)$/,
        use: 'raw-loader',
      },
    ],
  },
};

不要用战术上的勤奋掩盖站略上的懒惰

前两天,有个同学在群里问一道面试题:

  1. 写一个函数,返回一个长度为5的数组
  2. 数组里的元素都是 2-32 不重复的整数
  3. 需要用递归的方式写,不超过15行

这道题其实蛮简单,而且我觉得出的并不好,不过最后再说,先回到群里。然后就有热心同学动手写代码了,但是他犯了两个严重错误:

第一个错误

我们都知道 Math.random() 会返回一个 [0, 1) 的随机数,我们可以乘上一个数然后取整来获取一定范围内的随机数,比如 Math.random() * 100 >> 0 就能取到 0 ~ 99。那位同学也想到了,但是这次范围不太规整,2~32正好是31个数,跟平时不太一样。于是他可能突然脑子抽筋,先试了 Math.floor,又试了 Math.ceil,都不行,然后,他就用了 Math.round

这是他第一个错误。四舍五入之后,随机数就不再均匀,此时他有很多种选择,但他偏偏选择了一定不对的方案。

第二个错误

然后我就指出“你这种做法是错的”,接着他就犯了第二个也是更严重的错误,他写了个循环,跑100w次,检查结果是否符合预期。

这里的问题在于,首先他只检查能否覆盖到 2 ~ 32,其次他完全没有考虑到概率。

结论

这就是典型的,用战术上的勤奋,掩盖战略上的懒惰。看起来似乎也很努力,响应很及时,实际上纯粹瞎搞。

明明应该先想清楚,或者先查清楚,再去做好的事情。变成了“上来就瞎JB搞”,搞出一个疑似有效的方案,就心满意足。遇到挑战的时候,则顺手抄起一套方案去验证,也不管这套方案的设计思路和覆盖面。

这样做的结果,运气好的时候,勉强不出错;运气不好,事故错误一个不会少。类似的例子,在我们周围不胜枚举,比如 996,不管产品卖不卖的出去,先按住大家把活儿干了再说。看起来为了明天拼拼拼,其实只是老板一厢情愿的豪赌(或者小赌)。

解决方案

不要只顾着埋头苦干,也要学会抬头看路。不要在错误的道路上努力耕耘,赶紧找到正确的道路。

比如找工作。有些同学海投,能投则投,所有都投,然后没有面试机会,回来抱怨说三本没人权。实际一看简历,非常烂,没有重点,没有区分,看不出他擅长什么,能做什么岗位。

准备简历并不简单。

  1. 要找几家公司作为主攻。比如拥有自己的产品、有大牛坐镇、赛道比较喜欢、技术成长空间比较大。
  2. 针对这几家公司的 JD,针对性的修改简历。比如做后台系统,那你就突出 Vue/React 等框架经验;比如做小程序,你就突出小程序开发。
  3. 海投简历也应该根据岗位调整。前端岗位有一些区分度,需要突出不同技术能力和经验。这样做可以让你显得更加适合一些岗位。比如:
    1. 数据可视化:Canvas、SVG、WebGL
    2. JS 框架、语言开发:编译原理、执行基础
    3. 后台等工具类开发:三大框架
    4. Hybrid 开发,比如 RN
    5. 小程序开发:小程序、普适类框架

随便做个简历,乱投,有面试就去面,也不考察公司,最后要么找不到工作,要么找不到好工作,都是典型的“用战术的勤奋掩盖战略的懒惰”问题。

另外,如果一件事是正确的,但是暂时没有收获到正确的结果,那么不要着急变换思路,再想想再看看再查查,排除错误,要在正确的道路上找到正解。

吐槽面试题

这道题出的不好。看得出来想考察候选人是否会使用递归(可能还要考察尾递归优化),但是题目本身不用递归就能做,而且效果更好。其实随便出个归并排序之类的就好了嘛。

总结

我们从小接受到很多歌颂勤奋的教育,所以大家喜欢“没有功劳,也有苦劳”,用勤奋来感动自己。现在一定要明白,闷头苦干是不对的,一定要看请道路,选好方向。

与诸君共勉。

在 Chart.js 的线图里增加竖线

我经常使用 Chart.js 生成图表,无它,名字好记+免费+持续更新。现在主要基于 Vue 开发项目,所以经常使用 vue-chart.js。前阵子遇到一个需求:

  1. 把一组数据画成线图
  2. 用户可以任意点击时间
  3. 用数据生成饼图

那么就需要在线图中画一条竖线,标识出当前时间点。本以为这个需求不复杂,没想到不仅 Chart.js 不支持,包含这个功能的插件因为 Chart.js 升级的关系,暂时没法用。所以只好自己实现。

继续阅读“在 Chart.js 的线图里增加竖线”

三道前端编程面试题

面试题要有区分度。不能太容易,让对方有屈辱感(“看不起人么?让我做这个?”);也不能太难,把所有候选人都干掉,对自己的时间也是一种浪费。其实挺难选的。

很多大公司,因为买方市场,大把候选人排队等着挑,所以干脆把面试题弄得难一些,目的是筛选,只要好的,合适不合适另说。而一些小公司,比如我厂,得到优秀简历的机会本就不多,如果因为面试题设计不好,没法很好的考察候选人的水平,或者让候选人感到不舒服拒接 offer,都是损失。

这里分享我近期总结的三道编程题,对应初中高三档候选人,我觉得很有区分度,大家也可以试试。

继续阅读“三道前端编程面试题”

我厂技术沙龙

其实是我厂老板的个唱……但仍然非常值得看。

近期我厂老板春哥回国,在北京和深圳分别开了一场技术沙龙,介绍他的职业生涯、开发实践、最新成果等等。作为程序员的终极形态,我觉得这两场演讲非常值得有志于把程序员当成终身职业的同学学习。也可以回答很多类似“35岁的程序员应该怎么走”的问题。

先来是北京场:

然后是深圳场:

两场的内容并不一样,可以理解成上下半场。建议顺序观看。

最后说说最近半年来的工作感受。

首先远程工作还是挺好的。虽然光环褪去,负面感受更多更具体,不过对比普通上下班,感觉还是蛮好的。

其次,春哥是很牛的程序员,但作为老板有不少缺陷;公司也同样不完美。不过世上本就没有完美的老板和公司,在 OpenResty,春哥证明了他的想法的确有前瞻性,我们有机会改变未来,所以在这里工作还是很兴奋的。

希望接下来会更好。

浏览器切换中

最近比较忙,博客有些荒废。忙过这阵子再写吧。

接下来的三周,会强迫自己把开发浏览器切到 Firefox,争取从现有项目中找到兼容性问题,并且修复。

再接下来如是反复,Chrome > Firefox > Edge > Safari > Chrome……

以后客户越来越多了,兼容性得多费心了。

下午4点更新

Firefox 不支持 SourceMap……已经切回 Chrome 了,晚上继续尝试。

8-14 更新

Firefox 团队曾经抱怨 Google Chrome 不正当竞争,故意在几个大型产品中给 Firefox 挖坑,打压他们在用户心目中的地位。然而经过我这一周来的使用,我觉得 Firefox 实在做得不够好,很难让开发者选择它作为主力开发工具。

  1. 使用 Vue Cli 会不停报错,找不到 sw.js,连接不到 sockjs-node 等等
  2. 使用 webpack 无法加载到 sourcemap,无法 debug。(应该是配置问题,因为 Vue Cli 3 可以。
  3. 报错多了就影响性能,各种卡顿。
  4. 断点不会自动跳过去,屏幕没有明显的视觉效果,开始被迫重启好几次
  5. 断点不会自动更新堆栈、变量状态,需要点击一次“Step over”

问题很多,很影响开发效率。可惜我厂老板特别爱用 Firefox,所以我还必须照顾下 Firefox,经过一周的挣扎,现在倒是好一些了,Windows 10 的表现还不错。

crontab 笔记

在服务器上定时跑程序。重点:

  1. 要执行的程序,比如 php,必须全局可用
  2. 执行的程序,必须处理内部的文件结构,因为执行路径不太确定

生成日期时间配置,可以使用这个工具

生成日志

1 0 * * * php /var/www/laravel/artisan check:daily > /var/log/laravel.log

每天凌晨 00:01 执行 php,跑一个 laravel command,并且把日志放在 /var/log/laravel.log

续写日志,而不是覆盖

使用 >> 替换 >