失败比成功更重要

(题图为今天公园中发芽的小草,温哥华居然在2月进入早春)

最近我经常思考如何快速学习、快速进步,有一点小小的收获:

人生之路上,失败带来的价值,远远高于成功。

一次成功,有可能只是因为你运气好,而你完全不知道自己「做对」了哪些关键步骤。一次失败,却可以让你得到的是真实的、最值钱的、最不可替代的知识。

就像软件工程,一个脚本跑不通,马上获取报错信息,通过 Google 和 chatGPT 找到知识盲区,迅速改正,再跑,又错,再改,成功跑通。因为可以快速失败、快速重建,所以传统行业可能几年都无法完成的迭代,对程序员来说一个上午就能完成。软件行业因此才能用相比其他行业来说堪称「光速」的效率来进步。

又如开车,老司机坐进一辆陌生的车,会先狠踩油门然后狠踩刹车,熟悉一下车辆的极限性能,才安稳上路。我开车时,也会这样测试车辆性能和操控感,例如拐弯不减速、故意压过一个水坑、用较快速度通过减速带等等,用这些日常错误的操作方式,来获取正常渠道难以获得的第一手知识。这是人类自古以来就有的学习捷径。

尽可能频繁、低成本的去失败,会带给你大量而珍贵的知识储备。久而久之,将迎来毫无疑问的、确定性的、无比稳固的成功。

我有个富一代朋友,他30岁前在深圳龙华开了一个专做外贸礼品定制的工厂,自己就是公司的金牌销售、创造了70%的销售额,靠自己一双手在深圳福田买了两套房,一辆150万的车,并支撑了一家人的豪华生活。闲聊的时候,他曾经问出一个奇葩的天问——为什么我比同龄人优秀这么多?

他既有骄傲的一面,也有谦卑的一面。一方面那几年真的意气风发、必然觉得自己是天纵奇才;另一方面,他或许真的好奇自己到底作对了哪些事情。后来,他搞软件,做的乱七八糟,赔的底掉,惨淡收场。显然,我这位朋友最终也没想明白那个奇葩问题的答案。

太顺利,会让人放松警惕。更进一步,太顺利,实际上剥夺了你了解「真相」的机会。当你一路畅通无阻、却并不清楚「真相」的时候,如盲人骑瞎马,危矣。

例如我前段时间发现自己的车载电池不太经用,简单换了个新电池。有一次出门加油,直接趴在加油站无法启动了,最终连转向助力系统都停摆,汽车完全死掉。一个人坐在车里,紧急研究如何低成本拖车,尽力找一个周六晚上还上班的靠谱修车场,等拖车,最终换了汽车发电机和皮带,彻底解决了电池问题。如果未经历过这件事,我对发电机、道路救援等将一无所知,虽然过程很麻烦,但知识和经验实打实的得到了。现在我定期检查电池健康度,不必担心发电机效率过低,也知道万一再次趴窝应该怎么处理。

成功,不仅只是一个结尾,更应该是一个「必然到来的胜利」。如同玩RTS游戏,开局一条狗,其他全靠一点一点探索战争迷雾,最终心中对胜率大致有个预计。失败,就是不停探路的过程,拼凑自己的世界地图,迎来自己预期中的胜利。

我们应该追求的是知识和经验,而不是一次成功。知识和经验当然会导向成功,但成功本身只是追求知识和经验的副产品、而不是目的。如果失败能带来知识和经验(往往确实如此,而且带来的是价值最高的那部分),那么我们应该勇敢的追求失败,越快、越多、越好。

主动、快速、频繁的失败,是一个伟大的战略。如果人人都明白失败带来的东西有多么宝贵,我猜这个世界上很少有人会直奔成功了。幸好大多数人并不喜欢失败,「失败」这个赛道才不至于太卷,追求知识的过程才显得更加有趣。

Tagged : / / /

2023年终总结

(头图为我用DALL-E为小虎设计的个人徽章)

我2023年的关键词只有一个:适应。

学习

5月,我开始读master,整体的难度不算很大。写了几年代码以后,对计算机的基础知识也不算陌生,相比一些零基础转码的同学要轻松一些。在学习上,经常在碰到某个此前不了解的知识点、和过往的工作经历产生一些联系。对于正常读计算机、然后成为程序员的人来说,顺序一般是先学习理论知识再用代码实践,而我的顺序相反。这种逆序学习带来的感受,非常奇妙。

举个例子,在学习操作系统的进程间同步时,涉及到进程的fork概念,期中还包含如何处理内存等等细节。以前我在创建新进程时,并不会考虑这些理论,只是把系统API当作语言本身的普通功能来使用。显然这种理解不足以支撑一个健壮的系统。我已熟稔这个功能,所以理解理论的时候反倒异常简单。

类似的情况时有发生,让我对学习计算机有了一点新的认识:先实践、后理论,是否是一个更好的学习方法?计算机本科大一大二的基础课,是否应该挪到大三大四以后再学?

带娃

小虎越来越壮,现在已经16个月了。我看到他圆胖的脸,就会想起他从母体中被剖出、继而大声哭闹的那一瞬间,居然已经是480天前的事情。

3月,我从Vancouver搬家到Richmond,来到了一个小区,我们全家很快和小区的娃爹娃妈们熟络起来,彼此经常聊天、帮忙、互相带娃等等。这个小社区的存在,让我们的生活温馨了很多,也方便了很多。缺了干活工具,直接去隔壁要;带娃时临时有事,就让邻居看一会;各个节日,几家人凑到一起吃饭;连我在外面车子无法启动时,都直接让邻居开车过来救援。有这一群邻居,千金难换。

邻居家中都有孩子,从0岁到5岁,彼此友爱非凡、关系亲密,我尤其喜欢对门家的两个女孩,漂亮可爱,她们也很喜欢小虎。孩子们来我家玩的时候,我喜欢给他们读书。看着几个小孩倚靠着我围坐一圈、认认真真的听我讲儿童绘本上的简单故事,老父亲的温暖情绪就像一缕香火,慢慢的环绕心脏。

再过2个月,小虎要去day care了,他会面对一些严峻的挑战。对我来说,也是一样。

开车

4月,买了一辆二手SUV,随后紧锣密鼓的持续学习汽车知识。如今从一个完全不会开车的新手司机,变得可以给汽车做各种保养、家中陆陆续续添置了若干工具,甚至时不时还可以帮朋友检查检查车况、换换油液等。回想起2023年4月那个买了车都需要让邻居帮忙把车开回家的小白,时间真的过的很快。

2024年,老婆也需要添置一辆刚需车,目前在研究 Nissan Leaf,这个廉价纯电车比较适合我的需求,无论价格还是功能都不错。缺点是电池容量较低,二手续航也就100公里出头。在 Facebook 的车主群里咨询了一番,Leaf车主们都觉得这车挺适合我的通勤需求。

新年里,买第二辆车,更多的实操整备车辆。期待自己的修车技术继续提高。

理解

年底,我带领学生们发动了一场对抗学校选课新政的活动,和系主任有很大冲突,被叫了保安赶出办公室等等。一直觉得有某些地方不对劲,但说不出来。前些天,趁着圣诞节和一个本地朋友 Jade 会面,聊了聊这些问题,询问了很多关于价值观的问题。

Jade 认为,应该 respect,应该 be humble,这是此地的基本规则。被允许在加拿大学习和生活,是主人对客人的邀请,客人不应该反过来教主人做事。这一点我深表赞同。

我的个人经历造就了身上的斗争精神,遇到事情的第一反应并不是「合作」「商讨」和「求助」,而是「对抗」「强硬」和「斗争」。在跟「造反团队」成员内部沟通的时候,我说「我的个人经历告诉我,让我幸存下来的从来都是强硬的对抗而非软弱妥协」,这个观点现在有了一些改观。毕竟加拿大不是中国,这里有新的社会规范,我源自中国的世界观,似乎还应该做更多的适变。

我的脑子里时常存在两种完全矛盾的想法,例如一方面会觉得对抗是争取利益的唯一途径,另一方面深深的厌恶持久的「斗争」、想和所有人友好相处;又例如我愿意从恐怖分子的角度去理解他们的思考逻辑甚至同情他们的处境,但坚决站在他们的对立面。

加拿大是个奇怪的国家。思来想去,想要理解这个国家,可能最好的方式是「冲突」,用摩擦来互相调和,最终和平共处。我不喜欢用「躲避」的方法来规避理念冲突,因为这本质上只是延迟了冲突、并没有达到互相理解的目的。以后,我和加拿大社会恐怕还会有更多的冲突,这就是我和这个社会彼此真正兼容和接纳之前的阵痛吧。

工作

圣诞节前夕,我开始投简历,目标是软件类 Intern,截至目前无一斩获。后面还要继续投,希望可以早点找到第一个落脚点,有一点收入。毕竟已经靠积蓄在加拿大呆了一年半,生活上捉襟见肘。

很多同学目前在做一些无门槛的工作,例如门店销售、仓库管理员等等。我不想用时间换钱,想把时间用来滚雪球。最近听朋友老婆的劝(我身边唯一一个零基础转码上岸微软的牛人),从Udemy上买了一个 Unreal 5 的课程,用零碎时间学习一下游戏开发。相比普通的软件公司,温哥华的游戏公司倒是不少,而且很多知名企业,例如 CDPR 和暴雪等等,掌握一些引擎开发技术,对找工作应该有些帮助。

朋友

除了天天见面的邻居,我的朋友主要是大陆老同学、桌游玩伴、刚登陆时帮过我忙的本地人、几个同学、隔壁装修请的工人等等。2023年新认识了不少人,大多数是中国人。2024年,我想更多接触不同族裔的人,了解大家各自的想法,让自己变得更加友善和柔软,收收身上的尖刺,花更多时间关心朋友。

2024

活着不容易,不出大事就很好。没什么新的期盼,只是希望生活越来越顺滑,家人健康,小虎在day care开心,我掌握更多的知识、有一个安稳工作。人到中年,想要的东西越来越实在了。

祝各位读者2024年一切顺心。

Tagged : / / / / /

绝大多数人都是错的

最近有个体会:这个世界上,绝大多数人在做绝大多数事的时候,都在用错误的方法、或者根本从头到尾都在犯错。

其实这个论断在逻辑上推导也很简单:每个领域中拔尖的人都是极少数,即便把运气等不可知的要素排除,顶尖者之所以顶尖,也是因为做对了很多事情,普通人不能冲到前面只是因为做错了太多事甚至所有事。

前几天我在一节课上,旁边的女生让我帮忙连接学校打印机、想把几十页讲义都打印出来。这种无用的激情让我瞬间梦回本科,每次课后都有学生围上去要老师的ppt、觉得这玩意是期末考的精华、必须敲骨吸髓充分吸收。其实做了这么多年学生,大家应该都能体会到,越是“高级”和“复杂”的知识,在学习过程中找到那种“体系感”才是关键,而这种体系感的获得只能依赖自主学习、读书和思考,ppt不过是零散知识的目录。如同中小学时代那些很努力但始终没能进步的学生,拥有这样错误学习习惯的人,其掌握计算机这种庞杂体系知识的过程想必会非常艰难。

又如我在温哥华有个很好的玩伴Harry,和我同龄,印尼人,来加拿大二十年了,我有困难的时候都会问问他。他在我请教轮胎问题的时候,给我推荐了轮胎店和轮胎品牌,都是大厂和大牌。后来经我研究,发现自己并不需要去大厂买一整套大牌轮胎,只需要按需购买即可(在我的个案中,通过可靠渠道买两条二手轮胎就行了,因为要大致确保前后轮磨损程度接近,所以要么弄两条二手胎,要么换四个全新胎,我当然选择前者),可以把绝大多数成本节省下来。Harry选择大厂和大牌轮胎当然都没错,但他对轮胎的知识并不够深入,不了解轮胎的实际寿命和更换原则,给我的建议就不太符合我的需求。

第三个例子和加拿大移民中介相关。最近一年我听了太多人抱怨自己的中介不靠谱,从来没听哪个人夸奖自己的中介。其实加拿大移民、签证相关的所有信息都放在了ircc网站上,大部分中介自己英语稀碎、对政策只有二手知识。我从申请旅游签、申请visitor record延期、到加拿大境内申请学签、境内访客变学生、再到境内开学前转学等等,从头到尾都是DIY,并且由于情况极其特殊,很多事情都只能自己研究。经历过所有流程,看了很多中介的视频和文章,就很清楚移民相关行业甚至可以说是一个“合法诈骗”的行业。但为什么还有那么多人找中介呢?我只能理解为“恐惧心理”,花钱买安心。其实正确的方法只有一个,上官方网站查看文件,独立填写并递交各种文件,然后等待结果。而走这条路的人,太少了。

上面的三个例子,分别代表了“做错事”的几个维度:错误的学习方法,不够深入的信息获取,和恐惧压倒理性。

如果是年轻的时候,我会对“绝大多数人都是错的”这个论断持高度怀疑态度。但随着这么多年的历练,越来越确信自己的观察。这让我想起一件事。我的本科老师曾去芝加哥大学呆了一年,和世界最顶尖的经济学家朝夕论道,一年后回国,某日他在浙大后门的烧烤摊上一边大快朵颐一边口出暴论:“以前觉得自己水平很高,在芝大呆了一年以后,发现自己水平真的很高。”当年我付之一哂,现在我深以为然。

当然,我除了在几个领域里做对了很多事情以外,也必然在更多领域是“做错事的大多数人”。可能这就是成长带来的好处之一,不再耻于自己的愚蠢,同时敢于承认自己的正确,而后者往往需要更大的勇气,也更加重要。

成为1%的一个简单方法,就是首先不做那剩余的99%。本文大意基本可以总结为这一句话。

对了,再附上一条tip:做任何事时,想一想“大多数人都是错的”,你就会对从众心理免疫,并自动带上了critical thinking这个利器,你把事情做成功概率将无限趋近于100%。

Tagged : /

我的近况(2023.5)

今天说一点关于我读书的事情。

先说说同学。

最近开学了,我参加了开学典礼,和很多同学接触下来,发现一些比较有趣的事情。

首先,在学校里,来加拿大读书的同学国籍基本是印度+中国+伊朗,另外还有一些小众来源诸如墨西哥、孟加拉、韩国、哥伦比亚、巴西等。但三大古国有绝对优势,总和占总人数90%以上。

其次,学生们的年龄都偏大,我35岁这种站在「优化线」的年纪,反而是班里偏小的,绝大部分学生都是中年人,有一些是带着自己上小学的孩子来读master的。我交流过的最小的学生大概是26岁左右,以中国一线城市标准其实也不算很年轻了。

其他国家不清楚,但可以想见,这批来自中国的中年人漂洋过海来读书显然都是为了身份,并且都有极强的理由和动力,看衣着谈吐也都是社会中坚,估计在国内都是有点事业基础,甚至很可能拿一样的剧本:事业成功,有房有家,防疫三年,保命润加。

中国、印度、伊朗,这三个国家在最近几年都有着肉眼可见的巨大退步,其百姓四散逃难是历史的必然,也蕴含着未来剧变的种子。

再说说老师。

在选课结束后几天,我选的一门课的教授以「笔误」为由突然更改了课程时间,导致我的时间表变得很糟糕,会额外浪费很多时间和金钱。我用很不客气的语气发邮件拒绝更改时间,之后又在开学典礼后找到教授面谈,依然没能改变,于是当晚drop了包括该教授课程在内的所有课程,重选了另一批必修课,把时间重新调整到我可以接受的水平,顺便发邮件告知教授他的「笔误」给我造成了多严重的后果。

现在年级大了,耐性比小时候要强,但反而更加习惯于对侵犯自己利益的人直接摆出进攻姿态。在全系大会的时候,每个同学都有30秒发言,可能由于我的课程时间被随意修改,我带着点脾气来开会,于是在自己的发言里也夹枪带棒的有点冲,说自己是野生自学程序员、在场大部分人手机里都跑着我的代码、以及自学(而非学校教育)才是最佳学习方式。

这些年,自己从楞头青变成30多岁的中年油腻男子,再过几年就快40岁了,但遇到可以装逼的地方,依然忍不住站起来装一把。这次依然如此。我有一种愚蠢的理论:当自己80岁行将就木之时,如果想起这一天,是否后悔于「当年应该装逼一把,反正人都要死」?每次问自己,答案都是「今天不装逼,死前必后悔」。有种预感:如无大碍,可能我还得装几十年。

最后说说身份。

我所在的项目处于加拿大BCPNP硕博通道的名录内,属于毕业后无需找工作、无需积攒分数、可直接申请枫叶卡的类别。正因为这一巨大优势,这两年越来越火爆。我在以前的文章中,分享过自己申请Master的各种困难,实际上,当我所有申请尘埃落定后,我拿到了2个BCPNP Offer(NYIT和UNBC),以及2个安省硕博项目Offer(Laurentian和Lakehead)。这四个学校,都不是什么牛校,但由于政策的特殊性,都属于毕业就能拿卡的范围(安省的两个学校还是要打分的,但各种加分极多、亦无需工作offer,基本上毕业就能过线,因此也被我归类于毕业就能申请枫叶卡的范围)。

进入了这样的项目,只要能顺利毕业,在场的同学都能获得PR。只是其间有经验的程序员并不多,绝大多数人还是「转码」状态,目前短暂的沟通中还看不到各自的闪光点。在我的刻板印象中,中年人「各怀鬼胎」,不知道未来能否达成愉快的合作。

但是不管怎么样,这群勇敢的突破舒适圈的中年人,都可以算是自己家庭中的英雄。

最近想写的东西很多,但真正落笔的很少。想起最高产的时候,竟然是小虎刚出生的那两个月,那时候最忙、最难、也写的最多。

人生境遇之奇妙,不可知也不可说。

Tagged : / / /

抛弃「确定性」

普通人往往高估「确定性」的收益、又低估「确定性」带来的风险。

例如考公的人看到了后面三十年连续不断的几千元/月工资外加各项福利的稳定性,却忽视了自己的真实需求和沉没成本。考公的显著沉没成本之一,就是牺牲了自己未来所有可能性和应对风险的抵抗力。当风险来袭,你将没有任何应对能力。从去年开始的大范围、高强度的公务员降薪,已经实在的影响全国上千万体制内选手;而 90 年代的「国企工人下岗潮」带来的无数人间悲剧,就是「确定性」危害的一次大规模显现。

除了考公大军以外,因就业困难而去考研的兄弟姐妹们,更只是延后了处理风险的时间,不仅没有消弭风险,反而给自己注射了麻醉剂,使得下次面对风险更加弱势(年龄增长、对市场的敏锐度下降、学历成本带来的经济压力等)。一言以蔽之,还不如考公。

除了考公考研等传统项目,当代市场化职业中,“转码”也是一种“赛博考公”。你做了500道 Leetcode 算法题,便可以中人之姿跻身Google/Microsoft等一流大厂,获得稳定的高薪和社会地位,哪怕这几百道题对真实工作而言毫无意义,亦算是你进入大厂的「投名状」。其付出的时间、精力、沉没成本,虽足以让你获取更有价值、历久弥新的知识,却并无即刻的、现金化的收益。

更何况,在人工智能等技术的加持之下,传统工程师的职业寿命到底能否继续维持下去,这是一个尚无答案的问题。但是,此类职业风险的出现,意味着「大厂工程师」的收益期望被降低了。而这,仅仅是一个开始。

上述「确定性」的存在,为很多人提供了舒适的生活,但,是时候抛弃这些「确定性」了。

我的老读者都知道,我是一直是「不确定性」的拥趸。2015年以政治学本科+互联网运营总监背景裸辞自学编程,在2016年顺利成为初级后端开发工程师,这在当时是一种巨大的不确定性,后来却为我带来了巨大的好处:掌握了工程技能,深入理解计算机系统,也为多年后「润加」做了铺垫。

2019离职,此后两年间家里蹲写公众号。这可能是我风险最高的一段职业经历,因言获罪,得到了警察的「登门认证」,以及百度的「诉讼认证」。同时,我也习得了普通人终生难以获得的技能:大量的法律实践。在与百度长达半年的缠斗中,我学到了很多法律知识以及法律实践(在中国的司法体系中,对法条的理解和对司法的实践,几乎是各占50%的独立知识),也获得了「打官司」这个业余爱好。

2022年再次转职,回归职场,成为字节跳动高级工程师,很快与字节撕逼,凭借过去的自媒体经历和对法律的熟稔,全身而退,开开心心拿钱走人。至此,我清楚自己可能与国内任何一家大厂都水火不容,未来不会再为 BAT 之流贡献任何一行代码、任何一次管理实践。

去年以旅行签入境加拿大,一个月后莫名决定留下,接着在加拿大境内考雅思、申学校、申学签,从毫无准备到尘埃落定,每一步都充满风险,但每一步都带给我巨大的收益。

可以说,我生命中最宝贵的这些经验和收益,全部来自于「风险」。一来,我本人对于「确定性」的实际收益一直报以怀疑态度,二来作为一个风险偏好的个体,我对于「确定性」有一种来自 DNA 的排斥。

在「系统性风险」越来越鲜明的今天,不确定性,实际上是这个世界的主流;确定性,才是一种「例外」。我不觉得对于「确定性」的追求有什么道德劣势,但「追求确定性」这个行为本身最严重的问题,是其存在着手段与目的的二律背反:将身家性命寄托于「确定性」,这本身就是一种高风险行为,而这种会导致高风险的手段,恰恰与「追求确定性和安全性」的目标背道而驰。换言之,你明明想寻求安全,最终却将导向危险。这就是「确定性」最大的逻辑悖论。

既然如此,是时候抛弃「确定性」和「安全」,拥抱「不确定性」和「风险」,拥抱自己的本性。这样,每天都会收获意料之外的命运馈赠。剩下的,交给时间即可。

最近小虎7个多月大,学会了扶站,早于平均速度约2.5个月。我很好奇,为什么他学习的这么快?经过观察,一方面是因为他天生强壮,另一方面,就是他胆子大、敢冒险、不怕磕碰、屡败屡战。简单说,就是他对于“风险”有较高的偏好,对于安安稳稳的“确定性”(例如用躺、坐等安全姿势玩耍)则较为厌恶。反反复复的冒险,让他快速习得了很多实用技能,又进一步加速了学习速度、不断的自我强化。这是小虎示范给我的「不确定性」的优点,看来他未来恐怕也是一个风险偏好者。
Tagged : / / / / / /

字节跳动和 Go 语言

字节跳动

2022年1月5日,我正式入职字节跳动,高级测试工程师,负责一个字节非常底层的网络库的质量保障工作。这次找工作没有选择开发岗位的一个原因是,开发工程师对于整个工程的控制力是比较弱的,一般来说基本相当于一个纯「产出单元」,没有宏观调度的能力与意愿。我想要做更多宏观的工作、加强自己对于工程的把握感,就只有QA、项目经理、产品经理这几个岗位,后两个岗位对我吸引力很低,QA 则刚好和我的个人履历与兴趣相结合。

绝大部分大厂对于 QA 的运用,基本上还是作为测试部门,以调研各种测试流程和技术为主,为「产出单元」们提供后勤保障工作。换言之,说是 QA,其实就是测试+一些 bug 数据统计+打包发版。

当然,并不是说,QA 应该彻底脱离测试、成为一个飘浮在半空中的岗位。但如果 QA 部门自己都不能深刻的理解「何为质量」这个命题,如何能带领整个团队进入下一个质量高潮呢?

以手工回归测试来说,这项工作用来了解产品特性还凑合,但了解产品最好的方式不是使用产品,而是开发产品——买的永远没有卖的精明。但业内的 QA 或测试工程师对产品源码一般来说没什么兴趣,精力都放在测试流程和技术上。国内高强度的工作方式,的确会抑制工程师们的想象力。

在和开发工程师的一次午餐中,我向大家阐述了自己的职业目标,以及我对「质量」二字的理解:

我个人永恒的职业目标,就是把自己当下的岗位「干没」。「干没」,意味着永久性的、终极的解决了这个岗位面临的一切问题——如果我是一个开发,那么我的目标就是减少掉自己这个开发;如果我是测试,就要让团队不再需要测试;如果我是 QA,就要让开发过程不再需要 QA 的校准;如果我是团队 leader,就要让团队不需要我这个 leader 也同样能高效运转。

这是非常终极的目标,有可能永远不可能达到,但应该有这样的追求。作为工匠,不必担心自己未来会失业,如果一个职场人能达到以上高度,那么一定有更重要的岗位等着你。

我对质量的理解,则是——「质量」不应该成为一个岗位,而是一种思想、一种意识形态。因为质量诞生于开发部门,而 QA 永远只能「揭示」质量、而非产出质量。既然「质量」是开发工程师的产出,那么应该让开发工程师来负责质量,才是最正确的事情。就像打铁铸剑,一个产品在诞生之时,其品质已经确定,后期再修补也无济于事。

在传统的「开发-测试-发版」流程中,如果测试发现质量有问题,就应该将之返回给开发团队,由开发团队去内部处理一切有关「质量」的问题。试想一下,这个世界上存在与质量相关、却不应该由开发亲自处理的事情吗?

换言之,「质量」是一个开发问题,而不是测试或 QA 问题。

那么 QA 这个岗位,还有存在的意义吗?

QA 仅存的意义,我认为是一个类似战锤40K中的「牧师」角色。

这就是战锤40K中的牧师,勇武更超普通星际战士

在战锤40K的作战小队中,队长负责战术指挥,牧师负责思想和信仰工作。当士气低落、信仰垂危时,牧师要首当其冲的站出来,挽狂澜于既倒,扶大厦于将倾,即便为了一线胜利而牺牲自己,也在所不惜。

这个牧师不是躲在堡垒中对战士们指指点点的文官,他本身就是一个和兄弟们冲锋在前的顶尖士兵。只是相比于其他人,他的信仰更坚定更执着,也更有大局观、更优秀。

战锤40K 的牧师,实际上就类似项目组中的 QA 角色,这样的 QA 拥有如下特点:

  1. 战斗于一线,而非文官(本身就是开发,而不是开发团队之外的「指导者」)
  2. 更具宏观思维,能超脱于实际战斗以外(视野超出普通开发,更关注整个团队的产出质量)
  3. 来自于团队内部,而非外部(从开发中遴选一个开发人员成为QA,而非在团队外部设置QA岗位)

在这几个原则的规范下,我们很容易确定团队中谁来成为 QA,同时将团队外部的 QA 岗位直接取消。

目前微软已经取消了测试和 QA 岗位,全部测试工作都由开发工程师来做。这种意义上,字节还相当于普通星界军、而微软已经人均星际战士了。

Go语言

早在几年前,我就开始关注 Go 语言,只是耽于舒适区,一直没有向前一步。最近做了下调研,发现除了 Shopee 之外,字节也大量使用 Go 作为后端开发语言;另外作为区块链开发的重要技术栈,Go 语言未来也可能越来越重要。

所以从本周开始,我利用工作和业余的一些零散时间,开始逐渐学习 Go 语法,了解生态现状。

和我最熟悉(应该是唯一熟悉)的语言 Python 相比,Go 的生态要小很多,但是他们的特点都非常显著:Python 生态强大,几乎可以做一切事情,代码编写灵活;Go 的目标就是一个轻量版 C 语言,在「灵活快捷」和「高性能」之间尽量寻找平衡点。

中国互联网企业,实在是没什么技术含量,如果硬说,那就剩下一个「高并发」独步全球。在解决这种并发问题上,Go 有天然优势,goroutine 的内存占用非常小,同时通过 Channel 进行安全的数据处理,避免了 Python 那种一团乱麻式的异步和锁。所以新兴互联网企业喜欢用 Go 来构造后端,是非常理性的。

Python 是当之无愧的王者,但其中势必包含大量的非专业工程师 Python 开发者(例如科学家,量化交易员,等等)

区块链同样面临性能问题,传统比特币、以太坊性能都令人无法接受,所有新型公链一定会号称解决了性能问题。毕竟,以「代币」为核心机制的新型互联网,如果不能解决性能问题,则毫无未来。Go 语言在这个领域可能是最优选择。未来如果有机会进入这个行业,Go 肯定是必修课。

Go 位列13名,已经是非常好的成绩,仅次于 SQL/Swift/PHP/R。

以目前的发展趋势来看,Go 断然不会成为 Python 这样的全能语言,但其后端领域的影响力很可能会在未来几年达到甚至超过 Python。所以对于有 Python 基础的人来说,应该尽快学会 Go 并掌握开发技巧,不仅会带来收入上的提升,还能更好的了解到技术界的新趋势。

所以,这篇文章也算是一个节点,看看我下一次更新博客的时候,能用 Go 写出什么样的东西来了。

祝我的读者们新年快乐,虎虎生威(下面弄两个小老虎凑合凑合吧)!

虎虎生威,新年快乐!

Tagged : / / / / /

工作,有多重要?

文章转自我现在写的公众号「古老湿」,欢迎大家扫码关注!


我以前觉得,「工作」是生命中最不重要的东西,是「必要的恶」。
人的自由意志并不来源于所做的事情,一个图书管理员同样可以做个一统江山的梦。劳心者治人,劳力者治于人,工作就是打工,打工就是劳力,「治于人」的人生,不值一提。
工资?只是生存的必需品,出力干活、提高薪水、像机器人一样重复这个过程,就是工作的全部意义。
所以我以前经常处于一种奇怪的状态——会想各种方法、制作各种工具来优化自己的工作,但其实在心理上对工作的投入很少,工作于我而言仅仅是换取收入的途径。
改变,发生在我转职成码农之后。
入职的第一天,我就发现码农同事们的气场和以前我所见过的「职场」完全不一样——每个人认认真真的写着自己代码,偶尔互相开着玩笑,然后继续喝着咖啡盯着屏幕噼噼啪啪的敲打机械键盘。
如果说有什么不一样的地方,可能是这群新的同事在在实实在在的建造什么东西。或者说,他们对工作的态度,和我不太一样。
这可能和码农的工作方式有关:每个人维护一部分旧代码,同时每天生产新代码,这些新代码也自然进入「待维护」
状态。很多开发工作,不是不能转移给别人,而是成本实在太高——你需要给对方讲业务逻辑,测试方法,以及某些难懂的奇技淫巧;即便如此,对方也可能隔三差五过来问你这行代码什么意思、那行代码是否写错……
逐渐的,我对于自己负责的代码,也有一种「亲密感」,在那些平平无奇的字里行间,是我对产品的设计、思考和传承。工程师这个职业,甚至改变了我曾经的文科生懒散的思维习惯,变得理智和严谨。
也就是在写代码的工作中,我慢慢感觉到,工作不仅仅是混一份工资,也是把自己的生活与这个世界的某一部分连接起来的过程。你需要对自己的产出负责,你是一个手艺人。
以前,我觉得工作是自己的延续,你喜欢做什么,就找个工作完成自己的爱好;现在,我觉得工作更像是一块补全自己人生的拼图,找到这块拼图很难,但找到后,你会变成一个更完整的人。不仅仅为了薪水,还为了自己做了一些有意义的事情。
所以工作到底有多重要呢?
大概有这么重要吧:

开玩笑,比这大多了!
工作不仅给我一张饭票,也改变了我很多,让我变得完整,也是生活的指南针。如果你的工作没有给你这个感觉,或许是时候做点改变了?

Tagged : / /

程序员年龄增大后的职业出路是什么?

这篇文章是我在知乎上的的一个回答,讲的略微有点深。另外感觉自己这两年越来越左翼,越来越觉得马克思不愧是20世纪最伟大的思想家之一。

今年 30 了,也开始考虑年龄问题了。
不过虽然 30 岁,但我实际作为程序员、以编程为业,也只是最近两年的事情(关于我的编程职业经历,在这个回答里写的比较详细:知乎用户:自学编程的人,都是怎么找到第一份软件开发工作的?)。因此对编程这个职业的理解,可能还不如一些 90 后小朋友深,写的不对的地方贻笑大方,请见谅了。

注:以下叙述,不局限于程序员,实际上包含所有职业。

中国的程序员在市场中的地位,不客气的说,随便翻开《1844经济学哲学手稿》里描写产业工人的段落,把这些一百年前的论断放到程序员身上,都言之凿凿:
例如:关于程序员的先进生产力与其对应的可怜回报

「的确,今天由于有了新的动力和完善的机器,棉纺织场的一个工人往往可以完成早先 100 甚至 250-350 个工人的工作。在一切生产部门中都有类似的结果,因为外部自然力日益被用来加入〔X〕人类劳动。如果说为了满足一定量的物质需要必须耗费的时间和人力比现在比过去减少了一半,那末,与此同时,在不损害物质福利的情况下,给精神创造和精神享受提供的余暇也就增加一臂。但是,在我们甚至从老克伦纳士自己领域中夺得的虏获物的分配方面,仍然取决于像掷骰子那样盲目的、不公正的偶然性。法国人有计算过,在目前生产状况下,每个有劳动能力的人平均每日劳动五小时,就足以满足社会的一切物质利益……尽管因机器改进而节省了时间,工厂中奴隶劳动的时间对多数居民说来却有增无已。」

例如:关于「越工作越贫穷」这一现象的分析

「工人生产的财富越多,他的产品力量和数量越大,他就越贫穷。工人创造的产品越多,他就变成廉价的商品。物的世界的增值同人的世界的贬值成正比.劳动不仅生产商品,它还生产作为商品的劳动自身和工人,而且是按它一般生产商品的比例生产的。」

例如:关于程序员异化为程序的奴隶

「因此,工人在这两方面成为自己的对象的奴隶:首先,他得到劳动的对象,也就是得到工作:其此,他得到生存资料。因而,他首先是作为工人,其次作为肉体的主体,才能够生存。这种奴隶状态的顶点就是:他只有作为工人才能维持作为肉体的主体的生存,并且只有作为肉体的主体才能是工人。」

以上,并不是呼吁大家都去读马克思,我也无意挑起关于马克思的政治经济学的争论(也希望大家尊重题主和读者们,不要做跑题辩论),只是希望各位静下心来想一想,我们和百多年前的纺织工人的区别,到底是什么?
伴随一个产业工人或程序员的老去,不可避免的是工作时长与强度的降低、工资的刚性提升(正常来说只能升不能降)、对家庭福利需求的增高(例如需要公司为家人购买保险)等等。而普通工人(程序员)的工作效率增长速度一旦无法达到其福利需求的增长速度,在公司里即成为累赘。换句话说,辞退你、换新人,对公司有很大好处,而这对资方来说是一个巨大的诱惑。
多亏劳动法和近二十年来的互联网产业红利,程序员的处境已经远远优于当年的工人,不用时刻担心被辞退,但是当到达了一定年龄后,大多数程序员的个人价值已到峰值,收入封顶,但生活压力却越来越重。这是「年龄-收入」的悲剧冲突核心,也是大量程序员夙夜忧叹的唯一原因。
而这种悲剧,集中式的出现在中国,其直接表现就是程序员的薪酬过低(例如在美国,普通工程师拿个十几万刀的 package 并不算天方夜谭,这种问题也就并不严重。)。
所以程序员老了怎么办?唯一靠谱的解答,就是脱离自己的产业工人身份,直面残酷的市场食物链,尽一切可能向上爬,脱离这个「产业工人诅咒」。
那么程序员以上的食物链有哪些?最直接的就是技术管理层、公司中高层,再次是资本方,最后是权力方。故而其方法也分外直接:要么争做管理层并获取股份、股权激励等非劳动收入,要么以资本进行投资、让别人为你打工,要么当个省委副书记、起码乡镇干部之类(这一条过于奇幻,当做笑话吧)。
但凡符合上述逻辑的职业规划,都是靠谱的,区别仅在于风险大小。
至于计算机领域的、乃至其他各行各业的技术专家,这是一类我非常崇敬和羡慕的人群,他们往往已经获得了超额收益,故而不在我上述论证范围内。我所说的一切,仅仅针对你我这样的普通职员。
所以,程序员们,不要为自己掌握先进的知识而沾沾自喜,这个世界并不属于知识劳动者,所有利润最终将归属资本和权力……
……和猫。

Tagged : / / /

树莓派3初体验之一:搭建 Python 开发环境

最近新买了一个树莓派3(购买前还考虑了 Orange Pi 等 Linux 开发板,但最终仍然选择了树莓派),主要目标是想通过折腾这个信用卡大小的 Linux 电脑,学习一下 Linux 系统知识,熟悉服务器的各项操作,顺便给自己搭建个 Web Server。
WechatIMG17
安装步骤很顺利,通过官网下载了 NOOBS 版的 Raspbian 系统,并复制到 TF 卡中,然后启动树莓派,一路 Next,很快就可以看到图形界面。然后看了一下树莓派内置的 Python 版本,发现是 2.7.9 以及 3.4.2,于是机智的我马上制定了第一个任务——把树莓派的系统自带 Python 3.4 升级到最新的 Python 3.6.2。
升级的过程是这样的:
1. 从 Python 官网下载 Python 3.6.2 的压缩包。
wget https://www.python.org/ftp/python/3.6.2/Python-3.6.2.tgz
2. 解压编译
cd ./Python-3.6.2
./configure
make
sudo make install

3. 将 /usr/bin/python 的原文件删除,然后link到刚编译好的Python3命令上
rm /usr/bin/python
ln -s /usr/bin/python ~/Python-3.6.2/python

结果是虽然我把原本是2.7.9版本的python命令变成了3.6.2,但是配套的pip等工具却乱套了,一运行就会报语法错误,看来这样生变过去是不行的,于是想恢复回去,几经尝试后失败,遂格式化TF卡,重装系统。
第二次我不再 link /usr/bin/python, 而是机智的换成了/usr/bin/python3,但是依然出错,具体什么错误已经不记得了。再次格盘重装。
第三次终于成功,在命令行输入python3指向了/usr/local/bin/python3,我还没搞明白是怎么弄得,反正搞定了,明天去问问同事在哪里设置……

后来才想起来,要改环境变量里面的$PATH……这是刚学 Python 时候就遇到的问题,现在居然都想不起来了……

WechatIMG16
此时又遇到了第二个坑——Rsapbian没有安装若干必要的库,需要手动安装。
顺利配置好 Python3.6 后,我试着pip3 install requests,结果出现ssl module in Python is not available的报错,几经搜寻,发现是由于 OpenSSL 等库没有预置在 Raspbian 中,而 pip 则需要访问 https 加密的地址,故而报错。
首先,apt-get 安装这些库:
sudo apt-get install libreadline-gplv2-dev libncursesw5-dev libssl-dev libsqlite3-dev tk-dev libgdbm-dev libc6-dev libbz2-dev
然后重新编译一次 Python 即可解决问题:
cd ~/Python-3.6.2
./configure
make
sudo make install

于是经过不知多少次编译,我终于装好了 Python3.6。后来又安装了 PyCharm,但实际运行中感觉延迟严重,所以这样大型的 IDE 可能无法在树莓派上顺畅运行,如果需要写代码,可以考虑轻量级编辑器(同时还有一个问题没有解决,就是如何卸载 PyCharm ……)。
最后说一下树莓派的整体感觉。
开箱之后的树莓派需要自己安装散热片、风扇、外壳,当然这些配件都需要另外购买。组装过程很简单,把散热片粘到处理器上,然后一层一层安装外壳,最后在外壳上方固定和连接风扇。如果有过装机经验,那么整个过程即为简单。组装完成后,我通过一根 HDMI 转 VGA 线,将树莓派连接至一个古董19寸显示器。
我(也是大多数树莓派素人)选择的是官方推荐的 Raspbian 系统,是 Debian 的树莓派分支。其实树莓派有大量的系统版本可以选择,例如 CentOS 的 ARM 版、Ubuntu Mate等等,可按需选择。Raspbian 的 GUI 没有 Ubuntu 那么炫酷,但是能在这么小的板子上运行如此完整而流畅的桌面版 Linux,也让人很欣喜。
目前我已经把若干连接线(视频线、鼠标、键盘)从树莓派上移除,仅剩供电线路并连上 WiFi,通过 Mac 远程登录进行管理。本来想设置一下 DNS 实现通过 hostname 直接访问主机,结果家里没有多余的机器做 DNS Server,华硕路由器的官方系统又不原生支持 DNS、我还懒得再折腾路由器,所以只是通过改本地的 hosts 来实现 hostsname 登录(我给树莓派起的名字叫做 footboy)。以后可能会在树莓派上搭建几个服务,通过 supervisor 管理;或者做几个 Cronjob 的定时任务。
WechatIMG15

Tagged : / / / /

关于开发流程的一些体会

工作近5周,共完成了2个项目(第二个项目已经基本完成测试,准备收尾中)。第一个项目,是用爬虫抓取数据,然后做好 API 供用户使用。第二个项目,是扫描僵尸用户,发邮件唤醒,如未唤醒则关停僵尸用户的进程。
做这两个项目的过程中各有各的体会。
首先,是关于解决问题的方式。做第一个项目时,刚刚进入公司,很难适应工程师文化,加上和同事不熟悉,脸皮薄,不愿意问问题,甚至没有仔细确认需求和工程方式就动手开搞,最终耽误了不少时间。在工程上,沟通极为重要,工程师不是低着头闭门造车的,恰恰相反,工程师们是用集体合作的方式共同搭建一个或繁或简的系统,最终完成个体无法完成的大规模工程。这应该是工程师们在一起工作的最重要意义之一吧。
工程被分割成一张张工单,并不意味着其整体被切割成无关联的个体。在完成工作的时候需要尽可能多的理解工程的有机性。例如我将爬下来的时间序列存入数据库时,每条数据的时间都被我存成了str,于是在后期制作 API 的时候就遇到了一些问题,最后需要通过将其转成datetime来解决。类似的问题说明我在完成某件工作时,并不知道这件工作在工程中的位置与意义,这就需要多问和多做了,在对整体熟悉了以后,自然会逐渐清晰。
其次,是关于单元测试的重要性。其实『单元测试』这四个字,有弱化其意义的副作用。我在做第二个项目的时候,由于内部处理数据的逻辑比较复杂,导致大大小小的 Bug 一大堆,每次提交都认为自己已经做得差不多了,但还是在 code review 时被打脸,来来回回提交了若干次,花费大量时间,甚至同事成了我的人肉 Debug 处理器。最后同事说,你还是写一些测试用例吧,覆盖的情况越多越好。
果然,写了一百多行的测试用例后,将单元测试完成,自然发现了一些之前很难发现的 Bug,无论对我还是其他工程师来说,都节省了大量调试改错的时间,多灾多难的第二个任务也随之迎刃而解。经此一役,我对单元测试的意义恍然大悟,其实单元测试并不仅仅是『测试』这么简单。在『测试』的背后,其实是将代码化整为零、各个击破的写作过程,因此单元测试的写作时间,应当与程序本体同步,也即『写一个函数,就写一个测试』,二者几乎是同步完成的。这样看上去花了很多时间在设计测试用例上,其实是规范了自己的思路和代码,同时大大提高了后期的可维护性。
在明白了第二点(也就是单元测试的真正意义后),觉得自己仿佛突破了一个模糊边界——一个软件工程师和业余代码爱好者的界限。虽然现在代码依然很烂,但是本着对代码负责的态度和对自己职业的尊重,我会把以后写下来的所有代码都同步加上单元测试,配得上一个专业人士应有的严谨。
以上就是我在完成了两个项目后的些微体会。工程师的快乐,是由一个个微小的痛苦组成的。此生竟有幸成为工程师,真是一件幸福的事情。

Tagged : / /