<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>浮云计算</title><link>https://liriansu.com/</link><description>Recent content on 浮云计算</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><lastBuildDate>Thu, 11 Jan 2024 00:16:25 +0800</lastBuildDate><atom:link href="https://liriansu.com/index.xml" rel="self" type="application/rss+xml"/><item><title>杂思丨近日状况</title><link>https://liriansu.com/posts/2024-01-11-thoughts-2024-01/</link><pubDate>Thu, 11 Jan 2024 00:16:25 +0800</pubDate><guid>https://liriansu.com/posts/2024-01-11-thoughts-2024-01/</guid><description>&lt;p>最近 James 瞄了一眼我博客以后，&lt;br>
点评了一下：“某个博主很久没更新了。”&lt;br>
我看着 2023 年仅更新的 3 篇文章，&lt;br>
也只能直面拥抱自己找不到借口的懒惰。&lt;/p>
&lt;h2 id="一">（一）&lt;/h2>
&lt;p>去年没看几本书，微信读书说我读的最快的是《道诡异仙》，&lt;br>
这本书给我的情感冲击无异于中二时读到的《佣兵天下》。&lt;br>
佣兵属于是年少轻狂的少年遇到了构建完整的西幻世界，&lt;br>
道诡异仙则是属于这个混沌时代的顶尖发疯文学。&lt;/p>
&lt;p>最近一个月经受着各种年终盘点的轰炸，&lt;br>
似乎手机上只要是个像样的应用，&lt;br>
年底就会分一部分产研来做年度回顾的项目。&lt;br>
很多习惯就是在奇怪的默契中发展成习俗。&lt;/p>
&lt;p>我个人并不喜欢把文化中新的习俗称之为“创新”。&lt;br>
比如去年朋友圈火过一天的闻会军，&lt;br>
他有趣的点在于给日常生活中插入不和谐的部分，&lt;br>
本质上与“脑残游戏”中乐趣来自于醒不来的人是一样的。&lt;br>
不过我也不算老几，我也发了闻神状态玩得很开心。&lt;/p>
&lt;h2 id="二">（二）&lt;/h2>
&lt;p>人总是会陷入或这或那的矛盾中。&lt;br>
我前阵子煞有介事地写了&lt;a href="https://liriansu.com/why-i-hate-smoking/">《为什么我讨厌吸烟》&lt;/a>，&lt;br>
几年过后，今天的我突然发现自己并不讨厌吸烟的人。&lt;br>
从好的方面而言，烟草在社会层面贡献了收入、岗位，提供了消费、娱乐，&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/cigarettes-data.png" alt="data">&lt;/p>
&lt;p>从坏的方面来说，吸烟的人拥有更短的平均寿命，降低了养老压力，&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/cigarettes-death-rate.jpg" alt="rate">&lt;/p>
&lt;p>从吸烟本身而言，这个行为不致幻、影响较小、可以被自制。&lt;br>
只要我关心的人不吸烟，吸烟的人看起来也挺友善的。&lt;/p>
&lt;p>写到这里，我一惊，不禁想到了以前跟我爸的一次经典对话。&lt;br>
我问我爸：“你对同性恋是怎么看法？”&lt;br>
我爸：“噢，现代社会很正常的存在啊，他们也都是正常人blabla”&lt;br>
我：“假如我是同性恋呢？”&lt;br>
我爸：“啊你不能是同性恋。”&lt;/p>
&lt;p>利益相关原则是成熟社会人必须学会的法则，&lt;br>
但这也是我心里偷偷伤心的“大人已经不如小朋友可爱”的一环。&lt;/p>
&lt;h2 id="三">（三）&lt;/h2>
&lt;p>之前跟 Mia 郁闷吐槽，我感慨最近时常感到自己相当油腻、一点也不可爱了。&lt;br>
Mia 安慰我，说：“你这个年纪有一些油腻是很正常的，男人中年都这样。”&lt;br>
我：…………&lt;br>
这种伤春悲秋被打蛇随棍上结果无话可说的体验令人接话不能。&lt;/p>
&lt;p>好在我后来体重轻了几斤，并且遇到了《大地雷公》这首歌，心态也可以很快转变过来了。&lt;br>
俗话说人知道自己的愚蠢就不愚蠢，那人知道自己的油腻大概也不油腻了。&lt;br>
勇敢的人享受生活，无知的人一直快乐。&lt;/p>
&lt;blockquote>
&lt;p>平生不修善果，只爱杀人放火。忽地顿开金绳，这里扯断玉锁。咦！钱塘江上潮信来，今日方知我是我。&lt;br>
—— 偈语，鲁智深圆寂前&lt;/p>
&lt;/blockquote>
&lt;p>有时觉得做男生还挺简单的，&lt;br>
不当成功人士就没有太多的社会压力，&lt;br>
只要不肥多运动、谦虚少吹牛、自律爱学习、干净且克制就可以一直像一个少年。&lt;br>
而成为一个少年本身就是最快乐的事情。&lt;/p>
&lt;h2 id="四">（四）&lt;/h2>
&lt;p>2024年是我近几年最喜欢的一年。&lt;br>
2024这个数字本身就很妙，&lt;br>
是2的倍数、4的倍数、7的倍数、8的倍数，在算错的情况下还可以是3的倍数、6的倍数。&lt;br>
是龙年，也是奥运年，跟2012末日年比是两倍末日，跟印象深刻的2008相比会有三倍回忆，&lt;br>
而且在这一年所有人的出生年份加上年龄恰好也等于2024。&lt;br>
总而言之，2024就是我很喜欢的一年。&lt;/p>
&lt;p>就像调电视音量一样，25是合适的音量，24也是合适的音量，但是23肯定不是，至少得下调到21或者20。&lt;br>
每个人都会有若即若离的强迫症。&lt;/p>
&lt;p>强迫症对于程序员，就像是洁癖对于医生一样，&lt;br>
是一个略苦恼但对职业发展大有脾益的毛病。&lt;br>
除了在《我的一点强迫症》里标记的正确使用全半角、文本文件要换行、正确使用的地得，&lt;br>
近几年我特别在意的问题还包括“优惠券、阈值的正确发音”、“别在接口里面拼错单词”以及“说鸡&lt;del>就&lt;/del>不说吧文明你我他”。&lt;/p>
&lt;p>没有波动的生活是相对乏味的人生，并不好玩。&lt;/p>
&lt;h2 id="五">（五）&lt;/h2>
&lt;p>最近大部分时间都献给了工作，&lt;br>
在 Opus 工作的这几个月是我近几年最兴奋的时光：&lt;br>
队友们三头六臂、增长上披荆斩棘、战略侧谨慎乐观、开发时百废待兴。&lt;br>
想说的话有很多，更详细的感言我会等到蜜月期过了以后，好好思考以后再单独行文。&lt;/p>
&lt;p>关于工作我感触最深的一点，倒是学长常说的那句个人奋斗与历史进程。&lt;br>
在以数十年为尺度的职业生涯中，很多早早躺下的人与“奋斗”这两个词已经无缘了，&lt;br>
许多人快乐地浪费着自己的才华，在我看来只是有点惋惜。&lt;br>
而在剩下的事业中，“历史的进程”或者说“周期”是一个跨不过去的门槛。&lt;br>
再优秀的个体、再灿烂的十年、再好的一代年轻人，可能都会耗在康波周期的阶段中。&lt;br>
不过这点辩证难度，对中国人来说还是太简单了：&lt;br>
就像爬山一样，在平原期好好休息享受风景，但爬坡时要目标坚定大力攀登，这样就能享受顶峰的风景。&lt;br>
所谓“逆风蓄力，顺风起势”。&lt;/p>
&lt;p>希望我能把自己这一点才能，转换成旺盛的火苗，投入 Opus 的这把大火里。&lt;/p>
&lt;h2 id="六">（六）&lt;/h2>
&lt;p>最近工作上还有一个很好玩的感触，来自于讲英文。&lt;br>
Yes, speak English。&lt;br>
虽说是创业团队，但是我们同事来自各个国家和地区，&lt;br>
大家都用不同的乡音讲着同样的英语。&lt;/p>
&lt;p>热知识：两个朋友用英语沟通时，更吃力的其实是英语讲得更好的那位。&lt;br>
由于他讲的英语更标准，所以对面的朋友理解起来也更简单，&lt;br>
但对面朋友脑子中不会记得语态词性，更多还是得靠听来理解。&lt;br>
偷偷感谢一下我的同事们，我的英语顺畅沟通完全得益于他们强大的听力。&lt;/p>
&lt;p>除了语言能力外，英语相比于中文的表意是更直接的，&lt;br>
对我个人感觉尤其明显。&lt;br>
比如在给技术观点时，我用中文默认会委婉表达“那样可能更好”，&lt;br>
但用英文我就会更直白地说“No, I don&amp;rsquo;t recommend to do this.”&lt;br>
更直接的表意会带来更清晰的观点，&lt;br>
这确实也更接近奈飞文化中的“成年人文化”。&lt;/p>
&lt;h2 id="七">（七）&lt;/h2>
&lt;p>在工作之外的时间里，最近还对运动比较着迷，&lt;br>
不过鉴于运动是结果比过程重要，这个就等有结果了再来分享一二吧 :)&lt;/p>
&lt;p>过程与结果之争永远是一个迷人的话题，&lt;br>
不论是Mia&amp;amp;Sebastian的结局，还是Joker&amp;amp;Batman的正义之争，甚至是封控&amp;amp;放开的论战，&lt;br>
都是可以认真感受的品评。&lt;/p>
&lt;p>人最宝贵的所有就是时间，时间也会平等地浪费在每一个人身上。&lt;br>
从这一点而言，人注定是要当一个长期主义者的。&lt;/p>
&lt;p>当然啦，那又是另一篇文章了，希望以后的文章，比现在的更有营养也更可爱 :)&lt;/p>
&lt;p>（完）&lt;/p></description></item><item><title>骑行一年记</title><link>https://liriansu.com/posts/2023-10-16-cycling/</link><pubDate>Mon, 16 Oct 2023 20:09:04 +0800</pubDate><guid>https://liriansu.com/posts/2023-10-16-cycling/</guid><description>&lt;p>过去的一年来，&lt;br>
我骑行了 1000km+ 的距离。&lt;br>
骑行是孤独的，&lt;br>
但孤独也是美丽的。&lt;/p>
&lt;h1 id="契机">契机&lt;/h1>
&lt;p>以前上中学时，我有一阵总是周末骑到隔壁镇找女朋友玩，&lt;br>
记忆里的 5km 是尘土飞扬、野花丛生、时间飞逝的旅程。&lt;/p>
&lt;p>后来在大学的小树林单车店也买了车，&lt;br>
载室友郁翔的时间比载女朋友的时间多多了。&lt;br>
但是那个年代车多锁差，&lt;br>
大学四年我连着丢了四辆车。&lt;br>
后来回校跟学弟们感慨“校园里单车真容易丢”，&lt;br>
从他们疑惑的眼神里，&lt;br>
我看出了时代的参差。&lt;br>
这就是共享单车——新时代经济对旧时代文化的彻底冲击。&lt;br>
当然了，丢车不算什么好的旧时代文化，一点也不值得怀念。&lt;/p>
&lt;p>大学毕业以后，我就安心地当一个阳光宅男，&lt;br>
靠着高代谢维持着高热量的生活，再也没有认真运动过。&lt;br>
—— 直到 22 年幸福的封控生活把我抬到了 80kg。&lt;/p>
&lt;p>或许给我运动人格的转变找到了合适的理由？&lt;br>
这么想着的我，去迪卡侬逛了一圈，&lt;br>
在网上下单了一辆公路车：迪卡侬 RC100。&lt;/p>
&lt;h1 id="后勤">后勤&lt;/h1>
&lt;p>骑行跟跑步类似，是一项运动（此句为废话）。&lt;br>
骑行与跑步不同，需要更多的后勤工作。&lt;/p>
&lt;p>骑行最重要的是——要有一辆自行车。&lt;br>
市面上常见的有两种，公路车和山地车。&lt;br>
公路车一般是弯把细胎，适合铺装路面的骑行，&lt;br>
对于城市通勤、晨起夜骑咖啡骑的场景都是完美适配。&lt;br>
山地车一般是直把粗胎，避震效果良好，适合路况复杂的骑行，&lt;br>
对于山路草地、负重骑行的场景是非常适合的。&lt;br>
1000多元可以买到带变速的各方面都不错的自行车，&lt;br>
但假如按三分钟热度来算，每分钟要几百块，不便宜了。&lt;br>
于是我在下决心买车的前一个月，骑了30天共享单车：&lt;br>
得想自己证明一个决定是可坚持的。&lt;/p>
&lt;p>除了车以外，最重要的设备是头盔。&lt;br>
头盔这种东西跟寿险某种程度上很像：&lt;br>
你并不希望它发挥作用，&lt;br>
但买的时候总想算一下“投资回报率”。&lt;br>
在这一年的骑行旅途中，&lt;br>
除了压制我爆炸的头发，&lt;br>
我的头盔没有发挥任何实际作用。&lt;br>
这令我十分欣慰。&lt;/p>
&lt;p>剩下的后勤准备大致分为三个类别：防护、数据、消耗品。&lt;/p>
&lt;p>防护用品包括手套、速干衣、骑行裤、护膝、长袜，&lt;br>
这些零散的外设是我随着骑行旅途逐个获取的。&lt;br>
因为在实际的骑行中，我实际感受到了手疼、汗多、蛋疼、摔跤、脚滑。&lt;br>
每个人骑行的实际体感都是不一样的，&lt;br>
要么学会忍受，要么改进后勤。&lt;/p>
&lt;p>数据上的准备，包括体重秤、手环、码表、心率计、踏频计等。&lt;br>
最令我兴奋的是体重秤：“我都开始骑行了，你至少给我轻几斤吧？”&lt;br>
于是体重秤很诚实的告诉我：“你体重没变。”&lt;br>
（骑行确实不能减重，少吃才能减重）&lt;br>
数据是最诚实的伙伴，&lt;br>
没有数据前，我只能感受到自己是个菜鸡，&lt;br>
有了数据后，我就能量化地看到自己有多菜。&lt;/p>
&lt;p>消耗品则包括且不限于内胎、香蕉、运动饮料等等。&lt;br>
在骑行苏州的过程中，我尝试统计了一下自己的消耗：&lt;br>
大概是每百公里8L康师傅冰红茶。&lt;/p>
&lt;p>算上自行车，这一年陆陆续续花在骑行上的钱大概是5千多。&lt;br>
往年给手游老婆们氪的金，今年基本氪给自己了。&lt;/p>
&lt;p>骑行圈跟装机圈一样，也有攀比设备的价格党们。&lt;br>
但骑行也像跑步一样，最大的瓶颈永远是骑手本人。&lt;/p>
&lt;h1 id="路线">路线&lt;/h1>
&lt;p>在后勤工作还没做到位的情况下，&lt;br>
我就迫不及待地开始骑行了。&lt;br>
——甚至连网购的车还没到，&lt;br>
我就先戴上头盔，&lt;br>
骑上共享单车，&lt;br>
沿着之前查好的路线往返于公司和家之间。&lt;/p>
&lt;p>当时我常骑的路线是人民广场（黄浦区）到第六人民医院（徐汇区），&lt;br>
单程10公里，红绿灯30余个（……），全程耗时约50分钟，不计停时约30分钟。&lt;/p>
&lt;p>从我个人感受来说，&lt;br>
每天20公里是一个非常适合骑行的距离：&lt;br>
有一定的量，但不累，不用为此单独换衣服，如果下雨或是正装见客户就可以先不骑；&lt;br>
通勤时间可控，比地铁通勤也就多花几十分钟，但带来的是能迎着阳光上班的体验。&lt;/p>
&lt;p>上班通勤路线最大的挑战是路况。&lt;br>
市区通勤一般等价于被外卖小哥抢道、被违规停车挡道、被路边行人插道。&lt;br>
核心就是记住一句话：谁弱谁有理，但谁弱谁先死。&lt;br>
不论如何，希望大家行走、骑行、驾车都要注意安全。&lt;/p>
&lt;p>周末骑行的路线则有很多选择了。&lt;br>
我最喜欢的两条线路是龙腾大道往返和黄浦江绕圈。&lt;/p>
&lt;p>龙腾大道往返，路线是从龙美术馆到徐浦大桥，&lt;br>
往返一圈约14公里，是骑行团们晨骑喜欢的去处。&lt;br>
早上5点，徐汇滨江湖面辉映射出浅金色的阳光，&lt;br>
清晨的雾气打在了每一个努力爬坡的骑手腿上，&lt;br>
晨骑团在路口转弯发出的整齐花鼓声也是这幅画的一份子。&lt;/p>
&lt;p>黄浦江绕圈，则是一个更加休闲的路线。&lt;br>
上海沿着黄浦江摆放了多个渡口，&lt;br>
从三林路渡口过浦东，一直到东昌路渡口归浦西是我喜欢的路线。&lt;br>
假若是清晨出发，则一路上人烟稀少，偶有骑行俱乐部共行一路；&lt;br>
某次在傍晚出发，突然倾盆大雨，暴雨中躲在南浦大桥发光的肚皮下躲雨，&lt;br>
雨滴随着耳机里的音乐让整个世界都混进了同一个节奏。&lt;/p>
&lt;p>如此这般，非日常的体验会让日常格外美丽。&lt;/p>
&lt;h1 id="体验">体验&lt;/h1>
&lt;p>骑行的一年来，除去学修车、减了脂的这种副作用，&lt;br>
我最开心的一点是找到了“本命运动”：&lt;br>
假如英灵殿里有我，那我大概离 Rider 这个职介更近了。&lt;/p>
&lt;p>生命在于体验，体验产生回忆，回忆是快乐的，快乐则是生命的美好未来。&lt;/p>
&lt;p>骑行路过七宝时，阳光明媚的天气突然一道黑影掠过。&lt;br>
我愣了几秒以后才反应过来：一架飞机的影子恰巧掠过了我的肩上。&lt;br>
踩回闵行的路上，红灯路口一个反着坐在妈妈摩托上的小朋友好奇地看着我，&lt;br>
我虽然捂得严严实实，但还是努力对他做了个笑容，比了个赞，希望他快高长大。&lt;br>
在黄浦江绕圈的某天早上，也是突发大雨，我和陌生的骑手朋友躲在屋檐下聊了半小时，&lt;br>
共骑了半程，互换了微信，他邀我入骑行群，认识了更多的朋友。&lt;br>
从苏州归来的我，在省道边的一个休息站疲惫地停了下来，&lt;br>
服务员小妹妹则是特别贴心地给我拿了小板凳，示意我坐着休息一会儿。&lt;/p>
&lt;p>总的来说，骑行就是这样一个普通的运动：&lt;/p>
&lt;ul>
&lt;li>需要投入，但是不必攀比。&lt;/li>
&lt;li>无法减肥，但是上手简单。&lt;/li>
&lt;li>旅程孤独，但是世界很大。&lt;/li>
&lt;/ul>
&lt;p>在后续的时间里，&lt;br>
我计划尝试 200km 的单日沪杭挑战，&lt;br>
有可能的话以后也试试西藏骑行、环台湾岛、世界各处的骑行。&lt;br>
不过话说回来，现在还早，&lt;br>
先从通勤骑起来吧~&lt;/p>
&lt;p>（完）&lt;/p></description></item><item><title>我的妈妈苏琳</title><link>https://liriansu.com/posts/2023-08-17-my-mom-sulin/</link><pubDate>Thu, 17 Aug 2023 22:06:52 +0800</pubDate><guid>https://liriansu.com/posts/2023-08-17-my-mom-sulin/</guid><description>&lt;p>我的妈妈叫苏琳。&lt;br>
她还有一个弟弟和一个妹妹，&lt;br>
名字分别是“农”和“静”，&lt;br>
这几个名字都铿锵响亮，&lt;br>
大概也许都是外公取的吧。&lt;/p>
&lt;p>我时常会跟我妈聊起她小时候的事情。&lt;br>
在断断续续的记忆碎片里，&lt;br>
她从民国前讲到了我小时候，&lt;br>
我知道了我外公的爷爷以前就在湖南经商，&lt;br>
也听到了生于 1968 年的妈妈是如何津津有味地过着普通的生活。&lt;/p>
&lt;p>湖南的天气与上海没有太大的差别。&lt;br>
去年上海下了一阵雪，&lt;br>
我妈在语音电话中感慨：&lt;br>
她在像我这么大时（指30岁），&lt;br>
经历了携母带子在大雪天乘火车南下，&lt;br>
与搬家先行出发的我爸在广东汇合，&lt;br>
最终二人在广东定居，&lt;br>
如此教书三十年。&lt;/p>
&lt;p>“时间过起来可真快啊！”&lt;br>
苏琳老师如此感慨。&lt;br>
而后，她又对我补充了一句：&lt;br>
“感觉你嗖一下就长大了。”&lt;/p>
&lt;p>如今我儿时记忆已逐渐远去，&lt;br>
但父母小时候讲的故事总是难以忘怀。&lt;br>
其中一幕更是铭记于心：&lt;br>
小学做完作业后，我妈会捧着一本《岳飞演义》给我念上一段，&lt;br>
这种可以边听边问的“互动式评书”成了我翘首以盼的期待。&lt;br>
在那之后，虽然我再也没重读过这本书，&lt;br>
但岳母、牛皋、金兀术、岳云等形象也随着妈妈的话刻在了我的脑海中。&lt;/p>
&lt;p>前阵子我想起这桩往事，&lt;br>
又找我妈求证：“为什么我就记得你给我念了一本书？”&lt;br>
苏琳老师无奈地告诉我了真相：&lt;br>
那时因为我识字不多，&lt;br>
她又嫌注音版的儿童读本愚笨，&lt;br>
便尝试给我念了一段，&lt;br>
没想到一年就是大半年。&lt;br>
后来看我能囫囵吞枣地自己读，&lt;br>
就让我自力更生去读了。&lt;/p>
&lt;p>苏琳老师全权负责着她儿子的教育，&lt;br>
这也是她颇为自豪、颇有成就感的事情。&lt;br>
工作以后，我也体会到类似的感受：&lt;br>
作为程序员的我全权负责着家里面的计算机与网络，&lt;br>
这也让我颇为自豪、颇有成就感。&lt;/p>
&lt;p>苏琳老师教的是初中历史。&lt;br>
在学校教学任务忙的时候，&lt;br>
也曾经客串过语文、英语或地理老师。&lt;br>
后来在学校的安排下，&lt;br>
她每年都兼任着历史课组长和毕业班老师的工作。&lt;br>
我也才知道，&lt;br>
并不是所有老师都是一届教三年，&lt;br>
稀有的好老师原来是一年教一届。&lt;/p>
&lt;p>除了业务能力优秀，苏琳老师还很受学生喜欢。&lt;br>
不仅每年都会被学生票选为最受欢迎老师，&lt;br>
出门逛超市的苏琳老师也会遭遇毕业十几年的学生热情相认。&lt;br>
今年的毕业班上，&lt;br>
有学生听闻了她要退休的传言，&lt;br>
非常震惊地找苏琳老师求证，&lt;br>
她却逗学生：“我今年还没退休呢，你毕业以后记得回学校看老师哦！”&lt;/p>
&lt;p>苏琳老师也是最早的一批网民。&lt;br>
她在论坛里的名字叫“青夏”，&lt;br>
有着许多认识了十几年的网友。&lt;br>
最开始我好奇地问她：“这个论坛是做什么的？”&lt;br>
“是网友们交换种子的。”&lt;br>
我大为震惊：“交换种子？！？”&lt;/p>
&lt;p>是的，青夏是本地园艺论坛的一员。&lt;br>
她在家里收拾了一片种菜的天地。&lt;br>
这一片地里种了黄瓜、丝瓜、南瓜，&lt;br>
那一片地里种了芒果、火龙果、圣女果，&lt;br>
而在拐角处的那几十个花盆里，&lt;br>
分别是金银花、满天星、七彩凤、旱金莲等五彩缤纷的花朵们…&lt;/p>
&lt;p>园艺论坛偶尔会举办线下花友会。&lt;br>
青夏也带着花种子从线上蹦到了线下，&lt;br>
聚会地点一般是本地的公园，&lt;br>
花友们还会带水果、特产，&lt;br>
还有外地驱车赶来的花友参与这场盛会。&lt;br>
从花友会回来的青夏不仅会带着新鲜种子，&lt;br>
也会带着新认识的朋友新鲜事讲给她儿子听。&lt;/p>
&lt;p>后来我每次看到“中国人自带种菜基因”，&lt;br>
总有些疑惑与期待。&lt;br>
既觉得这句话不像是编的，&lt;br>
又不知道我的那部分基因何时觉醒。&lt;/p>
&lt;p>我外公退休后也沉迷过钓鱼种菜，&lt;br>
沉迷时，每天早上5点就要出门锄地，&lt;br>
后来身体不好也就在家享享清福。&lt;br>
我妈便挑选了些适合阳台种的菜拿给外公，&lt;br>
让他可以在小的花园里培育大的世界。&lt;/p>
&lt;p>身边的人也都知道苏琳老师是植物大师。&lt;br>
以前出门徒步时，&lt;br>
经常有朋友问她：“苏老师，这是什么花？这是什么树？这是什么植物？”&lt;br>
我也经常这么问她，&lt;br>
她同样的问题答了很多遍，&lt;br>
看我是真的不懂而且没记性，&lt;br>
便真诚地教我：“你可以下载一个百度，首页就有拍照识图的功能，很好用的。”&lt;br>
如今我看到路边的花花草草，&lt;br>
好奇心就有点骚动。&lt;/p>
&lt;p>就像你能从文字里读出来的一样，&lt;br>
苏琳老师有着盛开的好奇心与求知欲。&lt;br>
比如她一直会纠结汉字的正确读音，&lt;br>
遇到生僻字一定会现场查出正确读法，&lt;br>
也会纠正我爸和我的错误读音，&lt;br>
即使我们都不用做语文卷子了。&lt;br>
这或许也很大程度影响了我，&lt;br>
以及我听到优惠“卷”或者“阀”值时的毛躁程度。&lt;/p>
&lt;p>我妈今年满55岁要退休了。&lt;br>
不论按阴历生日七月初四，&lt;br>
还是按身份证生日8月22号来算，&lt;br>
这都是她过的最后一个暑假了。&lt;br>
她也终于下定了决心，&lt;br>
拉上我爸去西藏来了一次毕业旅行。&lt;/p>
&lt;p>一生里我只见到几次苏琳女士有真正想去的地方。&lt;br>
2008年，她差点报上了离家去四川的支教团。&lt;br>
但子女在，难远游。&lt;br>
后来十几年里，她一直期待着去西藏，&lt;br>
这次也总算是没有严重高反地顺利旅行了。&lt;br>
我为她感到高兴。&lt;/p>
&lt;p>从我出生起，妈妈就是妈妈的样子了。&lt;br>
但我总觉得，作为苏琳老师，妈妈也有着非常的潇洒一面。&lt;/p>
&lt;p>最了解我妈妈的人是我爸，&lt;br>
他对我妈妈的评价是：&lt;br>
你妈妈是有内美的人。&lt;br>
这句话与屈原自评惊人的一致：&lt;br>
纷吾既有此内美兮，又重之以修能。&lt;/p>
&lt;p>以前在网上搜索“苏琳”，&lt;br>
可以搜到第一只赴美的大熊猫就名为苏琳。&lt;br>
希望以后，苏琳老师也可以随着本文，&lt;br>
以一个潇洒的形象活在互联网的某个角落里，&lt;br>
就像青夏曾经也活跃在某个花友论坛里。&lt;br>
她退休的日子，&lt;br>
也肯定像她的学生们和受她影响的人们一样，&lt;br>
把普通的生活里过得津津有味。&lt;/p>
&lt;p>这就是我的妈妈，&lt;br>
苏琳老师。&lt;/p></description></item><item><title>在北极九章工作的这一年</title><link>https://liriansu.com/posts/2023-02-28-first-year-with-datarc/</link><pubDate>Tue, 28 Feb 2023 22:09:15 +0800</pubDate><guid>https://liriansu.com/posts/2023-02-28-first-year-with-datarc/</guid><description>&lt;p>与宇轩吃饭时，&lt;br>
突然意识到我已经来了北极一年整了。&lt;br>
在再惠工作一年时，&lt;br>
我写下了&lt;a href="https://liriansu.com/my-work">《我的工作》&lt;/a>，&lt;br>
今天或许是个合适的时间来记点什么。&lt;/p>
&lt;h1 id="引言">引言&lt;/h1>
&lt;p>致远刚入职北极的时候，&lt;br>
她经常与我感慨：“真的非常喜欢咱们北极，太符合我的口味了！”&lt;br>
我总会这么安慰她：“前半年总是新鲜的，长情才是对公司最好的告白。”&lt;/p>
&lt;p>同处新鲜期的我，&lt;br>
去年经常有给工作写点什么的冲动，&lt;br>
但也被我自己摁下来了。&lt;/p>
&lt;p>一年至今，热情稍退，热枕依然。&lt;br>
今日再回头，&lt;br>
可以从创业的心态、变化的环境、持续的思考这几个角度分享一些心得跟体会吧。&lt;/p>
&lt;h1 id="创业的心态">创业的心态&lt;/h1>
&lt;p>又从初创阶段开始做起，&lt;br>
终于可以有底气地说：&lt;br>
我确实很喜欢在创业型公司工作。&lt;/p>
&lt;h2 id="创新">创新&lt;/h2>
&lt;p>由于我司做的是行业里新的方向，&lt;br>
所以很多功能实现、产品体验都要摸着别人过河。&lt;br>
更有甚者，作为先发者还会被别人摸着过河，&lt;br>
当然了，最后还是得比拼产品功能体验。&lt;/p>
&lt;p>2022年我参与的好几个项目，&lt;br>
都是全球行业内只能找到寥寥几个竞品，&lt;br>
甚至还有首创的功能。&lt;br>
后来客户赞赏产品的时候，&lt;br>
我就像看着小孩考上了复旦一样开心。&lt;/p>
&lt;p>但是也有不少苦逼的时候，&lt;br>
我们也有许多胎死腹中的需求文档、&lt;br>
半路夭折的技术实现、&lt;br>
市场验证下急需优化的产品功能。&lt;/p>
&lt;p>创业做创新，&lt;br>
就像用有限的精力和资源，&lt;br>
加上无限的智慧和勇气，&lt;br>
去面对超限的困难和未知。&lt;/p>
&lt;h2 id="充实">充实&lt;/h2>
&lt;p>在工作了几年以后，&lt;br>
我的同龄人们基本对自己想要什么都很清楚。&lt;br>
想躺平的同学回了老家，&lt;br>
想稳定的同学进了大厂（前几年进的），&lt;br>
而我，有梦饮水饱。&lt;/p>
&lt;blockquote>
&lt;p>人还是要做事的，不做事不行。&lt;br>
—— &lt;a href="https://liriansu.com/my-grandma">我奶奶&lt;/a>&lt;/p>
&lt;/blockquote>
&lt;p>在北极做事情突出一个充实。&lt;br>
我们的工作方式是双月OKR + 单周迭代，&lt;br>
没有不写代码的 Tech Lead，&lt;br>
也没见到有不爱写代码的 Tech Lead。&lt;/p>
&lt;p>刚参加工作的我曾经受到过 &lt;code>Work Hard, Play Hard.&lt;/code> 的文化影响，&lt;br>
今天确实也沉浸在了这种开心充实的状态中。&lt;/p>
&lt;p>朋友们讨论何时提前退休，&lt;br>
而发出“希望一直开心的工作下去”的我，&lt;br>
就像一个可爱的异类一样，&lt;br>
跟大家开开心心地鬼混在了一起。&lt;/p>
&lt;p>我一向认为工作是生活的一部分。&lt;br>
因为喜欢，所以充实是幸福。&lt;/p>
&lt;h2 id="同道">同道&lt;/h2>
&lt;p>俗话叫“不怕别人聪明，也不怕别人努力，就怕别人比你聪明还比你努力。”&lt;br>
（另一个现实版本是有钱、帅气）&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/datarc/nana-node.png" alt="nana">&lt;/p>
&lt;p>跟前端周五分好的技术调研，&lt;br>
周一她就说“周末没啥事，我这部分做差不多了…”&lt;br>
能与同样在业余时间学习技术的人当队友，&lt;br>
真的是十分幸福。&lt;/p>
&lt;p>队友们在技术上也有相对一致的好品味，&lt;br>
像保持新版本依赖、单元测试覆盖率、清晰的提交历史与严苛的代码风格，&lt;br>
这些最佳实践也融入了大家的编码日常，&lt;br>
这让有一定技术洁癖的我感觉十分舒服。&lt;/p>
&lt;p>这一年也有几个我喜欢的队友离开了，&lt;br>
Andrew 去了美国，&lt;br>
Eva 追着林俊杰跑，&lt;br>
芷依在溜她的柴犬。&lt;br>
这一年也与更多志同道合的朋友成为了伙伴，&lt;br>
为了避免厚此薄彼，就不额外点名了 :)&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/datarc/pm-wish.png" alt="pm">&lt;/p>
&lt;blockquote>
&lt;p>👆 神奇的是，许愿生效了，一个月内确实赐予了&lt;/p>
&lt;/blockquote>
&lt;p>不过这也是生活美丽的地方：&lt;br>
没人能预测与谁会在转角再相遇。&lt;/p>
&lt;h1 id="变化的环境">变化的环境&lt;/h1>
&lt;p>刚毕业的时候，&lt;br>
听老板讲大环境趋势，&lt;br>
听前辈讲行业变革，&lt;br>
总是有种隔靴搔痒的感觉。&lt;br>
但如今视野更开阔以后，&lt;br>
确实对“个人的奋斗与历史的车轮”有了更加切身的体会。&lt;/p>
&lt;h2 id="经济形势">经济形势&lt;/h2>
&lt;p>当今世界影响最大的进程是中美事实上的脱钩，&lt;br>
背后是中美各自面对的经济难题。&lt;/p>
&lt;p>一方面影响是 UVCA 时代下的不确定性主题。&lt;br>
包括个人对未来搞钱形式的判断不一，&lt;br>
导致人才去向的不一；&lt;br>
也包括资本从收益率转向盈利率，&lt;br>
导致整体融资投资环境的风口变化。&lt;/p>
&lt;p>另一方面影响则是企业跟国际政治的绑定更紧。&lt;br>
不少外资企业逐步撤出了中国，&lt;br>
国内对专精特新、信创产业等有着非常高的需求。&lt;br>
因为我司是自研核心专利的信创公司，&lt;br>
这一年给很多客户讲解产品以后，&lt;br>
不仅功能本身收到了很好的反馈，&lt;br>
而且作为扎实做产品的信创公司也受到了很好的评价。&lt;/p>
&lt;p>以前我并没接触过多少500强级别的大客户，&lt;br>
但去年很快进入了状态，&lt;br>
实在是感谢带着我跑客户的牛逼销售伙伴们。&lt;/p>
&lt;h2 id="行业趋势">行业趋势&lt;/h2>
&lt;p>数据行业最大的趋势，是大家都在极力做低门槛。&lt;/p>
&lt;p>就像从刀塔、到英雄联盟、到王者荣耀，&lt;br>
操作门槛在降低，&lt;br>
但是玩家数目极大上升，&lt;br>
影响了更多人的娱乐方式。&lt;/p>
&lt;p>数据分析最早只有懂 SQL 或者懂 Python 的人才能做。&lt;br>
后来出现了 tableau、帆软这样的拖拽式 BI，&lt;br>
了解数据格式、数据关系的人就可以做报表了。&lt;br>
而北极做的是语义化的数据分析，&lt;br>
首页就是一个聊天框，会聊天就可以分析数据了。&lt;/p>
&lt;p>最近 ChatGPT 又火了一轮，&lt;br>
这次更加出圈，&lt;br>
倒是把行业趋势大大往前推了一把。&lt;br>
以前可能还要教育市场什么是“语义化增强型分析”，&lt;br>
现在经常会遇到很懂行可以深入交流的客户。&lt;/p>
&lt;h2 id="工作文化">工作文化&lt;/h2>
&lt;p>文化是时代跟水土的产物。&lt;br>
对于工作亦然。&lt;/p>
&lt;p>工作推进要讲文化。&lt;/p>
&lt;p>我在北极开始工作的时候，&lt;br>
给自己定下了一个规矩：&lt;br>
“不能有思维定势，不能有路径依赖。”&lt;br>
具体来说，就是我不能说任何类似&lt;br>
“我在前司是全线上k8s的”&lt;br>
或是“我们以前是后端功能保持向前兼容”这样的话。&lt;br>
一方面涉嫌在现女友面前夸前女友：居心不良，&lt;br>
另一方面也是不能依葫芦画瓢：要实事求是。&lt;br>
所以在推进技术决策、需求组织时，&lt;br>
我更愿意采用预研、讨论、共识、推进的节奏，&lt;br>
相比于直接推进“怎么做”，&lt;br>
让大家了解“为什么”是更重要的。&lt;/p>
&lt;p>团队沟通要讲文化。&lt;/p>
&lt;p>不同人因为不同背景、不同角度会有不同方式。&lt;br>
我一直不适应看大家吵架，&lt;br>
假如开会时有人观点激烈冲突，&lt;br>
我总会想建议大家先确定共识，&lt;br>
然后私下温和（也不一定温和）地讨论。&lt;br>
但这一年我时常在会议中发现，&lt;br>
几个队友吵着吵着也达成了一个共识，&lt;br>
并在这个过程中充分表达了自己的观点，&lt;br>
到了中午还一起勾肩搭背去吃盖浇饭……&lt;br>
确实，团队里不同人适应的沟通风格也是不一样的。&lt;/p>
&lt;p>也要适应时代变化。&lt;/p>
&lt;p>每个时代会有自己的“政治正确”。&lt;br>
在如今的工作文化里，&lt;br>
“要工资，更要发展”是比“吃亏就是占便宜”更能公开宣扬的理论，&lt;br>
“适量工作，恰当躺平”也比“努力，奋斗”有着更主流的思潮位。&lt;br>
所以在这个背景下，“结果导向”、“人情味”、“严于律己”是做好事情的最基础要求。&lt;/p>
&lt;p>时代变化伴随着文化变化，&lt;br>
文化变化要求组织形式的变化。&lt;/p>
&lt;p>虽然写的有点虚无缥缈了，&lt;br>
但这确实是最近我对世界的认知，&lt;br>
看起来我确实践行了自己的格言：&lt;br>
“唯心地思考，唯物地生活。”&lt;/p>
&lt;h1 id="持续的思考">持续的思考&lt;/h1>
&lt;p>我对这个小标题并不满意，&lt;br>
看起来“的”、“地”似乎写错了，&lt;br>
但我想讲的确实是一个持续的思考。&lt;/p>
&lt;p>&lt;a href="https://liriansu.com/adult-life">一直以来&lt;/a>我都有一个很大的恐惧，&lt;br>
就是担心自己变成1+N年工作经验的人：&lt;br>
只有工作的第一年在学习思考，&lt;br>
后面的N年都在机械重复。&lt;/p>
&lt;p>而我目前的工作也对我提出了新的挑战：&lt;br>
“避免做一个战术上勤奋、战略上懒惰的人。”&lt;/p>
&lt;p>就比如我们做产品，&lt;br>
看似有非常多事情可以做，&lt;br>
有无数的功能等待去完成。&lt;br>
但不加以深入思考，&lt;br>
就会陷入做起来很忙，&lt;br>
但实际上对客户不关键的陷阱中。&lt;/p>
&lt;p>“人云亦云”、“顺水推舟”、“三不原则”（不主动不抗拒不负责）&lt;br>
在我眼里都是“战术上勤奋、战略上懒惰”的 bad case。&lt;/p>
&lt;p>不论如何，人还是要多多学习一个的。&lt;/p>
&lt;h1 id="结语">结语&lt;/h1>
&lt;p>脚踩西瓜皮，写到哪里是哪里。&lt;br>
一连写到这，我也忘了要说啥。&lt;br>
那最后以一个小趣事结尾吧。&lt;/p>
&lt;p>一年前的“北极九章”并不叫“北极九章”，&lt;br>
当时的名字还叫“北极数据”。&lt;br>
2022年，这家名为“北极数据”的公司已经创立了三年有余，&lt;br>
但醉心于产品研发的创始人居然忘了申请商标，&lt;br>
于是只能顺势改名为“北极九章”完成一个品牌的升级。&lt;/p>
&lt;p>“北极九章”组成于“冰山理论”的“北极”跟“九章算术”的九章。&lt;br>
不过我个人倒是认为，&lt;br>
可能名字也会来源于创始人Allen特别喜欢的🐻这个动物，&lt;br>
以及“楚辞九章”这么一个美好的语言文学文本。&lt;/p>
&lt;p>最后，希望大家也都能像土豆一样，&lt;br>
在新的一年对自己发出“纷吾既有此内美兮，又重之以修能”的楚辞式感慨。&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/datarc/netflix.png" alt="netflix">&lt;/p>
&lt;p>（完）&lt;/p></description></item><item><title>杂思丨屁股决定脑袋</title><link>https://liriansu.com/posts/2022-09-26-thoughts-from-position/</link><pubDate>Mon, 26 Sep 2022 20:00:36 +0800</pubDate><guid>https://liriansu.com/posts/2022-09-26-thoughts-from-position/</guid><description>&lt;p>人贵在连续性，&lt;br>
即使前言不搭后语，&lt;br>
我的心中一直这么想道。&lt;br>
但真到了发现与旧日的我思考异化的那天，&lt;br>
自己不仅也是有点感慨的。&lt;/p>
&lt;h2 id="一招聘标准">（一）招聘标准&lt;/h2>
&lt;p>我经常与朋友分享招聘中的趣事，&lt;br>
其中有一个我以前很喜欢讲。&lt;/p>
&lt;p>当时公司面试后端工程师，&lt;br>
采用的是多轮面试与一票否决制的招聘制度，&lt;br>
我经常担任第一轮的面试官。&lt;br>
某一天，我与同事内推的归国小哥聊完了，&lt;br>
很开心地与队友们说：“这个候选人不错，可能会队友+1了！”&lt;br>
但一小时后，第二轮的面试官出来，面露难色：“这个候选人不太行啊，我给pass了。”&lt;br>
把候选人送走以后，大家问面试官为何，他复述了如此一个场景：&lt;/p>
&lt;p>在聊完了具体的计算机网络、数据库、服务器等话题以后，&lt;br>
面试官接着问：“你能讲讲你在上家公司做的最成功的一件事是什么吗？”&lt;br>
候选人非常开心地接过了话：&lt;br>
“当然可以！我上家公司是做衣服批发的，当时公司的物流成本居高不下，因为衣物占用了很多体积空间。&lt;br>
后来我发现了可以用上一种真空包装，在减少衣物体积的同时，不损失衣物质量！&lt;br>
最终给公司节省了上百万美元的费用呢！”&lt;/p>
&lt;p>每次讲完这个面试故事以后，&lt;br>
我的听众朋友们都会陷入沉默，&lt;br>
然后问道：“那这个跟后端工程师有什么关系呢？”&lt;br>
我们便一起哄笑：“对啊，这就是不合适的面试策略。”&lt;/p>
&lt;p>但不知何时起，&lt;br>
我心中常常浮现出讲完故事后跟着一起哄笑的场景，&lt;br>
这个场景散发出的回忆刺微微地痛着我。&lt;/p>
&lt;p>后来的我再也没跟新朋友们聊起过这个故事，&lt;br>
当面试官的时候也更有耐心。&lt;br>
过去作为纯技术面试官，会首先要求候选人写代码能力要好。&lt;br>
但如今作为面试官，我更看重候选人能解决事情的能力。&lt;br>
假如他给出了一个不切题的答案，&lt;br>
我会多问一句：“能不能分享一下这件事情对你职业上的影响呢？”&lt;/p>
&lt;p>当我们聊到招聘标准时，&lt;br>
招聘队友，确实跟招聘队员，会有着不同的看法。&lt;/p>
&lt;h2 id="二公司制度">（二）公司制度&lt;/h2>
&lt;p>今年我想得很多的一个话题就是远程工作。&lt;br>
一番思考以后，我发现了自己是一个彻底的双标狗：&lt;br>
“作为老板，我不愿意推行灵活远程办公制度。&lt;br>
作为员工，我希望公司推行灵活远程办公制度。”&lt;/p>
&lt;p>简单的逻辑思考如下：&lt;/p>
&lt;ol>
&lt;li>人只有自制力强，远程办公才不会损失效率。假如自制力差，远程办公就会损失效率。&lt;/li>
&lt;li>除非招聘环节中特别考核，否则员工们的自制力会呈正态分布。&lt;/li>
&lt;li>自制力高与生产力高，不是强相关的属性。&lt;/li>
&lt;/ol>
&lt;p>所以这个问题就得出了这么一个结论：&lt;br>
要推行远程办公，要么依赖员工自制力，要么就得接受效率损失。&lt;br>
而我们很清楚，工作中的二选一往往答案都是全选：&lt;br>
推行远程办公，既要依赖员工自制力，也得接受一定的效率损失。&lt;/p>
&lt;p>而像这种问题，与&lt;br>
“以防纸巾经常拿光，纸巾畅拿政策改为每人每周一包政策”、&lt;br>
“年假无限，但因为真的有人请了连续一个月假期，而改为法定的每年五天”一样，&lt;br>
它们不仅是人性的问题，还是利润最大化的问题、温度分割线的问题。&lt;/p>
&lt;p>公司制度，可能最终都会回落到中庸但正确的公约数。&lt;/p>
&lt;h2 id="三奋斗态度">（三）奋斗态度&lt;/h2>
&lt;p>有的时候相比于个人的思想转变，&lt;br>
群体的言论转变更是耐人寻味。&lt;/p>
&lt;blockquote>
&lt;p>关于工作本身的社会舆论一直在变化，&lt;br>
从以前的“支持宣扬狼性文化”到现在的“警惕提防996资本吸血”也不过数年时间。&lt;br>
但随着舆论两边踏浪的大众，&lt;br>
会有多少人真正思考过自己的事业、阶段、坚持、独特、苦难与成就呢？&lt;br>
个中之人，能坚持自己独立思考并走一条不后悔的路也是少之又少。&lt;br>
——&lt;a href="https://liriansu.com/say-think-behave">《我言、我知、我行》&lt;/a>&lt;/p>
&lt;/blockquote>
&lt;p>在躺平论引领风潮后，&lt;br>
如今越来越频繁地看到网上出现了更多不一样的声音：&lt;br>
“说着躺平，那楼主你躺平了吗？”&lt;br>
“996 真的是福报了，至少你还有工作。”&lt;br>
这种话里话外透出的悲观，&lt;br>
可以看得到大势影响下的集体性思潮。&lt;br>
这或许就是一种循环吧。&lt;/p>
&lt;p>另一个好玩的事，是我现在很难开口劝别人要努力工作了。&lt;br>
在我刚工作的时候，我一边开心，一边在&lt;a href="https://liriansu.com/my-2018-okr">2018年的OKR&lt;/a>里写下“工作的奖赏就是工作本身”。&lt;br>
到了今天，我被视为“有能力的前辈”，我也尝到了“工作的奖赏就是工作本身”的美妙滋味，&lt;br>
但我却无法红着脸说出这样的话语。&lt;/p>
&lt;p>少年劝进，是为活力。&lt;br>
中年劝进，是为油腻。&lt;/p>
&lt;h2 id="四写代码">（四）写代码&lt;/h2>
&lt;p>甚至写代码也会受到思考角度的影响。&lt;/p>
&lt;p>在无数网站的个人签名中，&lt;br>
我最喜欢自己在 GitHub 上留下的介绍：&lt;/p>
&lt;blockquote>
&lt;p>Lirian Su:&lt;br>
This is a vimer, a pythonista, a gopher&lt;br>
and a business man on the way.&lt;br>
Code for life rather than code for work.&lt;br>
Wubba lubba dub dub.&lt;/p>
&lt;/blockquote>
&lt;p>但随着能力与责任范围的变大，&lt;br>
产品、运营、业务也摆在了我的面前：&lt;br>
事业的成功需要领域的手段，技术也是其中之一。&lt;br>
于是“万般皆下品，唯有写代码”的思维开始松动，&lt;br>
逐渐走向了“工程师是解决问题的人”。&lt;/p>
&lt;p>如今在团队中，&lt;br>
假如瓶颈是技术，我就做技术；&lt;br>
假如瓶颈在产品，我便优化产品；&lt;br>
假如瓶颈在压缩衣服的物流费用，&lt;br>
我就会寻找一款真空压缩包。&lt;/p>
&lt;p>写到这儿，我不禁又想起了当年的那个小哥。&lt;br>
希望他找到了一个心仪的岗位，做着喜欢的事情，&lt;br>
聊到自己的成功经历时，眼里依然透着光。&lt;/p>
&lt;p>（完）&lt;/p></description></item><item><title>那个喊了十三声发物资的邻居</title><link>https://liriansu.com/posts/2022-04-11-neighbor-during-omicron/</link><pubDate>Mon, 11 Apr 2022 20:39:47 +0800</pubDate><guid>https://liriansu.com/posts/2022-04-11-neighbor-during-omicron/</guid><description>&lt;p>这次疫情我在上海这个风暴中心，&lt;br>
居家工作也使我对大大了解了小区情况。&lt;br>
居委书记住在我们楼，&lt;br>
隔壁住着一个三口之家，&lt;br>
楼下还存在一位以最大音量公放音乐的狂热刀郎粉丝。&lt;br>
但这一切都比不上那个喊了十三声发物资的邻居。&lt;/p>
&lt;p>第一声呐喊是在早上开晨会的时候。&lt;br>
逐渐炙热的天气让我推开了窗，&lt;br>
温热的空气带着一句“发物资！”窜了进房间，&lt;br>
击中了不知所措的我，&lt;br>
一时间分不清是耳机里北京会议室的戏谑，&lt;br>
还是上海隔离中的压抑。&lt;/p>
&lt;p>第二声呐喊紧随其后。&lt;br>
一声“我要物资！”以精准的主谓宾表达了诉求。&lt;br>
疫情褪下了马斯洛虚假的繁华，&lt;br>
让大家都在第一层级需求硬碰硬。&lt;br>
Mia 说最近的情景经常让她想到三体，&lt;br>
或许就是这种感觉吧。&lt;/p>
&lt;p>第三声呐喊就没那么有力了。&lt;br>
“物资…”的尾音逐渐在风中散去，&lt;br>
四月带来了你的呼喊，&lt;br>
但曹刿不会骗人，三而竭。&lt;/p>
&lt;p>第四声、第五声呐喊过了一会才传来。&lt;br>
“物资呢？发物资！”六个字混杂了不甘、不忿、不服，&lt;br>
两个符号也修辞了提问、反问、设问。&lt;br>
整个小区既处在白天的嘈杂里，&lt;br>
又处在呐喊衬托下的寂静中。&lt;br>
或许其它人也和我一样，&lt;br>
在微信里发“笑死，我们隔壁楼有人大喊发物资”，&lt;br>
同时扮演一个心情复杂的看客吧。&lt;/p>
&lt;p>第七声、第八声呐喊来的十分意外。&lt;br>
笑也笑过了，我本来以为可以回归正常的线上工作。&lt;br>
但没想到邻居好像掏出了一个铁盆，&lt;br>
边敲边喊：“发物资！咚咚咚！发物资！咚咚咚！”&lt;br>
仿佛洗菜的铁盆临时被委以重任，&lt;br>
它便抖擞精神不负众望地发出了振聋发聩之声。&lt;/p>
&lt;p>第九声呐喊稍微柔和了些。&lt;br>
可能是敲盆的声音也吵到了自己的耳朵，&lt;br>
邻居停下了手，但没有闭上嘴。&lt;br>
“物资！”这两个字的呐喊穿透我的耳膜直达我的心灵，&lt;br>
我不禁也想，还好我们抢菜有收获，公司有帮助，&lt;br>
才不至于在2022年体验儿时父母口中的艰辛。&lt;/p>
&lt;p>第十声呐喊后来一直没出现。&lt;br>
我们小区一共是五六栋高层塔楼，&lt;br>
每栋楼住了一两千人，&lt;br>
疫情期间大家也难得在家集中做饭。&lt;br>
要是实在没菜了，&lt;br>
可以用邻居家的炒胡萝卜香味下饭，&lt;br>
我这么跟 Mia 开玩笑道。&lt;br>
可能是中午的油烟声盖住了这声呐喊，&lt;br>
这句“发物资”被大家有意识地错过了。&lt;/p>
&lt;p>第十一声、第十二声呐喊带着一丝阴阳怪气。&lt;br>
“有没有物资！发不发物资！”的两句感叹号问句发泄出了一个月来的情绪。&lt;br>
在窗前坐着的我也站了起来，&lt;br>
想用双耳效应找一下这位大哥究竟在哪。&lt;br>
但找一句曾经的话，就像收一盆泼出去的水，&lt;br>
有回忆、有现场，但没可能、也没办法，&lt;br>
就像许多人的爱情就是这么结束的一样，&lt;br>
喜剧的背后是悲剧，悲剧的背后也是喜剧，&lt;br>
生活就是莫比乌斯环，&lt;br>
总是有人听到一个词就在乱用……&lt;/p>
&lt;p>纷乱的情绪中，我似乎听到了第十三声呐喊，&lt;br>
又是“我要物资！”这句简单直白，但又希望渺茫的需求。&lt;br>
但我似乎也没听见这声呐喊，&lt;br>
反思了一下，&lt;br>
隔离的一个月来除了发过一次物资，&lt;br>
其它时间我也只能靠自己的手来抢菜、抢肉、抢蛋、抢奶。&lt;/p>
&lt;p>让这哥们去喊吧，&lt;br>
希望他有吃有喝。&lt;br>
这么想着，我站起来，关上了窗。&lt;/p>
&lt;p>（完）&lt;/p></description></item><item><title>再惠教会我的五句话</title><link>https://liriansu.com/posts/2022-02-24-ways-in-zaihui/</link><pubDate>Thu, 24 Feb 2022 18:00:00 +0800</pubDate><guid>https://liriansu.com/posts/2022-02-24-ways-in-zaihui/</guid><description>&lt;p>前阵子我跟洋神感慨，&lt;br>
这段在再惠的经历是我非常宝贵的财富。&lt;br>
今天或许是个合适的日子，&lt;br>
就让我挑拣一二，&lt;br>
把其中最亮的几颗宝石分享给大家。&lt;/p>
&lt;blockquote>
&lt;p>本文适合伴以 Daft Punk 的 Veridis Quo 作为背景音乐，&lt;br>
这样你就可以获取与我写作时相类似的心境。&lt;/p>
&lt;/blockquote>
&lt;h1 id="边工作边生活">边工作，边生活&lt;/h1>
&lt;p>毕业后接触到工作生活两点一线的我，&lt;br>
心中一直萦绕着一个问题：&lt;br>
“虽然大家都说要 Work Life Balance，&lt;br>
但我究竟喜欢怎样的 Work Life Balance 呢？”&lt;/p>
&lt;p>后来我发现，我所喜欢的状态，就是&lt;strong>边工作，边生活&lt;/strong>。&lt;/p>
&lt;p>入职再惠以后，某天回家我很兴奋地跟 Mia 感慨：&lt;br>
“再惠的队友们跟我是同类人！&lt;br>
他们追番打机，周末也会写代码！”&lt;/p>
&lt;p>住在塘桥的我，很快交到了朋友，&lt;br>
与津铭、仲印、旭凤组成了4号线4雄。&lt;br>
不论是上班下班，&lt;br>
我们一边嘲讽 Python/Javascript 哪个更烂，&lt;br>
也一边吹捧说对方学到了廖雪峰/尤雨溪的三成功力，&lt;br>
有时还会聊聊多想买任天堂新出的 Switch 游戏机。&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/switch.jpg" alt="switch">&lt;/p>
&lt;p>项目忙的时候我们也会在周六加会班，&lt;br>
有的队友期待加班时的加餐，&lt;br>
也有队友期待事情做完以后，&lt;br>
赌上奶茶的德扑大战。&lt;/p>
&lt;p>在这样的环境下，工作与生活并没有写死的隔阂。&lt;br>
大家既是工作上的同事，&lt;br>
也是生活里的朋友，&lt;br>
我们也彼此互称为伙伴。&lt;br>
有些伙伴间化学反应过了头，也会发展成情侣，&lt;br>
光是我身边就产生了10对以上的情侣（总感觉哪里不对）。&lt;/p>
&lt;p>大家并不把公司看作是“老板的公司”，&lt;br>
而是看作是“我们的公司”。&lt;br>
怀揣着同样愿景的人，&lt;br>
做事的时候也不会瞻前顾后。&lt;br>
去酒吧团建时，&lt;br>
一个伙伴还很兴奋地给老板娘推荐了我们合作的点菜机，&lt;br>
当然他义正言辞地否定了我们对他动机的怀疑。&lt;/p>
&lt;p>对我而言，&lt;br>
工作本身就是生活，&lt;br>
跟喜欢的人做热爱的事，&lt;br>
这就是最好的 Work Life Balance。&lt;/p>
&lt;h1 id="谋其政在其位">谋其政，在其位&lt;/h1>
&lt;p>子曰：不在其位，不谋其政。&lt;br>
但我从一线开发到 Leader 的升级之路上，&lt;br>
体会最深的却是这句话的“逆反定理”：&lt;br>
&lt;strong>谋其政，在其位&lt;/strong>。&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/weibo/way_up.png" alt="way-up">&lt;/p>
&lt;p>有些职场伙伴会存在预期差的抉择：&lt;br>
“是先给我加薪，我再做更多事情呢？&lt;br>
还是先奉献更多，然后再谋求加薪？”&lt;br>
这个困境非常常见，&lt;br>
我总会选先承担更多责任。&lt;/p>
&lt;p>往小了说，升职加薪需要理由或借口。&lt;br>
往大了说，创业的路径就是先在不确定性中寻找路径，&lt;br>
然后产生创造性的价值。&lt;/p>
&lt;p>做点菜机业务还没招到Windows开发的伙伴时，&lt;br>
我握着刚学的C#开始上手。&lt;br>
做社群业务从零到一需要用户积累时，&lt;br>
我拉着地推就去扫码加人。&lt;br>
团队分工项目缺少责任人时，&lt;br>
第一时间举手自荐的也总有我。&lt;/p>
&lt;p>权利与义务总是共生的，&lt;br>
不必过于在意他们的顺序。&lt;/p>
&lt;p>或许这跟不同的公司有关，&lt;br>
再惠不吝于奖赏付出努力做出成绩的伙伴。&lt;br>
或许这也跟不同人的气质有关。&lt;br>
Mia 以后会变成“自由而无用的灵魂”，&lt;br>
但我的印记大概永远都是“选择了交大，就选择了责任”…&lt;/p>
&lt;h1 id="身段软站得稳">身段软，站得稳&lt;/h1>
&lt;p>工作前听“拥抱变化”四个字，&lt;br>
是没什么切身体会的。&lt;br>
直到工作了以后，才明白这四个字的重量。&lt;/p>
&lt;p>在再惠我换过好几个组，&lt;br>
亲口通知了最好的朋友他被炒的消息，&lt;br>
经历过整个事业部的撤裁，&lt;br>
也看过水土不服的高管空降后火速撤退。&lt;/p>
&lt;p>每次我都会想到台风过境后不受影响的小草，&lt;br>
&lt;strong>身段软，站得稳&lt;/strong>。&lt;/p>
&lt;p>身段软，意味着不骄傲、不自满。&lt;br>
CTO华哥从百度被挖来再惠以后，&lt;br>
并没有握锤找钉、把所有的流程百度化。&lt;br>
最终他以再惠的方式，&lt;br>
产销结合，&lt;br>
推进了最适合业务的产品技术。&lt;/p>
&lt;p>身段软，也意味着不屈不挠不放弃。&lt;br>
在推行更高的代码标准、更严格的编码规则时，&lt;br>
一开始大家都无从下手，&lt;br>
屎山陋习过重无法推进，&lt;br>
但后来团队每个人都认可并做到了高标准。&lt;/p>
&lt;p>不论是走出舒适区迎接变化，&lt;br>
还是尝试引入鲇鱼创造变化，&lt;br>
拥抱变化的最好方式就是微笑着面对他。&lt;/p>
&lt;h1 id="耐得烦霸得蛮">耐得烦，霸得蛮&lt;/h1>
&lt;p>做好事情要&lt;strong>耐得烦，霸得蛮&lt;/strong>，&lt;br>
就像发条技师经常跟我们讲的一样：&lt;br>
“长跑比赛乌龟胜利了。”&lt;/p>
&lt;p>再惠所处的本地生活行业，&lt;br>
非常注重对客户的服务质量。&lt;br>
给客户提供的优质服务，&lt;br>
就来源于每次服务的持续优质。&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/sad_lirian.png" alt="sad-lirian">&lt;/p>
&lt;p>这也偶尔会给我带来精力磨损导致的疲惫，&lt;br>
但更多时候想想像二狗这样的伙伴也会在周六录一天主动营销，&lt;br>
我便很快会被彼此的斗志所感染。&lt;del>（总不能比二狗差吧）&lt;/del>&lt;/p>
&lt;p>即使是技术领域的工程化，&lt;br>
也需要持续地添砖加瓦。&lt;br>
我们最早的手动拉代码发布，&lt;br>
发展到到今天的调试发版报警全自动化流程，&lt;br>
所有的想法都是六年间的一个个 commit 铸成的。&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/kevin_repo.png" alt="kevin-repo">&lt;/p>
&lt;p>人会对一蹴而就的抽卡感到兴奋，&lt;br>
但日月兼程的养成才是我的乐趣。&lt;/p>
&lt;h1 id="路何方在脚下">路何方？在脚下&lt;/h1>
&lt;p>我跟 Mia 戏称自己是 “米Boy”：&lt;br>
喜欢的是米娅，玩的是米哈游，用的是小米系产品。&lt;br>
我对小米一半的了解起源于雷军，&lt;br>
而我对雷总一半的了解起源于《R U OK》…&lt;/p>
&lt;p>当我们能主导事业的方向时，&lt;br>
一定会问自己的问题是：“&lt;strong>路何方&lt;/strong>”？&lt;br>
此时的回答就是“&lt;strong>在脚下&lt;/strong>”：&lt;br>
不论别人说的怎么样，就是放手去做就好。&lt;/p>
&lt;p>就像主站上灰度发布之前，&lt;br>
内部研讨总有觉得现在流量不算大，&lt;br>
流量路径尚未治理的各种担忧。&lt;br>
但只要真正去做了，&lt;br>
就会实际地发现灰度能有效地控制问题影响范围，&lt;br>
但也对代码兼容性提出了新的要求。&lt;/p>
&lt;p>职场中也一样，&lt;br>
对工作、职位的判断也跟小马过河一个道理：&lt;br>
驼的是盐还是海绵只有自己知道，&lt;br>
水有多深只有走过去才知道，&lt;br>
真正的道路是自己双脚走出来的。&lt;/p>
&lt;p>更多的选择往往不是幸福，&lt;br>
它带来的可能是更多的烦恼。&lt;br>
就如同苇名一心教导的那样：&lt;/p>
&lt;blockquote>
&lt;p>“犹豫就会败北。”&lt;/p>
&lt;p>—— 苇名一心&lt;/p>
&lt;/blockquote>
&lt;p>（完）&lt;/p></description></item><item><title>2021, 我微博没了</title><link>https://liriansu.com/posts/2022-01-16-kill-weibo/</link><pubDate>Sun, 16 Jan 2022 19:52:27 +0800</pubDate><guid>https://liriansu.com/posts/2022-01-16-kill-weibo/</guid><description>&lt;p>年底的某一天，&lt;br>
我日常地登上了微博，&lt;br>
收到了惩戒的一条消息：&lt;br>
@浮云 微博没了？&lt;/p>
&lt;h2 id="被夹了">被夹了&lt;/h2>
&lt;p>对我而言，&lt;br>
一方面这是意料之中的事情。&lt;br>
互联网服务之靠谱，&lt;br>
就像百度空间给我的体验。&lt;br>
另一方面这也是让人伤心的事情，&lt;br>
毕竟十年来我不在朋友圈感慨的肺腑之言，&lt;br>
都留在了微博里，&lt;br>
它也拥有着我素未谋面过的网友关系链们。&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/weibo/baidu_wenzhang.png" alt="baidu_wenzhang">&lt;/p>
&lt;p>我尝试着去申诉，微博给我回了个邮件，大意是：&lt;br>
“经我们审核，你微博太黄了，所以被封。（注：永远无法解封）”&lt;/p>
&lt;p>这让我很头大。&lt;br>
我既想要回我的账号，&lt;br>
又不想被迫承认我不涩。&lt;/p>
&lt;p>朋友们知道我申诉无用以后，&lt;br>
纷纷为我鸣不平，&lt;br>
并让我展示下究竟我发啥了。&lt;/p>
&lt;p>我很无奈，只是让他们关注了禾野。&lt;br>
只不过我的防爆红宣言或许得重新声明一次了：&lt;br>
&lt;img src="https://liriansu.com/assets/pics/weibo/be_famous.png" alt="be_famous">&lt;/p>
&lt;p>写到这里，&lt;br>
我决定给微博举办一场小型的葬礼，&lt;br>
葬礼的内容就是我2021年的随想。&lt;/p>
&lt;h2 id="考完了">考完了&lt;/h2>
&lt;p>父辈们有着比我辈们多的兄弟姐妹，&lt;br>
可能这也是他们比我更能享受家庭温情的原因。&lt;/p>
&lt;p>年初被小姨夫（我称呼为叔叔）的朋友启发了可以去“买个文凭”，&lt;br>
于是年末我跟 Mia 就一起去参加了全国统考。&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/weibo/work_a_life.png" alt="work_a_life">&lt;/p>
&lt;p>面试还算顺利，笔试还算麻木。&lt;/p>
&lt;p>因为很久没正经当过面试者了，&lt;br>
去母校面试的感觉尤其错乱。&lt;br>
这里多了一颗树，那里多了一个工地充斥在我考前的大脑里。&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/weibo/waiting.png" alt="waiting">&lt;/p>
&lt;p>就像一个矛盾的闻一多，&lt;br>
我有时说了不做，做了不说，&lt;br>
但更多时候是先说再做，边做边说。&lt;/p>
&lt;p>对我而言，想创业就像是要过河，&lt;br>
我知道最终我会在对岸，&lt;br>
也明白有许多种过河的法子。&lt;br>
但也觉得旅途还长，&lt;br>
总能再等等，&lt;br>
“优势在我”。&lt;/p>
&lt;h2 id="干活了">干活了&lt;/h2>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/weibo/stay.png" alt="stay">&lt;/p>
&lt;p>即使身处软件行业，&lt;br>
近两年我也能感受到从“反内卷”到“反卷”的思潮涌动。&lt;br>
有时我感觉这思潮像一桌人一起吃饭，&lt;br>
养尊处优的人劝面黄肌瘦的人“少吃点不健康的肉，多吃点健康的青菜”。&lt;/p>
&lt;p>就像是被云朵裹挟一样，跟着走只因为飘了。&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/weibo/friend_salary.png" alt="friend_salary">&lt;/p>
&lt;p>我时常感觉世界很多道理都是很浅显的，&lt;br>
就像是我小时候常听的那句“劳动最光荣”，&lt;br>
又或者是外公会念叨的“干活，然后吃五碗饭”。&lt;/p>
&lt;p>天才的瞬间在日复一日的坚持下会变为天才的永恒。&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/weibo/teammate.png" alt="teammate">&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/weibo/coding.png" alt="coding">&lt;/p>
&lt;p>啊，永恒。&lt;br>
对了，21年我最喜欢的角色是雷电将军。&lt;/p>
&lt;h2 id="变强了">变强了&lt;/h2>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/weibo/okr.png" alt="okr">&lt;/p>
&lt;p>年末的时候，我跟 Mia 感慨说三个目标都没达到。&lt;br>
体重来到了 145, 书只看了 10 本，投资收益在 -8%（然后元旦后来到了 -20%&amp;hellip;）&lt;br>
不过我也安慰自己：“我比你弱没什么丢人的。”&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/weibo/think.png" alt="think">&lt;/p>
&lt;blockquote>
&lt;p>我们互称对方公司为“学校”&lt;/p>
&lt;/blockquote>
&lt;p>有时我们也会讨论其他情侣的相处方式，&lt;br>
对比下来我们戏称自己为“互相竞争”。&lt;br>
毕竟考研前我半夜偷偷做数学题的行为，让 Mia 非常不屑。&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/weibo/night_with_mia.png" alt="night_with_mia">&lt;/p>
&lt;p>翻看着 21年 的自我，&lt;br>
相对论再一次地应验了：&lt;br>
过去的时间总是如梭的，&lt;br>
未来的时间总是煎熬的。&lt;/p>
&lt;p>人在世界上无法独一无二地存活，&lt;br>
或许一千个人眼中只有一个哈姆雷特，&lt;br>
或许数学期望是五百多个，&lt;br>
或者也是一千个。&lt;br>
不过总的来说，哈姆雷特好像也跟我差不多，&lt;br>
一样地不孤独。&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/weibo/same_with_me.png" alt="same_with_me">&lt;/p></description></item><item><title>Python 这几年都更新了啥</title><link>https://liriansu.com/posts/2021-10-21-whats-new-in-python-these-years/</link><pubDate>Thu, 21 Oct 2021 20:26:58 +0800</pubDate><guid>https://liriansu.com/posts/2021-10-21-whats-new-in-python-these-years/</guid><description>&lt;p>最近我们终于全线升到了 py39/go117,&lt;br>
在大家对 go 新特性兴奋之余，&lt;br>
@ackerr 提了一个很犀利的问题：&lt;br>
“Python 新版本都更新了啥？”&lt;/p>
&lt;p>确实，&lt;br>
除了 f-strings/dataclasses 这种大家可能熟知的功能，&lt;br>
新的版本究竟更新了什么呢？&lt;/p>
&lt;p>以前 dota 一个小版本的 changelog 都能读的津津有味的我，&lt;br>
今天决定咀嚼一遍从 py36 至 py310 的更新日志 &lt;del>（HOHO&lt;/del>&lt;/p>
&lt;blockquote>
&lt;p>以下代码片段都可以在最新的 Python 3.10.0 Repl 中执行。&lt;/p>
&lt;/blockquote>
&lt;h1 id="whats-new-in-python-36py36">&lt;a href="https://docs.python.org/3/whatsnew/3.6.html">What&amp;rsquo;s new in Python 3.6&lt;/a>&lt;/h1>
&lt;p>Python 3.6 是在 2016-12-23 发布的，官方维护至 2021-12-23。&lt;br>
感知比较大的几个改动包括：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python3" data-lang="python3">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 字符串拼接中，支持使用 f-strings 的 inline 拼接方法&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 终于能像 JS 那样方便地进行字符串拼接了&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>name &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;ackerr&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>precision &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">2&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>height &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">183.2&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">assert&lt;/span> &lt;span style="color:#e6db74">f&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">{&lt;/span>name&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74"> is &lt;/span>&lt;span style="color:#e6db74">{&lt;/span>height&lt;span style="color:#e6db74">:&lt;/span>&lt;span style="color:#e6db74">0.&lt;/span>&lt;span style="color:#e6db74">{&lt;/span>precision&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">f&lt;/span>&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">cm tall.&amp;#34;&lt;/span> &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#e6db74">&amp;#34;ackerr is 183.20cm tall.&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 常数定义中，可以使用下划线增加可阅读性&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>number &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">3_735_928_559&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>magic &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0xDEAD_BEEF&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">assert&lt;/span> number &lt;span style="color:#f92672">==&lt;/span> magic
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 变量定义中，支持类型声明了&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 值得注意的是 Python 依旧不是强类型，只是写在了 __annotations__ 这个变量里&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">import&lt;/span> typing
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>numbers: typing&lt;span style="color:#f92672">.&lt;/span>List[int] &lt;span style="color:#f92672">=&lt;/span> [&lt;span style="color:#ae81ff">1&lt;/span>,&lt;span style="color:#ae81ff">1&lt;/span>,&lt;span style="color:#ae81ff">4&lt;/span>,&lt;span style="color:#ae81ff">5&lt;/span>,&lt;span style="color:#ae81ff">1&lt;/span>,&lt;span style="color:#ae81ff">4&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>complex_data: typing&lt;span style="color:#f92672">.&lt;/span>Dict[int, typing&lt;span style="color:#f92672">.&lt;/span>Set[int]] &lt;span style="color:#f92672">=&lt;/span> {}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">assert&lt;/span> &lt;span style="color:#e6db74">&amp;#34;complex_data&amp;#34;&lt;/span> &lt;span style="color:#f92672">in&lt;/span> __annotations__
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 加了一个 enum.auto 的函数，开发者不用费心去自增了&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">import&lt;/span> enum
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">Colors&lt;/span>(enum&lt;span style="color:#f92672">.&lt;/span>Enum):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> R &lt;span style="color:#f92672">=&lt;/span> enum&lt;span style="color:#f92672">.&lt;/span>auto()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> G &lt;span style="color:#f92672">=&lt;/span> enum&lt;span style="color:#f92672">.&lt;/span>auto()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> B &lt;span style="color:#f92672">=&lt;/span> enum&lt;span style="color:#f92672">.&lt;/span>auto()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">assert&lt;/span> Colors&lt;span style="color:#f92672">.&lt;/span>B&lt;span style="color:#f92672">.&lt;/span>value &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#ae81ff">3&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>其它的一句话更新包括：&lt;/p>
&lt;ul>
&lt;li>Windows 上默认编码都设定为 &lt;code>utf-8&lt;/code>.&lt;/li>
&lt;li>修改了 dict 的实现，使其内存占用量比 py35 下降了 25%.&lt;/li>
&lt;li>标准包 &lt;code>asyncio&lt;/code> 更新了一大串功能，使其变得能用了.&lt;/li>
&lt;/ul>
&lt;h1 id="whats-new-in-python-37py37">&lt;a href="https://docs.python.org/3/whatsnew/3.7.html">What&amp;rsquo;s new in Python 3.7&lt;/a>&lt;/h1>
&lt;p>Python 3.7 是在 2018-06-27 发布的，官方维护至 2023-06-27。&lt;br>
感知比较大的几个改动包括：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python3" data-lang="python3">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 类型系统支持惰性求值了，可以不需要用字符串来指代自己了&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">from&lt;/span> __future__ &lt;span style="color:#f92672">import&lt;/span> annotations
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">QuerySet&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">def&lt;/span> &lt;span style="color:#a6e22e">filter&lt;/span>(self, &lt;span style="color:#f92672">**&lt;/span>params) &lt;span style="color:#f92672">-&amp;gt;&lt;/span> QuerySet:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;&amp;#34;&amp;#34;some database filter&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 新增了 dataclass 标准包&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 相比于 dict 传参大大优化了可读性&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">import&lt;/span> dataclasses &lt;span style="color:#66d9ef">as&lt;/span> dc
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">@dc&lt;/span>&lt;span style="color:#f92672">.&lt;/span>dataclass
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">Person&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> name: str
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> age: int
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> gender: str &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#39;Unknown&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">assert&lt;/span> Person(&lt;span style="color:#e6db74">&amp;#39;me&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;24&amp;#39;&lt;/span>)&lt;span style="color:#f92672">.&lt;/span>gender &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#e6db74">&amp;#39;Unknown&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>其它的一句话更新包括：&lt;/p>
&lt;ul>
&lt;li>&lt;code>async&lt;/code>/&lt;code>await&lt;/code> 现在是保留关键字了.&lt;/li>
&lt;li>新增了 &lt;code>breakpoint()&lt;/code> 系统函数用于调试.&lt;/li>
&lt;li>可以通过定义包的 &lt;code>__getattr__()&lt;/code> 来控制包变量的访问行为.&lt;/li>
&lt;li>标准包 &lt;code>time&lt;/code> 支持了纳秒级的精度.&lt;/li>
&lt;li>标准包 &lt;code>asyncio&lt;/code> 更新了一大串功能，使其变得好用了.&lt;/li>
&lt;/ul>
&lt;h1 id="whats-new-in-python-38py38">&lt;a href="https://docs.python.org/3/whatsnew/3.8.html">What&amp;rsquo;s new in Python 3.8&lt;/a>&lt;/h1>
&lt;p>Python 3.8 是在 2019-10-14 发布的，官方维护至 2024-10-14。&lt;br>
感知比较大的几个改动包括：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python3" data-lang="python3">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 新增了赋值判断的语法（也被形象地叫做海象操作符）&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">import&lt;/span> re
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">if&lt;/span> match &lt;span style="color:#f92672">:=&lt;/span> re&lt;span style="color:#f92672">.&lt;/span>search(&lt;span style="color:#e6db74">r&lt;/span>&lt;span style="color:#e6db74">&amp;#34;(\d+)%&amp;#34;&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;Total coverage: 80%&amp;#34;&lt;/span>):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> print(&lt;span style="color:#e6db74">&amp;#34;Coverage is {match.group(1)}&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 函数支持用 `/` 限制非命名参数&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">def&lt;/span> &lt;span style="color:#a6e22e">calculate_data_length&lt;/span>(data, &lt;span style="color:#f92672">/&lt;/span>):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">pass&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 官方指出，这种情况 `calculate_data_length(data=data)` 的可读性显然更低，其实可以在定义函数时禁掉&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 而且该语法可以避免 `**kwargs` 传参冲突的情况&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">def&lt;/span> &lt;span style="color:#a6e22e">get_values&lt;/span>(data, &lt;span style="color:#f92672">/&lt;/span>, &lt;span style="color:#f92672">**&lt;/span>kwargs):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> print(data, kwargs)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>get_values({}, data&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#39;some_data&amp;#39;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># f-strings 支持了自解释的语法&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>name &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;ackerr&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">assert&lt;/span> &lt;span style="color:#e6db74">f&lt;/span>&lt;span style="color:#e6db74">&amp;#34;Debug: &lt;/span>&lt;span style="color:#e6db74">{&lt;/span>name&lt;span style="color:#e6db74">=}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span> &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Debug: name=&amp;#39;ackerr&amp;#39;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 新增了 `functools.cached_property` 方法，支持属性的缓存&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">import&lt;/span> functools
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">DB&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">@functools&lt;/span>&lt;span style="color:#f92672">.&lt;/span>cached_property
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">def&lt;/span> &lt;span style="color:#a6e22e">connection&lt;/span>(self):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> print(&lt;span style="color:#ae81ff">1&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>db &lt;span style="color:#f92672">=&lt;/span> DB()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">assert&lt;/span> db&lt;span style="color:#f92672">.&lt;/span>connection &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#66d9ef">None&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">assert&lt;/span> db&lt;span style="color:#f92672">.&lt;/span>connection &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#66d9ef">None&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>其它的一句话更新包括：&lt;/p>
&lt;ul>
&lt;li>&lt;code>finally&lt;/code> 语句中不允许使用 &lt;code>continue&lt;/code> 了.&lt;/li>
&lt;li>新增了计算欧几里得距离的方法 &lt;code>math.dist()&lt;/code>.&lt;/li>
&lt;li>新增了支持混合l类型的 &lt;code>typing.TypedDict&lt;/code>.&lt;/li>
&lt;li>标准包 &lt;code>asyncio&lt;/code> 更新了一大串功能，使其变得稳定了.&lt;/li>
&lt;li>官方给出的 benchmark 中，相比于 py37 总体性能提升了 5%~20%.&lt;/li>
&lt;/ul>
&lt;h1 id="whats-new-in-python-39py39">&lt;a href="https://docs.python.org/3/whatsnew/3.9.html">What&amp;rsquo;s new in Python 3.9&lt;/a>&lt;/h1>
&lt;p>Python 3.9 是在 2020-10-05 发布的，官方维护至 2025-10-05。&lt;br>
感知比较大的几个改动包括：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python3" data-lang="python3">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># dict 支持并集操作符 `|` 了&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>x &lt;span style="color:#f92672">=&lt;/span> {&lt;span style="color:#e6db74">&amp;#34;a&amp;#34;&lt;/span>: &lt;span style="color:#ae81ff">1&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;b&amp;#34;&lt;/span>: &lt;span style="color:#ae81ff">2&lt;/span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>y &lt;span style="color:#f92672">=&lt;/span> {&lt;span style="color:#e6db74">&amp;#34;b&amp;#34;&lt;/span>: &lt;span style="color:#ae81ff">3&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;c&amp;#34;&lt;/span>: &lt;span style="color:#ae81ff">4&lt;/span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">assert&lt;/span> x &lt;span style="color:#f92672">|&lt;/span> y &lt;span style="color:#f92672">==&lt;/span> {&lt;span style="color:#e6db74">&amp;#34;a&amp;#34;&lt;/span>: &lt;span style="color:#ae81ff">1&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;b&amp;#34;&lt;/span>: &lt;span style="color:#ae81ff">3&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;c&amp;#34;&lt;/span>: &lt;span style="color:#ae81ff">4&lt;/span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">assert&lt;/span> y &lt;span style="color:#f92672">|&lt;/span> x &lt;span style="color:#f92672">==&lt;/span> {&lt;span style="color:#e6db74">&amp;#34;a&amp;#34;&lt;/span>: &lt;span style="color:#ae81ff">1&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;b&amp;#34;&lt;/span>: &lt;span style="color:#ae81ff">2&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;c&amp;#34;&lt;/span>: &lt;span style="color:#ae81ff">4&lt;/span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 支持 `list`/`dict`/`set` 这样的原生类型作为类型标注&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">def&lt;/span> &lt;span style="color:#a6e22e">occurance&lt;/span>(names: list[str]) &lt;span style="color:#f92672">-&amp;gt;&lt;/span> dict[str, int]:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> {name: names&lt;span style="color:#f92672">.&lt;/span>count(name) &lt;span style="color:#66d9ef">for&lt;/span> name &lt;span style="color:#f92672">in&lt;/span> names}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>其它的一句话更新包括：&lt;/p>
&lt;ul>
&lt;li>编译器由基于LL, 改为了基于PEG, 以便日后提供更强大的语言特性.&lt;/li>
&lt;li>新增了 &lt;code>str.removeprefix()&lt;/code>/&lt;code>str.removesuffix()&lt;/code> 方法.&lt;/li>
&lt;li>&lt;code>hashlib&lt;/code> 支持了 &lt;code>SHA3&lt;/code>/&lt;code>SHAKE&lt;/code> 的计算.&lt;/li>
&lt;li>非 Windows 平台不支持构建 &lt;code>bdist_wininst&lt;/code> 了(所以很多第三方库没及时更新).&lt;/li>
&lt;li>官方给出的 benchmark 中，相比于 py37 总体性能并无提升.&lt;/li>
&lt;/ul>
&lt;h1 id="whats-new-in-python-310py310">&lt;a href="https://docs.python.org/3/whatsnew/3.10.html">What&amp;rsquo;s new in Python 3.10&lt;/a>&lt;/h1>
&lt;p>Python 3.10 是在 2021-10-04 发布的，官方维护至 2026-10-04。&lt;br>
感知比较大的几个改动包括：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python3" data-lang="python3">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 新增了类似 switch+case 的 match+case 语法&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">def&lt;/span> &lt;span style="color:#a6e22e">check&lt;/span>(status_code: int, message: str):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> match status_code:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> case &lt;span style="color:#ae81ff">200&lt;/span> &lt;span style="color:#66d9ef">if&lt;/span> message:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> message
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> case &lt;span style="color:#ae81ff">200&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#e6db74">&amp;#34;ok&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> case &lt;span style="color:#ae81ff">400&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#e6db74">&amp;#34;bad request&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> case &lt;span style="color:#ae81ff">500&lt;/span> &lt;span style="color:#f92672">|&lt;/span> &lt;span style="color:#ae81ff">502&lt;/span> &lt;span style="color:#f92672">|&lt;/span> &lt;span style="color:#ae81ff">503&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#e6db74">&amp;#34;something wrong&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> case _:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#e6db74">&amp;#34;not implemented&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># `typing.Union` 可以写成更优雅的 `|`&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">def&lt;/span> &lt;span style="color:#a6e22e">add_all&lt;/span>(&lt;span style="color:#f92672">*&lt;/span>numbers: int &lt;span style="color:#f92672">|&lt;/span> float) &lt;span style="color:#f92672">-&amp;gt;&lt;/span> int &lt;span style="color:#f92672">|&lt;/span> float:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> sum(numbers)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">assert&lt;/span> isinstance(&lt;span style="color:#ae81ff">42&lt;/span>, int &lt;span style="color:#f92672">|&lt;/span> float)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># `dataclass` 支持 keyword-only 模式&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">import&lt;/span> dataclasses &lt;span style="color:#66d9ef">as&lt;/span> dc
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">@dc&lt;/span>&lt;span style="color:#f92672">.&lt;/span>dataclass(kw_only&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#66d9ef">True&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">Person&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> name: str
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> age: int
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> gender: str &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#39;Unknown&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>其它的一句话更新包括：&lt;/p>
&lt;ul>
&lt;li>优化了 Python 自带的各种报错信息.&lt;/li>
&lt;li>增加了 &lt;code>zip(*args, strict=True)&lt;/code> 强制校验等长的参数.&lt;/li>
&lt;li>优化了 &lt;code>str()&lt;/code>/&lt;code>bytes()&lt;/code> 的性能，日常情况中快了 40%.&lt;/li>
&lt;/ul>
&lt;h1 id="结语">结语&lt;/h1>
&lt;p>可以看到 Python 作为一个“步入成年的”编程语言，&lt;br>
这几年并没有 Golang 的泛型、错误处理那样令人 excited 的更新。&lt;br>
但总体的语言迭代也是基于 Python Zen 的小步快跑。&lt;/p>
&lt;p>对于开发者而言，只要第三方依赖允许，&lt;br>
保持最新的环境并不是一个很难的事情。&lt;/p>
&lt;p>笔者关心的功能只是语言标准的一个子集，&lt;br>
读者们也可以在官网上找到更详细、更实在的 changelog。&lt;/p>
&lt;p>下期（如果还有的话）可能会带来 go115-go117 的版本变更日志，&lt;br>
到时候再见 :)&lt;/p>
&lt;p>（完）&lt;/p></description></item><item><title>HR与程序员的日常（三）：人才发展</title><link>https://liriansu.com/posts/2021-09-09-limited-position/</link><pubDate>Thu, 09 Sep 2021 22:00:38 +0800</pubDate><guid>https://liriansu.com/posts/2021-09-09-limited-position/</guid><description>&lt;p>“哎，刚跟同事沟通完为什么他晋升被拒。”&lt;br>
“哦？为什么呢？”&lt;br>
“因为他的位子没到那个位置。”&lt;/p>
&lt;h2 id="一">（一）&lt;/h2>
&lt;p>从 Mia 到卡夫亨氏已经有三年多时间了，&lt;br>
她基本上以内部管培生的路径做遍了各种工作。&lt;br>
最近一年 Mia 在做 CB (Compensation&amp;amp;Benefit)，&lt;br>
其中的职责之一便是审核员工的招聘加薪晋升事宜。&lt;/p>
&lt;p>“你同事晋升被拒是怎么回事，展开讲讲？”&lt;br>
Lirian 十分好奇，开始捧哏。&lt;/p>
&lt;p>“本质是他理解跟公司产生了偏差，&lt;br>
他以为自己努力工作一定就能晋升，&lt;br>
但其实他的岗位已经到头了。”&lt;/p>
&lt;p>“噢噢噢，就是说这个岗位只要P6，&lt;br>
但就算他有P7的能力也用不着，&lt;br>
所以就不给晋升？”&lt;/p>
&lt;p>“对，大概是这个意思。&lt;br>
不过P6/P7是阿里那一套说辞，&lt;br>
我们公司按B14/B13这么算的。”&lt;/p>
&lt;p>确实，很多时候大家的理解都是“努力一定有收获”，&lt;br>
但放在工作里好像跟岗位很有关系。&lt;br>
Lirian 想了想，问：&lt;br>
“所以在工作中，不同的岗位确实有着不同的上限？”&lt;/p>
&lt;h2 id="二">（二）&lt;/h2>
&lt;p>“肯定的啊！”Mia接着说，&lt;br>
“虽然一家公司几千个人，&lt;br>
但就是有些岗位更能出彩，&lt;br>
上限更高。”&lt;/p>
&lt;p>“确实的，公司岗位皆平等，但有些岗位更加平等。”&lt;/p>
&lt;p>Mia 意犹未竟地接着感慨：&lt;br>
“排除专业技能来说，&lt;br>
一个岗位离业务越近、或者越不可替代，&lt;br>
这个岗位一般就很重要。&lt;br>
比如 HR 里面，CB 相比 SSC 肯定岗位更占优势一点。”&lt;/p>
&lt;p>“就是这个道理！&lt;br>
怪不得好多人都觉得 HRBP 会比其他岗位更有职业发展空间。”&lt;/p>
&lt;p>“就算是同样的职位，在不同公司的上限也不是一样的。”&lt;br>
说到这，Mia 做了个比喻：&lt;br>
“假如你们公司的招聘来说，&lt;br>
看拼多多给多少多少，&lt;br>
我们这个岗位也要给多少，&lt;br>
那你们 HR 估计要吐血了…&lt;br>
同样的职业，在不同公司也是不一样的。”&lt;/p>
&lt;p>确实是清醒的认知，Lirian 点头。&lt;br>
“道理是这样没错的，但也有很多人不懂。”&lt;/p>
&lt;p>突然 Mia 灵光一闪，问 Lirian：&lt;br>
“有些岗位虽然离业务近，但是可替代程度也高。&lt;br>
考考你，什么岗位符合这样的描述？”&lt;/p>
&lt;h2 id="三">（三）&lt;/h2>
&lt;p>“客服？专柜？”&lt;br>
略加思考后的 Lirian 脑子里首先蹦出了印度人呼叫中心的画面，&lt;br>
“他们离一线业务是近的，但岗位上限其实肉眼可见。”&lt;/p>
&lt;p>“对，你说的没错。还有像一线的普通销售也是这样的。”&lt;/p>
&lt;p>“咦，这怎么讲？”&lt;/p>
&lt;p>“比如我们公司的销售是卖酱油的。&lt;br>
一线销售其实只是做执行，&lt;br>
把酱油上到某几个地点的某几个货架上就行了。”&lt;/p>
&lt;p>“科学的，这样好像确实不需要很高深的水平。”&lt;br>
……&lt;br>
一阵沉默以后，Lirian 又好奇道：&lt;br>
“那为什么还有人愿意做这样的工作呢？”&lt;/p>
&lt;p>“销售上限高啊！&lt;br>
况且只是一线销售容易被替换，&lt;br>
职位做上来了有这个能力了还是很稀缺的。”&lt;/p>
&lt;p>“那客服呢？”&lt;/p>
&lt;p>“呃…”Mia 迟疑了一下，&lt;br>
“哎呀，反正我不是他们，我也不知道他们想法是怎么样的。”&lt;/p>
&lt;h2 id="四">（四）&lt;/h2>
&lt;p>“所以其实公司里每个岗位都对应有评级的。&lt;br>
你这个同事就是以为自己能晋升，但被驳回了对吧。&lt;br>
这种道理也不难明白，他不懂就算了，他主管也不懂吗？”&lt;/p>
&lt;p>“每个人的出发点是不一样的。&lt;br>
可能业务团队他们只会看到自己团队的情况，&lt;br>
但是像 HRBP 就能看到整条业务线的情况，&lt;br>
我们能看到全公司的情况，&lt;br>
甚至总部那边能看到各个国家的情况，&lt;br>
就更容易比较了。”&lt;/p>
&lt;p>“嗯，维持一个相对的公平还是很重要的。&lt;br>
那听起来纵览全局的话，&lt;br>
全公司各个职位的评级、人才的诉求这种就顺水推舟地能做出来了？”&lt;/p>
&lt;p>“对的，这个就是 OD 做的事情。”&lt;/p>
&lt;p>又听到了一个没见过的词，Lirian 再次好奇了起来：&lt;br>
“OD? OD 是什么意思？On Demand?”&lt;/p>
&lt;p>“OD 就是 Organization Development, 组织发展。”&lt;/p>
&lt;p>“噢噢噢，战略级别的工作了属于是。&lt;br>
那你这个工作听起来很有前途啊，小伙子好好干！”&lt;br>
Lirian 拍着 Mia 的肩膀，替她给自己画了个美好的未来。&lt;/p>
&lt;h2 id="五">（五）&lt;/h2>
&lt;p>“不过很多大公司到后面，&lt;br>
老板都会请咨询公司的人来做这部分事情。&lt;br>
我们是做甲方的，这种时候还是乙方来比较合适。&lt;br>
所谓‘外来的和尚好念经’。”&lt;/p>
&lt;p>“对的，我之前看 SAP 的业务分析也是这个道理。&lt;br>
像用友、金蝶他们带来的只是模块上的工作方式，&lt;br>
SAP 是直接搞定老板，&lt;br>
把老板想做很久的公司改革做了，&lt;br>
整套组织架构图给你扬了，&lt;br>
再顺便赚个软件费实施费。”&lt;/p>
&lt;p>“只要能搞定老板，那不什么都好做。”&lt;/p>
&lt;p>“也是…这么说来老板挺惨的，要一直被搞定。”&lt;/p>
&lt;h2 id="六">（六）&lt;/h2>
&lt;p>此时刚好散步到飞洲国际对面，&lt;br>
Lirian 与 Mia 准备右拐过马路，&lt;br>
话题也拐到了领导者的态度上。&lt;/p>
&lt;p>“老板很多时候都不想当坏人，&lt;br>
此时就只能 HR 上了。”&lt;/p>
&lt;p>“没办法，有限公司的职位分工就是如此。”&lt;/p>
&lt;p>Mia 回忆了下公司业绩变动时的情况，接着说：&lt;br>
“就像之前业绩不太好的时候，公司首先就把外聘的岗位停了。&lt;br>
老板也不可能公开说公司没钱了，但财务跟人事还是一清二楚的。&lt;br>
财务就只管钱，别说有的没的，给我把钱给省下来。&lt;br>
但是人事这种时候就得当坏人了。&lt;br>
那阵子我们HR老大让所有招聘晋升加薪都得经过他，然后想尽办法拖延…”&lt;/p>
&lt;p>我想象了下那个工作场景，叹了口气：&lt;br>
“可以想象很多人对他都会有怨言，&lt;br>
而且级别不一定还比他低，&lt;br>
估计老板也没少收到投诉。&lt;br>
这种时候 HR 还是得需要老板的鼎力支持啊。”&lt;/p>
&lt;p>“那肯定啊，毕竟是背锅位。”&lt;/p>
&lt;h2 id="七">（七）&lt;/h2>
&lt;p>快到飞洲国际了，&lt;br>
傍晚散步消食之旅也接近尾声。&lt;/p>
&lt;p>“我突然想到还有一个岗位：&lt;br>
离一线远，可替代程度高，但可能很重要。&lt;br>
你猜这个岗位是什么？是 EA。”&lt;/p>
&lt;p>“EA 是什么东东？那个游戏厂商？”&lt;/p>
&lt;p>“Executive Assistant. 执行助理。&lt;br>
做的差的就是端茶倒水打印文件，&lt;br>
做得好的就是真的部门二把手了。”&lt;/p>
&lt;p>Lirian 马上叫道：&lt;br>
“哇！那我也想要一个 EA！&lt;br>
这样我就是一把手了！”&lt;/p>
&lt;p>Mia：“想！得！美！”&lt;/p>
&lt;h2 id="完">（完）&lt;/h2></description></item><item><title>Jeff Ehco Facts</title><link>https://liriansu.com/posts/2021-06-07-jeff-ehco-facts/</link><pubDate>Mon, 07 Jun 2021 22:07:09 +0800</pubDate><guid>https://liriansu.com/posts/2021-06-07-jeff-ehco-facts/</guid><description>&lt;p>最近认识了编程界的半壁江山 Jeff，&lt;br>
与本人确认过，&lt;br>
确实与传说一致，&lt;br>
特此记录。&lt;/p>
&lt;ul>
&lt;li>Jeff 跟 Ehco 都是扇贝网的开发，但 Ehco 不一会儿就离职了，因为水镜先生说他们两个在一起太影响这个版本的平衡性了。&lt;/li>
&lt;li>Jeff 是扇贝的核心开发，他一部分工作是给背单词的用户换单词卡。&lt;/li>
&lt;li>扇贝不支持德语，是因为 Jeff 还没抽出时间学德语。&lt;/li>
&lt;li>扇贝开放了编程课，因为 Jeff 发现他有余力教编程。&lt;/li>
&lt;li>扇贝编程里，学生不懂问助教，助教不懂问扇贝工程师，工程师不懂问 CTO，CTO 不懂就会给 Jeff 提工单，Jeff 有空就会按优先级处理。&lt;/li>
&lt;li>扇贝没有线上事故，因为 Jeff 都会提前写好复盘，然后提前修复掉。&lt;/li>
&lt;li>扇贝几次宕机，都是因为 Jeff 在追综艺忘了处理前端请求。&lt;/li>
&lt;li>Jeff 业余时间会看所有综艺。&lt;/li>
&lt;li>《Rick and Morty》里看的电视综艺就是 Jeff 指导创作的。&lt;/li>
&lt;li>金泰浩跟罗英石每次的争论，他们都会找 Jeff 做最终拍板裁判。&lt;/li>
&lt;li>Jeff 偶尔会帮小米电视优化综艺页面。&lt;/li>
&lt;li>AKB48/SNH48/NMB48 的 48 是 Jeff 的体重，代表了他在团里的分量。&lt;/li>
&lt;li>Jeff 最近的愿望是等干反田爱瑠拍综艺，而 Ehco 在等龙女仆第二季。&lt;/li>
&lt;li>Ehco 小时候叫 Echo，但他后来自己改了身份证上的名字。&lt;/li>
&lt;li>扇贝的错题集由 Ehco 负责给返回值。&lt;/li>
&lt;li>AbnerLee 与 Ehco 共事以后，才想好自己的软件叫 Typora。&lt;/li>
&lt;li>Ehco 能用美式键盘写出 31 个字母。&lt;/li>
&lt;li>Ehco 只要 1 小时就顶别人 8 小时，多出来的 7 小时在改单词拼写错误。&lt;del>是真的&lt;/del>&lt;/li>
&lt;li>Ehco 写前端喜欢从混淆后的开始写，因为这样变量名短不容易拼错词。&lt;/li>
&lt;li>Ehco 的数据库技巧如此炉火纯青，以至于他一般只用 for 解决问题，而不是 MAX 或者 MIN 函数。&lt;/li>
&lt;li>但 Ehco 与 Jeff 的联调也出现过问题，因为 Jeff 返回值给的太快，Ehco 错字还没来得及改完。&lt;/li>
&lt;li>后来 Ehco 给 Jeff 加了一点安眠药，强制 sleep 解决了这个问题。&lt;/li>
&lt;li>Ehco 在 PingCAP 的主要工作是给 TiDB 加钛。&lt;/li>
&lt;li>TiDB 把引擎改为 Ehco 后，单机效率提升了 200%，但 Ehco 暂不支持高可用。&lt;/li>
&lt;li>在 Ehco 的建议下，戴佳伟开始以“异灵术”的身份直播炉石传说。&lt;/li>
&lt;li>Ehco 建议设计师把 Jeff 加入炉石传说，本地化翻译后为“杰弗里斯”。&lt;/li>
&lt;li>当你向 Jeff 许愿时，他会尽量满足你的愿望，但注意他身边的 Ehco，小心别被篡改错别字成别的含义了。&lt;/li>
&lt;li>毕竟 &lt;code>I want to be rich&lt;/code> 跟 &lt;code>I want to be lich&lt;/code>, 一字之差，失之千里。&lt;/li>
&lt;/ul>
&lt;p>（完）&lt;/p></description></item><item><title>我的奶奶</title><link>https://liriansu.com/posts/2021-05-31-my-grandma/</link><pubDate>Mon, 31 May 2021 22:37:13 +0800</pubDate><guid>https://liriansu.com/posts/2021-05-31-my-grandma/</guid><description>&lt;p>“工作累不累呀？”&lt;br>
“不累不累，我很喜欢工作的。”&lt;br>
“子岳要吃健康一点啊。”&lt;br>
“我知道的啦~”&lt;/p>
&lt;p>不像袁隆平爷爷是一个很厉害的爷爷，&lt;br>
我的奶奶就是一个普通的奶奶。&lt;/p>
&lt;h2 id="粒米闯三关">粒米闯三关&lt;/h2>
&lt;p>小时候我爸妈常给我讲故事。&lt;br>
我妈会抱着我读《岳飞演义》，&lt;br>
我爸则会在睡前跟我讲各种他从小听到大的故事。&lt;/p>
&lt;p>有一个叫“金鼓锣”的故事他来来回回地跟我、子南、恺恺都讲了许多遍，&lt;br>
乃至 Mia 跟我回家时也听了一遍这个故事。&lt;/p>
&lt;p>小孩子对世界的好奇心是无穷的，&lt;br>
听完故事的我会缠着我爸讲更多故事。&lt;br>
但人有限的故事储备怎能满足无限的好奇心呢？&lt;br>
所以后来我爸也常给我讲他自己小时候的故事。&lt;/p>
&lt;p>“你的妈妈是一个什么样的人呢？”&lt;br>
我问我爸，他想了想，说：&lt;br>
“你奶奶虽然没读过书，&lt;br>
但是她是有大智慧的。”&lt;/p>
&lt;p>我对奶奶的认识，&lt;br>
便是在我爸这一言一语的描述中建立的。&lt;/p>
&lt;p>后来小学时候，&lt;br>
奶奶来到广东陪着我们生活了几年，&lt;br>
我便也能亲耳听到奶奶跟我讲故事。&lt;/p>
&lt;p>“粒米闯三关”是奶奶很喜欢讲的一个故事。&lt;br>
大意是苦命但善良的主角靠着一粒米闯过了三个考验，&lt;br>
好人有好报，教育我们要善良。&lt;/p>
&lt;p>这个故事虽然没有反转、没有套路，&lt;br>
但它一直留在了我心里。&lt;/p>
&lt;h2 id="克勤克俭">克勤克俭&lt;/h2>
&lt;p>奶奶在广东呆了几年以后，&lt;br>
最终还是要回到湖南老家去。&lt;br>
走的时候老人有点伤心，&lt;br>
可能是觉得以后再也难有机会来广东了，&lt;br>
便额外嘱咐了许多大道理与小琐事。&lt;/p>
&lt;p>奶奶其实不是一个喜欢说教的人。&lt;br>
爷爷走得早，&lt;br>
奶奶一个人把抚养了好几个小孩拉扯大，&lt;br>
苦活也没少做。&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/grandma/family.jpg" alt="grandma">&lt;/p>
&lt;p>她的子女们有了下一代，&lt;br>
下一代又有了下一代，&lt;br>
组成了庞大的“傅氏家族”。&lt;/p>
&lt;p>几十年来，&lt;br>
她的生活用一句湖南俗语就是“克勤克俭”。&lt;/p>
&lt;p>老去的她眼睛不好，&lt;br>
叔叔一直照顾着她，&lt;br>
奶奶也基本没有踏出过村里。&lt;/p>
&lt;p>我寒假暑假去看她时，&lt;br>
她也就呆在屋里，&lt;br>
下午阳光好的时候搬把板凳，&lt;br>
坐在门口听着子孙们扯谈。&lt;br>
偶尔也会对轶事里懒惰的人发出评价：&lt;br>
“人还是要做事的，不做事不行”&lt;br>
然后转头劝她小儿子：“现在康康很好了，你可以少做点事了”&lt;/p>
&lt;h2 id="伸手不打笑脸人">伸手不打笑脸人&lt;/h2>
&lt;p>奶奶在年前病情突然恶化，&lt;br>
年后便不在了。&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/grandma/weibo.jpg" alt="weibo">&lt;/p>
&lt;p>当时 Mia 提醒我多注意我爸的心情，&lt;br>
因为岳父当时也是低落了一两年。&lt;/p>
&lt;p>前阵子视频的时候，&lt;br>
我问我爸：“高考完你打算去干什么？”&lt;br>
他说：“唉，之前本来是打算陪完学生高考，就马上回湖南的…”&lt;br>
言语之间的失落难以掩盖。&lt;/p>
&lt;p>我不禁想起了之前看《寻梦环游记》，&lt;br>
看到剧里面满脸皱纹的奶奶，&lt;br>
我也一下想起了我的奶奶。&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/grandma/coco.jpg" alt="coco">&lt;/p>
&lt;p>coco 留下的是一首歌，&lt;br>
奶奶在我心里留下的是一句话：&lt;br>
“伸手不打笑脸人。”&lt;/p>
&lt;p>上学时，我会笑着做题，&lt;br>
工作时，我会笑着写代码。&lt;br>
有时别人会觉得我很奇怪：&lt;br>
“人家上班你也上班，为什么你这么开心？”&lt;br>
我便会用 TVB 回答他：&lt;br>
“开心也是一天，不开心也是一天呀~”&lt;/p>
&lt;p>人活于世上，&lt;br>
骨肉精血魂是他几十年所见所闻、所食所想汇聚而成的。&lt;br>
跟奶奶相处的点点滴滴虽然逐渐磨损，&lt;br>
但她讲的故事、坚持的为人处世、教我的道理却每每在晚上响起。&lt;/p>
&lt;p>希望她像《狮子王》里说的那样，&lt;br>
成为了天空中繁星的一颗，&lt;br>
照耀着我们。&lt;/p>
&lt;p>（完）&lt;/p></description></item><item><title>杂思丨近日状况</title><link>https://liriansu.com/posts/2021-04-28-thoughts-these-days/</link><pubDate>Wed, 28 Apr 2021 20:14:38 +0800</pubDate><guid>https://liriansu.com/posts/2021-04-28-thoughts-these-days/</guid><description>&lt;p>近两周在旅途上的时间不少，&lt;br>
看了两本书，&lt;br>
要写篇文章。&lt;br>
大概这就是“读在飞机，写在高铁”的都市虚假成年知识分子吧。&lt;/p>
&lt;h2 id="一">（一）&lt;/h2>
&lt;p>上周看完了一本《定投十年财务自由》，&lt;br>
除了学习到各种宽基指数，以及各种名词以外。&lt;/p>
&lt;p>“十年”这样的字眼，&lt;br>
也像定期的心理按摩一样，&lt;br>
使我看得账上的 -15% 总收益慈眉善目起来。&lt;/p>
&lt;p>就像巴菲特说过的那样：&lt;br>
“活着才有输出。”&lt;br>
不论你年收益率是 5% 还是 10%，&lt;br>
活得越久，总是收益率更高的那个。&lt;/p>
&lt;p>当然了，虚空第一件装备就出龙心的时候，&lt;br>
“活着才有输出”这句话可不是有力的证词。&lt;/p>
&lt;h2 id="二">（二）&lt;/h2>
&lt;p>想到 dota，不禁感慨最近玩大型游戏的时间变少了。&lt;/p>
&lt;p>以前总有人教育我：“游戏有什么好玩的，你长大了自然就不喜欢玩了。”&lt;br>
现在我才体会到，游戏是一种我挤时间也想玩的东西。&lt;/p>
&lt;p>最近的时间也只够玩玩《明日方舟》这种上海本土游戏，&lt;br>
不过也是奇妙，我两年前访谈里一句“我喜欢玩明日方舟”，&lt;br>
居然认识了熊博士这个好友。&lt;/p>
&lt;p>以至于我每个月给鹰角冲月卡，&lt;br>
都理直气壮地对熊博士说：&lt;br>
“给你男人发工资了，不用谢！”&lt;/p>
&lt;h2 id="三">（三）&lt;/h2>
&lt;p>“你工资里有我的一份。”&lt;br>
我也会对在莉莉丝干活的 hulucc 这么说，&lt;br>
不过这种歧义诱导生不了效，&lt;br>
他并不会给我返利。&lt;/p>
&lt;p>只是以前 Mia 在看跳槽机会的时候，&lt;br>
会让我问 hulucc：&lt;br>
“你们这种二次元公司，HR 真的不需要强制 cosplay？”&lt;/p>
&lt;p>我作为专业的传话中间人，&lt;br>
就像中学时候帮忙递纸条但一定会拆开看的同学一样：&lt;br>
冷静思考、放弃思考、大声赞扬、好！cosplay 好啊！&lt;/p>
&lt;h2 id="四">（四）&lt;/h2>
&lt;p>Mia 的跳槽之路比较漫长。&lt;/p>
&lt;p>有个老美说过一句话：&lt;br>
随着逐年晋升，每个人都将被提拔到他无法胜任的位置上。&lt;/p>
&lt;p>Mia 在现在的公司尽心尽力做了三年多，&lt;br>
一路高升，直系老板都换了四五个。&lt;br>
这导致工作 5 年的她，现在看的职位都要求 7 年甚至 10 年以上的工作经验。&lt;/p>
&lt;p>“要不咱把加班时间算上，凑个十年？”&lt;br>
我在一旁出馊主意，Mia 不置可否。&lt;/p>
&lt;p>不过被嫌弃年龄太小经验不足，&lt;br>
也确实是个幸福的烦恼。&lt;br>
不像写代码的，老是被嫌弃体力不如年轻人，&lt;br>
说的好像写代码就是青春饭似的！&lt;br>
这世上绝无这样的道理！&lt;br>
我祖上一直是程序员！&lt;br>
我至少能干到 36 岁！&lt;/p>
&lt;p>Mia 赶忙安慰加速主义发作的我：&lt;br>
“没事没事以后我养你。”&lt;/p>
&lt;h2 id="五">（五）&lt;/h2>
&lt;p>可能是因为当成年人当太久了，&lt;br>
最近 Mia 与我都在讨论“如何健康工作五十年”这个话题。&lt;/p>
&lt;p>在短暂的交流以后，&lt;br>
我们初步商定了以后我当 CEO，&lt;br>
她当 HRD 的分工。&lt;br>
鉴于“不与同公司 HR 发生恋爱关系”的职场原则，&lt;br>
我们也基本确定了不在同一家公司就职。&lt;/p>
&lt;p>这个目标很明确，&lt;br>
就像高考只要 700 分就能上清华了。&lt;br>
冲啊！&lt;/p>
&lt;p>不过俗话也说“多条退路多条路”，&lt;br>
我也安排了一下当不上 CEO 的退路：&lt;br>
可以去美团送外卖。&lt;br>
毕竟我现在了解单车的扫码与开锁、熟悉电梯按钮的点击与撤销、清楚“我能不能提前点个送达”的问询话术。&lt;/p>
&lt;h2 id="六">（六）&lt;/h2>
&lt;p>梦想归梦想，玩笑归玩笑。&lt;br>
认真考虑的话，未来的路还是要对自己负责。&lt;/p>
&lt;p>以前跟 Mia 在交大散步的时候，&lt;br>
我们就会畅想以后会不会一人读书、一人养家。&lt;br>
最近发现时机合适，&lt;br>
我们也就生出了报考在职 MBA 的想法，&lt;br>
毕竟名人自传里，&lt;br>
好像都有一段一边工作一边读书的时光呢。&lt;/p>
&lt;p>“那么问题来了，上海 MBA 读哪家？”&lt;br>
听到这个问题，我想也不想地回答：&lt;br>
“当然是交大啦！不然你还想当个自由而无用的灵魂吗？”&lt;/p>
&lt;p>罪过。&lt;br>
向受影响的复旦灵魂们道个歉。&lt;/p>
&lt;h2 id="七">（七）&lt;/h2>
&lt;p>报考 MBA 首先要了解 MBA，&lt;br>
MBA 的全称是 Married But Available，&lt;br>
许多人通过读书找到了第一个或者第几个真爱。&lt;br>
但这个是考上了才要考虑的问题，不重要。&lt;/p>
&lt;p>在面试的时候，&lt;br>
会有这么三个固定模式的问题出现：&lt;br>
“你为什么要报考 MBA？为什么选我们学校？你读完 MBA 的五年计划是怎么样的？”&lt;/p>
&lt;p>这种问题一定要好好演练，&lt;br>
并且最好反复询问自己、重复回答。&lt;/p>
&lt;p>于是我每天都在 Mia 耳旁念叨：&lt;br>
“闲着也是闲着，交大离家近，读完再说…”&lt;/p>
&lt;p>好在 Mia 已经对爱搞事的我生出了免疫力了。&lt;/p>
&lt;h2 id="八">（八）&lt;/h2>
&lt;p>小学时候我喜欢看一个叫《信不信由你 Believe it or not》的节目，&lt;br>
里面会半真半假地讲述四个故事，&lt;br>
然后让嘉宾与电视观众们猜哪个是真的。&lt;/p>
&lt;p>我也很喜欢跟朋友们讲述这类故事，&lt;br>
比如意大利面其实是一个宗教的神、&lt;br>
每个月的 14 号都是情人节、&lt;br>
12月12号晚上12点拨打12个0会听到“对不起你拨打的是空号”等等。&lt;/p>
&lt;p>久而久之身边的同事朋友们也滋生出了免疫力。&lt;/p>
&lt;p>希望以后通过我的努力，&lt;br>
所有中国人都能这么自信、自知、自强，&lt;br>
对谣言有抵抗力，&lt;br>
做到不信谣、不传谣。&lt;/p>
&lt;h2 id="九">（九）&lt;/h2>
&lt;p>京沪高铁此时已经驶过济南。&lt;br>
这次到北京与 ldsink/allen 短暂地聚了一次，&lt;br>
不知不觉他们创业也数载了，&lt;br>
都在感慨时间变化真快。&lt;/p>
&lt;p>我上家公司有不少十年老员工，&lt;br>
但目前我司却一个十年老员工都没有，&lt;br>
真是气抖冷，吃人的互联网行业换血太快啦！&lt;/p>
&lt;p>……&lt;/p>
&lt;p>当然了，同样的道理也适用于 90 后程序员朋友们：&lt;br>
震惊！到现在为止，没一个90后程序员活过40岁！&lt;/p>
&lt;h2 id="十">（十）&lt;/h2>
&lt;p>年初的时候，&lt;br>
公司一个好友问我：&lt;br>
“你是如何在这家公司呆五年还不跑的？”&lt;/p>
&lt;p>我论公司与个人的共同成长、论正确战略与慢就是快、论从零到一的异世界之旅讲了一通。&lt;br>
好友听的头昏脑胀，只得问了一句：&lt;br>
“所以其实你还是看好公司的？”&lt;/p>
&lt;p>我仔细愣住，冷静无语，放弃推论，讲出大白话：&lt;br>
“当然啦！我要觉得我呆的地方不好，我早跑了！”&lt;/p>
&lt;p>某种意义上，工作与谈恋爱也是一样的。&lt;br>
不管如何细数优缺点，&lt;br>
爱了就是爱了，&lt;br>
不爱了也就是不爱了。&lt;/p>
&lt;h2 id="结">（结）&lt;/h2>
&lt;p>除了投资类的书，&lt;br>
最近我还在看《西行漫记》（又名《红心照耀中国》）。&lt;/p>
&lt;p>书中“一个党员的由来”一章，&lt;br>
看得我关联记忆不停。&lt;br>
一会儿是《金色的鱼钩》闯入脑海，&lt;br>
一会儿又是《小萝卜头》唤起回忆。&lt;/p>
&lt;p>有许多事情，&lt;br>
当时看可能是平凡人做的平凡事，&lt;br>
后来回味起来却历久弥香，&lt;br>
浓缩成了一个个可以传下去的故事。&lt;/p>
&lt;p>这或许就是时间的魅力吧。&lt;/p>
&lt;p>（完）&lt;/p></description></item><item><title>我的金钱观</title><link>https://liriansu.com/posts/2021-03-18-my-concept-of-money/</link><pubDate>Thu, 18 Mar 2021 20:41:35 +0800</pubDate><guid>https://liriansu.com/posts/2021-03-18-my-concept-of-money/</guid><description>&lt;p>天生我材必有用，&lt;br>
千金散尽还复来。&lt;/p>
&lt;p>前几天一次内部周常分享，&lt;br>
我讲了“事业计划”的话题。&lt;br>
果然，成年人们还是对“如何搞钱”这个话题最感兴趣，&lt;br>
在讲这一小节的时候，大家都放下了手机，热情地参与了讨论。&lt;/p>
&lt;p>这几天我又细想了几回，&lt;br>
我对“如何搞钱”这个话题的理解，&lt;br>
其实就是“我的金钱观”了。&lt;br>
今晚可能是个合适的时间，&lt;br>
可以用个合适的姿势，&lt;br>
在博文里写下来。&lt;/p>
&lt;p>财富在我理解中，&lt;br>
是由家族基业、劳动收入、投资理财、风险收益等多方面组成的。&lt;/p>
&lt;h2 id="家族基业">家族基业&lt;/h2>
&lt;blockquote>
&lt;p>有的人用一生治愈童年，&lt;br>
有的人用童年治愈一生。&lt;/p>
&lt;/blockquote>
&lt;p>阶级论是最近甚嚣尘上的一种观点。&lt;br>
经过建国几十年的财富积累，&lt;br>
时运、机遇、奋斗导致了各个家庭财富积累的不一。&lt;br>
但撇去使矛盾激化的拱火观点，&lt;br>
“人生而平等，而有人更加平等”是一个确凿的事实。&lt;/p>
&lt;p>在《全面战争·三国》游戏中有一个设定：&lt;br>
不同的势力基础家业是不一样的。&lt;br>
比如卖草席出身的刘备，虽是中山靖王之后，&lt;br>
但没有任何遗产，每回合只有0的家族基业收入。&lt;br>
河北袁绍，往上数四世三公，&lt;br>
不说继承的领土，每回合光家族基业收入就有4000之多。&lt;/p>
&lt;p>人类也是如此。&lt;br>
不说“含着金钥匙出生”的王思聪、姚安娜、潘瑞，&lt;br>
即使是坐在同一个教室上着同一节课的学生们，&lt;br>
毕业以后也会发现，&lt;br>
家境的差别确实很难只用几十年的奋斗来追平。&lt;/p>
&lt;p>当我们谈论个人的金钱时，&lt;br>
家族基业确实是一个需要直面的话题。&lt;/p>
&lt;h2 id="劳动收入">劳动收入&lt;/h2>
&lt;blockquote>
&lt;p>“听说搞IT的培训三个月就月入上万，是真的吗？”&lt;br>
“可以是真的。”&lt;br>
《&lt;a href="https://liriansu.com/is-it-possible-to-be-rich-easily-by-programming">链家小哥问我：听说搞IT的培训三个月就可以月入上万，是真的吗？&lt;/a>》&lt;/p>
&lt;/blockquote>
&lt;p>劳动最光荣是中华民族的传统美德。&lt;br>
程序员朋友们的绝大部分收入都来自于劳动，&lt;br>
也就是码代码。&lt;br>
因为成年人最关心搞钱，&lt;br>
所以程序员聚集的地方大家都会讨论薪资、奖金、涨幅。&lt;/p>
&lt;p>但除了算996时薪之外，&lt;br>
我很少看见有人会量化地去计算劳动的金钱转化率。&lt;br>
其实可以用积分的思想，&lt;br>
来估计一个当代程序员一辈子可以通过劳动赚取报酬的量级。&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/coder_salary.png" alt="coder">&lt;/p>
&lt;blockquote>
&lt;p>👆“写代码只是青春饭，生化环材越老越吃香”&lt;/p>
&lt;/blockquote>
&lt;p>我们以上图橙线（码农）的薪酬线，尝试做一个很粗糙的估计：&lt;/p>
&lt;ol>
&lt;li>假设每级灰色横线代表 5W 的年薪差别&lt;/li>
&lt;li>假设码农年薪最高点，38岁时年收入 48W&lt;/li>
&lt;li>那么码农22岁起薪大概是 22W&lt;/li>
&lt;li>健康工作五十年，70岁时年收入是 25W&lt;/li>
&lt;/ol>
&lt;p>在粗糙的估计之下，很容易得出一个结论：&lt;br>
&lt;strong>程序员（码农）朋友们一辈子的劳动收入，量级是千万级&lt;/strong>。&lt;/p>
&lt;p>大家可以尝试做一个量级的粗糙估计，&lt;br>
甚至可以加上“996拼搏三年”、“35岁收入断崖式下降”或者“40岁提前退休”之类的设定，&lt;br>
也可以得出类似的答案。&lt;/p>
&lt;p>虽然一千万也是千万级，&lt;br>
八千万也是千万级，&lt;br>
但光量级上来说：&lt;br>
程序员健康工作一辈子，&lt;br>
劳动收入大概就是千万级。&lt;/p>
&lt;p>所以许多程序员朋友对薪资不满意，&lt;br>
或许是他们处在更窘迫的青年时代，&lt;br>
又或许是他们的理想比千万这个量级要更广阔。&lt;/p>
&lt;h2 id="投资理财">投资理财&lt;/h2>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/my_fund.jpg" alt="fund">&lt;/p>
&lt;blockquote>
&lt;p>👆“要做时间的朋友。”我这么安慰自己。&lt;/p>
&lt;/blockquote>
&lt;p>读完了《小狗钱钱》以后，&lt;br>
年初我就准备学习一个理财，&lt;br>
我便开始用工资买基金。&lt;br>
一月份买了 1W 元小赚 2% 以后，&lt;br>
我找 Mia 追加投资了 4W 元，&lt;br>
然后从山顶一直滑翔至今，&lt;br>
期间收获了无数的表情包、梗图以及段子笑话。&lt;/p>
&lt;p>在《&lt;a href="https://liriansu.com/a-chat-with-roommates">室友聊天&lt;/a>》的年代，&lt;br>
我便抱着一种朴素的财富自由观：&lt;/p>
&lt;p>假设工作 10 年攒够 100W，&lt;br>
只要我理财收益率能到 5%，&lt;br>
那我每年都会进账 5W，&lt;br>
省着点就完全够花啦！&lt;br>
就算考虑 CPI 什么的，&lt;br>
把本金、收益率想想办法搞一搞也没问题。&lt;/p>
&lt;p>这种朴素的财富自由观，&lt;br>
一直伴随我到现今。&lt;br>
我也逐渐地往上打了更多的补丁：&lt;/p>
&lt;p>一是，我大概也许确实会工作一辈子，&lt;br>
就算撇去自我价值的实现只谈钱，&lt;br>
10W 的年薪在 10% 的收益率下也相当于 100W 的稳定资产包。&lt;/p>
&lt;p>二是，我对收益率确实不能太乐观，&lt;br>
5% 到 10% 我或许可以奢望下，&lt;br>
但 10% 到 15% 乃至 20% 是一个需要学习的系统工程，&lt;br>
毕竟巴菲特这么多年也才 20%+ 的年化收益率。&lt;/p>
&lt;h2 id="风险收益">风险收益&lt;/h2>
&lt;blockquote>
&lt;p>你甘愿一直默默无闻，还是希望一鸣惊人？&lt;/p>
&lt;p>—— 杰克 from 夜之城&lt;/p>
&lt;/blockquote>
&lt;p>财富某种意义上是很公平的。&lt;br>
有人可以一辈子只吃家族基业，&lt;br>
也有人的家族基业让他背上一辈子的负债。&lt;br>
有人杠杆短线成为股神一代传奇，&lt;br>
也有人一家五口接连在天台一跃而下。&lt;br>
所有的回报都伴随着风险，&lt;br>
每一条冒险路都有一个宝箱。&lt;/p>
&lt;p>重疾险是一个确实值得购买的保险。&lt;br>
虽然许多企业已经把重疾险纳入了员工保障计划，&lt;br>
但个人而言是值得花时间去研究一下的。&lt;br>
有这么一个（危言耸听的）说法：&lt;br>
“一百万能治好很多病；&lt;br>
而一百万也治不好的，&lt;br>
可能五百万也治不好。”&lt;/p>
&lt;p>重疾险是一款针对风险的兜底，&lt;br>
那期权、股票是一款针对收益的兜底。&lt;/p>
&lt;p>&lt;a href="https://www.bilibili.com/video/BV1gx411R7ke">zettaranc 在B站讲过&lt;/a>他长期看好并持有李宁，&lt;br>
资产翻四倍的故事。&lt;br>
在我的观点里，&lt;br>
假如程序员希望获得比千万级更高的量级收益，&lt;br>
那么期权股票是必须要了解的。&lt;/p>
&lt;p>不论是在市场上长期看好抄底持有，&lt;br>
还是以劳动附加价值的方式，&lt;br>
找一个小独角兽公司，&lt;br>
陪着它长大。&lt;/p>
&lt;h2 id="仓位管理">仓位管理&lt;/h2>
&lt;p>家族基业、劳动收入、投资理财、风险收益这四部分构成了一人一世的财富。&lt;br>
而其中不同的仓位占比，&lt;br>
甚至会影响到一个人的人生观、世界观、价值观。&lt;/p>
&lt;p>比如“富二代”的财富构成中，&lt;br>
家族基业占比高达九成以上。&lt;br>
别说劳动收入了，&lt;br>
像投资理财等操作，&lt;br>
能有正向的收益就已经很不错了（参见 pandaTV）。&lt;/p>
&lt;p>那对于家族基业占比九成以上的人类而言，&lt;br>
以财富的视角来看，拼命劳动完全没有收益。&lt;br>
这时候要么切换成“自我实现”的价值观视角，&lt;br>
要么切换成“我也不知道干嘛，但孝敬好父母就对了”的咸鱼心态。&lt;/p>
&lt;p>那对于“奋斗逼”（中性），&lt;br>
为什么他要全身心投入工作呢？&lt;br>
因为也许他是一个财富积累主要靠工作薪资的人类，&lt;br>
劳动收入在财富中构成占比极大。&lt;br>
相比其它选择，&lt;br>
显然是加大自己对“劳动”的投入收益更高。&lt;/p>
&lt;blockquote>
&lt;p>我的梦想是：&lt;br>
&lt;strong>世界和平&lt;/strong>，&lt;br>
&lt;strong>我爱的人跟爱我的人都能幸福&lt;/strong>，&lt;br>
&lt;strong>我要成为温柔的强者&lt;/strong>。&lt;/p>
&lt;/blockquote>
&lt;p>而在我心中，&lt;br>
要实现我的梦想我需要远比千万级更高的财富量级。&lt;br>
以为人一世的时间维度去看，&lt;br>
家族基业、劳动收入或许只是我奋斗的一小步，&lt;br>
我真正要做的，&lt;br>
或许是把再惠做上市以后（x&lt;br>
某一天去创立一份未竟的事业，&lt;br>
有可能的话兼济天下，&lt;br>
大庇天下寒士俱欢颜吧。&lt;/p>
&lt;h2 id="杂记">杂记&lt;/h2>
&lt;p>我总跟 Mia 念叨：&lt;br>
“别看我们现在不富有,&lt;br>
but we will be rich.”&lt;/p>
&lt;p>Mia 也总是安慰我：&lt;br>
“我没你那么志向远大，&lt;br>
我尽量在你 35 岁失业的时候能养的起你吧。”&lt;/p>
&lt;p>（完）&lt;/p></description></item><item><title>我言、我知、我行</title><link>https://liriansu.com/posts/2021-03-15-say-think-behave/</link><pubDate>Mon, 15 Mar 2021 23:03:39 +0800</pubDate><guid>https://liriansu.com/posts/2021-03-15-say-think-behave/</guid><description>&lt;p>“人家是说了再做，我是做了再说。”&lt;br>
——闻一多&lt;/p>
&lt;h1 id="言易知难知易行难">言易知难，知易行难&lt;/h1>
&lt;p>人活在世界上，诉说着、思考着、行动着。&lt;br>
标题的这句话，就是我对人类交互的一个思考。&lt;/p>
&lt;p>言，说话，是人类最基础的一个交流功能。&lt;br>
人类是一个奇特的物种。&lt;br>
像《乡村教师》里感慨的那样，&lt;br>
明明信息交流只能靠喉咙震动通过声波传播，&lt;br>
但文化硬是传承发展了几千年。&lt;/p>
&lt;p>知，思想，往往只能通过说话来表达。&lt;br>
在工作以后，&lt;br>
不少朋友会感慨很少有机会能跟他人深度交流了。&lt;br>
他们偶尔会怀念学校时候的夜聊，&lt;br>
虽然可能大部分时候讲的是学习、老师、校园的日常，&lt;br>
但也总有成年人独居生活时不会发生的人生、世界、价值的探讨。&lt;/p>
&lt;p>行，行动，因为过于具象而经常被忽视。&lt;br>
而行动，却是这三者中最能表达立场的铁证。&lt;br>
不论是极端的“父亲的爱逼死孩子”中错位的表达与行动，&lt;br>
还是日常经常发生的“白天一起玩晚上偷偷学习”中流露的真实认知，&lt;br>
无一不说明着行动本身的价值。&lt;/p>
&lt;p>所以说，&lt;strong>言易知难，知易行难&lt;/strong>。&lt;/p>
&lt;h2 id="学习教育改变命运">学习·教育改变命运&lt;/h2>
&lt;p>在我上学的年代，&lt;br>
考完试以后大家对完答案，&lt;br>
就会互相捧对方：&lt;br>
“哎呀我这次雪崩！”&lt;br>
“周神你肯定又第一啦！”&lt;br>
“学渣啦我也就三流成绩！”&lt;br>
结果成绩一出来，&lt;br>
排名竞争更加激烈。&lt;/p>
&lt;p>学习、教育上，&lt;br>
说话只要重复一句“教育改变命运”或者“啊呀也太卷了”的抱怨就行了。&lt;/p>
&lt;p>但“认为教育是能改变命运”的这种思想其实是更难得的（虽然中国很普遍）。&lt;br>
《贫穷的本质》中提到，&lt;br>
统计学上越富裕的人越舍得在教育上投资。&lt;br>
这也是一种思想的偏好。&lt;/p>
&lt;p>行动本身就更难了。&lt;br>
现代学生除了懒惰还要抵御电子产品的诱惑，&lt;br>
成年人也如是，&lt;br>
许多人不仅放弃了读书的习惯，还放弃了探索未知的好奇心。&lt;/p>
&lt;p>所以真的贯彻“教育改变命运”，&lt;br>
不能只靠口号，&lt;br>
也需要知行合一地持续付出。&lt;/p>
&lt;h2 id="事业穷则独善其身达则兼济天下">事业·穷则独善其身，达则兼济天下&lt;/h2>
&lt;p>面试的时候除了专业问题，&lt;br>
我有两个喜欢问的个人问题。&lt;br>
一个是“给我讲讲你最喜欢的一次项目内容”，&lt;br>
另一个是“你以后想成为什么样的人”。&lt;br>
虽然可能会有离题的回答，&lt;br>
但我不止一次在一双眼睛中看到了燃烧起来热情的火光。&lt;/p>
&lt;p>关于工作本身的社会舆论一直在变化，&lt;br>
从以前的“支持宣扬狼性文化”到现在的“警惕提防996资本吸血”也不过数年时间。&lt;br>
但随着舆论两边踏浪的大众，&lt;br>
会有多少人真正思考过自己的事业、阶段、坚持、独特、苦难与成就呢？&lt;br>
个中之人，能坚持自己独立思考并走一条不后悔的路也是少之又少。&lt;/p>
&lt;p>之前与Mia聊天时，提到过一个好玩现象，我称之为“沉默的大多数”。&lt;br>
在我们观察中，群体对公司的看法往往是单元的，但个体的行动却是复杂的。&lt;br>
比如一个团队中，内部以公司不好的看法为主流，那认为公司还不错的员工也不会发声，以免被孤立。&lt;br>
但同样的团队，却也能表现出韧性，工作上的困难能客观分析并解决，并且离职率保持在可接受的范围内。&lt;/p>
&lt;p>所以在攀登事业山峰的路上，&lt;br>
会有复杂的舆论干扰人的想法，&lt;br>
但最终最确定的，还是抛去杂念、端正认知以后一步一个脚印的行动。&lt;/p>
&lt;h2 id="爱情这简单又强烈的感情支配了一生">爱情·这简单又强烈的感情支配了一生&lt;/h2>
&lt;p>与朋友们聊天时，经常戏谑一句话叫“男人的嘴骗人的鬼”。&lt;br>
去年流行的“小丑竟是我自己”的舔狗2.0这个梗，&lt;br>
本质上也是心口不一导致的戏剧化满载。&lt;/p>
&lt;p>《新鸳鸯蝴蝶梦》里唱到：&lt;br>
是要问一个明白，&lt;br>
还是要装作糊涂？&lt;br>
知多知少难知足…&lt;/p>
&lt;p>同一件事情，&lt;br>
叠加上言、知、行三者，&lt;br>
真值就有八种可能性。&lt;/p>
&lt;p>所以为了避免误会、揣测、猜疑等古典狗血，&lt;br>
一条可行的路是三者合一：&lt;br>
我言、我知、我行。&lt;/p>
&lt;p>但复读“不以结婚为目的的恋爱都是耍流氓”的人，&lt;br>
有多少人是真的这么想的呢？&lt;br>
又有多少人能真的这么做到呢？&lt;/p>
&lt;h2 id="生死或重于泰山或轻于鸿毛">生死·或重于泰山，或轻于鸿毛&lt;/h2>
&lt;p>就如同在&lt;a href="https://liriansu.com/carpe-diem">《消逝的此刻》&lt;/a>中感慨的一样，&lt;br>
我一直不太能接受“人固有一死”这个事实。&lt;/p>
&lt;p>有这么一把达摩克利斯之剑悬在头上，&lt;br>
我便执行着战术上重视、战略上藐视的策略。&lt;/p>
&lt;p>“死亡，不足为惧也。”&lt;br>
我说着这样的话。&lt;br>
同时每天躺在床上看着天花板，&lt;br>
我开始了三省吾身：&lt;br>
“明早吃啥？明中午吃啥？明晚上吃啥？”&lt;br>
噢不好意思，没吃饱，想岔了，我又开始了三省吾身：&lt;br>
“今天有什么话我能表达的更好？&lt;br>
我有什么想法是不该有的？&lt;br>
未来我要怎么改变自己的行动？”&lt;/p>
&lt;p>今天的我比昨天的我更好了，值了。&lt;/p>
&lt;h1 id="知行合一言行不一">知行合一，言行不一&lt;/h1>
&lt;p>真正去观察着生活，&lt;br>
就感知到“言易知难，知易行难”就像是宇宙的规约一样，&lt;br>
限制着人类的交互。&lt;/p>
&lt;p>假如你是个知行合一的人，&lt;br>
那么恭喜你，&lt;br>
你现在的状态是我设想中的完美状态，&lt;br>
剩下的就只需要调整说的话，&lt;br>
表达自己就行了。&lt;/p>
&lt;p>假如你意识到“知我”与“行我”是部分分裂的，&lt;br>
那也恭喜你，&lt;br>
你的意识更加强大了，能超脱地观察自己的言行了。&lt;/p>
&lt;p>而倘若摄像机调转方位，&lt;br>
我们来观察芸芸众生，&lt;br>
就会发现大地上战栗的一个个个体。&lt;br>
他们的“言我”、“知我”与“行我”，&lt;br>
或隐藏、或纠结、或一统、或漠视。&lt;/p>
&lt;p>这种时候，掏出绝世武功一看，&lt;br>
上面释义“让行动与认知统一、但不必说出来”的一句话赫然在目：&lt;/p>
&lt;blockquote>
&lt;p>知行合一，&lt;br>
言行不一。&lt;/p>
&lt;/blockquote>
&lt;p>（完）&lt;/p></description></item><item><title>我的世界观</title><link>https://liriansu.com/posts/2021-01-20-my-worldview/</link><pubDate>Wed, 20 Jan 2021 22:31:35 +0800</pubDate><guid>https://liriansu.com/posts/2021-01-20-my-worldview/</guid><description>&lt;p>罗马军队大破希拉库扎国时，&lt;br>
一个带头挥着刀冲锋的士兵被一位蹲在地上的老人挡住了。&lt;br>
士兵吼着：“给我滚开你个老家伙！”&lt;br>
老人头都没抬地说：“不要弄坏我的圆！”&lt;br>
阿基米德，死于公元前 212 年。&lt;/p>
&lt;h2 id="一">（一）&lt;/h2>
&lt;p>最近跟 Mia 在路上玩猜人名游戏，&lt;br>
一方想人名另一方问，&lt;br>
问题只会得到“是”或“不是”的答案，&lt;br>
如此反复直到猜出来或者猜不下去。&lt;/p>
&lt;p>当我猜出来 Mia 想的是阿基米德时，&lt;br>
我脑海中除了 &lt;code>Aha moment&lt;/code>, &lt;code>F = P水gV排&lt;/code>，&lt;br>
还浮现出了本文最开始的那个故事。&lt;/p>
&lt;p>就像《百年孤独》的经典开头一样，&lt;br>
《进击的巨人》开头语也为粉丝们津津乐道：&lt;/p>
&lt;blockquote>
&lt;p>那一天，&lt;br>
人类终于回想起来了，&lt;br>
曾经一度被它们支配的恐怖，&lt;br>
还有被困在牢笼的那份屈辱。&lt;/p>
&lt;/blockquote>
&lt;p>数学本身，也像这样的文字一样，&lt;br>
即使经历了数次危机，&lt;br>
也在费马、牛顿、高斯等伟人的掌舵下成为人类智慧的源泉。&lt;/p>
&lt;h2 id="二">（二）&lt;/h2>
&lt;p>即便是小学级别的数学，&lt;br>
也会让人有仰望天空的冲动。&lt;/p>
&lt;p>最开始从整数、小数，&lt;br>
了解到了负数、分数，&lt;br>
再到无理数、复数的认知过程，&lt;br>
我就像一个第一次被放在星空下的孩子，&lt;br>
看着满天前辈留下的星星，&lt;br>
闪烁得一句话也说不出来。&lt;/p>
&lt;p>那个时候坐我舅开的车，&lt;br>
他是当时我身边的最“理科”的人了，&lt;br>
我跟他讲述了我的新发现：&lt;br>
“Π是个无理数，意味着我们对Π的探索就是无穷尽的，也意味着Π里面可以含有全世界！”&lt;/p>
&lt;p>后来细细想来，&lt;br>
Π一个数字包含的随机混沌，&lt;br>
就是我认识的世界的本质。&lt;/p>
&lt;h2 id="三">（三）&lt;/h2>
&lt;p>04年的时候看《儿童文学》，&lt;br>
里面连载了一篇李志伟写的中篇小说&lt;a href="https://book.douban.com/subject/1064307/">《圣域传说》&lt;/a>，&lt;br>
情节跟后来的&lt;a href="https://www.bilibili.com/video/BV1az4y1D73Y">《异次元骇客》&lt;/a>异常同步。&lt;br>
大致讲的就是主角创造了一个电脑世界，&lt;br>
但后来主角发现现实也不过是被创造的另一个虚拟世界。&lt;br>
这样的套娃故事简单来说，&lt;br>
可以通过“我思故我在”的思辨逃避过去，&lt;br>
但当时给我的冲击不亚于第一次看完《楚门的世界》的重生感。&lt;/p>
&lt;p>从那时候开始，直到现在，&lt;br>
我一直在思考这个问题：&lt;br>
“我是谁？”&lt;/p>
&lt;p>那时留校培训，我们几个好伙伴会挤在一间寝室睡觉。&lt;br>
晚上夜话时，我跟 FHN 聊到了世界观，&lt;br>
我说了“世界有可能是被创造出来的”后，&lt;br>
他拍床而起：“对！我也是这么觉得的！”&lt;br>
后来我们一电脑室的人都在《Ever17》中找到了观测者原理的绝妙故事。&lt;/p>
&lt;p>中学时，我非常敬佩教我物理的万老师，&lt;br>
那时他是我认识的最“理科”的人。&lt;br>
在一天中午，跟他讨论完题目后论道中，&lt;br>
我顺着逻辑说出了一段日后反复咀嚼了十几年的话：&lt;/p>
&lt;blockquote>
&lt;p>人生是没有实际意义的。&lt;/p>
&lt;p>为什么呢？我们来尝试反证法。&lt;br>
首先假设人生有意义。&lt;/p>
&lt;p>这个意义是寄托于心灵（意识）的吗？&lt;br>
不是，因为我只要否定心灵它就不存在了。&lt;/p>
&lt;p>那这个意义是存在现实世界（物质）的吗？&lt;br>
不是，我相信科学，我不信来生。&lt;br>
宇宙会毁灭，一切物质都会消亡。&lt;/p>
&lt;p>所以，论实际意义的话，&lt;br>
人生就是没有实际意义的。&lt;/p>
&lt;/blockquote>
&lt;p>在物理竞赛题目上能教导我的万老师，&lt;br>
对这番“中二”的言论也是无语，&lt;br>
挥了挥手让我自己去继续我个人的思考了。&lt;/p>
&lt;h2 id="四">（四）&lt;/h2>
&lt;p>所以我困惑就更大了。&lt;/p>
&lt;p>人生没意义的话？为什么人还要活着呢？&lt;br>
但我迷恋于雨后路边浮上来的扭曲蚯蚓壮观场面，&lt;br>
揪心于恋爱时两颗心撞击的揪心情感，&lt;br>
沉浸于游戏版编码思维宫殿里的心流。&lt;br>
那世界肯定有一个理由，让我灿烂地活下去。&lt;/p>
&lt;p>于是我寻找了许多的思想实验。&lt;/p>
&lt;p>&lt;a href="https://liriansu.com/adult-life-memories">《毕业五年-回忆》&lt;/a>里，提过一嘴“忒修斯之船”，&lt;br>
前文里提到的基本上类似于黑客帝国式的“缸中大脑”，&lt;br>
我心中还坚信的是一个《信条》式的宿命论。&lt;/p>
&lt;blockquote>
&lt;p>有些人二十岁就死了，八十岁才埋。&lt;/p>
&lt;/blockquote>
&lt;p>这是一句《读者》里鸡汤故事的典藏句子，&lt;br>
但在我眼中却包含科学的“宿命”的含义：&lt;br>
只有在八十岁回首往事时，&lt;br>
才知道这个人二十岁就死了。&lt;/p>
&lt;blockquote>
&lt;p>当你老了，回顾一生，就会发觉：&lt;/p>
&lt;p>什么时候出国读书、&lt;br>
什么时候决定做第一份职业、&lt;br>
何时选定了对象而恋爱、&lt;br>
什么时候结婚，其实都是命运的巨变。&lt;/p>
&lt;p>只是当时站在三岔路口，&lt;br>
眼见风云千樯，&lt;br>
你作出选择的那一日，在日记上，&lt;br>
相当沉闷和平凡，&lt;br>
当时还以为是生命中普通的一天&lt;/p>
&lt;/blockquote>
&lt;p>虽然古人云了又云：&lt;br>
“人定胜天”、“路在脚下”、“事在人为”&lt;br>
但是从未来的视角看来，&lt;br>
非洲的蝴蝶必然会振动翅膀，&lt;br>
章北海按钮必然会慢下几秒，&lt;br>
张华、李萍和我也必然有光明的前途。&lt;/p>
&lt;h2 id="五">（五）&lt;/h2>
&lt;p>三观中的世界观，&lt;br>
讲的就是我对世界的观感。&lt;/p>
&lt;p>经济学里的这句话，&lt;br>
放在普世观点里也或许成立。&lt;/p>
&lt;blockquote>
&lt;p>过去十年里，这是最坏的一年。&lt;br>
未来十年里，这是最好的一年。&lt;/p>
&lt;/blockquote>
&lt;p>“人生是没有实际意义的”这句论断，&lt;br>
在我的人生观里留下了深刻的影响。&lt;br>
但我的世界观里，&lt;br>
我给自己写下了这么一句话：&lt;/p>
&lt;blockquote>
&lt;p>唯心地思考，唯物地活着。&lt;/p>
&lt;/blockquote>
&lt;p>这也是我博客站点名字“浮云计算”、以及我网名“浮云总是梦”的由来：&lt;br>
世上万物就像天上的浮云一样，&lt;br>
既具体、又空心，&lt;br>
既实用，凝集降雨泽润大地，&lt;br>
又虚无，让人欣赏变幻莫测。&lt;/p>
&lt;p>或许智人的历史长河中，&lt;br>
就有这么一朵调皮云，&lt;br>
在一个晚上它飘在大地上，&lt;br>
挡住了一个仰望星空的智人的视线，&lt;br>
把这份仰望星空而对世界产生的好奇，&lt;br>
推迟了那么几百年。&lt;/p>
&lt;p>（完）&lt;/p></description></item><item><title>为拼多多而死，不值得</title><link>https://liriansu.com/posts/2021-01-05-no-more-dying-for-pinduoduo/</link><pubDate>Tue, 05 Jan 2021 20:21:20 +0800</pubDate><guid>https://liriansu.com/posts/2021-01-05-no-more-dying-for-pinduoduo/</guid><description>&lt;p>润肺的离去，&lt;br>
是个悲剧，&lt;br>
也是一个警钟。&lt;/p>
&lt;h1 id="一">（一）&lt;/h1>
&lt;p>最近所有群都被拼多多员工（花名“润肺”）离世的消息刷屏了。&lt;/p>
&lt;p>&lt;a href="https://www.zhihu.com/question/437702180/answer/1659225588">网上信息爆料说&lt;/a>，润肺是一名98年的女生，在新疆的拼多多买菜工作。&lt;br>
2020年12月29日凌晨一点半，她在下班路上晕倒，抢救无效而离世。&lt;/p>
&lt;p>此次事件还因为两点而被放得更大：&lt;/p>
&lt;p>一是润肺同学并不是刻板印象中闷闷的程序员，&lt;br>
而是一个积极乐观、大学玩过乐队的运营妹子，&lt;br>
而且她的公司签名是“肺宝为多多守边疆”。&lt;br>
这让包括程序员之外的更多同学，也与润肺有了共情。&lt;/p>
&lt;p>二是拼多多公关“辟谣式造谣”，&lt;br>
引发知乎官方下场对峙拼多多的低水平公关。&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/zhihu_pdd.png" alt="zhihu">&lt;/p>
&lt;p>这种“黑历史打脸”式的操作引发了吃瓜群众的狂欢，&lt;br>
以沙雕行为迅速出圈，&lt;br>
在更大范围内施加影响的同时也引发了不小规模的刻奇行为。&lt;/p>
&lt;p>整场时间在一周后并没有完全被遗忘，&lt;br>
反而引发了诸如“反资本家反996”&lt;br>
“在下班路上猝死，算工伤吗”等系列可能会影响更深远的讨论。&lt;/p>
&lt;blockquote>
&lt;p>“这是一个影响深远的选项，请谨慎选择”&lt;/p>
&lt;/blockquote>
&lt;h1 id="二">（二）&lt;/h1>
&lt;p>从社会的角度，这可能是历史河流中上的一只小蝴蝶。&lt;/p>
&lt;p>随着网民年纪的变大，自媒体话语的放大，&lt;br>
这件事情与最近其它的几件事情一样，都引发了类似的讨论：&lt;br>
人为什么而活。&lt;/p>
&lt;p>马云在三年前还是“马云爸爸”，但最近被叫的最多的还是“资本家马云”。&lt;br>
前几年还经常能见到华为狼性文化、阿里文化价值观的通稿，但最近这些文章的评论区只能控评。&lt;br>
更不用说去年刮起来的“内卷”“PUA”之风，也不知道它们能不能在汉语体系中留有一席之地，&lt;br>
还是与“屌丝”一样失去了最初精准的内涵。&lt;/p>
&lt;p>大事件对长远的影响，我们可以看看历史。&lt;br>
与这次事故对应的，由近及远我想到三件事：&lt;br>
拼多多优惠券事件，导致了企业内部的整顿，似乎并没有影响到社会层面。&lt;br>
滴滴乐清女孩遇害案，督促了网约车安全体系的改革、监管体系的完善。&lt;br>
富士康连环跳楼惨剧，引发了全社会对于“血汗工厂”的讨论，把“员工也是人”的这种最基础的思想重新宣传了一遍。&lt;/p>
&lt;p>这次的蝴蝶会产生什么样的效应呢？&lt;br>
我不确定。&lt;br>
但它一定会改变社会的一部分，&lt;br>
可能是我们一部分的共识，&lt;br>
又或者是一部分我们的生活方式。&lt;/p>
&lt;h1 id="三">（三）&lt;/h1>
&lt;p>从互联网从业者的角度，这又是一个鲜血淋漓的例子。&lt;/p>
&lt;p>Mia 跟我讲过，她在的公司有个不成文的候选人模型，叫：&lt;br>
“Poor, smart, desire to be rich.”&lt;br>
（穷，聪明，渴望有钱）&lt;/p>
&lt;p>互联网的工作模式也是类似的，&lt;br>
以“两个人拿三个人的工资干四个人的活”这样的方式，&lt;br>
吸引了一大批聪明人在这样的公司奋斗。&lt;br>
在上海，拼多多的薪资是独一档，&lt;br>
之前我们面试看中的好几个优秀候选人，&lt;br>
都以至少 50% 的薪资差价被拼多多吸走了。&lt;/p>
&lt;p>不过讲到比惨，似乎总有更惨的，比如“生化环材”的同学就会说：&lt;br>
“我们也不比互联网轻松啊，互联网至少拿的多啊。”&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/shhc.jpeg" alt="2">&lt;/p>
&lt;p>确实。&lt;/p>
&lt;p>况且这只是同时代的横向比较。&lt;br>
假如是跨时代地去比，&lt;br>
就更容易把话题引向了“宁为太平狗，莫作离乱人。”的感慨了。&lt;br>
所以说：&lt;/p>
&lt;blockquote>
&lt;p>一个人的成功，&lt;br>
当然要靠个人奋斗，&lt;br>
但也要考虑到历史的进程。&lt;/p>
&lt;/blockquote>
&lt;h1 id="四">（四）&lt;/h1>
&lt;p>从个人的角度，假如类似的事情发生在自己身上，&lt;br>
我会感到很不值得。&lt;/p>
&lt;p>知乎宇宙里有很多脑洞题目，其中有一个叫&lt;br>
&lt;a href="https://www.zhihu.com/question/316942582">《假设有个游戏，你可以无偿获得五千元，但有百万分之一的几率会当场毙命。那么你会玩多少次游戏？》&lt;/a>&lt;br>
理性人们给出的回答是：“这个概率？我能玩到你破产！”&lt;/p>
&lt;p>炉石传说这款游戏因为随机性很大，&lt;br>
里面也经常有各种各样的概率性斩杀问题。&lt;br>
疯狂的玩家们给出的回答是：“斩杀概率肯定是 50%，因为要么死了，要么没死。”&lt;/p>
&lt;p>这当然是风马牛不相及的两件事。&lt;br>
但在我眼中，生命的道理也与之一样：&lt;br>
“人固有一死，或重于泰山，或轻于鸿毛。”&lt;/p>
&lt;p>我并不欣赏“计算 996 模式工作十年后全身而退的收益比”这样的行为，&lt;br>
但我非常敬佩那些“明知不可为而为之”的“最美逆行者”们。&lt;br>
假如公司是你事业的一部分，那么为之奋斗吧，&lt;br>
否则请一定要爱护好自己的身体，以投身于更大的革命事业中。&lt;/p>
&lt;p>最后，引用保尔柯察金这段话，作为给大家美好的祝愿：&lt;/p>
&lt;blockquote>
&lt;p>人生最宝贵的是生命，生命对于我们只有一次。&lt;br>
一个人的生命应当这样度过：&lt;br>
当他回忆往事的时候，&lt;br>
他不因虚度年华而悔恨，&lt;br>
也不因碌碌无为而羞愧。&lt;br>
在临死的时候，他能够说：&lt;br>
“我的整个生命和全部精力，&lt;br>
都已献给世界上最壮丽的事业&lt;br>
——为人类的解放而斗争。”&lt;/p>
&lt;/blockquote>
&lt;p>（完）&lt;/p></description></item><item><title>软件工程实践之网段管理</title><link>https://liriansu.com/posts/2020-12-13-software-engineering-vpc/</link><pubDate>Sun, 13 Dec 2020 21:48:22 +0800</pubDate><guid>https://liriansu.com/posts/2020-12-13-software-engineering-vpc/</guid><description>&lt;p>软件工程实践系列文章，&lt;br>
会着重讲述实际的工程项目中是如何协作开发软件的。&lt;br>
本文主要介绍了如何规划、搭建、管理网段。&lt;/p>
&lt;h1 id="outline">outline&lt;/h1>
&lt;p>本文包括以下内容：&lt;/p>
&lt;ul>
&lt;li>concepts: 网段中的概念都很基础
&lt;ul>
&lt;li>ip/cidr: IP 是服务的点，而 CIDR 就是描述它的面&lt;/li>
&lt;li>vpc/subnet: VPC 就是云服务提供划分网段的工具&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>boundary: 网段的设计核心是边界划分
&lt;ul>
&lt;li>scene: 利用场景维度来划分，以区别开发、测试、生产环境&lt;/li>
&lt;li>network: 利用网络维度来划分，以区分外网、内网&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>example: 实际开发中的例子
&lt;ul>
&lt;li>ipsec: 用作 VPC 打通的常用工具&lt;/li>
&lt;li>openvpn: 用作连接内网的常用工具&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>conclusion&lt;/li>
&lt;/ul>
&lt;h1 id="concepts">Concepts&lt;/h1>
&lt;p>在我们日常开发中，&lt;br>
只要用到网络就一定会跟各类网段打交道。&lt;br>
很多时候网段作为一种稳定的基础设施，&lt;br>
我们并不会注意到它。&lt;br>
但是关于网段、网络的一些知识，&lt;br>
是确实在软件工程过程中需要考虑的。&lt;/p>
&lt;h2 id="ip-and-cidr">IP and CIDR&lt;/h2>
&lt;p>现代网络中，&lt;br>
IP 是服务的点，而 CIDR 就是描述它的面。&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/ip_types.jpg" alt="ip">&lt;/p>
&lt;blockquote>
&lt;p>IPv4 的类别分类&lt;/p>
&lt;/blockquote>
&lt;p>列举一些能想到的 IP，会包括：&lt;br>
&lt;code>127.0.0.1&lt;/code> 这个约定的本地地址；&lt;br>
&lt;code>8.8.8.8&lt;/code>/&lt;code>8.8.4.4&lt;/code> 这个谷歌提供的 DNS 地址；&lt;br>
&lt;code>59.78.3.25&lt;/code> 这个上海交大东三楼的 IP 地址…&lt;/p>
&lt;p>而 CIDR 则是描述一系列 IP 地址的修饰符。&lt;/p>
&lt;p>比如 &lt;code>59.78.3.25/32&lt;/code> 代表二进制前 32 位都严格与 &lt;code>59.78.3.25&lt;/code> 相等的 IP 地址段（也就是特指这个地址）。&lt;br>
类似地，&lt;code>10.0.0.0/16&lt;/code> 就是以 &lt;code>10.0.&lt;/code> 开头的 IP 地址段。&lt;/p>
&lt;h2 id="vpc-and-subnet">VPC and subnet&lt;/h2>
&lt;p>AWS 作为云服务的始祖，&lt;br>
它开创了 VPC 服务让用户配置自己的网段，&lt;br>
后来 VPC 也逐渐成为了云服务的标配。&lt;/p>
&lt;p>VPC 之间可以相互隔离，也可以打通。&lt;br>
（这里的隔离与打通，指的都是软件上的）&lt;br>
一般 VPC 会用作区分生产、开发环境。&lt;/p>
&lt;p>比如我们可以在云服务上开两个 VPC，&lt;br>
生产环境的 CIDR 是 &lt;code>10.0.0.0/16&lt;/code>，&lt;br>
开发环境的 CIDR 是 &lt;code>10.1.0.0/16&lt;/code>。&lt;/p>
&lt;p>而 VPC 下面可以拆分 subnet (子网)，&lt;br>
subnet 需要有更加具体的 CIDR，&lt;br>
比如生产环境的子网可能会是 &lt;code>10.0.0.0/24&lt;/code>,&lt;code>10.0.10.0/24&lt;/code> 这样的。&lt;/p>
&lt;h1 id="boundary">Boundary&lt;/h1>
&lt;p>网段的核心是边界的划分。&lt;br>
而划分好网段的目的，&lt;br>
既有安全性的考量，&lt;br>
也会利用异地达到高可用容灾的目的。&lt;/p>
&lt;h2 id="scene">Scene&lt;/h2>
&lt;p>云服务一般在全球各大城市会设立数据中心，&lt;br>
每个数据中心会有多个机房，&lt;br>
我们网段的边界至少得以这个为界。&lt;/p>
&lt;p>比如线上服务会跨机房部署，&lt;br>
分布在多个 subnet 中，&lt;br>
当某个机房发生清洁工拔电插吸尘器之类的事故时（一般不会发生）&lt;br>
服务能做到高可用。&lt;/p>
&lt;p>subnet 级别还能配置网络流量的进出权限，&lt;br>
这点特性可以用来规划内部网络权限。&lt;/p>
&lt;p>比如我们可以划分“外网可进可出”、“外网只出不能进”、“外网不可访问（仅可内网访问）”三类 subnet，&lt;br>
以部署不同特性的服务（负载均衡、普通业务、数据库）。&lt;/p>
&lt;h2 id="network">Network&lt;/h2>
&lt;p>网络流量走的是内网还是外网也是值得考量的因素。&lt;/p>
&lt;p>除了安全性因素以外，&lt;br>
一般的云服务商给外网流量定价 1元/GB，&lt;br>
价格因素也是一个需要考虑的点。&lt;/p>
&lt;p>大部分时候，开发可以严格遵循分层的原则，&lt;br>
所有前端走的肯定是外网 API，&lt;br>
所有后端走的肯定是内网 API，&lt;br>
只有负载均衡、网关层考虑内外网转换的问题。&lt;/p>
&lt;p>还有一些时候，可以通过 DNS 自动配置流量网络。&lt;br>
比如默认 &lt;code>api.liriansu.com&lt;/code> 指向负载均衡的外网地址，&lt;br>
但是修改内网的 DNS 使其指向负载均衡的内网地址。&lt;/p>
&lt;h1 id="example">Example&lt;/h1>
&lt;p>最后再附加一些实际开发中的例子。&lt;/p>
&lt;h2 id="ipsec">IPsec&lt;/h2>
&lt;p>在业务庞杂了以后，&lt;br>
就会遇到跨云服务商的开发场景。&lt;br>
跨云服务商的内网打通，&lt;br>
一般会用 IPsec 这个工具，&lt;br>
云服务自己提供的 VPN 服务也是基于此的。&lt;br>
IPsec 的本质是起两台能外网互通的服务器，&lt;br>
互相转发流量。&lt;/p>
&lt;p>比如要配置阿里云与亚马逊云互通的步骤大概会包括：&lt;/p>
&lt;ul>
&lt;li>两边搭建 VPC/subnet (CIDR 不重复)&lt;/li>
&lt;li>两边各起一台有公网访问地址的机器，装好 ipsec
&lt;ul>
&lt;li>配置 ipsec 证书、密钥等&lt;/li>
&lt;li>打开 ip forwarding, 配置好 iptables 防火墙规则&lt;/li>
&lt;li>AWS 注意关掉机器的 source/dest check&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>subnet 路由表配置跳转至 ipsec 机器&lt;/li>
&lt;li>打开两边的安全组，即可互通访问
&lt;ul>
&lt;li>&lt;code>traceroute&lt;/code> 命令可用于检测跳转&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h2 id="openvpn">OpenVPN&lt;/h2>
&lt;p>我们还会遇到的一种场景，&lt;br>
是开发环境接入内网开发。&lt;/p>
&lt;p>这个一般可以用 OpenVPN 之类的工具打通，&lt;br>
但鉴于目前我们还是用的手动流量转发的路子去搞的，&lt;br>
等涉及这部分了再在之后的文章里分享吧 :)&lt;/p>
&lt;h1 id="conclusion">Conclusion&lt;/h1>
&lt;ul>
&lt;li>网段管理是跟开发息息相关的基建，最好能尽早规划好&lt;/li>
&lt;li>网段规划的核心是边界划分，主要考虑安全性与高可用&lt;/li>
&lt;li>云服务的基础概念是类似的，需要考虑好跨云服务、开发测试生产等多维度网段&lt;/li>
&lt;li>内外网流量的复杂因素，可以通过分层或者 DNS 的方式屏蔽掉&lt;/li>
&lt;/ul>
&lt;p>（完）&lt;/p></description></item><item><title>毕业五年的报告之未来</title><link>https://liriansu.com/posts/2020-11-15-adult-life-future/</link><pubDate>Sun, 15 Nov 2020 21:00:54 +0800</pubDate><guid>https://liriansu.com/posts/2020-11-15-adult-life-future/</guid><description>&lt;p>每一年的生命都很重要，&lt;br>
每一年我也总想获得些不同的&lt;a href="https://liriansu.com/my-programmer-habits">经验&lt;/a>。&lt;br>
现在的我，&lt;br>
相比于&lt;a href="https://liriansu.com/adult-life">毕业三年时的我&lt;/a>，&lt;br>
更加接受了一个事实：&lt;br>
“狭义上，我也是个成年人了。”&lt;/p>
&lt;p>广义上的成年人，&lt;br>
可能是年满十八岁。&lt;br>
狭义上的成年人，&lt;br>
是像成年人一样思考、&lt;br>
像成年人一样生活、&lt;br>
并且自认为自己是成年人。&lt;/p>
&lt;p>当然，这话很有那种&lt;br>
“有些人20岁已经死了，但60岁才埋”的中二感觉。&lt;br>
所以请让我仰望星空，&lt;br>
讲一些脚踏实地的，&lt;br>
对未来的思考。&lt;/p>
&lt;h2 id="生活">生活&lt;/h2>
&lt;p>&lt;a href="https://liriansu.com/a-chat-with-roommates">大学时期对未来的畅想&lt;/a>比较随意，&lt;br>
觉得以后可能会在上海开分基地，&lt;br>
也有可能肉身翻墙，&lt;br>
或者是回广东进入“父母在，不远游，游必有方”的状态。&lt;/p>
&lt;p>但随着成年人生活年岁的增加，&lt;br>
肉身翻墙的吸引力逐渐下降了。&lt;br>
一方面是觉得自己的祖国挺温暖的，&lt;br>
另一方面是习惯了以后，&lt;br>
也没觉得网络环境多么不便了。&lt;/p>
&lt;p>回广东的话，我确实可以“父母在，不远游”，&lt;br>
但 Mia 就会“父母在，远，回家得游”…&lt;br>
以前我总觉得相亲条件里“本地人优先”这一点并不科学，&lt;br>
但现在，我也算理解了这个想法的出发点了。&lt;/p>
&lt;p>按目前的想法，&lt;br>
我应该会活在上海这个很舒适的城市里。&lt;br>
气候、交通、机会这些因素我并不看重，&lt;br>
我喜欢的是大城市的&lt;del>人口福利&lt;/del>科技辐射跟君子慎独的城市文化。&lt;br>
科技辐射是指所有民用科技会首先从大城市开始普及；&lt;br>
而君子慎独是指上海这地方很讲规则，&lt;br>
并不是人情优先的。&lt;/p>
&lt;p>不过按照我突发奇想、喜欢折腾的性格，&lt;br>
以后去成都跟大熊猫一起生活、&lt;br>
去泰国新加坡印度尼西亚、&lt;br>
去德国科隆住下也确实是未可知的事情呢。&lt;/p>
&lt;h2 id="职业">职业&lt;/h2>
&lt;p>虽说在哪生活是未可知的，&lt;br>
但是做什么工作我其实很清楚：&lt;br>
做能让技术发挥影响力的事情。&lt;/p>
&lt;p>排去可能性比较低的当业务出身的 HRBP=&amp;gt;HRD 这条职业路线，&lt;br>
能让技术发挥影响力的职业选择，大体上就是：&lt;/p>
&lt;ul>
&lt;li>专家路线：利用某个领域的深入造诣创造价值，代表职位比如资深工程师、架构师&lt;/li>
&lt;li>经理路线：以软件工程方法管理项目，代表职位如项目经理、技术主管&lt;/li>
&lt;li>资本路线：以技术贡献入股，并参与公司级别的经营管理，代表职位如技术VP、CTO&lt;/li>
&lt;/ul>
&lt;p>专家路线下限高、上限不低、机会也多。&lt;br>
&lt;a href="https://liriansu.com/company-stategy">有朋友跟我讲过他的跳槽策略&lt;/a>：&lt;br>
挑着C轮/D轮的独角兽公司去，&lt;br>
一两年公司上市，四五年期权变现，&lt;br>
如此反复，在大公司锻炼的同时，也能获得非常可观的报酬。&lt;br>
大体量的公司往往能锻炼并使用到屠龙技，&lt;br>
随着技术力的上升，&lt;br>
未来像 Linus/Donald-Knuth 一样的专家/科学家也定会人才辈出。&lt;/p>
&lt;p>经理路线更偏工程向，跟公司绑定更深入，同级别影响力也更大。&lt;br>
某种意义上，&lt;br>
软件行业像是画家与工厂的结合体。&lt;br>
既讲究灵感设计与积极性，&lt;br>
又讲究管理科学与计划性。&lt;br>
好的经理能在管理、成本、协作的基础上，&lt;br>
保证最终产品的惊艳质量，&lt;br>
像张小龙、雷军这样最终会被冠以“产品经理”的桂冠。&lt;/p>
&lt;p>资本路线则机会更少、风险更大，&lt;br>
但人最宝贵的就是梦想。&lt;br>
走这条路线的，&lt;br>
既有做到了拼多多CEO的陈磊，&lt;br>
也有&lt;a href="https://www.zhihu.com/question/38295860/answer/76086628">从饿了么早期做起，但最后却黯然离职的叶峰&lt;/a>。&lt;br>
更多的是名字被世界吞没的人，&lt;br>
他们也只能在下一份工作面试时，&lt;br>
在简历里写上“上一份工作：创业（失败）”。&lt;/p>
&lt;p>按照我现在的年龄与技能点，&lt;br>
这三个方向完全都是可以去尝试的。&lt;br>
专家（纯技术）路线能快乐地写代码，&lt;br>
经理（偏管理）路线可以完成更完美的产品，&lt;br>
而资本路线，可以把技术的美妙带给更多的人类。&lt;/p>
&lt;h2 id="行业">行业&lt;/h2>
&lt;p>这五年多在技术行业里工作，&lt;br>
除了一大堆的普世溢美之词，&lt;br>
我对这个行业的两个特质感受非常深：&lt;br>
终身学习、极致分工。&lt;/p>
&lt;p>终身学习从正面来说，&lt;br>
就是&lt;a href="https://liriansu.com/adult-life-memories">认真对待每一个知识&lt;/a>，&lt;br>
永远像十五岁的学生一样去认真学习。&lt;br>
从反面来说，&lt;br>
就是做技术的人只要懈怠了，&lt;br>
就会被刚毕业的同学们超越。&lt;/p>
&lt;p>软件技术就像在站在巨人的肩膀上的巨人的肩膀上的巨人的肩膀上去眺望一样，生生不息。&lt;br>
现世代所流行的应用层技术，&lt;br>
一部分会沉淀成后世代的底层技术，&lt;br>
而另一部分则会消失在世代更迭里。&lt;/p>
&lt;p>所以刚毕业的优秀同学们，&lt;br>
因为年轻，有许多时间学习当下的技术。&lt;br>
不论是薪资还是实力，&lt;br>
很容易就把懈怠的技术人超了过去。&lt;/p>
&lt;p>那些期待着靠工作年限、工作经验来积累职业资本的人，&lt;br>
往往是很难在技术行业生存下去的。&lt;/p>
&lt;p>极致分工的意思，&lt;br>
其实就是“软件工程师就是信息时代的工人”。&lt;br>
（附带说一句，这也是最近阶级论在软件行业思潮里很受欢迎的原因）&lt;/p>
&lt;p>这个比喻本意是无奈的技术行业从业者自嘲，&lt;br>
但是它可以引申出来一点：&lt;br>
技术行业（特指程序员）缺少传统意义上的社会价值。&lt;/p>
&lt;p>在生活里，&lt;br>
医生朋友能给你健康意见；&lt;br>
律师朋友能给你法律建议；&lt;br>
销售朋友给你介绍了工作里认识的朋友，有医生也有律师；&lt;br>
但是程序员的工作只有月薪。&lt;/p>
&lt;p>于是看到了这一点的程序员们，&lt;br>
会积极地与人交互，&lt;br>
保持稳定积极的社会关系。&lt;br>
但也有很多程序员，&lt;br>
在朋友问到“能不能帮我写个小程序”的时候，&lt;br>
只能回答：“我是后端，不会写前端。”&lt;/p>
&lt;p>而终身学习、极致分工这两个技术行业特质，&lt;br>
是在考虑“健康工作五十年，幸福生活一辈子”时无法回避的两点。&lt;br>
有朋友在打算 35 岁攒足够的钱提前退休，&lt;br>
也有朋友考虑好了年纪大了就换行，&lt;br>
去参与本地生活服务业的建设了（此处指送外卖）。&lt;/p>
&lt;h2 id="价值">价值&lt;/h2>
&lt;p>因为思考未来，&lt;br>
所以人会思考自己的价值，&lt;br>
生活的价值、工作的价值、存在的价值。&lt;/p>
&lt;p>再惠（我在的公司）的愿景是“让美食生意更轻松”，&lt;br>
关于&lt;a href="https://liriansu.com/my-work">我工作我之前也写过一些文章&lt;/a>。&lt;br>
从价值角度来讲，美中不足的主要有两点：&lt;/p>
&lt;p>其一是餐饮这个成熟的服务行业里，&lt;br>
技术能发挥的作用已经被探索了许多了，&lt;br>
相比于再多一个小的功能，&lt;br>
客服一次及时的响应更能让商家、消费者安心。&lt;/p>
&lt;p>其二是餐饮行业虽然高频、市场大、机会多，&lt;br>
但并不能经常“改变人的命运”。&lt;br>
“改变命运”的行业，&lt;br>
人们称之为“新三座大山”：&lt;br>
住房、医疗、教育。&lt;br>
正是因为这几个行业的基础性以及重要性，&lt;br>
国家政府制定了非常多的调控政策。&lt;/p>
&lt;p>倘若未来某一天，&lt;br>
我准备出门去&lt;del>创业&lt;/del>搞搞事情，&lt;br>
那我或许会先考虑好，&lt;br>
如何在这三座大山里找到我的价值。&lt;/p>
&lt;p>不过在那之前，&lt;br>
我还是先徜徉在代码的海洋里吧 :)&lt;/p>
&lt;h2 id="梦想">梦想&lt;/h2>
&lt;p>人考虑现实问题时，容易忘记梦想；&lt;br>
但仰望梦想时，现实问题仿佛都不重要了。&lt;/p>
&lt;p>在&lt;a href="https://liriansu.com/about">我的自述&lt;/a>里，我以前这么写道：&lt;/p>
&lt;blockquote>
&lt;p>我的梦想是世界和平，好人都能幸福，&lt;br>
以及要成为一个很厉害的人。&lt;/p>
&lt;/blockquote>
&lt;p>现在我有了更具象的描述，叫：&lt;/p>
&lt;blockquote>
&lt;p>我的梦想是：&lt;br>
&lt;strong>世界和平&lt;/strong>，&lt;br>
&lt;strong>我爱的人跟爱我的人都能幸福&lt;/strong>，&lt;br>
&lt;strong>我要成为温柔的强者&lt;/strong>。&lt;/p>
&lt;/blockquote>
&lt;p>有的时候觉得语文真的挺神奇的。&lt;br>
梦很容易，想也很容易，&lt;br>
但梦想感觉却没那么容易。&lt;/p>
&lt;p>即使按照从大到小的递进关系来看，&lt;br>
这几条里看似最简单的一条&lt;br>
“我要成为温柔的强者”也并不简单。&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/good_and_strong.png" alt="good-strong">&lt;/p>
&lt;p>成年人生活并不像学生一样，&lt;br>
会有期中、期末、寒假、暑假这种明显的节点让你自省，&lt;br>
很多人逐渐是靠着惯性活着。&lt;br>
而靠惯性活着就很难做到“有则改之，无则加勉”了。&lt;/p>
&lt;p>风口让猪飞了起来，&lt;br>
猪可不能以为自己真能飞。&lt;br>
按&lt;a href="https://liriansu.com/adult-life-teamwork">我自己的说法&lt;/a>，&lt;br>
叫 Stay Awake；&lt;br>
而按&lt;a href="https://liriansu.com/thoughts-on-1984">电影《辛德勒的名单》的比喻&lt;/a>，&lt;br>
会这么说：&lt;/p>
&lt;blockquote>
&lt;p>“你可以轻而易举地处决一个集中营的人，但这不是权力。&lt;br>
真正的权力，是你把刀架在别人脖子上时，可以说：‘我宽恕你’。&lt;br>
这才是真正的权力。”&lt;/p>
&lt;/blockquote>
&lt;h2 id="结">结&lt;/h2>
&lt;p>写到此处，&lt;br>
因为我笔力不足而一分为四的《毕业五年的报告》也终于完工了。&lt;br>
相比于两年前的《毕业三年的报告》，&lt;br>
感觉作者的可爱度下降了(x&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://liriansu.com/adult-life">《毕业三年的报告》&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://liriansu.com/adult-life-memories">《毕业五年的报告之回忆》&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://liriansu.com/adult-life-teamwork">《毕业五年的报告之团队》&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://liriansu.com/adult-life-code">《毕业五年的报告之技术》&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://liriansu.com/adult-life-future">《毕业五年的报告之未来》&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>这个系列的下一篇，&lt;br>
估计也将是两年后、三年后，&lt;br>
甚至五年后的“毕业十年的报告”了吧。&lt;/p>
&lt;p>或者，看到这的你，&lt;br>
其实是五年后通过文内超链接点回来的呢？&lt;br>
嘿嘿。&lt;/p>
&lt;p>那最后，祝你身体健康，有缘再见！&lt;/p>
&lt;p>（完）&lt;/p></description></item><item><title>对加速主义保持清晰认知</title><link>https://liriansu.com/posts/2020-11-12-speedupism/</link><pubDate>Thu, 12 Nov 2020 21:44:34 +0800</pubDate><guid>https://liriansu.com/posts/2020-11-12-speedupism/</guid><description>&lt;blockquote>
&lt;p>这屋子太暗，须在这里开一个窗，大家一定不允许的。&lt;br>
但如果你主张拆掉屋顶，他们就会来调和，愿意开窗了。&lt;/p>
&lt;p>——鲁迅&lt;/p>
&lt;/blockquote>
&lt;p>鲁迅先生的这句话，&lt;br>
很传神地阐述了一个加速主义的例子。&lt;/p>
&lt;h1 id="认识到加速主义的存在">认识到加速主义的存在&lt;/h1>
&lt;p>什么是加速主义呢？&lt;br>
加速主义，&lt;br>
就是顺着事物发展方向，&lt;br>
一路不收手地推下去，&lt;br>
直到失去控制。&lt;br>
一般加速主义会在什么情况下出现呢？&lt;br>
不担责的建议决策时。&lt;/p>
&lt;p>除了拆屋顶来开窗这个经典例子，&lt;br>
加速主义日常生活中也很常见。&lt;/p>
&lt;p>比如年轻男女谈朋友，&lt;br>
遇到些矛盾，&lt;br>
就会有很多围观群众拱火：&lt;br>
“快分手，别谈了！&lt;br>
连生日/国庆节/双十一/圣诞节/冬天来临都不会给你买礼物的肯定不是好伴侣！”&lt;br>
但其实恋爱这种冷暖自知的事情，&lt;br>
真的分手了旁人也不用承担孤独的煎熬，&lt;br>
往往只会留下“快进到分手”这种一句话的狂欢。&lt;/p>
&lt;p>又比如像写代码的程序员，&lt;br>
其实可以在项目搭建时，&lt;br>
引入一些自己喜欢的冷门的技术栈（比如 Lisp）。&lt;br>
但承受后果的，&lt;br>
却会是人员离职交接时，&lt;br>
没人能顶上来做业务的公司。&lt;br>
而挂在 GitHub 个人主页的一句 &lt;code>I'm Lisper&lt;/code> 也成了此时映照加速主义的最好信条。&lt;/p>
&lt;h2 id="当下的群体容易产生加速主义">当下的群体容易产生加速主义&lt;/h2>
&lt;p>2020 年的时代思潮下，&lt;br>
自由主义与个人权力意识大量觉醒。&lt;br>
只论个人，&lt;br>
加速主义微不足道，&lt;br>
因为_冷暖自知_。&lt;br>
但在群体的语境下，&lt;br>
总会浮动着加速主义的潮汐。&lt;/p>
&lt;p>谦虚是美好的品德，&lt;br>
儒家文化圈中更是。&lt;br>
群体生活中，不自觉地就会出现比这还夸张的行为。&lt;br>
比如前阵子多益公司，&lt;br>
宣布“公司业绩很好，让大家自愿选择降薪”，&lt;br>
然后嘉奖那些主动降薪的人。&lt;br>
这个行为在外部看来是“过于弱智，以至于让人怀疑是否在反串”，&lt;br>
但在内部真正踊跃接受了这个决定的人，&lt;br>
不也会有抱着“一脚油门踩死，毁灭吧”这样的加速主义心态吗？&lt;/p>
&lt;p>之所以群体容易产生自由主义，&lt;br>
是因为群体是不需要为结果负全责的。&lt;br>
天花板被拆掉了，&lt;br>
受凉了不只有你，&lt;br>
所谓“天塌了高个子顶着”，&lt;br>
那嚷嚷一下拆天花板又有什么关系呢？&lt;/p>
&lt;p>比如像&lt;a href="https://liriansu.com/fight-with-the-feminist-me">女权男德&lt;/a>、政治正确、性自由这样的话题，&lt;br>
每一个在当下的群体语境中其实都充斥着加速主义论点。&lt;br>
正面迎击加速主义，&lt;br>
不如顺着舆论踩一脚油门，&lt;br>
吟一句“生命诚可贵，自由价更高。”&lt;/p>
&lt;h2 id="对加速主义保持清晰认知">对加速主义保持清晰认知&lt;/h2>
&lt;p>加速主义是主观的、强烈的、不可抗拒的。&lt;br>
工作生活中，&lt;br>
我经常看到加速主义的身影，&lt;br>
并且我也很多次受着加速主义的影响。&lt;/p>
&lt;p>我以前是弹性上班，早上 10:30 左右到即可。&lt;br>
但工程师同事们习惯懒散自由，&lt;br>
一方面这个管理方式过于特别，&lt;br>
另一方面早上客户参观也影响销售情况，&lt;br>
后来公司便讨论改到了 10:00 上班，迟到罚款。&lt;br>
讨论时，基于加速主义思想，&lt;br>
我还加了统计下班时间、引入打卡系统这两个并不弹性的设定。&lt;br>
虽然打卡没打上，&lt;br>
但这样的策略一引入，&lt;br>
早上上班的状态确实焕然一新。&lt;/p>
&lt;p>有时顺着事物发展方向用力一推，&lt;br>
确实能得到跟认知并不一样的答案。&lt;/p>
&lt;p>还有一个类似的事情，&lt;br>
就是公司的大家一直觉得网络很卡。&lt;br>
因为总带宽低，每个设备都被限了低速。&lt;br>
但后来大家抱怨多了，&lt;br>
便给每个人的限速都开高了。&lt;br>
（此处有加速主义存在）&lt;br>
网络情况却更恶劣了，&lt;br>
因为只要有一个人卡了网速，&lt;br>
他占用别人的部分就会更多。&lt;br>
真正清晰认识到加速主义的办法，&lt;br>
是合理规划流量、网络分片、加高总带宽。&lt;/p>
&lt;h2 id="综述">综述&lt;/h2>
&lt;p>社会上、工作中、生活里少不了要跟群体打交道，&lt;br>
站在 2020 年的这个时代当下，&lt;br>
你会观测发现到处都存在着加速主义。&lt;/p>
&lt;p>当你是参与者的时候，&lt;br>
你可以不必迎击加速主义，&lt;br>
而是利用加速主义来表达你的态度；&lt;br>
当你是决策者的时候，&lt;br>
你需要清晰认识到加速主义，&lt;br>
从情绪之中摘出真正的价值，&lt;br>
并与之共事。&lt;/p>
&lt;p>这屋子太暗，&lt;br>
有人主张拆掉屋顶，&lt;br>
而你知道，&lt;br>
他其实是想开扇窗。&lt;/p>
&lt;p>（完）&lt;/p></description></item><item><title>一厘米的权力</title><link>https://liriansu.com/posts/2020-11-11-ownership/</link><pubDate>Wed, 11 Nov 2020 20:53:43 +0800</pubDate><guid>https://liriansu.com/posts/2020-11-11-ownership/</guid><description>&lt;p>前阵子跟基友们聊到 S1 发的一张图，&lt;br>
hulucc 感慨：“讲道理这个作者至少占一半锅。”&lt;br>
eagzzycsl 附：“像是一厘米原则，开发有义务保证最终完整性。”&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/bad_ownership.jpg" alt="bad-ownership">&lt;/p>
&lt;h2 id="一厘米主权">一厘米主权&lt;/h2>
&lt;p>有一个流传很久的故事，&lt;br>
说还在柏林墙时期的德国，&lt;br>
有一个士兵射杀了一名翻墙逃亡的青年。&lt;br>
因此他被告上了法庭，&lt;br>
虽然他跟律师都辩称“这不过是执行命令”，&lt;br>
但法官指出：&lt;br>
“你确实要执行命令，但你完全可以没打准。”&lt;br>
最终，这个士兵被判了刑。&lt;/p>
&lt;p>这个故事虽然听起来很鸡汤，&lt;br>
而且也有一些人质疑故事的真实性，&lt;br>
但是故事里的道理是真切的：&lt;br>
良知是人类普世的原则，&lt;br>
不能因为有借口而降低伦理底线。&lt;/p>
&lt;p>这个故事总让我想到《孟子》里的一节，&lt;br>
说梁惠王觉得自己当国王当的尽心尽力了，&lt;br>
能做的都做了。&lt;br>
但孟子直接地指出了当时社会上存在的一系列问题，&lt;br>
并且作下了一个振聋发聩的比喻：&lt;/p>
&lt;blockquote>
&lt;p>狗彘食人食而不知检，涂有饿莩而不知发；&lt;br>
人死，则曰：“非我也，岁也。”&lt;/p>
&lt;p>是何异于刺人而杀之，曰：“非我也，兵也！”&lt;/p>
&lt;/blockquote>
&lt;p>梁惠王在执政过程中，&lt;br>
因为自己的借口能很好地给自己妥协，&lt;br>
但是世道却离他的期望值越来越远。&lt;/p>
&lt;p>生活中许多时候是可以依靠着借口得过且过的，&lt;br>
但是到了最终结果时，&lt;br>
还是得看我们具体做了什么。&lt;/p>
&lt;p>这就是我所认为的：&lt;br>
可以唯心地思考，&lt;br>
但要唯物地生活。&lt;/p>
&lt;h2 id="技术服务业">技术服务业&lt;/h2>
&lt;p>一厘米主权似乎是一个很遥远的故事，&lt;br>
我再讲一个我记了好一阵的回忆。&lt;/p>
&lt;p>大学时候在学校网管部，&lt;br>
每周都要值班报修。&lt;br>
我印象最深的，&lt;br>
是一个因为没选上课而上门吵闹了半小时的同学。&lt;/p>
&lt;p>确实，没选上课跟我们负责修网口的网管部同学们有什么关系呢？&lt;br>
但从他本人的角度来说，&lt;br>
除去发泄情绪的因素外，&lt;br>
难用的选课系统跟蹩脚的网络，&lt;br>
大概也是需要解决的。&lt;/p>
&lt;p>做技术也是如此。&lt;br>
我见过不少人在合作中，&lt;br>
都会以“我不管这个”的道理来解决他的问题。&lt;br>
而这样的人一多，&lt;br>
就会自然地形成足球场的感觉，&lt;br>
假如每天只在追逐这不能被解决的足球般的问题，&lt;br>
那人的热情就会被很快地耗光。&lt;/p>
&lt;p>技术工作里，&lt;br>
在被定义好的工作范畴中间，&lt;br>
就会有这么一些灰色的、偏向于服务的事情，&lt;br>
需要被完成。&lt;/p>
&lt;h2 id="我没错">我没错&lt;/h2>
&lt;p>一厘米主权故事里，&lt;br>
还有一个隐藏的信念，&lt;br>
叫“我没错”。&lt;/p>
&lt;p>就像头图里的那位开发，&lt;br>
讲道理，他是可以认为自己没有错。&lt;br>
不过假如是我，&lt;br>
我不会这么做。&lt;/p>
&lt;p>技术工作因为它的专业性，&lt;br>
所以讲出来的话很难被外行质疑。&lt;br>
就比如我告诉产品：&lt;br>
“这个功能历史实现逻辑就是这样的。”&lt;br>
他很难能亲自读代码来验证我说的话。&lt;br>
但假如我是厨师，我说：“这道菜就是这么做的。”&lt;br>
显然就有被质疑的空间。&lt;/p>
&lt;p>技术工作里，&lt;br>
随着工作范畴的固化，&lt;br>
每个人能获得的借口也越多。&lt;br>
但正是这种时候，&lt;br>
才显示出一厘米主权这样，&lt;br>
谦逊、自省这种品质的宝贵了。&lt;/p>
&lt;p>所以不论任何时候，都要记住：&lt;br>
人的边界，并不是被划定的，&lt;br>
我永远拥有多一厘米的权力。&lt;br>
（冬泳大叔语气）&lt;/p>
&lt;p>（完）&lt;/p></description></item><item><title>神通中学二三事</title><link>https://liriansu.com/posts/2020-08-31-work-as-schoolmate/</link><pubDate>Mon, 31 Aug 2020 19:45:02 +0800</pubDate><guid>https://liriansu.com/posts/2020-08-31-work-as-schoolmate/</guid><description>&lt;p>我的几个好友里，&lt;br>
灰灰当了语文老师，&lt;br>
佳佳当了英语老师，&lt;br>
而我成为了饭堂阿姨，&lt;br>
我们都有美好的未来。&lt;/p>
&lt;p>（一）&lt;/p>
&lt;p>不知何年何月，&lt;br>
神通中学成立了。&lt;br>
“为了一个伟大的目标，&lt;br>
让天下的同学都有书读！”&lt;br>
奠基典礼上校长这么说道。&lt;br>
为了这个不知何年何月但光芒万丈的目标，&lt;br>
学校从五湖四海招来了一批师资很不错的老师，&lt;br>
也在市内选拔了一批底子很不错的学生。&lt;/p>
&lt;p>（二）&lt;/p>
&lt;p>敏俊是神通中学的保安。&lt;br>
因为保安厅就在入口的“神通中学”四个金色大字旁边，&lt;br>
很多同学都把他漫溢的笑容跟“神通中学”等同在了一起。&lt;br>
以至于很多毕业的同学回来参加毕业典礼，&lt;br>
总会问道：“咱们那个爱笑的保安去哪了？”&lt;/p>
&lt;p>其实学校也没有什么安全问题，&lt;br>
所以作为一个壮实的保安，&lt;br>
敏俊总是需要时不时干各种杂活。&lt;br>
比如文艺晚会搬投影仪啦、&lt;br>
科技界组织操场上的水火箭比赛啦、&lt;br>
艺术节当油画模特啦等等等等。&lt;/p>
&lt;p>因为性格好，大家也喜欢开他玩笑。&lt;br>
比如什么“你小熊饼干呢？”&lt;br>
“食堂阿姨好像特别喜欢你啊！”&lt;br>
“你这么帅怎么不去当偶像练习生~”&lt;br>
每次别人这么调侃敏俊，&lt;br>
他也只是笑着做好一个保安该做好的事情。&lt;/p>
&lt;p>（三）&lt;/p>
&lt;p>神通中学的政治老师是冰冰，&lt;br>
他也是政治科的科组长，&lt;br>
四十多岁的冰冰有着跟稳重的外表完全不一的内心。&lt;/p>
&lt;p>虽然每次备课的时候他都认真教育年轻老师，&lt;br>
但他自己讲课的时候经常是脚踩西瓜皮——讲到哪里算哪里，&lt;br>
尤其是他讲法律的时候。&lt;br>
会考以后讲卷子的课，三分钟就把哲学、社会的部分给评完了，&lt;br>
剩下四十二分钟都在讲法律的题。&lt;br>
同学们也喜欢听他讲课，&lt;br>
还有同学从小道消息打听到他以前跟罗翔同学过一段时间。&lt;/p>
&lt;p>不过有一点就是他喜欢拖堂，&lt;br>
这个教导主任拿他也没办法。&lt;br>
他也总会把这句话挂在嘴边：&lt;br>
“现在拖堂是拖你们十分钟，但你们认真听的话，你们一辈子都会受用的！”&lt;br>
也算是苦口婆心了。&lt;/p>
&lt;p>（四）&lt;/p>
&lt;p>因为原来的地理老师海寒考上了牛津的研究生，&lt;br>
所以去年学校招了个应届生从实习做起。&lt;br>
新来的实习老师是四川来的，叫梦琴，&lt;br>
第一天到级部还给每个人都带了一包兔头，&lt;br>
连看门的保安都有一份。&lt;/p>
&lt;p>梦琴有一个很明显的缺点，&lt;br>
跟一个很明显的优点。&lt;br>
缺点是她虽然是地理系毕业的，&lt;br>
但对中国地理不太熟悉，&lt;br>
一次在上课时讲出“辽宁的首都是不是吉林啊”的话以后哄堂大笑。&lt;br>
导致她来了以后，海寒老师更忙了：&lt;br>
不仅要帮学生补课还要帮梦琴补课。&lt;/p>
&lt;p>优点就更明显了，&lt;br>
有她在的地方就不会缺少笑声，&lt;br>
大家都很喜欢她。&lt;br>
在她来了神通中学以后，&lt;br>
每学期的“你最喜欢的老师”匿名评选中，&lt;br>
梦琴总是能稳居前三名。&lt;/p>
&lt;p>不过这也可能是因为梦琴老师从来不拖堂，&lt;br>
大概也许是因为她想早点去吃饭吧。&lt;/p>
&lt;p>（五）&lt;/p>
&lt;p>神通中学最开始占地面积挺小的，&lt;br>
后来扩建以后有了自己的饭堂，&lt;br>
搬校区以后饭堂又重建了几次。&lt;br>
虽然饭堂换了几个地方，&lt;br>
但饭堂阿姨一直没有换过，&lt;br>
一直就是同学口中“胖胖的布达阿姨”。&lt;/p>
&lt;p>布达阿姨是那种刀子嘴豆腐心的人。&lt;br>
每次有同学在饭堂要关门前踩点吃饭了，&lt;br>
布达阿姨都是一边说着“饭没啦饭没啦，不早点来”&lt;br>
一边把收拾好的饭盆又拿了一个出来打饭。&lt;/p>
&lt;p>布达阿姨最享受的时光，&lt;br>
是“熊孩子们”吃完饭以后，&lt;br>
她给自己也打一盆饭，&lt;br>
坐在饭堂的一角，&lt;br>
跟其它学校后勤部门的同事聊聊天谈谈八卦。&lt;/p>
&lt;p>不过最近她在苦恼着要不要自己带饭，&lt;br>
因为后厨做饭油盐给的很重，&lt;br>
她既想自己做饭吃得清淡一点，&lt;br>
又不想每天做饭麻烦自己。&lt;/p>
&lt;p>（六）&lt;/p>
&lt;p>关于饭堂阿姨的千古话题，&lt;br>
就是她们对饭勺的精妙控制。&lt;br>
经常是一勺美满姻缘，&lt;br>
一抖红尘再见。&lt;/p>
&lt;p>在大家都埋怨饭堂的饭越来越少的时候，&lt;br>
保安敏俊倒是不觉得：&lt;br>
“没有啊，我感觉饭还挺多的？”&lt;/p>
&lt;p>后来吃饭时后勤部聊天，&lt;br>
布达阿姨邪魅一笑，&lt;br>
用耐克弯钩般的嘴角上扬揭露了秘密。&lt;br>
原来布达阿姨了解到，&lt;br>
敏俊其实高中毕业就出来打工了，&lt;br>
今年年初的疫情让温州的他现金流接近断裂，&lt;br>
敏俊已经啃了好几个月的馒头了。&lt;br>
于是布达阿姨就会在敏俊来吃饭的时候，&lt;br>
偷偷地给他加点饭，&lt;br>
米饭加一两，狮子多个头。&lt;/p>
&lt;p>管后勤的晓俊听完直感慨：&lt;br>
“虽然学校里面无大事，&lt;br>
但是小事你用真情做，&lt;br>
也是能做出很大影响的啊！”&lt;br>
管财务的关口（晓俊死对头）马上不留情面地评论道：&lt;br>
“陈晓俊你又乱说了！”&lt;/p>
&lt;p>（七）&lt;/p>
&lt;p>其实学校里还有很多微不足道的小事，&lt;br>
比如爱画画的美术老师重音与爱摄影的留级生几龙碰撞出的火花啦，&lt;br>
比如明明是副科老师但是呆学校时间比班主任还久的通用技术老师志强啦，&lt;br>
还有班长钉钉子跟副班长带带子之间的互怼啦。&lt;/p>
&lt;p>不过毕竟这篇小文章只是讲学校的二三事，&lt;br>
而并不是一本完备的校史。&lt;br>
就算是完备的校史，&lt;br>
那也只是过去的辉煌。&lt;br>
学校的未来，&lt;br>
依然是依靠每一个学生、每一个老师去书写的。&lt;/p>
&lt;p>不知何年何月，&lt;br>
神通中学成立了。&lt;/p>
&lt;p>（完）&lt;/p></description></item><item><title>毕业五年的报告之技术</title><link>https://liriansu.com/posts/2020-07-12-adult-life-code/</link><pubDate>Sun, 12 Jul 2020 23:45:58 +0800</pubDate><guid>https://liriansu.com/posts/2020-07-12-adult-life-code/</guid><description>&lt;p>16年接触了 Web 整套技术栈的我，&lt;br>
决定在这条路上不断攀爬，&lt;br>
直到找到我技术上的天花板。&lt;br>
当时我写了一篇&lt;a href="https://liriansu.com/backend-skill-tree">《后端工程师技能树》&lt;/a>。&lt;/p>
&lt;p>现在回过头再看，&lt;br>
我并没有按照叶子节点的顺序去一步步做。&lt;br>
除了系统地学习了解技术知识以外，&lt;br>
我更多是在“明天上线”以及“线上挂了”的血与火的泥泊里扑腾。&lt;/p>
&lt;p>这篇就以不同的视角，&lt;br>
记录一下我这几年技术上的感悟吧。&lt;br>
由于讲述的更偏 Web，&lt;br>
所以本篇基本都是以再惠的实际开发为例。&lt;/p>
&lt;h2 id="项目语言与框架">项目、语言与框架&lt;/h2>
&lt;p>16年的时候，公司的业务在一个大主站里就可以完全解决了。&lt;br>
这单个项目不仅包括了全部后端代码，&lt;br>
还包括了全部前端代码（不过后来前端就拆出去了）&lt;/p>
&lt;p>当时用的是 Python 2.7 + Django 1.8,&lt;br>
不过由于 Python2 在生命的末期，&lt;br>
后来我们就&lt;a href="https://liriansu.com/py2-to-py3">找了个周末升级到了 Python 3.5&lt;/a>。&lt;br>
顺带一提，当时不升 Python 3.6 的原因是 Ubuntu 16 默认带的是 Python 3.5。&lt;/p>
&lt;p>Python 是一门非常容易上手的语言，&lt;br>
我进再惠前其实没有认真用过（连 virtualenv 都不知道是什么，只会 print），&lt;br>
但很快就可以开始参与业务开发了。&lt;br>
整个主站在开发周期里，&lt;br>
框架没有大的变动，&lt;br>
基本上是前人怎么写的，后人就怎么写。&lt;/p>
&lt;p>当时我在语言上感兴趣的几个点，主要包括：&lt;/p>
&lt;ul>
&lt;li>magic method 与元编程：于是我实现了一套根据配置生成接口的逻辑&lt;/li>
&lt;li>性能、并发与处理能力：于是我们经常在小黑板上画各类网络架构图&lt;/li>
&lt;li>不同框架之间的对比：于是我们内部后面的项目尝试使用了 flask/tornado 等各类框架&lt;/li>
&lt;li>关于语言本身的话题：于是我们内部每天都在讨论&lt;a href="https://www.yinwang.org/">垠神@wangyin 的博客&lt;/a>（x&lt;/li>
&lt;/ul>
&lt;p>后来业务线逐渐开始变多，&lt;br>
我也有机会从零开始搭建一个项目。&lt;br>
因为是从零开始，所以我心中暗想：&lt;br>
“以前很多东西我都是知其然不知其所以然，&lt;br>
这次项目的所有方面我都要完全理解才行。”&lt;br>
于是那个月所有的业余时间我都在读各种文档…&lt;/p>
&lt;p>不读不知道，一读吓一跳。&lt;br>
我发现我以前默认的很多习惯用法，&lt;br>
其实都有更佳的实践：&lt;/p>
&lt;ul>
&lt;li>
&lt;p>&lt;strong>轻度使用&lt;/strong>：&lt;br>
以前项目里会搭配着使用 djangorestframework,&lt;br>
但我们从来都是手写各种序列化类，&lt;br>
并没有使用框架自带的 django model 支持。&lt;br>
而且我们自己实现了一套 schema 验证系统，&lt;br>
既没有用 djangorestframework,&lt;br>
也没有用 marshmellow 这样的库。&lt;br>
（这导致了后面支持 swagger 非常困难）&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>缺少检查&lt;/strong>：&lt;br>
Python 社区中有非常多的检查工具，&lt;br>
但我们只用到了最基础的 flake8 来验证 PEP8 风格。&lt;br>
我们在合作编程中，&lt;br>
因为每个人 PyCharm 配置的不一样，&lt;br>
解了无数次 import 的冲突。&lt;br>
（更别提还有数组末行加逗号的冲突了）&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>版本老旧&lt;/strong>：&lt;br>
我们用的很多三方库一直保持着版本更新，&lt;br>
但我们却一直用着旧的版本（更别说语言本身了，f-string 我们也是老后面才用上的）&lt;/p>
&lt;/li>
&lt;/ul>
&lt;p>这些问题在后面的项目开发中，&lt;br>
我逐个都解决掉了。&lt;br>
轻度使用的问题好说，找一个哥去研究正确的用法然后去优化就行了。&lt;br>
（有时这个优化会涉及几百个文件，所以需要一个 vim 用的溜的哥）&lt;br>
缺少检查也好说，像 flake8/isort/pytest/pylint/yapf/black 我们都尝试使用过，&lt;br>
后面按照项目规模我们开了不同级别的检查，&lt;br>
原则上，项目越大检查越严格。&lt;br>
关于语言与三方库版本的问题，&lt;br>
我每周基本都会保持跟社区的更新，&lt;br>
以人肉 dependency bot 的方式去维护代码。&lt;br>
在解决完这些明显的问题后，&lt;br>
19年我很开心地跟伙伴们感慨过：&lt;br>
“我很有信心说，我们写的这个项目就算放在开源社区也是一流的。”&lt;/p>
&lt;p>框架上最终我们还是大规模使用了 Django，&lt;br>
因为 Django 的整套 ORM 实在是对增删改查这样的业务太契合了。&lt;br>
性能上我们后面尝试并最终使用了 gevent，&lt;br>
让整个项目写起来体验一致，&lt;br>
跑起来性能合格。&lt;/p>
&lt;p>现在要我实现一个标准的 Python Web 服务的话，我会考虑使用这样的技术组合：&lt;/p>
&lt;ul>
&lt;li>使用最新的版本号，比如 Python3.8+/Django3+/Celery4.5+ 等&lt;/li>
&lt;li>在 CI 中开启一系列标准检查，比如 flake8/isort/pytest/black&lt;/li>
&lt;li>使用 gnumake/pipenv/drf-yasg 这样的工具链&lt;/li>
&lt;li>使用 gunicorn+gevent 作为运营环境&lt;/li>
&lt;li>在语言的性能问题成为了关键问题时，考虑使用 golang 重写关键部分（不过一般此时都要更大程度上更新架构了）&lt;/li>
&lt;/ul>
&lt;h2 id="平台">平台&lt;/h2>
&lt;p>过去几年的技术生涯里，&lt;br>
我最主要跟两个平台在打交道：&lt;br>
一个是云平台 (AWS/Aliyun/Azure)，&lt;br>
另一个是业务平台（微信开放平台）。&lt;/p>
&lt;p>业务平台没什么特别好说的，&lt;br>
因为我做的整块业务都是基于微信生态的，&lt;br>
所以对开放平台、小程序、OpenID/UnionID、支付回调这么一套非常熟悉。&lt;/p>
&lt;p>最早接触的云平台是 AWS(China)，&lt;br>
我觉得云平台最好的一点是运维扁平化。&lt;br>
招人的时候我会跟候选人说，&lt;br>
我们这个职位从网络、业务、数据到部署、监控都要接触。&lt;br>
而能做到这一点的基础，&lt;br>
就是我们“去运维化”地让大家直接去对接云平台&lt;br>
（有些地方可能会简单包一层）。&lt;/p>
&lt;p>最早我们用的是 AWS（国服），&lt;br>
相比于国际服，国服用户缺少了一些非常基础的设施&lt;br>
（比如像 ACM/Route53 等）&lt;br>
导致不论是像 zappa 这种跑 serveless 的库，&lt;br>
还是 AWS EKS 这种更高阶的服务能力都是缺失的。&lt;br>
在18年底我司就从 AWS 切换到了 aliyun。&lt;br>
其实整体的架构没有本质上的差别，&lt;br>
感受上阿里云的服务的确好些，&lt;br>
不过按 @lxkaka 的说法也可以叫：&lt;br>
“他们这个系统假如没地方问的话说不过去啊！”&lt;/p>
&lt;p>目前我们使用云平台的姿势包括：&lt;/p>
&lt;ul>
&lt;li>最基础的开机器、负载均衡、域名一系列&lt;/li>
&lt;li>数据相关的 MySQL/Redis/Mongo/EMR 一套&lt;/li>
&lt;li>监控报警日志相关系统&lt;/li>
&lt;li>全套托管的 K8S&lt;/li>
&lt;/ul>
&lt;p>随着对云平台使用的更加深入，&lt;br>
跟云平台强绑定的技术也会越来越多，&lt;br>
比如像日志系统就基本抛弃了 ELK 拥抱了阿里的日志。&lt;br>
但从成本的视角上看，&lt;br>
对工具的使用减少了冗余的运维需求，&lt;br>
一定程度上是解放了工程师的时间与效能。&lt;/p>
&lt;p>现在要我从头开始搭建云平台的基建的话，我会考虑这样的实现组合：&lt;/p>
&lt;ul>
&lt;li>拆分 VPC 网段，大部分情况分生产、测试、访客三个网段就可以了（并辅以合适的安全组策略）&lt;/li>
&lt;li>以托管的 K8S 服务为核心搭建业务系统，配上配套基建（云盘、日志、监控等）&lt;/li>
&lt;li>用 LB/Gateway 约束网络入口、出口，拆分各网段之间流量，尽量减少网络上的损耗&lt;/li>
&lt;li>选型时优先考虑云原生功能，如 MySQL/ES/MQ 等&lt;/li>
&lt;/ul>
&lt;h2 id="部署">部署&lt;/h2>
&lt;p>在大主站时期，&lt;br>
我们的 Python 服务以 supervisor+virtualenv 裸部署在三种机器上：&lt;/p>
&lt;ul>
&lt;li>Web: nginx+uwsgi+django&lt;/li>
&lt;li>Worker: celery worker&lt;/li>
&lt;li>Cron: celery beat&lt;/li>
&lt;/ul>
&lt;p>此时的更新代码是用 fabric 直接连入机器 &lt;code>git pull + supervisorctl restart&lt;/code> 二连。&lt;/p>
&lt;p>这样的问题是无缝发版（蓝绿部署）是需要自己手动实现，&lt;br>
比如我们最早实现了一套基于 AWS LB 的动态添加、摘除节点的逻辑。&lt;br>
这部分逻辑称不上优雅，&lt;br>
也需要自己维护。&lt;br>
而且这么做对机器环境有着强依赖，&lt;br>
在前文的升级 Python 版本中，&lt;br>
我们也需要一并进行系统级别的升级。&lt;/p>
&lt;p>不过后来很快我们就进行了全站的 docker 化，&lt;br>
并有过一段短暂的基于 docker network 的无缝发版实现。&lt;br>
此时的部署换成了 &lt;code>docker pull + docker(compose) restart&lt;/code>。&lt;br>
整条技术链路中我们摘掉了 supervisor/fabric/system 相关的依赖。&lt;/p>
&lt;p>伴随着平台从 AWS 迁移到 aliyun，&lt;br>
我们大部分服务也上了 K8S。&lt;br>
部署也从上机器部署升级到了 k8s 相关的部署工具链。&lt;/p>
&lt;p>大部分情况项目里用的是手写的 &lt;code>envsubst + kubectl&lt;/code>，&lt;br>
不过 kubectl 对版本的支持非常有限，&lt;br>
所以很多时候我们也会附带使用 kustomize。&lt;br>
helm chart 而言对业务系统提供了多余的版本控制功能&lt;br>
（我们一般在线上不会同时跑很多个版本，&lt;br>
往往只会保留最新版跟灰度版）。&lt;br>
但 kustomize 也仅在输出部署文件上做的比较好，&lt;br>
在展示部署进度上并没有特别的功能，&lt;br>
而且&lt;a href="https://github.com/kubernetes-sigs/kustomize/issues/1806">很多时候会在项目里漏一大堆的 configmap&lt;/a>&amp;hellip;&lt;br>
所以到目前，我们不少项目都使用了 kapp 进行部署。&lt;/p>
&lt;p>而在构建上，我们从最早的 Jenkins CI 全线迁移到了 GitLab CI。&lt;br>
除了集成单元测试、体验版自动更新、灰度发布这些核心流程以外，&lt;br>
我们还深度尝试了许多 GitLab CI 提供的工具集成。&lt;br>
比如像 kaniko/minio+artifacts/gitlab+sentry 等系列自动集成自动部署的工具基本我们都用到了。&lt;/p>
&lt;p>时至今日，我考虑新起的一个 Python 服务会包括以下的技术组合：&lt;/p>
&lt;ul>
&lt;li>核心部署流程基于 K8S，生产测试使用相同的配置，以 namespace 区分不同组的业务&lt;/li>
&lt;li>不采用 helm, 而是使用 kubectl+kustomize+kapp 的方式完成部署&lt;/li>
&lt;li>以合适的姿势起新三样：
&lt;ul>
&lt;li>对于 HTTP/RESTful 服务, Web 上使用 gunicorn+django (uwsgi 年久失修了)&lt;/li>
&lt;li>对于内部的 gRPC 调用服务，使用内部的 djangrpc 实现 (基于 django，支持一套代码起 http+grpc)&lt;/li>
&lt;li>对于异步任务，就是简单的 celery 走起&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>对于以上提到的服务，部署中考虑完整的向前兼容、按流量/用户的灰度、标准的监控日志报警的搭建&lt;/li>
&lt;/ul>
&lt;h2 id="架构">架构&lt;/h2>
&lt;p>早期我们的网络拓扑相对简单，&lt;br>
流量的路线是 &lt;code>外部 ==&amp;gt; aws elb ==&amp;gt; nginx+uwsgi+django(单台机器)&lt;/code>，&lt;br>
我们仅在整条链路上做了少数配置，&lt;br>
比如在 aws elb 上配置 https 的处理，&lt;br>
在机器上做了简单的日志收集。&lt;/p>
&lt;p>而现在我们的网络拓扑有多种路径，&lt;br>
以其中相对标准的阿里云上托管的 K8S Web 服务为例：&lt;br>
&lt;code>外部 ==&amp;gt; ali slb ==&amp;gt; k8s ingress ==&amp;gt; nginx ==&amp;gt; gunicorn+django&lt;/code>.&lt;br>
可以比较发现除了 k8s ingress 层外，&lt;br>
nginx 层也被单独拆分了出来。&lt;br>
这样的网络拓扑我们对其的控制粒度更加精细，&lt;br>
不仅可以在每一层单独处理 IP/流量/日志/行为 等逻辑，&lt;br>
而且每一层也都是可拆卸可更换的。&lt;br>
比如目前我们的集群中，&lt;br>
就有使用到 &lt;code>nginx-ingress-controller&lt;/code> 的，&lt;br>
也有使用 &lt;code>kong-ingress-controller&lt;/code> 的。&lt;/p>
&lt;p>而在整体的服务架构上，&lt;br>
我们拆分了三层的服务。&lt;br>
顶层是 Web 层，这些服务主要对外部提供服务，走的主要是公网流量的 RESTful 调用；&lt;br>
中间是 Service 层，这些服务主要对内部提供服务，走的主要是内网流量的 RESTful/gRPC 调用&lt;br>
（我们正在使用 gRPC 逐步替换内网 RESTful）；&lt;br>
底层是 Tool 层，包括了一系列我们维护的中间件、工具服务或者是包了一层的云原生服务。&lt;/p>
&lt;p>以我现在的认识，在一个中型规模的技术团队（100人规模），我会采取这样的架构技术组合：&lt;/p>
&lt;ul>
&lt;li>以网络为边界拆分内外部流量，外部使用 RESTful HTTP 调用，内部使用 gRPC 调用&lt;/li>
&lt;li>在业务合适的情况下，使用比如类似 Kong 这样的技术作为网关，处理鉴权、灰度、分流等系列逻辑&lt;/li>
&lt;li>内部服务之间不限制选型（前提是做好人员梯度培养），但要划分清晰的服务边界，进行合适的分层&lt;/li>
&lt;li>区分不同层服务的级别，以定义好稳定性要求、创新余地与网络拓扑&lt;/li>
&lt;/ul>
&lt;h2 id="协作">协作&lt;/h2>
&lt;p>团队协作的核心，就是人跟人的交流。&lt;/p>
&lt;p>因为业务线相对较多，我们基本上是以 two pizza team 的粒度来拆分团队的&lt;br>
（two pizza team 的意思就是点外卖时，两份披萨可以让整个团队吃饱）&lt;br>
每个相对较小的团队会负责数个独立的服务，&lt;br>
组内成员互为 backup、互相学习、共同成长。&lt;/p>
&lt;p>最早我们的 git 开发流是基于 commit diff 的，&lt;br>
换句话说只要你的改动是正确的，&lt;br>
那基本就可以合并进主干分支了。&lt;br>
——不过我们很快尝到了苦头（这个很快≈三年）&lt;br>
一些老的代码因为当时的产品也没有留下成建制的 PRD，&lt;br>
而且我们公司做的是B端产品，逻辑有时又巨特么合理的绕，&lt;br>
导致后人在 blame history 时，&lt;br>
经常需要去分析这究竟是 bug 还是 feature。&lt;/p>
&lt;p>到目前，我们整个团队（强行被）达成了一致，&lt;br>
使用的是“一个 PR 只有一个 Commit 只做一件事情”的基于 rebase 的协作流，&lt;br>
我们这样产出了接近于线性的完美 git 历史。&lt;/p>
&lt;p>而另一方面，关于版本控制我们基于 git tag 使用了内部的小机器人来管理。&lt;br>
因为我们不需要考虑旧版本的兼容维护问题，&lt;br>
所以大部分情况我们用的是日期化的格式 (&lt;code>v2020.07.01&lt;/code>)。&lt;br>
基于 git tag 我们又跟 sentry-release/ticket-system 做了一系列的工具链，&lt;br>
包括自动生成版本之间的 changelog，&lt;br>
自动对每个版本的发布内容进行归类分析等。&lt;/p>
&lt;p>整套使用 git rebase 开发，使用 git tag 发布的协作机制让我们获益不少。&lt;br>
而为了达到这样的效果，我们在团队内部达成了这样的约定：&lt;/p>
&lt;ul>
&lt;li>认知上，项目以 rebase 为开发基础
&lt;ul>
&lt;li>没有什么“我不会用 git”的接口，不会可以学。&lt;/li>
&lt;li>个人当然可以喜欢 merge，那请在个人项目里用，团队项目大家统一规范&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>行动上，就做到我们设想的那样好
&lt;ul>
&lt;li>每个 PR 只包含一个 Commit，每个 Commit 只修改一类内容&lt;/li>
&lt;li>提了 PR 就求 Code Review, Review 了就留评论，评论改完了就合并，不拖泥带水&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>工具上，我们需要有个哥来解决协作工具完善的问题
&lt;ul>
&lt;li>我们优化了 Pipeline 的速度，跑完 97% 覆盖率的单元测试+所有检查只要 3 分钟左右&lt;/li>
&lt;li>针对线性历史，我们提供了一系列发版、合并、变动检测的机器人助手功能&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;p>除了基于 git 的整套开发流，&lt;br>
我们还共同维护着一整个新手村任务（在以前的文章里有讲过），&lt;br>
而且我们推行的 Buddy 制度会让一个有经验的同学完全手把手地带新人&lt;br>
（不过这个具体要看每个人用心的程度了）&lt;/p>
&lt;h2 id="总结">总结&lt;/h2>
&lt;p>回过头看，这几年参与的技术讨论、选型、命名、开发、协作、复盘都历历在目。&lt;br>
了解的技术越多，我就越觉得技术世界的广博与好玩。&lt;br>
其实做技术就像玩游戏一样，本质上都是打怪升级穿装备。&lt;br>
本文里讲的，也可能只是我在这世界的一隅，提笔能想起来的一些只言碎语。&lt;/p>
&lt;p>但假如我要把整篇文章都删掉，&lt;br>
只能留下一句话。&lt;br>
那我会毫不犹豫地留下这句话：&lt;/p>
&lt;p>&lt;strong>不会可以学&lt;/strong>&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/u_can_learn.jpg" alt="u-can">&lt;/p>
&lt;p>（未完待续）&lt;/p></description></item><item><title>毕业五年的报告之团队</title><link>https://liriansu.com/posts/2020-07-06-adult-life-teamwork/</link><pubDate>Mon, 06 Jul 2020 23:45:13 +0800</pubDate><guid>https://liriansu.com/posts/2020-07-06-adult-life-teamwork/</guid><description>&lt;p>从17年底负责一整个团队开始，&lt;br>
一直到今天，&lt;br>
我都保持着 Dev + Leader 的双重角色。&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/weibo/as_leader.png" alt="weibo">&lt;/p>
&lt;h2 id="起">（起）&lt;/h2>
&lt;p>上篇主要是流水账地记录了一下我零碎的回忆，&lt;br>
这篇报告我想系统地整理一下我与团队相处的方法论。（或者说团队文化）&lt;br>
我总想着以后有机会，&lt;br>
可以去开辟一方属于我自己的土地，&lt;br>
那时的我或许也会这么去创建、带领、组织团队吧。&lt;/p>
&lt;h2 id="谨记目标---always-aiming">谨记目标 - Always Aiming&lt;/h2>
&lt;p>我很喜欢辩证法里关于矛盾的这种观点：&lt;br>
矛盾有主次之分，很多时候抓住解决了主要矛盾，&lt;br>
其它次要矛盾也会迎刃而解。&lt;/p>
&lt;p>举个栗子，&lt;br>
工程师在团队协作流中发挥的作用是我很关注的一个话题。&lt;br>
同样一个工程师，他主动去工作与被动地接锅，效果差别是很大的。&lt;br>
所以每次在协作中，&lt;br>
我都会尽可能地提醒每一个伙伴，&lt;br>
用户最需要的点在哪、业务的目标是什么、谁需要做什么事情。&lt;br>
大型项目尤其需要这样的校准。&lt;br>
很多技术上的难题，或是产品上看起来绝妙的方案，&lt;br>
可能放在目标上都不值一提。&lt;/p>
&lt;p>在连连团开发初期，&lt;br>
我们自己写了一个毒液系统，&lt;br>
提供了一整套实时的数据展示，&lt;br>
让开发、产品、运营都能很方便地解决自己的困惑。&lt;br>
后来整套系统用开源的 metabase 重构了一遍，&lt;br>
演变成了现在的蓝冰内部数据总览，&lt;br>
时刻用量化的数字瞄准着目标。&lt;/p>
&lt;p>同样的道理，&lt;br>
放到成员的成长计划也是一样的道理。&lt;/p>
&lt;p>我的团队招人的目标是什么？&lt;br>
是干活解决业务目标吗？&lt;br>
是的。（笑）&lt;br>
但不仅限于此。（严肃）&lt;br>
在过去的实践中，&lt;br>
团队的成长不仅源于上篇报告里聊到的招聘理念：&lt;/p>
&lt;blockquote>
&lt;p>坚持只招优秀的人，不会可以学。&lt;/p>
&lt;/blockquote>
&lt;p>还源于团队每一个成员与公司的共同成长。&lt;br>
假如团队只有招聘标准，没有成长计划，&lt;br>
那么入职即巅峰。&lt;/p>
&lt;p>幸运的是，在过去几年里，&lt;br>
有很多优秀的同学刚毕业就来了再惠。&lt;br>
除了技术上的成长，&lt;br>
我也会特别关注他们薪资上的涨幅。&lt;br>
我觉得大部分人都是从刚毕业的窘迫中走出来的，&lt;br>
只要努力去提供一个适合飞翔的环境，&lt;br>
我们都可以起飞。&lt;/p>
&lt;p>在这几年的团队成长计划中，&lt;br>
我帮过性格内敛默默贡献的同学争取了（特批的）升职加薪，&lt;br>
也设立了固定的内部沟通与分享机制，&lt;br>
还尝试过不定期的《人类补完》邮件计划给团队同步公司级的目标。&lt;/p>
&lt;p>对我而言，团队协作里首先让我想到的方法论就是&lt;strong>谨记目标&lt;/strong>，&lt;br>
做任何事情都去想办法抓住主要矛盾。&lt;/p>
&lt;h2 id="快乐协作---keep-laughing">快乐协作 - Keep Laughing&lt;/h2>
&lt;p>前面好像过于严肃了，让我们快乐一下。&lt;br>
这是我脑海中经常蹦出来的一句话。&lt;br>
工程师里也会流传这么一句都市传说：&lt;br>
人生苦短，我用 Python。&lt;/p>
&lt;p>一个快乐的轻松的环境，&lt;br>
对事情协作，或者是工程师这种脑力工作者有着非常大的效率提升。&lt;br>
而且因为工作在里面占的比例非常大，&lt;br>
一个充满欢笑的工作也更能激发大家的热情，&lt;br>
或者更狭窄地只说我自己的想法：&lt;br>
我喜欢充满笑声的团队。&lt;/p>
&lt;p>我们给帮我们提醒 PR 的小机器人加上了昵称功能，&lt;br>
可能记录着三年前一个同事刚入职时绰号的由来；&lt;br>
研发跟产品也会在对需求之外的时间互怼&lt;br>
（表面上针锋相对其实就是打情骂俏.jpg）；&lt;br>
我们也保持着微信群的非工作消息活跃，&lt;br>
各类烂梗破图无穷尽。&lt;/p>
&lt;p>对应的，快乐的环境是需要相对宽松的制度的。&lt;br>
假如团队由是严苛的赏罚、强制的高压、强行统一的思想构成的，&lt;br>
那团队也是很难长出快乐的小花。&lt;/p>
&lt;p>更进一步，&lt;br>
快乐的氛围会让大家发展出工作之外的友情，&lt;br>
而友情会让团队更加紧密、更加团结。&lt;/p>
&lt;h2 id="都是朋友---make-friends">都是朋友 - Make Friends&lt;/h2>
&lt;p>我跟 @hulucc 都组织过网游的公会，&lt;br>
一次夜聊时，我讲到了我关于网游公会稳定的观点：&lt;/p>
&lt;p>假如一个组织是层级制的，&lt;br>
那这个组织的关键节点就是脆弱的。&lt;br>
比如我见过不少公会是会长跟核心玩家 AFK 以后就凉了的。&lt;br>
想让组织变得稳定跟可发展，&lt;br>
那么这个组织就得是网状的，&lt;br>
这样每一环都是可以缺失的，&lt;br>
同时每一环也都是非常重要的。&lt;/p>
&lt;p>而构建网状组织的方法很简单：友情。&lt;/p>
&lt;p>我在的团队里，我不一定跟每个人都保持着很好的关系。&lt;br>
但是我会关注每一个人有没有在组织里找到至少一个好朋友，&lt;br>
并且我还会有意在分工时，让好友们做一块项目。&lt;br>
他们的友情就会在并肩战斗中得到炮火的磨练。&lt;/p>
&lt;p>友情构建的网状组织，&lt;br>
从团队的角度来说，更加稳定、效率更高、沟通更省力；&lt;br>
从个人的角度来说，收获了一份互相理解、能交予后背的件事友谊。&lt;br>
很多从我司毕业的同事，至今也跟他们的好友们保持着联系，&lt;br>
这些跟他们在工作里学到的技术一样，&lt;br>
都会是大家一辈子的美好回忆与珍贵财富。&lt;/p>
&lt;p>在实际的协作中，&lt;code>Make Friends&lt;/code> 与 &lt;code>Keep Laughing&lt;/code> 这两条原则相辅相成。&lt;br>
有不少人跟我说过羡慕我们团队的文化跟精神面貌，&lt;br>
但让我更开心的是看到大家在工作上有所成长，&lt;br>
在工作以外的人生中也遇到知音。&lt;/p>
&lt;h2 id="交换信任---spread-trust">交换信任 - Spread Trust&lt;/h2>
&lt;p>在团队整体的良好氛围里，&lt;br>
交换信任就是一个显而易见的方法论了。&lt;br>
交换信任不仅意味着信任某一个同学，&lt;br>
还意味着信任着团队这个整体。&lt;/p>
&lt;p>我们在内部的权限、任务认领、发言机制上都给予了每个人最大的信任。&lt;br>
比如我们日常敏捷开发时，&lt;br>
只要举手说“我想/我不想做这个”，&lt;br>
Scrum Master 就会修改对应的分工。&lt;br>
甚至只要举手说“我想做 Scrum Master”就可以当上 Scrum Master&lt;br>
（然后成为工具人）&lt;/p>
&lt;p>对于工程师关心的技术话题也是如此，&lt;br>
我们从不固化某个事情。&lt;br>
新同学接手项目的时候，&lt;br>
我也会反复说明：&lt;br>
“不管你觉得项目里任何地方看不懂或者不科学，&lt;br>
都随时提出来，我们一起想想办法。”&lt;/p>
&lt;p>还有相对特殊的一点是，&lt;br>
我在团队里并没有维持固定的 one-one（一对一单独沟通）机制。&lt;br>
不论是大事小事、业务技术、个人发展、&lt;br>
传统意义上合适或不合适单独沟通的内容，&lt;br>
我们都会在固定的周会上跟全团队一起同步这个消息。&lt;/p>
&lt;p>&lt;code>Spread Trust&lt;/code> 的方法实践下来，&lt;br>
最直观能感受到的一点是团队里大家的安全感都很高，&lt;br>
培养出了非常多有 ownership（主人翁意识）的伙伴。&lt;br>
因为信任，团队工作不会有后顾之忧，&lt;br>
大家就可以一起保持 &lt;code>Always Aiming&lt;/code>。&lt;/p>
&lt;p>就像《珍珠鸟》里讲的一样：&lt;/p>
&lt;blockquote>
&lt;p>信赖，往往会创造出美好的境界。&lt;/p>
&lt;/blockquote>
&lt;h2 id="保持清醒---stay-awake">保持清醒 - Stay Awake&lt;/h2>
&lt;p>很多都市传说里说新人进公司会有蜜月期。&lt;br>
撇去这个说法的准确性，&lt;br>
的确很多时候工作会上头，&lt;br>
认真的同事认真工作的时候就更加容易上头。&lt;/p>
&lt;p>这时候就需要有“众人皆醉我独醒”的气质了，&lt;br>
&lt;strong>Stay Awake&lt;/strong>。&lt;/p>
&lt;p>举些例子。&lt;/p>
&lt;p>团队里吵起来的时候，&lt;br>
需要分辨是因为观点吵起来的还是因为沟通吵起来的，&lt;br>
看情况打断这个沟通。&lt;/p>
&lt;p>在做一件看起来百分百有把握的事情的时候，&lt;br>
一方面鼓励并肯定团队，&lt;br>
另一方面做好塞翁失马结果让子弹飞一会儿的准备。&lt;/p>
&lt;p>在团队发生变动大家陷入迷茫的时候，&lt;br>
去了解最全面的信息，&lt;br>
用积极的想法、活跃的态度去影响团队。&lt;/p>
&lt;p>大部分时候，团队工作是多元的复杂的，很难片面地去评价；&lt;br>
但个人、尤其是群体，总会倾向于非黑即白的二元论。&lt;br>
这种时候团队里就需要有个哥站出来，&lt;br>
给大家展示现实里这张纸的另一面——另一种可能性。&lt;br>
即使这张纸或许是莫比乌斯环。&lt;/p>
&lt;p>&lt;strong>Stay Awake&lt;/strong> 的思考时常让我感受到自己跟团队的撕裂，&lt;br>
但如此的思辨，是的确能对团队整体有很大帮助的。&lt;/p>
&lt;h2 id="永无止境---never-stop">永无止境 - Never Stop&lt;/h2>
&lt;p>随着时间的翻滚，历史的进程轰轰作响。&lt;br>
团队作为一个整体，达到的里程碑会不断增加。&lt;br>
我们平常接触的事情，往往是有一个固定的终点的。&lt;br>
比如电影会有一个结尾，&lt;br>
项目会有一个上线时间，&lt;br>
每年会有一次述职。&lt;/p>
&lt;p>但在我信奉的这套方法论里，&lt;br>
团队的锻造、成长、发展是没有止境的，&lt;br>
在团队里的个体也一样。&lt;br>
我会每天跟自己说：你很棒。&lt;br>
但我从不会跟自己说：你足够棒了。&lt;/p>
&lt;p>即使这几年我很多时间需要花在管理的事务里，&lt;br>
我也一直一头栽在开发的第一线。&lt;br>
我也给自己加上这个思想钢印：&lt;br>
我希望我是团队里技术力最强的，&lt;br>
假如我不是的话，&lt;br>
那样就更好了，&lt;br>
意味着有其他哥的天赋乘以努力居然超过我了。&lt;/p>
&lt;p>我会与公司之外的同行、朋友们交流，&lt;br>
去横向学习如何能更好地发展进化团队；&lt;br>
我也会像今天一样停下来想一想，&lt;br>
我所在的团队在过去几年之间的演化之路。&lt;/p>
&lt;p>不论是团队还是个人，&lt;br>
我们都走着一条永无止境的修行之路，&lt;br>
与时间为伴，与时间为友。&lt;/p>
&lt;h2 id="结">（结）&lt;/h2>
&lt;p>从17年第一次团队开周例会的时候，&lt;br>
我跟大家分享了我关于个人奋斗的感悟。&lt;/p>
&lt;p>一个人的成长并不是孤立的线性，&lt;br>
而是多因子的乘法原则，&lt;br>
让我们写成公式就是：&lt;/p>
&lt;p>&lt;code>成长 = 个人 x 团队 x 公司 x 社会 x 历史进程&lt;/code>&lt;/p>
&lt;p>当我们想获得更多的成长时，&lt;br>
不仅要考虑个人的奋斗、团队的进步、公司的壮大、社会的发展，&lt;br>
也要考虑历史的进程。&lt;/p>
&lt;p>当我在兼顾个人的奋斗之外，&lt;br>
还想做出更大的贡献时，&lt;br>
我就会努力推动团队的进步、公司的壮大、社会的发展。&lt;br>
有朝一日若是有幸，&lt;br>
我也希望能参与到历史的进程，&lt;br>
并骄傲地说出那句：&lt;/p>
&lt;blockquote>
&lt;p>苟利国家生死以，&lt;br>
岂因祸福避趋之。&lt;/p>
&lt;/blockquote>
&lt;p>（完）&lt;/p></description></item><item><title>毕业五年的报告之回忆</title><link>https://liriansu.com/posts/2020-07-05-adult-life-memories/</link><pubDate>Sun, 05 Jul 2020 21:46:03 +0800</pubDate><guid>https://liriansu.com/posts/2020-07-05-adult-life-memories/</guid><description>&lt;p>这周末去安吉吃了烧烤。&lt;br>
里脊肉需要反复被刷油，&lt;br>
最终它才会散发出迷人的香味。&lt;br>
人的记忆也是如此。&lt;/p>
&lt;h2 id="起">（起）&lt;/h2>
&lt;p>在两年前我写了一篇万字长文&lt;a href="https://liriansu.com/adult-life/">《毕业三年的报告》&lt;/a>&lt;br>
我看着两年前写下的文字，&lt;br>
仿佛眼前是两年前的紫月给我讲着他当时的心境。&lt;br>
末了，他还跟我说：&lt;br>
当你五年级的时候，&lt;br>
记得要写一篇《毕业五年的报告》。&lt;/p>
&lt;blockquote>
&lt;p>这篇文章记录了我一些并不靠谱的回忆，&lt;br>
纯粹个人感想，没有借鉴意义。&lt;/p>
&lt;/blockquote>
&lt;h2 id="一终身学习">（一）终身学习&lt;/h2>
&lt;p>在 QAD 时，我并不了解很多 Web 知识，&lt;br>
比如像 RESTful 这样的概念我就不甚了解。&lt;br>
当时系统要接入 Jira RESTful API,&lt;br>
这个事情分给了队友 Raymond 做，&lt;br>
后来他赴美读书，事情就交接给我了。&lt;br>
我头疼地想：“接这个锅还要特别学一下 RESTful，&lt;br>
这个以后不知道有没有用。&lt;br>
还不如认真学学 sudo 权限组拆分，&lt;br>
这个可能对业务有用。”&lt;br>
于是交接时我就没认真看 raymond 的代码，&lt;br>
结果他写的代码运行的异常稳定，&lt;br>
到我从 QAD 毕业后我也没有被迫学 RESTful 的借口。&lt;br>
直到后来，&lt;br>
我才知道 RESTful 这个概念是如此的基础跟重要。&lt;/p>
&lt;p>后来我在工作里遇到了很多这样的事情：&lt;br>
有时不得不学习一些“我以为很临时”的事情，&lt;br>
这些事情甚至不一定是技术方面的：&lt;br>
比如微信迁移公众号是可以顺带迁移 openid 的；&lt;br>
比如A支付渠道退款是24小时，但B支付渠道退款是7天；&lt;br>
比如点菜机是有临时开桌、合并桌台的特殊操作的。&lt;/p>
&lt;p>现在回过头确认，我很认可“认真对待每一个知识”的态度。&lt;br>
对于像 Vim 这样普世的技术，&lt;br>
我会非常有信心地安利给身边每一个人：&lt;br>
这是你学了就一辈子受益的技术。&lt;br>
对于像 Jira 某个接口这样特定的知识，&lt;br>
我会把它存在心里，织成一张大的知识图谱。&lt;/p>
&lt;p>这串回忆给我留下的印记是：&lt;br>
摒弃实用主义，&lt;br>
保持终身学习。&lt;/p>
&lt;h2 id="二海绵宝宝">（二）海绵宝宝&lt;/h2>
&lt;p>2016年11月28日是再惠录取我的第一天，&lt;br>
前一天，11月27日，我跟 Mia 一起搬家到了塘桥。&lt;br>
因为徒手搬了两个人三十多个箱子上下六楼，&lt;br>
入职第一周我光荣感冒了，&lt;br>
到了周末感冒没好的我，&lt;br>
跟着公司去了某个度假村开了次全员年会，&lt;br>
并与室友 @huangzilong 聊了很多有的没的。&lt;/p>
&lt;p>当时的我就像&lt;a href="https://liriansu.com/adult-life/">《三年报告》&lt;/a>里写的那样：&lt;/p>
&lt;blockquote>
&lt;p>我那阵子每天回家都跟女朋友说：&lt;br>
“我好菜啊，队友好强啊，&lt;br>
但我真的好开心啊，感觉啥都能学到，&lt;br>
而且他们下班也会写代码，&lt;br>
感觉找到同类了啊，不过感觉再也追不上他们了啊”&lt;/p>
&lt;/blockquote>
&lt;p>我能感受到把自己丢到一个新环境的时候，&lt;br>
就像把海绵丢到水里，&lt;br>
短时间内我能吸收大量信息。&lt;br>
而且更令我开心的是，&lt;br>
即使是我眼中技术力已经很强的伙伴，&lt;br>
他们也依然是海绵宝宝，&lt;br>
吸收着外部的信息与知识。&lt;br>
我始终记得靖哥哥当时讲过的一句话：&lt;br>
“我们其实也是全栈，只不过不是职能全栈，而是业务全栈。”&lt;/p>
&lt;p>在一个相对较小的团队里（20人），&lt;br>
我们以前端、后端这样的角色区分了工程师，&lt;br>
但是每个后端从网络数据库部署这样的基础素质、&lt;br>
到支付营销微信这样的业务知识都会努力去做到完全了解。&lt;/p>
&lt;p>俗话说“三人行，必有我师焉”，&lt;br>
越广阔，就意味着要学习的越多。&lt;br>
所以大家一起，也都成为了会输出想学习能吸收的海绵宝宝。&lt;/p>
&lt;p>这串回忆给我留下的印记是：&lt;br>
做一个广博的海绵宝宝。&lt;/p>
&lt;h2 id="三爱与陪伴">（三）爱与陪伴&lt;/h2>
&lt;p>公司每周上班五天，早的时候我九点能到家，&lt;br>
每次在沙发上坐下来以后，我都会问 Mia: “今天学校里都有什么事情呀？”&lt;br>
然后我们就会讨论一番工作、八卦、人生，非常让我放松。&lt;/p>
&lt;p>公司不打卡，所以偶尔我也会加速清理完一天的事情，&lt;br>
晚上七点就跑去跟 Mia 约会，&lt;br>
其实就是在大众点评上找能吃得起的看起来不错的店挨个吃过去。&lt;br>
有时吃到用我司产品的餐厅，&lt;br>
我会很兴奋地跟 Mia 讲：“快来试试支付，看有没有服务器出错啦”&lt;/p>
&lt;p>还有很多个夜晚，&lt;br>
我在房间盯着黑色的屏幕写文章/发版，&lt;br>
Mia 在隔壁已经沉沉睡去；&lt;br>
第二天早上我醒来时，&lt;br>
上班时间比我早一个小时的 Mia 已经出门了。&lt;br>
我们也会开玩笑，说这种工作日我们就是互相暗恋但是互不相见的室友。&lt;/p>
&lt;p>后来一次跟 @lvxinyan 聊天时，&lt;br>
他问我对自己的工作有什么想法。&lt;br>
我想了想，说：&lt;br>
你应当找一个女朋友。&lt;/p>
&lt;p>假如人生是电影，你就是主角。&lt;br>
假如你是主角，你就会经历起承转合。&lt;br>
可能会有这么一天，你从工作回家，&lt;br>
心里非常沮丧，觉得整片天空都是灰色的。&lt;br>
但此时一个可爱温柔美丽亲近的美少女问你：&lt;br>
“今天学校里都有什么事情呀？”&lt;br>
你就不会被这片单薄的灰色天空影响。&lt;br>
到了明天，依然晴天。&lt;/p>
&lt;p>这串回忆给我留下的印记是：&lt;br>
多跟喜欢的人呆在一起。&lt;/p>
&lt;h2 id="四招聘理念">（四）招聘理念&lt;/h2>
&lt;p>我是被 @ldsink 内推进来的，&lt;br>
后面我也推荐了几个朋友来我司逛逛/面试，&lt;br>
大家的一致好评是：你们公司好多美少女啊！&lt;br>
尤其是前台、设计跟 HR 得到了非常多的赞扬与仰慕，&lt;br>
但是好看的同事，好像并不影响我们很难招人这个事实。&lt;/p>
&lt;p>当时写了一篇&lt;a href="https://liriansu.com/what-a-hard-backend-interview">《HR就讨厌我们这样的技术，今年一个offer都没发》&lt;/a>&lt;br>
后面我还专门统计过当时的面试数据，&lt;br>
看了 200 封简历，最终才招到了 2 个工程师。&lt;br>
后来 HR 严厉警告：上海的 Python 工程师简历池已经快被击穿了！&lt;br>
于是趁着业务发展，我司引入了 Java 技术栈，&lt;br>
后来更是有华哥跟海兵把控全局，整个招聘节奏才是缓了下来。&lt;/p>
&lt;p>我进再惠的第一周就被拉去当面试官了，&lt;br>
靠着大学在 NIMO 锻炼的经历我非常顺畅地面了下来，&lt;br>
遇到过面试刚开始就丢逼走人的，&lt;br>
也遇到过面试完成为了好朋友的。&lt;/p>
&lt;p>18年我独立负责组一个团队的时候，&lt;br>
我就在想，究竟怎样才能尽可能地做好。&lt;br>
然后脑海中就复现了那个经典的思想实验：&lt;br>
忒修斯之船。&lt;/p>
&lt;p>@luyu 说过一个观点，&lt;br>
对于互联网的产研同事，&lt;br>
三年左右跳槽是很常见的现象。&lt;br>
虽然我不喜欢这样的设定，&lt;br>
但一个组织的确会面临忒修斯之船这样的困惑。&lt;/p>
&lt;p>后来在一次跟 @hulucc 的聊天中，&lt;br>
我得到了心里的答案：&lt;br>
顶级人才构建顶级组织，&lt;br>
次级人才构建更次级组织。&lt;br>
但假如我现在还很弱小怎么办？&lt;br>
很简单，不会可以学。&lt;/p>
&lt;p>所以后来我面试的方法论就从以前期望的“只招优秀且对口的候选人”，&lt;br>
变成了“只招优秀的候选人”。&lt;br>
并且在后面的实践中，&lt;br>
我确认了这条是可行且让我自己、让团队能变得更好的实践。&lt;br>
后来有同学私下跟我说，&lt;br>
他觉得团队有种“独特又干净的理想主义气质”，&lt;br>
他很喜欢。&lt;/p>
&lt;p>这串回忆给我留下的印记是：&lt;br>
坚持只招优秀的人，&lt;br>
不会可以学。&lt;/p>
&lt;h2 id="五长期价值">（五）长期价值&lt;/h2>
&lt;p>谢老板退居二线以后，&lt;br>
再惠又一次邀请华哥来当 CTO。&lt;br>
在还没最终确定前，拉总跟我一起去参加了华哥的饭局，&lt;br>
这种提前认识潜在 Leader 的感觉是挺奇妙忐忑的。&lt;/p>
&lt;p>后来18~19年我们在刷完业务所有需求之外，&lt;br>
整体完成了云平台级别的迁移、架构级别的安全升级、授权统一的项目。&lt;br>
我最认同的一点是持续为长远的价值投资。&lt;/p>
&lt;p>因为餐饮行业的服务业属性，&lt;br>
产研在整个链路中是处在中后台提供解决方案跟工具的。&lt;br>
很容易就变成“办公室做题家”，&lt;br>
业务方给一道题就做一道题。&lt;br>
长远看来别说业务全栈了，&lt;br>
连技术本身也会被懈怠，&lt;br>
并不会去更新、改进、朝着更高更好的方向去变革。&lt;/p>
&lt;p>这种时候我司里常会念叨一句话：&lt;br>
“需要有个哥想想办法。”&lt;br>
于是可能在某个周末，某个深夜，&lt;br>
或者是某个早早做完事情的时候，&lt;br>
就会有一个饱含智慧与研究耗时的 PR 被提了出来。&lt;/p>
&lt;p>这串回忆给我留下的印记是：&lt;br>
每一天都发起变革，&lt;br>
持续地投资长期价值。&lt;/p>
&lt;h2 id="六输入输出">（六）输入输出&lt;/h2>
&lt;p>之前跟卡布达玩成语接龙，&lt;br>
卡布达一连接了三个成语并给快乐的我贴上了这样的标签：&lt;br>
&lt;code>神神叨叨、叨叨逼逼、逼逼赖赖&lt;/code>&lt;/p>
&lt;p>而我想到的是钱钟书在《围城》里讲过的：&lt;/p>
&lt;blockquote>
&lt;p>譬如咱们这次同船的许多人，没有一个认识的。&lt;br>
不知道他们的来头，为什么不先不后也乘这条船，以为这次和他们聚在一起是出于偶然。&lt;br>
假使咱们熟悉了他们的情形和目的，就知道他们乘这只船并非偶然，和咱们一样有非乘不可的理由。&lt;br>
这好像开无线电。你把针在面上转一圈，&lt;br>
听见东一个电台半句京戏，西一个电台半句报告，&lt;br>
忽然又是半句外国歌啦，半句昆曲啦，鸡零狗碎，凑在一起，莫名其妙。&lt;br>
可是每一个破碎的片段，在它本电台广播的节目里，有上文下文并非胡闹。&lt;br>
你只要认定一个电台听下去，就了解它的意义。我们彼此往来也如此。&lt;/p>
&lt;/blockquote>
&lt;p>在做神付神点的时候，&lt;br>
连续几个月我跟 @hulucc 都是公司最晚走的两个人，&lt;br>
后半夜我们就会一边写代码，&lt;br>
一边聊着游戏、A岛或者是人为何活着，&lt;br>
hulucc 给了我许多不亚于 rick&amp;amp;morty 给我的启发。&lt;/p>
&lt;p>这几年我也少有跟各个伙伴促膝长谈的机会，&lt;br>
但不论是四号线的地铁、莫干山的萤火虫，&lt;br>
还是雨树湾的电脑旁，海南的夜空，&lt;br>
都是我这几年工作里难得的回忆。&lt;/p>
&lt;p>刚毕业的时候看《代码大全》，&lt;br>
里面提到“假如你每年看一本技术书，你就已经超越了90%的同行了。”&lt;br>
当时的我嗤之以鼻：“你把工程师描述的太无知了。”&lt;br>
但我现在也时常惊醒，今年（2020）的我一本技术书都没看。&lt;/p>
&lt;p>每段输出都是因为有一段输入，&lt;br>
所以尽可能地去拥抱每一次输入吧。&lt;/p>
&lt;p>（未完待续）&lt;/p></description></item><item><title>[原则] 永远在路上</title><link>https://liriansu.com/posts/2020-05-24-principle-infinite-game/</link><pubDate>Sun, 24 May 2020 22:02:34 +0800</pubDate><guid>https://liriansu.com/posts/2020-05-24-principle-infinite-game/</guid><description>&lt;p>这天，坐在显示器前的我，&lt;br>
用键盘写下了我的这条原则：&lt;br>
&lt;strong>永远在路上&lt;/strong>&lt;/p>
&lt;p>我做事实际专注于事情本身的用时占比并不高，&lt;br>
倒是会花很多时间在自我对话、自我思考上。&lt;br>
不论是事前、事中、还是事后，&lt;br>
以局外人的角度去思考问题总会特别有趣。&lt;/p>
&lt;p>而且为了渡过年月事务发展的长河，&lt;br>
我就会借由思考为绳，&lt;br>
把一根根名为原则的竹子，&lt;br>
绑成我的一艘小竹筏。&lt;/p>
&lt;p>今天我想分享的一条原则，叫：&lt;/p>
&lt;h2 id="永远在路上">永远在路上&lt;/h2>
&lt;p>不拘泥于表达本身的话，&lt;br>
这句话还可以是“永不停歇”，&lt;br>
“生命在于折腾”，&lt;br>
“百尺竿头更进一步”。&lt;br>
更加具体地阐述&lt;strong>永远在路上&lt;/strong>这句话，&lt;br>
就是：&lt;/p>
&lt;p>假如一件事情一天就做完了，&lt;br>
那一周后再去回顾下结果；&lt;br>
假如一周里你跟新朋友建立了友谊，&lt;br>
那就让这份友谊再延续一年；&lt;br>
假如你在一年后站到了不一样的高度，&lt;br>
那就让这样的旅途持续一生。&lt;/p>
&lt;h3 id="永远在工作路上">永远在工作路上&lt;/h3>
&lt;p>工作中，我信奉的“永远在路上”，&lt;br>
就是每天把每件事都做的比昨天更好，&lt;br>
即使大家都以为这件事已经完结了。&lt;/p>
&lt;p>我能看到很多人做事情，&lt;br>
只会把事情本身做好。&lt;br>
在完结后，&lt;br>
也许是“不在其位不谋其政”，&lt;br>
也许是觉得事情已经足够好了，&lt;br>
这个事情的结果就不会比结果更好了。&lt;br>
我做事情不会选择这么做。&lt;/p>
&lt;p>在&lt;a href="https://liriansu.com/engineer-culture">《为什么我喜欢工程师文化》&lt;/a>中，&lt;br>
我提到了我司的 &lt;code>the Hitchhiker's Guide to ZaiHui Dev&lt;/code>,&lt;br>
俗称“新手村任务”。&lt;/p>
&lt;p>三年前入职的时候我推着补完了这篇文档，&lt;br>
我便在业余时间一直维护着直到现在，&lt;br>
算上各种重构的内容，已经贡献了一万多字了，&lt;br>
加在一起顶我好几篇文章了…&lt;/p>
&lt;p>但也就是这样一篇文章，&lt;br>
让我能坦然地跟我们的面试候选人说：&lt;br>
“可能我们整套工程师培训体系不算完美，&lt;br>
但你做完这套新手村任务以后，&lt;br>
就能直观地感受到我们做事的风格，&lt;br>
并且喜欢上这个地方。”&lt;/p>
&lt;p>就像那个流传很广的说法一样：&lt;br>
“入职一天离职，怪流程；&lt;br>
入职一周离职，怪HR；&lt;br>
入职半年离职，怪Leader；&lt;br>
入职三年离职，怪文化。”&lt;br>
即使像文化这样玄乎的概念，&lt;br>
也是在一天天的维护升级优化中做出来的。&lt;/p>
&lt;h3 id="永远在情感路上">永远在情感路上&lt;/h3>
&lt;p>情感里，我信奉的“永远在路上”，&lt;br>
就是以初心来面对一切情感交流，&lt;br>
不做二元论的决策。&lt;/p>
&lt;p>人类就像是穿梭在三维世界的四维生物，&lt;br>
他会走过不同的世界。&lt;br>
很多曾经的好友，&lt;br>
会因为共同经历变少而慢慢疏远；&lt;br>
也有感情稳定的双方，&lt;br>
会因为“我们关系很好啦”的松懈而分离；&lt;br>
更多的时候，&lt;br>
我们会看到“没有人比我更了解他”的单方判定。&lt;/p>
&lt;p>现在经常可以在社交平台上看到汹涌的观点，&lt;br>
但这些被汹涌着裹挟的情感，&lt;br>
也只不过是“有一说一，这件事不过如此”的瞬时理解。&lt;br>
在那些消费主义记录美好生活下，&lt;br>
&lt;a href="https://www.zhihu.com/question/320279757">《90后的你负债多少？》&lt;/a> 或许才是更真实的大众情感。&lt;/p>
&lt;p>情感是复杂的，&lt;br>
但幸好，人也是复杂的。&lt;/p>
&lt;h3 id="永远在生活路上">永远在生活路上&lt;/h3>
&lt;p>生活上，我信奉的“永远在路上”，&lt;br>
就是用一切方法避免&lt;br>
“此人，死于20岁，葬于60岁。”&lt;/p>
&lt;p>&lt;a href="https://liriansu.com/adult-life">我很早就感慨过&lt;/a>，&lt;br>
自己很怕成为那种&lt;br>
“工作三年=工作一年+重复两年”的人。&lt;br>
就像“科技三定律”戏谑的那样，&lt;br>
真实生活中许多人在一定年纪就死在了自己的舒适区里。&lt;/p>
&lt;p>而我不一样，&lt;br>
就算我也死在了舒适区里，&lt;br>
&lt;del>我也要在墓里用这腐朽的声带喊出&lt;/del>&lt;br>
我也要死的晚一些 :)&lt;/p>
&lt;p>近期因为花在看书上的时间少了，&lt;br>
而且看的书里成功学占了不少…&lt;br>
所以写作的时候常常感受到自己笔力不足。&lt;br>
虽然以前也会感受到自己笔力不足，&lt;br>
但是最近的羞愧里还包含了：&lt;br>
“写了这么久文章还是笔力不足”的感受，&lt;br>
头就更大了。&lt;/p>
&lt;p>但我每次回头看过去的自己写下的文章，&lt;br>
我都能从拙劣的遣词粗糙的造句里，&lt;br>
看到当时的我独特的想法，&lt;br>
往往这些想法还会给几年后的我带来不一样的启发。&lt;/p>
&lt;p>自然而然，&lt;br>
我的想法、我的行动就会跟着时间一直传承发展下来，&lt;br>
这使我感受到了自己生命的活性。&lt;/p>
&lt;h2 id="结语">结语&lt;/h2>
&lt;p>在&lt;a href="https://liriansu.com/developer-team">《如何构建工程师团队》&lt;/a>的结尾中，&lt;br>
我这么写道&lt;/p>
&lt;blockquote>
&lt;p>就像唐代斯在最后赠给马克西米连的“等待与希望”一样。&lt;br>
我的朋友，作为工程师的我想送给你两个词，&lt;br>
它们饱含着“递归”、“复利”乃至“宇宙膨胀”的内在哲学：&lt;br>
思考，坚持。&lt;/p>
&lt;/blockquote>
&lt;p>永远在路上，&lt;br>
其实就是这样一个原则。&lt;/p>
&lt;p>（完）&lt;/p></description></item><item><title>如何加速 Docker Build 构建过程</title><link>https://liriansu.com/posts/2020-04-22-boost-docker-build/</link><pubDate>Wed, 22 Apr 2020 22:28:53 +0800</pubDate><guid>https://liriansu.com/posts/2020-04-22-boost-docker-build/</guid><description>&lt;h2 id="dockerfile">Dockerfile&lt;/h2>
&lt;p>docker 已经成为现代开发的基础技术，&lt;br>
而在 docker 开发流中，&lt;br>
Dockerfile 是最基础的文件。&lt;/p>
&lt;p>一个包括了系统配置、依赖安装、业务代码的 Dockerfile 可能长这样子：&lt;/p>
&lt;pre tabindex="0">&lt;code>FROM python:3.8-buster
WORKDIR /app
COPY Pipfile Pipfile.lock ./
COPY code /app/code
RUN pip install pipenv
RUN pipenv sync
RUN echo &amp;#34;Asia/Shanghai&amp;#34; &amp;gt; /etc/timezone
RUN dpkg-reconfigure -f noninteractive tzdata
RUN apt-get update
RUN apt-get -y dist-upgrade
RUN apt-get -y install vim tmux git
RUN curl -sL https://sentry.io/get-cli/ | bash
&lt;/code>&lt;/pre>&lt;p>然后很自然地，&lt;br>
开发者小周发现：&lt;br>
每次改完代码以后重新 &lt;code>docker build&lt;/code> 都非常慢。&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/xkcd_docker.png" alt="xkcd-docker">&lt;br>
他需要加速构建过程。&lt;/p>
&lt;h2 id="改写文件">改写文件&lt;/h2>
&lt;p>最简单的加速是改写 Dockerfile,&lt;br>
因为 Dockerfile 中的一些命令 (&lt;code>ADD/COPY/RUN&lt;/code>) 会产生新的 layer,&lt;br>
而 Docker 会自动跳过已经构建好的 layer。&lt;br>
所以一般优化的原则基于以下几点：&lt;/p>
&lt;ul>
&lt;li>变动越小的命令，越靠前，增加 cache 使用率。&lt;/li>
&lt;li>合并目的相同的命令，减少 layer 层数。&lt;/li>
&lt;li>使用国内源，或者内网服务加速构建。&lt;/li>
&lt;li>少装些东西，不是代码依赖的就尽量别装了…&lt;/li>
&lt;li>记得加上合适的注释，以便日后的维护。&lt;/li>
&lt;/ul>
&lt;p>改写以后的 Dockerfile 可能长这样：&lt;/p>
&lt;pre tabindex="0">&lt;code>FROM python:3.8-buster
WORKDIR /app
# 默认使用上海时区 + 阿里源
RUN echo &amp;#34;Asia/Shanghai&amp;#34; &amp;gt; /etc/timezone &amp;amp;&amp;amp; dpkg-reconfigure -f noninteractive tzdata &amp;amp;&amp;amp; \
echo &amp;#34;deb https://mirrors.aliyun.com/debian/ buster main non-free contrib&amp;#34; &amp;gt; /etc/apt/sources.list
# 预装必须的包，sentry-cli 是预先存入内网的
RUN apt-get update &amp;amp;&amp;amp; apt-get -y dist-upgrade &amp;amp;&amp;amp; apt-get -y install git &amp;amp;&amp;amp; \
wget https://internal-nginx-service.domain.com/sentry.sh /usr/bin/sentry-cli &amp;amp;&amp;amp; \
pip install pipenv
# 装依赖，顺便祝 pipenv 早日发布新版本
COPY Pipfile Pipfile.lock ./
RUN pipenv sync
# 代码频繁变更，放在文件底部，下面就别加更多命令了
COPY code /app/code
&lt;/code>&lt;/pre>&lt;p>改过以后的版本，&lt;br>
开发者小周发现，&lt;br>
每次本地改完代码 build 调试都飞快，&lt;br>
他很满意。&lt;/p>
&lt;p>但是用公司的分布式 gitlab runner 构建以后，&lt;br>
他发现：&lt;br>
有时镜像没用到 cache，又跑了一遍漫长的构建过程。&lt;/p>
&lt;h2 id="分布式构建">分布式构建&lt;/h2>
&lt;p>在 codebase 足够大的情况下，&lt;br>
CI/CD 一般都是分布式多台机器的，&lt;br>
默认的 docker build 只会从本地寻找 cache layer,&lt;br>
无法应对如此复杂的场面。&lt;/p>
&lt;p>简单的办法是使用 &lt;code>docker build --cache-from&lt;/code> 指定镜像，&lt;br>
我们会在 ci 脚本中这么写：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>docker pull LKI/code:latest &lt;span style="color:#f92672">||&lt;/span> true
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>docker build . -t LKI/code:latest --cache-from LKI/code:latest
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>docker push LKI/code:latest
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>但是这样手写的弊端是逻辑比较臃肿，&lt;br>
比如要完美适配多分支构建 (dev/master/hotfix/release) 的话，&lt;br>
往往就要自己实现一套判断究竟 cache from 哪个版本的逻辑。&lt;/p>
&lt;p>更通用的办法是使用类似 &lt;a href="https://github.com/GoogleContainerTools/kaniko">GoogleContainerTools/kaniko&lt;/a> 这样的工具来构建。&lt;br>
最适合 kaniko 的场景是 kaniko + kubernetes,&lt;br>
但这个我们留到最后一章再讲，&lt;br>
我们顺着我们的工作流往下看。&lt;/p>
&lt;p>使用 kaniko + docker 的构建，&lt;br>
我们可以把上面的 pull/build/push 三连改写为以下这样：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 这个命令包括了 cache/build/push&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>docker run &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> -v &lt;span style="color:#e6db74">&amp;#34;&lt;/span>$CODE&lt;span style="color:#e6db74">&amp;#34;&lt;/span>/LKI/code:/workspace &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> gcr.io/kaniko-project/executor:latest &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --cache&lt;span style="color:#f92672">=&lt;/span>true &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --context dir:///workspace/ &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --destination LKI/code:latest
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="and-kubernetes">and Kubernetes?&lt;/h2>
&lt;p>上面提到，kaniko 可以直接丢到 kubernetes 集群中构建：&lt;/p>
&lt;pre tabindex="0">&lt;code>apiVersion: v1
kind: Pod
metadata:
name: kaniko
spec:
containers:
- name: kaniko
image: gcr.io/kaniko-project/executor:latest
args: [&amp;#34;--dockerfile=Dockerfile&amp;#34;,
# 没错，可以直接从 s3 里捞代码构建
&amp;#34;--context=s3:///bucket/code/&amp;#34;,
&amp;#34;--destination=LKI/code:latest&amp;#34;]
volumeMounts:
- name: kaniko-secret
mountPath: /secret
restartPolicy: Never
volumes:
- name: kaniko-secret
secret:
secretName: kaniko-secret
&lt;/code>&lt;/pre>&lt;p>随着研究的进一步深入，&lt;br>
很容易想到，&lt;br>
其实 docker 开发流跟 kubernetes 的开发流理应有更好的集成。&lt;/p>
&lt;p>这就是 &lt;a href="https://github.com/GoogleContainerTools/skaffold/">GoogleContainerTools/skaffold&lt;/a> 在做的事情了。&lt;br>
skaffold 不仅支持前面讲到的 kaniko 构建，&lt;br>
还囊括了 port-forwarding/test/helm-deploy 等一系列常用工作流。&lt;/p>
&lt;p>有兴趣的同学可以自行了解，&lt;br>
关于 skaffold 的故事我们以后有机会，&lt;br>
再慢慢讲 :)&lt;/p></description></item><item><title>若初见与吴建国</title><link>https://liriansu.com/posts/2020-04-21-ruochujian/</link><pubDate>Tue, 21 Apr 2020 21:37:59 +0800</pubDate><guid>https://liriansu.com/posts/2020-04-21-ruochujian/</guid><description>&lt;p>若初见总是很喜欢跟吴建国一起放学。&lt;/p>
&lt;p>（一）&lt;br>
每次放学路上，&lt;br>
若初见总是非常跳跃地跟吴建国在讲在学校的见闻，&lt;br>
吴建国也总是默默听着。&lt;/p>
&lt;p>若初见说今天语文考试，&lt;br>
老师出了一道他特别喜欢的附加题。&lt;br>
吴建国问这题是什么，&lt;br>
若初见说附加题是解释你名字的含义：&lt;br>
“我的名字若初见，&lt;br>
就人生若只如初见嘛，&lt;br>
多么简单但帅气的名字。”&lt;br>
“不会有点中二吗？”&lt;br>
“中二是在别人反应过来以后，&lt;br>
但第一次认识我的人肯定觉得我超帅。”&lt;/p>
&lt;p>“不过这个也看人，你就做这题就不行。”&lt;br>
若初见看着认真看路走路的吴建国说道。&lt;/p>
&lt;p>（二）&lt;br>
若初见的朋友很多，&lt;br>
但吴建国的朋友不多。&lt;br>
不过若初见也会跟吴建国说：&lt;br>
“你这样挺好的，做你自己。”&lt;/p>
&lt;p>吴建国问：“你是怎么让大家都喜欢你的呢？”&lt;br>
“很简单，做自己就行了。&lt;br>
我能跟他们从魔戒的精灵语系聊到南方公园的政治正确，&lt;br>
也能从强人择原理讲到窃格瓦拉，&lt;br>
没人不喜欢我。”&lt;/p>
&lt;p>吴建国感慨道：&lt;br>
“那是，你懂的挺多的，&lt;br>
我觉得我懂的就越来越少了。&lt;br>
可能是上学让我越上越狭隘了。”&lt;/p>
&lt;p>“这怎么会呢？”&lt;br>
若初见一边说一边绕着吴建国转了个圈，&lt;br>
“你看嘛，俗话叫江山风月本无常主，&lt;br>
只要你有心，我们这放学路上都是风景。&lt;br>
比如你看，这棵树其实在对你笑，&lt;br>
但是实用主义的人类并不知道。”&lt;/p>
&lt;p>“你再看，天边隐隐约约的月亮，&lt;br>
从他的视角看过来其实我们跟台湾的好友都在一个视界里，&lt;br>
视线的视。&lt;br>
这就叫人类的渺小跟天涯的共比邻。”&lt;/p>
&lt;p>“比如还有一种说法叫‘回首之处皆是虚无’，&lt;br>
这句话是我瞎编的，但瞎编这个词是中文里固有的。”&lt;/p>
&lt;p>吴建国听着若初见讲的一大堆，&lt;br>
若有所思但又若隐若现。&lt;/p>
&lt;p>（三）&lt;br>
吴建国跟我们普通小孩一样，&lt;br>
觉得学校是个认真学习纪律严肃的地方。&lt;br>
但每次放学路上，&lt;br>
若初见总会跟他吐槽各种学校的不合理。&lt;/p>
&lt;p>“我们数学老师定了一个特别捞的规则，&lt;br>
叫考试拿积分，期末换奖品。&lt;br>
首先不说我觉得物质奖励反而会削弱学习的精神回馈，&lt;br>
这制度明显有问题：&lt;br>
得一次全班第一得 20 积分，&lt;br>
但每进步一名就得 1 积分；&lt;br>
我们班上一共 48 个同学，&lt;br>
那我拿两次第一还不如一次倒数第一、一次正数第一刷爆进步奖？”&lt;/p>
&lt;p>说干就干，&lt;br>
平时考满分的若初见，&lt;br>
下次考试的时候故意考了0分。&lt;br>
为了确保自己是有实力的，&lt;br>
若初见把所有的答案都右延了一位，&lt;br>
A变成了B，√变成了×，42变成了43。&lt;/p>
&lt;p>听到这种操作后，&lt;br>
吴建国都呆了。&lt;br>
不过若初见自豪又失望地补充道：&lt;br>
“不过这张卷子老师还是给了我满分，&lt;br>
并且取消了积分奖励这个不够合理的制度。”&lt;/p>
&lt;p>吴建国听出了这句话里的失望：&lt;br>
“怎么感觉你有种不够尽兴的感觉呢？”&lt;/p>
&lt;p>若初见耸了耸肩，表示无所谓。&lt;/p>
&lt;p>（四）&lt;br>
这天放学若初见很伤心，&lt;br>
他爱的人并不爱他。&lt;br>
吴建国没心没肺地安慰他道：&lt;br>
“没事，你像我这种长得丑的就没这种烦恼。”&lt;br>
“嗯，你不懂。”&lt;br>
一句话又把吴建国给噎住了。&lt;/p>
&lt;p>走了几步，&lt;br>
若初见还是忍不住继续感慨：&lt;br>
“我感觉，&lt;br>
一开始喜欢我的朋友们，&lt;br>
后来情感连接总是会慢慢褪色，&lt;br>
最终大家会发现我其实不是个一直有趣的人。&lt;br>
吴建国，你说世界上这么多外冷内热的人，&lt;br>
有没有可能存在外热内冷的人呢？”&lt;/p>
&lt;p>“你知道吗？我觉得这是你目前的知识构成导致的。”&lt;br>
吴建国停下了脚步，&lt;br>
想了一下措辞：&lt;br>
“以我对你的了解，你其实一直在追求新鲜而未腐烂的知识。&lt;br>
不论是你说的‘树也可以有生命’还是‘可以从月亮的角度来观察地球’，&lt;br>
他们都会在听到的一瞬间被吸收完所有价值。&lt;br>
就像你的名字‘若初见’一样，&lt;br>
一切的惊艳都留给了初见。”&lt;/p>
&lt;p>看着情绪逐渐低落的若初见，&lt;br>
吴建国赶紧补充道：&lt;br>
“不过这样也没问题。&lt;br>
就像刚才说的，我长得丑。&lt;br>
但丑的时候爱我，才是真的爱我。&lt;br>
美的时候不必爱我，美的时候人人都爱我。”&lt;/p>
&lt;p>（五）&lt;br>
若初见总是很喜欢跟吴建国一起放学。&lt;/p>
&lt;p>（完）&lt;/p></description></item><item><title>旅行之二·do things matters</title><link>https://liriansu.com/posts/2020-02-08-honeymoon-part-2/</link><pubDate>Sat, 08 Feb 2020 21:48:32 +0100</pubDate><guid>https://liriansu.com/posts/2020-02-08-honeymoon-part-2/</guid><description>&lt;p>蜜月旅行第二站，&lt;br>
从德国的慕尼黑到科隆，&lt;br>
再到西班牙的巴塞罗那、格拉纳达。&lt;/p>
&lt;h2 id="收费厕所">收费厕所&lt;/h2>
&lt;p>上次讲到&lt;a href="https://liriansu.com/honeymoon-part-1">德国展示了一种整洁地很严谨的城市风貌&lt;/a>，&lt;br>
这种感觉还体现在了一点上：收费厕所。&lt;/p>
&lt;p>在德国，&lt;br>
不论是旅游景点的厕所，&lt;br>
还是商场的厕所，&lt;br>
很多都要收个 0.5€ 的入场费。&lt;br>
（残疾人厕所例外）&lt;/p>
&lt;p>这让上遍天下厕所的我有点恍惚(x。&lt;br>
我记忆中的上一个收费公厕，&lt;br>
还是矗立在中学时期的人民广场公交车站旁，&lt;br>
欢迎着搭车上学的我的光临。&lt;/p>
&lt;p>我以奇葩说式问句问 Mia:&lt;br>
“以后中国的所有公厕都要收五毛的入场费，&lt;br>
你支持吗？”&lt;br>
Mia：“当然支持啊，前提是收费后得像德国一样干净。”&lt;br>
我：“我也支持，前提是得支持微信/支付宝缴费。”&lt;/p>
&lt;p>于是谈笑间我们又使用了一次“如果电话亭”。&lt;/p>
&lt;h2 id="如果电话亭">如果电话亭&lt;/h2>
&lt;p>“如果电话亭”是哆啦A梦带回来的一个未来科技，&lt;br>
在它的帮助下，&lt;br>
世界能以你想象的方式运作。&lt;br>
xkcd 的 what-if 系列也有这个功效。&lt;/p>
&lt;p>科隆大教堂旁边就是莱茵河，&lt;br>
莱茵河上面躺着一条霍亨索伦桥。&lt;br>
这个桥的特别之处并不是它名字很魔戒，&lt;br>
而是关于它有的都市传说：&lt;br>
把锁挂在桥上，钥匙丢进河里，爱情就会锁住一辈子。&lt;/p>
&lt;p>经&lt;del>标记重捕法&lt;/del>大致估算，&lt;br>
桥上挂了至少三十万把锁。&lt;/p>
&lt;p>Mia 跟我又聊起了在桥上挂锁情侣们的各种可能。&lt;br>
就像钱钟书关于收音机的比喻说的一样，&lt;br>
万千人类有着万千悲欢。&lt;br>
也像鲁迅说的一样，&lt;br>
我可以觉得他们聒噪。&lt;/p>
&lt;p>Mia 跟我感慨，&lt;br>
如果我们遇到的时间不是这么好，&lt;br>
那可能我们就会错过了。&lt;/p>
&lt;p>这让我想起我爸偶尔也会感慨，&lt;br>
如果当时他英语能再考好一点，&lt;br>
他最终可能会缺少很多简单的幸福。&lt;/p>
&lt;p>大雄还是像往常一样，&lt;br>
经历了失败后把“如果电话亭”还给了哆啦A梦。&lt;/p>
&lt;p>人类的个体的此刻，&lt;br>
只不过是他漫长生命的一个切片，&lt;br>
这大概就是高维生物的悲哀。&lt;/p>
&lt;h2 id="自然">自然&lt;/h2>
&lt;p>当参观人文景观的时候，&lt;br>
你总是需要各种各样的背景知识、作者分析、阅读理解、脑内作文。&lt;br>
但自然景观不一样，&lt;br>
就仿佛是大自然直接把大片蓝天、延绵山岭、无边海洋给甩到了你的脸上，&lt;br>
感知一下就从脑子掉进了脊椎血脉中。&lt;/p>
&lt;p>在巴塞罗那最后一天的下午我们去了蒙锥克山，&lt;br>
没有云的天空就像是蓝屏的 windows，&lt;br>
看不见的空气弥漫着植物的清香，&lt;br>
在山顶上看到的海天线就像是《楚门的世界》里看到的一样无暇。&lt;/p>
&lt;p>欧洲的小雨是跟着云走的，&lt;br>
而每朵云是跟着它的心情走的，&lt;br>
心情好就跑边上玩了，&lt;br>
心情不好就一边哭一边到处窜。&lt;/p>
&lt;p>所以地球这边打伞的人类比例明显下降了，&lt;br>
下雨了就戴个帽子躲躲雨，&lt;br>
出太阳了就懒洋洋地晒下阳光，&lt;br>
非常惬意。&lt;/p>
&lt;p>上海咋不是这样呢？&lt;br>
我不禁想。&lt;br>
可能是因为不是盟军，&lt;br>
没有天气控制器的原因吧。&lt;br>
我不禁这么回答自己。&lt;/p>
&lt;h2 id="高迪">高迪&lt;/h2>
&lt;p>虽说地球这边的天空令人沉醉，&lt;br>
但作为游客还是得有游客的自觉，&lt;br>
抱着包就在巴塞罗那踩遍了热门的人文景点：&lt;br>
米拉之家、巴约之家、圣家堂。&lt;/p>
&lt;p>这些建筑都有一个共同点：&lt;br>
建筑师都叫高迪。&lt;br>
精确的来说，&lt;br>
建筑师都是同一个人，他叫高迪。&lt;/p>
&lt;p>具体的彩虹屁就不吹了，&lt;br>
希望读者们有机会也可以去看看。&lt;br>
它最令我感到神奇的一点是：&lt;br>
高迪把“业务代码”写成了“传世名作”。&lt;/p>
&lt;p>米拉之家其实就是有个有钱人叫米拉，&lt;br>
他出钱让高迪帮他建房子，&lt;br>
但高迪硬是把一个工程作品做成了一个艺术作品。&lt;br>
巴约之家也是如此。&lt;/p>
&lt;p>想到这，&lt;br>
我瞻仰圣家堂彩绘玻璃的眼神，&lt;br>
明亮地更加复杂了。&lt;/p>
&lt;h2 id="do-things-matters">do things matters&lt;/h2>
&lt;p>我以前跟朋友们论道时，&lt;br>
经常会被反问的问题是：&lt;br>
“像 Linus 的确是厉害啊，&lt;br>
不过我们这种写业务代码的，&lt;br>
也不可能做出他们那样的作品吧。”&lt;/p>
&lt;p>这种时候，没有作文素材的我也只能更玄学地说：&lt;br>
“世界会因你而闪耀，&lt;br>
最终我们肯定都会搞个大新闻的。”&lt;br>
干巴巴的解释也只会让朋友苦笑着回答：&lt;br>
“你能这么想是因为你不一样……”&lt;/p>
&lt;p>我的朋友，&lt;br>
米拉在发布他的建房任务时，&lt;br>
他也不会说：“我要建一个世界文化遗产。”&lt;br>
高迪拿到的不过是“给米拉建一个房子”的任务，&lt;br>
世界上也有千千万万的工程师拿到了建房子的任务。&lt;/p>
&lt;p>但世界因为高迪而改变，&lt;br>
他用自己的才华跟心血把事情做出了不一样的杰出。&lt;/p>
&lt;p>我脑子里面立即蹦出了一句 slogan: &lt;code>do things matters&lt;/code>。&lt;br>
这不仅意味着努力去核心岗位做重要的事情，&lt;br>
还意味着每一件事都会因为是我做的，而 &amp;lsquo;matters&amp;rsquo;.&lt;/p>
&lt;p>世界上只有一个高迪，&lt;br>
世界上也只有一个你，&lt;br>
&lt;code>do things matters&lt;/code>&lt;/p>
&lt;p>（完）&lt;/p></description></item><item><title>旅行之一·可能回不去了</title><link>https://liriansu.com/posts/2020-01-31-honeymoon-part-1/</link><pubDate>Fri, 31 Jan 2020 06:38:22 +0100</pubDate><guid>https://liriansu.com/posts/2020-01-31-honeymoon-part-1/</guid><description>&lt;p>蜜月旅行第一站，&lt;br>
从上海到多哈再到慕尼黑的城市中心。&lt;/p>
&lt;h2 id="时差">时差&lt;/h2>
&lt;p>老实来说，&lt;br>
这是我第一次体会到物理时差，&lt;br>
以前都是&lt;del>生物&lt;/del>精神时差控制着我。&lt;/p>
&lt;p>慕尼黑在东一区，&lt;br>
我现在离 ED 在的伦敦更近了，&lt;br>
让我更能悟到半夜上线看到 ED 跟他夫人在刀塔的心情。&lt;/p>
&lt;p>晚上十点多我就睡过去了，&lt;br>
第二天凌晨五点自然醒来后，&lt;br>
我跟同样早醒的 Mia 说：&lt;br>
“诶，看来时差是的确会影响人的生物钟诶。”&lt;br>
Mia：“哦，我平时这个点都是自然醒的。”&lt;/p>
&lt;h2 id="疫情">疫情&lt;/h2>
&lt;p>第一天在住处安定下来以后，&lt;br>
我们想着打电话问问卡塔尔航空的国内客服，&lt;br>
看回去的航班会不会被取消，&lt;br>
结果电话中提示：“不在服务时间中。”&lt;/p>
&lt;p>微博上不少同学说，&lt;br>
因为疫情在国外有被差别对待，&lt;br>
我感觉其实还行。&lt;br>
大马路上的陌生人也并不会有什么交流，&lt;br>
外国人对中国人造成的语言伤害，&lt;br>
未必有其他省同胞对湖北同胞造成的语言伤害大。&lt;/p>
&lt;p>连上了国外的网，&lt;br>
Mia 与我依然刷的是国内的疫情。&lt;br>
Mia 感慨：“感觉我们像是逃到了个没人管的地方。”&lt;br>
我义正言辞地回答：“慕尼黑不是法外之地！”&lt;/p>
&lt;h2 id="出租">出租&lt;/h2>
&lt;p>我们叫了辆出租从机场到酒店，&lt;br>
土耳其的司机大叔操着浓重的口音跟我们讲：&lt;br>
“Don&amp;rsquo;t taxi. Take trains!”&lt;/p>
&lt;p>土耳其大叔说他在德国呆了二三十年，&lt;br>
但就最近德国人都疯了。&lt;br>
我们问为什么，&lt;br>
他说超市里的口罩全被抢光了！&lt;/p>
&lt;p>……&lt;/p>
&lt;p>我们路边经过了很多标着 BMW 标记的建筑，&lt;br>
司机说：慕尼黑经济是这边的 number one,&lt;br>
一方面是因为举世闻名的啤酒节，&lt;br>
另一方面也是因为这里有很多的 Fabric.&lt;br>
我：“Wow, great!”&lt;br>
后来 Mia 提醒我，&lt;br>
这个 Fabric 是司机的德英混用口音的一部分。&lt;/p>
&lt;h2 id="生活">生活&lt;/h2>
&lt;p>德语一直给我一种很硬核的感觉，&lt;br>
虽然我并不懂多少德语，&lt;br>
也就靠两句 &lt;code>Gutten Tag&lt;/code> 跟 &lt;code>Danke&lt;/code> 走天下。&lt;/p>
&lt;p>我们住在慕尼黑中央火车站旁边，&lt;br>
城市的建筑分布是非常严谨的街区式，&lt;br>
横平竖直非常让强迫症感到愉悦。&lt;/p>
&lt;p>在住处洗手的时候，&lt;br>
我摸到水龙头里特别细腻的水，&lt;br>
非常惊讶地跟 Mia 感慨道：&lt;br>
“这水看起来好干净啊，甚至有种能喝的错觉！”&lt;br>
Mia：“可以喝，但没必要。”&lt;/p>
&lt;h2 id="乡村">乡村&lt;/h2>
&lt;p>去天鹅堡的路上，&lt;br>
德国向我们展示了它的大乡村风貌。&lt;/p>
&lt;p>广袤的田野上散落着许多尖顶红瓦白墙房，&lt;br>
簇拥在一起的样子就是《席德梅尔的文明》里城镇的样子。&lt;br>
大片的田野都没有种特别的庄稼，&lt;br>
都是平整的草地与没有人类的清新空气。&lt;br>
我跟 Mia 讨论说，&lt;br>
这要是在中国，&lt;br>
那多么浪费田地呀，&lt;br>
也不种些白菜胡萝卜葡萄西红柿什么的。&lt;/p>
&lt;p>不过即使是没什么人的田间小镇，&lt;br>
德国人还是会把房子的白墙刷的非常干净。&lt;br>
这种感觉也在我们去了各式各样的洗手间以后冒了出来：&lt;br>
德国城市是真的会注意干净整洁。&lt;/p>
&lt;p>这很好，值得学习。&lt;/p>
&lt;h2 id="食物">食物&lt;/h2>
&lt;p>第一天放下东西以后，&lt;br>
我们去尝试了猪肘与本地啤酒。&lt;/p>
&lt;p>猪肘的皮做的硬又脆，&lt;br>
整一大块肉吃起来腻得很沉醉，&lt;br>
于是盘里还会配上一堆腌白菜跟一块大土豆丸子。&lt;br>
本地的小麦啤酒闻起来很香，&lt;br>
除此之外也给不出什么对照组的评价了。&lt;/p>
&lt;p>本地的食物店全部都在卖面包跟咖啡，&lt;br>
这里的面包有很多种：&lt;br>
有一大类是纯硬的干面包，&lt;br>
以至于店里会有专门的电锯切割机来切面包；&lt;br>
还有一大类是近似于三文治的面包，&lt;br>
里面的馅会囊括奶酪、生菜、西红柿、腌黄瓜、腌猪肉等一切能加的配菜。&lt;/p>
&lt;p>来了这么几天，&lt;br>
面包是吃了很多，&lt;br>
米饭是一粒没沾，&lt;br>
有一种我已经不住在中国的错觉。&lt;/p>
&lt;h2 id="物价">物价&lt;/h2>
&lt;p>作为一个外来客，&lt;br>
很多可能本地人习以为常的设定我都觉得很新鲜。&lt;br>
比如一点是这里的物价比例是不一样的。&lt;/p>
&lt;p>Mia 与我去逛本地的超市，&lt;br>
我们在牛奶区流连忘返：&lt;br>
一支 1L 的牛奶只要 0.99€！&lt;br>
于是我三天内喝了两升牛奶放了一堆屁。（是真的）&lt;br>
在水果店，我们买了两斤多的苹果也就花了 1€ 左右。&lt;/p>
&lt;p>与便宜的基础食品对应的，&lt;br>
在其它的一些方面显得就比中国贵很多。&lt;/p>
&lt;p>比如我们坐公交，&lt;br>
单程一趟就要 5€ 左右。&lt;br>
理发店一次洗剪吹就是 20€ ……&lt;/p>
&lt;p>更好玩的是，&lt;br>
我们买一瓶 1L 的&lt;del>农夫山泉&lt;/del>纯净水，&lt;br>
总价是 0.44€，&lt;br>
其中水的价格是 0.19€，&lt;br>
但是瓶子的价格是 0.25€。&lt;/p>
&lt;h2 id="erlangen">erlangen&lt;/h2>
&lt;p>在德国的第三天，&lt;br>
我们买了张单日票坐火车去 erlangen 找老韩玩。&lt;/p>
&lt;p>德国的车站也不需要什么身份证明，&lt;br>
既没炸鸡验票口也没固定座位，&lt;br>
买了票自己上车找空位坐就行了。&lt;br>
我立马想起来小学时候看的检票员系列笑话，&lt;br>
果然是一方水土一方笑话。&lt;/p>
&lt;p>老韩是 Mia 十年的好友。&lt;br>
写到这我也是一惊，&lt;br>
我们大学的同学，&lt;br>
现在换句说法居然能说是十年的好友了，&lt;br>
时间真的不经花。&lt;/p>
&lt;p>我在 erlangen 看到了开放式的大学，&lt;br>
Mia 跟我说德国的大学都是这样的。&lt;br>
整个小镇也不大，&lt;br>
一条主街横穿了整个镇，&lt;br>
主街两旁分布着图书馆、面包店、啤酒厂、教室、流动图书室、大型商场。&lt;br>
整条街上行走的都是充满朝气的年轻面孔，&lt;br>
大学就像是被拆成了许多条隐形的河流，&lt;br>
与 erlangen 这个镇融合在了一起。&lt;/p>
&lt;p>我们问老韩周末一般做什么，&lt;br>
老韩笑着说：&lt;br>
“他们说现在国内朋友的感受，&lt;br>
就是我们留学生的感受，&lt;br>
非常无聊。”&lt;/p>
&lt;p>不过在了解到德国有不少程序员的需求，&lt;br>
没有摆在台面上的年龄歧视，&lt;br>
网速很好，&lt;br>
外界诱惑不大一般不出门以后，&lt;br>
我泛起了 30 岁开始重拾德语的小心思。&lt;/p>
&lt;h2 id="未完待续">未完待续&lt;/h2>
&lt;p>这几天卡塔尔说部分去往中国的航班已取消，&lt;br>
虽然我们的航班还没受影响，&lt;br>
不过总顶着一种“回不去了呢”的快乐心情在游玩。&lt;/p>
&lt;p>在德国我们还会去科隆大教堂，&lt;br>
到巴塞罗那了还计划去巴塞罗那主教堂等一系列景点。&lt;/p>
&lt;p>希望到时候能忍住信仰之跃的冲动，&lt;br>
按 E 同步就够了。&lt;/p>
&lt;p>（完）&lt;/p></description></item><item><title>软件工程实践之 Git 开发流</title><link>https://liriansu.com/posts/2020-01-14-git-workflow/</link><pubDate>Tue, 14 Jan 2020 21:39:31 +0800</pubDate><guid>https://liriansu.com/posts/2020-01-14-git-workflow/</guid><description>&lt;p>软件工程实践系列文章，&lt;br>
会着重讲述实际的工程项目中是如何协作开发软件的。&lt;br>
本文主要介绍如何使用 Git 来支撑整个开发流。&lt;/p>
&lt;h2 id="outline">outline&lt;/h2>
&lt;p>本文包括以下内容：&lt;/p>
&lt;ul>
&lt;li>operation: 团队保持一致的操作
&lt;ul>
&lt;li>commit: 提交原子性的代码&lt;/li>
&lt;li>history: 保持线性干净的历史&lt;/li>
&lt;li>release: 遵循科学的发布规范&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>tool chain: 搭建自洽的工具链
&lt;ul>
&lt;li>gitlab/github: 使用现代的开发平台&lt;/li>
&lt;li>ci/cd: 让系统把控代码质量&lt;/li>
&lt;li>sentry/k8s: 用版本连接整个系统&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>conclusion&lt;/li>
&lt;/ul>
&lt;h2 id="operation-团队保持一致的操作">operation: 团队保持一致的操作&lt;/h2>
&lt;p>Git 提供了一套自由而又强大的 api,&lt;br>
我们可以通过它以各种姿势来完成代码协作。&lt;br>
但俗话说得好，&lt;br>
选择越多人越懵。&lt;del>并没有这句俗话&lt;/del>&lt;br>
所以在团队协作时，&lt;br>
保持一致的操作是很重要的。&lt;/p>
&lt;h3 id="commit-提交原子性的代码">commit: 提交原子性的代码&lt;/h3>
&lt;p>Git 的最小单元就是一个 commit。&lt;br>
我们团队遵循的最佳规范是保持每个 commit 的原子性：&lt;br>
&lt;strong>一个 commit 只做一件事情。&lt;/strong>&lt;/p>
&lt;p>比如一个关于缺陷修复的 commit 可以非常简单，&lt;br>
它只有两行：&lt;br>
一行修复了代码逻辑，&lt;br>
一行加了单元测试。&lt;/p>
&lt;p>另一个关于重构的 commit 可能会修改 200+ 个文件，&lt;br>
但也因为只做了一件事情，&lt;br>
所以不会给 code review 带来很大负担。&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/gitlab_large_commit.jpg" alt="large-commit">&lt;/p>
&lt;p>原子性的 commit 不仅能很好地支持 revert/cherry-pick/bisect 等一系列 Git 的原生命令，&lt;br>
而且在保持线性干净的历史这一点上，&lt;br>
也是至关重要的。&lt;/p>
&lt;h3 id="history-保持线性干净的历史">history: 保持线性干净的历史&lt;/h3>
&lt;p>随着时间的推移，&lt;br>
Git 的每一个 commit 会成长为一个枝叶繁茂的历史树。&lt;br>
基于 &lt;a href="https://git-scm.com/book/en/v2/Git-Branching-Basic-Branching-and-Merging">fast forward&lt;/a> 的合并能让 Git 的历史树保持干净与线性。&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/git_log_tree.jpg" alt="git-log-tree">&lt;/p>
&lt;blockquote>
&lt;p>这是我们项目 git log 翻到四个月以前的一张截图，&lt;br>
可以看到历史依旧是线性干净的。&lt;/p>
&lt;/blockquote>
&lt;p>线性的历史意味着在每个人提交代码前需要 rebase。&lt;br>
一个例外是在发布分支(master)上提交 hotfix 后，&lt;br>
合并回开发分支(dev)需要视情况关闭 fast forward (&amp;ndash;no-ff)。&lt;br>
而且要求大家 rebase 则对团队成员的 Git 水平以及合并习惯提出了一定要求。&lt;/p>
&lt;p>干净的历史则需要大家都严格遵循 commit 的原子性，&lt;br>
以及要按照标准撰写 commit message。&lt;br>
关于 commit message 的撰写，&lt;br>
阮老师有一篇&lt;a href="https://www.ruanyifeng.com/blog/2016/01/commit_message_change_log.html">《commit message 编写指南》&lt;/a>讲的够好。&lt;br>
我们也可以在 git hook 中开启对 commit message 的校验，&lt;br>
以确保格式的整洁统一。&lt;/p>
&lt;p>通过&lt;strong>fast forward merge + 统一的 commit message&lt;/strong>，&lt;br>
我们就能维护一个不断成长、但又干净线性的历史树，&lt;br>
能最大程度地给各种 git 的版本操作提供便利。&lt;/p>
&lt;h3 id="release-遵循科学的发布规范">release: 遵循科学的发布规范&lt;/h3>
&lt;p>&lt;strong>我们使用 git tag 来作为版本发布的标志。&lt;/strong>&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/git_log_tree.jpg" alt="git-log-tree">&lt;/p>
&lt;p>因为我们的项目是一个 web 服务端项目，&lt;br>
我们同一时刻基本上只需要维护最新的版本，&lt;br>
所以我们使用了日期型的版本号数字(&lt;code>v2019.9.9&lt;/code>)。&lt;br>
在大部分开源工具里，&lt;br>
都会使用&lt;a href="https://semver.org/lang/zh-CN/">语义化的版本号(semver: &lt;code>v2.0.0&lt;/code>)&lt;/a>。&lt;/p>
&lt;p>基于原子的 commit、线性的历史，&lt;br>
在每次版本发布时，&lt;br>
我们都会自动化地生成 tag/changelog。&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/gitlab_release.jpg" alt="gitlab-release">&lt;/p>
&lt;p>一个遵循了良好规范的 tag 能最大程度地利用工具链的集成功能，&lt;br>
给开发、测试、上线、监控提供完备的功能。&lt;/p>
&lt;h2 id="tool-chain-搭建自洽的工具链">tool chain: 搭建自洽的工具链&lt;/h2>
&lt;p>在注重团队协作、开发流程、发布质量的软件工程中，&lt;br>
会有一系列开发工具围绕 Git 的代码历史树，&lt;br>
提供了自洽的工具链。&lt;/p>
&lt;h3 id="gitlabgithub-使用现代的开发平台">gitlab/github: 使用现代的开发平台&lt;/h3>
&lt;p>我们使用 &lt;code>GitLab&lt;/code> 来管理代码项目，&lt;br>
其中重度使用的是 &lt;code>Merge Request&lt;/code> 来作为 code review 的载体。&lt;br>
&lt;del>不过我们跟着 GitHub 的设定，管它叫 PR (Pull Request)&lt;/del>&lt;/p>
&lt;p>为了维持 PR 的原子性，&lt;br>
大部分情况我们遵循单个 commit 对应单个 PR，&lt;br>
这样既方便 review 也方便分支管理。&lt;br>
不过这样的开发流会产生非常多的 PR，&lt;br>
需要团队开发者都保持在一个更积极的开发状态下。&lt;/p>
&lt;p>现代的开发平台还会集成更多工作流上的功能，&lt;br>
我们还重度使用的是把 GitLab Runner 作为我们 ci/cd 的工具载体。&lt;/p>
&lt;h3 id="cicd-让系统把控代码质量">ci/cd: 让系统把控代码质量&lt;/h3>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/gitlab_pr.jpg" alt="gitlab-pr">&lt;/p>
&lt;blockquote>
&lt;p>在提完 PR 以后，&lt;br>
系统会自动化地启用一系列的 Python/Django 检查。&lt;/p>
&lt;/blockquote>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/gitlab_pipeline.jpg" alt="gitlab-pipeline">&lt;/p>
&lt;blockquote>
&lt;p>通过 git tag 发布版本后，&lt;br>
系统会自动化地跑构建、灰度等一系列部署任务。&lt;/p>
&lt;/blockquote>
&lt;p>除了 GitLab Runner,&lt;br>
其它像 Jenkins/Travis CI/GitHub Actions 也可以类似的 ci/cd 功能。&lt;/p>
&lt;p>集成 ci/cd 能让整个开发流变得更加柔顺，&lt;br>
让每一个改动的影响都可以即时地通过数据展示出来。&lt;br>
ci/cd 加上 code review，&lt;br>
能最大程度地让代码库保持活性，&lt;br>
长远地能避免“往屎山上堆屎”的发生。&lt;/p>
&lt;p>前面提到我们的 PR/release 频率都会比较高，&lt;br>
所以 ci/cd 也需要在更短的时间内跑完，&lt;br>
以避免龟速检测导致的各种心态爆炸、skip ci。&lt;br>
目前我们项目平均能在 5min 内跑完包括 96% 覆盖率的单元测试的多项检查，&lt;br>
也能在 5min 内跑完从构建、灰度到全量的整个发布流程。&lt;/p>
&lt;p>整个 ci/cd 的流程其实也跟写接口这样的业务类似，&lt;br>
是需要不断迭代、不断优化、不断适应更好的开发流的。&lt;/p>
&lt;h3 id="sentryk8s-用版本连接整个系统">sentry/k8s: 用版本连接整个系统&lt;/h3>
&lt;p>在开发的流程走完以后，&lt;br>
软件工程还关心发布的流程、质量把控的流程。&lt;/p>
&lt;p>我们绑定了 docker image tag 与 git tag，&lt;br>
最终发布部署在 k8s 上的每一个版本也跟 git tag 的版本强关联。&lt;br>
这样的设定之下，&lt;br>
比如像 &lt;code>kubectl rollout&lt;/code> 的一系列操作就会跟 Git 历史树关联上。&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/sentry_release.jpg" alt="sentry-release">&lt;/p>
&lt;blockquote>
&lt;p>我们也使用了 sentry 来检测管理代码的线上问题。&lt;/p>
&lt;/blockquote>
&lt;p>所有的外部系统都使用着统一的 tag version 来关联问题，&lt;br>
这样我们就给 debug, 历史溯源，分锅都提供了统一的工程语言。&lt;/p>
&lt;h2 id="conclusion">conclusion&lt;/h2>
&lt;p>基于 Git 的开发流不是一个一成不变的框架，&lt;br>
它会因为项目特质、团队成员习惯、工具链的不一样而有着不同的表现形式。&lt;/p>
&lt;p>我们团队在软件工程的实践中，&lt;br>
保持并维护着这么一套开发标准：&lt;/p>
&lt;ul>
&lt;li>保持 commit 的原子性，一个 commit 只做一件事情。&lt;/li>
&lt;li>遵循编写 commit message 的标准，并且会在 code review 时关注。&lt;/li>
&lt;li>统一团队成员的操作习惯，使用 rebase + fast forward merge。&lt;/li>
&lt;li>自动化地生成 git tag 以及 changelog，并基于此做代码发布。&lt;/li>
&lt;li>搭建快速全面的 ci/cd 流程，自动化地做掉所有代码检查。&lt;/li>
&lt;li>使开发流与社区最佳实践一致，了解并利用好各类工具的集成功能。&lt;/li>
&lt;/ul>
&lt;p>这套开发流也给我们提出了这些挑战：&lt;/p>
&lt;ul>
&lt;li>要对 Git 有一定了解，包括历史树操作等进阶知识。&lt;/li>
&lt;li>除了编码时，在协作时也要保持积极的态度，以及协作上的高标准。&lt;/li>
&lt;li>最重要的，对最佳实践的追求，以及不懂就学的态度。&lt;/li>
&lt;/ul>
&lt;p>这样的 Git 开发流，最终带来了这些效果：&lt;/p>
&lt;ul>
&lt;li>线性的历史让 debug、追溯变更、了解项目发展过程都变得非常友好。&lt;/li>
&lt;li>项目一方面能保持快速活跃的开发效率，另一方面能保证长期维护的质量。&lt;/li>
&lt;li>最佳实践的讨论以及迭代，让团队内部一直维持着很好的工程师文化。&lt;/li>
&lt;/ul>
&lt;p>软件工程的实践中，&lt;br>
好的 Git 开发流是不可或缺的一部分。&lt;br>
以后我们再以不同的视角来分享更多软件工程的实践。&lt;/p>
&lt;p>（完）&lt;/p></description></item><item><title>软件工程实践之平滑发版</title><link>https://liriansu.com/posts/2019-12-09-gracefully-upgrade/</link><pubDate>Mon, 09 Dec 2019 23:39:28 +0800</pubDate><guid>https://liriansu.com/posts/2019-12-09-gracefully-upgrade/</guid><description>&lt;p>软件工程实践系列文章，&lt;br>
会着重讲述实际的工程项目中是如何协作开发软件的。&lt;br>
本文主要介绍了如何无中断地发布版本。&lt;/p>
&lt;h2 id="outline">outline&lt;/h2>
&lt;p>本文包括以下内容：&lt;/p>
&lt;ul>
&lt;li>why&lt;/li>
&lt;li>how: 其实平滑发版大体可以分为两部分。
&lt;ul>
&lt;li>service: 服务层做好切换管理就行。&lt;/li>
&lt;li>database: 数据库层就是标准操作。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>example: 举个实际的栗子。&lt;/li>
&lt;li>conclusion&lt;/li>
&lt;/ul>
&lt;h2 id="why-为什么要平滑发版">why: 为什么要平滑发版？&lt;/h2>
&lt;p>&lt;a href="https://ldsink.com/">ldsink&lt;/a> 说过以前他在百姓网的时候，&lt;br>
他们一直保持的实践就是“随时都准备好发版”，&lt;br>
这样不仅能保持功能上线的敏捷度，&lt;br>
还准备好了应对各种变化。&lt;/p>
&lt;p>当时我们的一体化服务每次发版都要停服几秒钟，&lt;br>
几秒钟对应的就是用户触发的一堆 5XX 网络错误。&lt;br>
更不用提发版更频繁的开发测试环境，&lt;br>
前端爸爸们经常惊呼：&lt;br>
“诶？服务器 502 了！诶，我刷新一下又好了……”&lt;/p>
&lt;p>后来在我认真研学了以后发现，&lt;br>
平滑发版其实是一个非常普世的话题，&lt;br>
任何涉及网络流量分发、请求逻辑处理的服务都会有这部分功能。&lt;/p>
&lt;p>平滑发版的英文是 &lt;code>gracefully upgrade/reload/restart&lt;/code>,&lt;br>
常用的工具都会对平滑发版的流程有完善的支持，&lt;br>
用工具名直接搜索就行了，比如 &lt;code>nginx gracefully upgrade&lt;/code> 或者 &lt;code>k8s gracefully upgrade&lt;/code>。&lt;/p>
&lt;p>为什么要平滑发版呢？&lt;br>
其实核心目的就一个：&lt;br>
防止发版带来的服务中断。&lt;/p>
&lt;h2 id="how-如何做到平滑发版">how: 如何做到平滑发版？&lt;/h2>
&lt;p>在实际工程中，&lt;br>
大部分的 web 服务本质都是从外部接受请求，&lt;br>
从数据库查询、处理数据返回。&lt;br>
本片中就以这个逻辑，&lt;br>
按 service/database 的平滑发版来逐个介绍。&lt;/p>
&lt;h3 id="service-业务层的平滑发版">service: 业务层的平滑发版&lt;/h3>
&lt;p>我们团队后端语言框架用的是 python/django，&lt;br>
详细情况在前文《软件工程实践之 django/python》中有介绍。&lt;br>
我们目前的网络链路是&lt;br>
&lt;em>(云负载均衡) -&amp;gt; (k8s-ingress-controller) -&amp;gt; k8s-pod(nginx+uwsgi)&lt;/em>&lt;/p>
&lt;p>云负载均衡跟 k8s-ingress-controller (目前用的是 kong) 的变动都不会太频繁，&lt;br>
就不过多赘述。&lt;br>
每次发版变动的都是业务服务，在前面的链路中指的就是 k8s-pod(nginx/uwsgi)。&lt;/p>
&lt;p>不论是 k8s/docker/systemctl/supervisord/pm2,&lt;br>
他们通用的逻辑是系统信号 (Signals)。&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Signal&lt;/th>
&lt;th>x86&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>SIGHUP&lt;/td>
&lt;td>1&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>SIGINT&lt;/td>
&lt;td>2&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>SIGQUIT&lt;/td>
&lt;td>3&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>SIGKILL&lt;/td>
&lt;td>9&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>SIGTERM&lt;/td>
&lt;td>15&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;blockquote>
&lt;p>part of unix signal numbers&lt;/p>
&lt;/blockquote>
&lt;p>以 k8s 为例，当旧的 pod 被终止时，k8s 执行的具体操作如下：&lt;/p>
&lt;ol>
&lt;li>发送 &lt;code>SIGTERM&lt;/code> 信号，然后等待最多 &lt;code>terminationGracePeriodSeconds(default=30)&lt;/code> 秒&lt;/li>
&lt;li>假如等待过程中，服务停了，那就做其它终止操作&lt;/li>
&lt;li>假如等待过程中，服务没停，那么就发送一个 &lt;code>SIGKILL&lt;/code> 信号&lt;/li>
&lt;/ol>
&lt;p>一般来说，标准的框架实现都会支持 &lt;code>SIGTERM&lt;/code> 与 &lt;code>SIGKILL&lt;/code> 的语义，&lt;br>
但具体的额外自定义逻辑就需要自己去实现把控了。&lt;/p>
&lt;p>业务层确保请求不中断，&lt;br>
需要正确处理信号。&lt;/p>
&lt;h3 id="database-数据库层的平滑发版">database: 数据库层的平滑发版&lt;/h3>
&lt;p>数据库层会涉及到发版变动，&lt;br>
主要可以分为数据的变动、结构的变动。&lt;br>
&lt;strong>核心的处理方法是双写&lt;/strong>。&lt;/p>
&lt;p>先讲一下关于数据变动的双写。&lt;/p>
&lt;p>比如我们以前有个字段A，&lt;br>
存储的是布尔值 true/false,&lt;br>
后来含义变丰富了要改成枚举值 0/1/2/3。&lt;br>
那么整个流程得是：&lt;/p>
&lt;ol>
&lt;li>增加默认为空的枚举值字段B。&lt;/li>
&lt;li>第一次发版引入双写，代码逻辑中涉及字段A的写入逻辑，以同样的逻辑增加对字段B的写入。&lt;/li>
&lt;li>清洗数据，把所有字段A的值以同样逻辑洗到字段B里。&lt;/li>
&lt;li>第二次发版摘除双写，代码逻辑中涉及字段A的读取逻辑，全部以字段B替代。&lt;/li>
&lt;li>确定正常以后，下掉字段A。&lt;/li>
&lt;/ol>
&lt;p>2~4 的这一步是以双写的方式处理兼容，&lt;br>
持续时长会因为具体的情况而相差很大：&lt;br>
可能 10 分钟就双写完了，&lt;br>
也有可能因为要给清洗大量数据留足时间而持续数天。&lt;/p>
&lt;p>再看一下关于结构变动的双写，&lt;br>
核心逻辑跟上面的 1/2/3/4/5 套路五步是一样的。&lt;/p>
&lt;ul>
&lt;li>增加字段：这个很简单，增加完字段以后再发版即可。&lt;/li>
&lt;li>删除字段：这个也很简单，发版摘除相关逻辑以后再删除即可。&lt;/li>
&lt;li>修改字段：假如是不兼容的改动，应当以增加新字段+双写+删除旧字段的逻辑来处理。&lt;/li>
&lt;/ul>
&lt;p>数据库层确保请求不中断，&lt;br>
需要以双写保证兼容。&lt;/p>
&lt;h2 id="example-举个实际的栗子">example: 举个实际的栗子&lt;/h2>
&lt;p>我们的 django 服务是以 nginx+uwsgi 的方式起来的，&lt;br>
nginx/uwsgi 本身对 SIGTERM/SIGKILL 语义有着良好的支持。&lt;br>
但同一个 pod 的情况下经常会出现 race condition，&lt;br>
nginx 有时会比 uwsgi 终止的更早，&lt;br>
最终导致请求中断的问题。&lt;/p>
&lt;p>网上的老哥们也遇到过类似的问题，&lt;br>
解决方法也简单地有点滑稽：&lt;br>
&lt;a href="https://github.com/kubernetes/ingress-nginx/issues/322#issuecomment-298016539">加点 sleep&lt;/a>&lt;/p>
&lt;pre tabindex="0">&lt;code>container:
name: nginx
lifecycle:
preStop:
exec:
command: [&amp;#34;sh&amp;#34;, &amp;#34;-c&amp;#34;, &amp;#34;sleep 10 &amp;amp;&amp;amp; kill -s HUP 1&amp;#34;]
&lt;/code>&lt;/pre>&lt;p>除了一般的服务层跟数据库层，&lt;br>
我们还用到 celery 做了异步 worker。&lt;br>
celery 对平滑发版的支持不算特别好，&lt;br>
所以像&lt;a href="https://github.com/celery/celery/issues/2700">社区里提的一样&lt;/a>，&lt;br>
自己在 task 层面处理信号。&lt;/p>
&lt;h2 id="conclusion">conclusion&lt;/h2>
&lt;p>总的来说，工程上实现平滑发版（无中断发版）核心思想是：&lt;/p>
&lt;ul>
&lt;li>服务层：处理好系统信号。&lt;/li>
&lt;li>数据库：用双写保持兼容性。&lt;/li>
&lt;li>其它：确保链路上的每一点都是无中断的，才能达成真正的平滑。&lt;/li>
&lt;/ul>
&lt;p>通过这么一系列操作，&lt;br>
我们就可以轻松地做到用户（包括拼命人肉 DDOS 测试环境的前端爸爸们）感知不到我们在发版，&lt;br>
最终达成那句“随时都准备好发版”的状态。&lt;/p>
&lt;p>当然了，&lt;br>
随时发版到此时也只是技术层面的可行，&lt;br>
并不是意味着实际工作中真的会每时每刻都发版 :)&lt;/p>
&lt;p>毕竟软件工程不仅牵涉软件技术，还有人的工程呀。&lt;/p>
&lt;p>（完）&lt;/p></description></item><item><title>搭建一个不需要自己开服务器的纯静态博客</title><link>https://liriansu.com/posts/2019-11-19-build-a-staic-blog/</link><pubDate>Tue, 19 Nov 2019 01:00:07 +0800</pubDate><guid>https://liriansu.com/posts/2019-11-19-build-a-staic-blog/</guid><description>&lt;p>又名：我是如何从 jekyll 切到 hugo 的。&lt;/p>
&lt;p>本文会包括以下内容：&lt;/p>
&lt;ul>
&lt;li>背景&lt;/li>
&lt;li>博客搭建&lt;/li>
&lt;li>使用感受&lt;/li>
&lt;li>挖坑&lt;/li>
&lt;/ul>
&lt;h2 id="背景">背景&lt;/h2>
&lt;p>前几个月一个老哥给我发邮件：&lt;br>
“commentit 已经凉了啊，记得换掉！”&lt;br>
我才意识到这个静态评论系统已经到了项目终结期。&lt;br>
连 &lt;a href="https://github.com/jillro/commentit">GitHub Repo&lt;/a> 都 archive 了。&lt;br>
然后我又意识到：&lt;br>
&lt;em>已经有一阵没有翻修我的主页了。&lt;/em>&lt;/p>
&lt;p>这可不行，&lt;br>
&lt;strong>生命在于折腾&lt;/strong>。&lt;/p>
&lt;p>于是趁着最近换了新的编码环境，&lt;br>
我重新整了一下我的博客。&lt;br>
俗话说，一图胜千言，&lt;br>
先放张翻修过的博客图：&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/blog-hugo/preview.png" alt="blog-preview">&lt;/p>
&lt;h2 id="博客搭建">博客搭建&lt;/h2>
&lt;blockquote>
&lt;p>这一章节讲的是枯燥的步骤，&lt;br>
下一章节才讲充满偏见的个人感受 XD&lt;/p>
&lt;/blockquote>
&lt;p>不想自己维护服务器的话，&lt;br>
托管在 GitHub Pages 上是个很好的选择。&lt;br>
四年前我用 jekyll 搭博客的时候也写过一篇：&lt;br>
&lt;a href="https://liriansu.com/how-this-blog-was-built">《这篇博客是怎么建成的》&lt;/a>。&lt;br>
大体上，搭建一个功能完备的静态博客分为这几个步骤：&lt;/p>
&lt;ol>
&lt;li>找一个静态内容框架&lt;/li>
&lt;li>装一个静态评论系统&lt;/li>
&lt;li>配配件：主题、域名等&lt;/li>
&lt;/ol>
&lt;h3 id="搞框架">搞框架&lt;/h3>
&lt;p>&lt;a href="https://gohugo.io/">hugo&lt;/a> 的安装非常容易，&lt;br>
直接用命令行或者&lt;a href="https://gohugo.io/getting-started/installing">去官网下载&lt;/a>就行了：&lt;/p>
&lt;pre tabindex="0">&lt;code>brew install hugo
&lt;/code>&lt;/pre>&lt;p>然后&lt;a href="https://gohugo.io/getting-started/quick-start/">按照官方的教程&lt;/a>，&lt;br>
一键创建目录 + 默认主题启动就行了：&lt;/p>
&lt;pre tabindex="0">&lt;code>hugo new site quickstart
cd quickstart
git init
git submodule add https://github.com/budparr/gohugo-theme-ananke.git themes/ananke
echo &amp;#39;theme = &amp;#34;ananke&amp;#34;&amp;#39; &amp;gt;&amp;gt; config.toml
hugo server -D
&lt;/code>&lt;/pre>&lt;p>其它高阶玩法读文档就是了。&lt;br>
至此，第一步，找框架算是做完了。&lt;/p>
&lt;h3 id="搞评论">搞评论&lt;/h3>
&lt;p>&lt;a href="https://utteranc.es/">utterances&lt;/a> 也是一个利用 GitHub Issues 来做评论的工具，&lt;br>
它利用 &lt;a href="https://primer.style/">Primer&lt;/a> 达成的 GitHub 还原度非常高。&lt;/p>
&lt;p>安装也非常简单，&lt;br>
找个模板页把它的配置写上就行了：&lt;/p>
&lt;pre tabindex="0">&lt;code>&amp;lt;script src=&amp;#34;https://utteranc.es/client.js&amp;#34;
repo=&amp;#34;[ENTER REPO HERE]&amp;#34;
issue-term=&amp;#34;pathname&amp;#34;
theme=&amp;#34;github-light&amp;#34;
crossorigin=&amp;#34;anonymous&amp;#34;
async&amp;gt;
&amp;lt;/script&amp;gt;
&lt;/code>&lt;/pre>&lt;p>对应的效果如下：&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/blog-hugo/utterances.png" alt="utterances-preview">&lt;/p>
&lt;h3 id="其它配件">其它配件&lt;/h3>
&lt;p>我用的主题是 &lt;a href="https://github.com/joway/hugo-theme-yinyang">joway/hugo-theme-yinyang&lt;/a>，&lt;br>
整体的简约风格让我很喜欢。&lt;/p>
&lt;p>字体的话，由于是个人博客，我就没用 FiraCode 这种严谨的字体了，&lt;br>
英文字体我用的是 &lt;a href="https://github.com/ipython/xkcd-font">ipython/xkcd-font&lt;/a>,&lt;br>
中文字体我还在寻找一个可爱的手写体。&lt;/p>
&lt;p>&lt;img src="https://imgs.xkcd.com/comics/compiling.png" alt="xkcd-303">&lt;/p>
&lt;p>域名的话，默认会开启 lki.github.io 这样的域名，&lt;br>
需要用自定义的域名可参考官方文档：&lt;a href="https://help.github.com/en/github/working-with-github-pages/about-custom-domains-and-github-pages">github-custom-domain&lt;/a>&lt;br>
设置里记得开一下 HTTPS:&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/blog-hugo/github-pages.png" alt="github-pages">&lt;/p>
&lt;p>要统计访问人数的话，可以用&lt;a href="https://busuanzi.ibruce.info/">静态计数器不蒜子&lt;/a>做到：&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/blog-hugo/header.png" alt="blog-header">&lt;/p>
&lt;h2 id="使用感受">使用感受&lt;/h2>
&lt;p>我之前的博客系统也是用的 GitHub Pages，&lt;br>
工具链是用的 jekyll + commentit。&lt;br>
整体有这么几个感受：&lt;/p>
&lt;ul>
&lt;li>用 GitHub Pages 相比于自建博客而言：
&lt;ul>
&lt;li>爽：&lt;strong>不需要维护&lt;/strong>&lt;br>
平常在公司做的后端已经够多了，并不想花时间研究自己博客的 502 (x&lt;/li>
&lt;li>爽：便宜&lt;br>
呃，拥抱开源，拥抱开源。&lt;/li>
&lt;li>烦：访问速度不够快&lt;br>
不过这个是 GitHub 的原因，烦也没用。&lt;/li>
&lt;li>烦：&lt;strong>受限制&lt;/strong>&lt;br>
比如评论功能，要是自建博客的话实现起来很轻松。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>用 hugo 相比于 jekyll 而言：
&lt;ul>
&lt;li>爽：有新鲜感&lt;br>
有一说一，确实。&lt;/li>
&lt;li>爽：&lt;strong>hugo 是 go 写的&lt;/strong>&lt;br>
之前为了 jekyll, 还得在电脑上冗余一套 ruby 的环境，而 go 的环境天然就有。&lt;/li>
&lt;li>爽：默认值选的很恰当，不需要过分定制&lt;br>
不论是 configuration 还是 archetypes, hugo 给我的感受更好，而且 &lt;a href="https://gohugo.io/getting-started/configuration/#blackfriday-extensions">hardLineBreak&lt;/a> 这个选项真的好用。&lt;/li>
&lt;li>烦：GitHub 只支持自动构建 jekyll&lt;br>
加个 git pre-push hook 其实就可以解决掉这点，不是特别大的问题。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>用 utterances 相比 commentit 而言：
&lt;ul>
&lt;li>爽：&lt;strong>默认样式更好&lt;/strong>&lt;br>
之前 commentit 的样式是我手写的，作为 css 苦手无数次倒在了 &lt;code>inline-block&lt;/code> 上…&lt;/li>
&lt;li>爽：&lt;strong>用 issue 同步评论的方式才是正确的&lt;/strong>&lt;br>
commentit 的哲学是通过 git push 来挂载评论，但是经过实践以后，其实还是用 GitHub Issues 来更王道。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;p>另外值得一提的是，&lt;br>
在考虑从 jekyll 迁出时，&lt;br>
我也认真考虑过 hexo。&lt;br>
不过最终是因为 hugo 看起来更迷人，&lt;br>
同时也为了坚持当时放弃了 hexo,&lt;br>
选了 jekyll 的不必要的倔强(x&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/blog-hugo/star_history.png" alt="star-history">&lt;/p>
&lt;blockquote>
&lt;p>附 star 增长趋势对比&lt;/p>
&lt;/blockquote>
&lt;p>还有一个开心的小的点，&lt;br>
就是这个主题对微信公众号的排版支持的比起以前好多啦 :)&lt;/p>
&lt;h3 id="挖坑">挖坑&lt;/h3>
&lt;p>目前的博客改造算是告一段落了，&lt;br>
接下来肯定还是回归到认真工作、认真记录生活的节奏中。&lt;/p>
&lt;p>而对于博客本身，&lt;br>
其实还是有不少可以做的坑：&lt;/p>
&lt;ul>
&lt;li>用 &lt;a href="https://primer.style/">Primer&lt;/a> 统一正文评论样式。&lt;/li>
&lt;li>找个好玩的中文手写字体。（其实这条跟上面那条会冲突）&lt;/li>
&lt;li>像 TravisCI 一样提供切换字体的选项。（除了 cooooool 以外并没什么用）&lt;/li>
&lt;li>把友链功能给加上，认真给大家介绍一下我的好友们的实力&lt;/li>
&lt;li>找个办法，把以前 commentit 的评论优雅地展示出来&lt;/li>
&lt;/ul>
&lt;p>要列的话，&lt;br>
能想到要填的坑是一个又一个。&lt;br>
毕竟就像鲁迅常说的那句话一样：&lt;br>
“个人博客是值得认真搞一搞的，&lt;br>
毕竟&lt;strong>生命在于折腾&lt;/strong>嘛。”&lt;/p>
&lt;p>（完）&lt;/p></description></item><item><title>[轶事] 为什么 requests 不是 python 标准库？</title><link>https://liriansu.com/posts/2019-10-30-anecdote-why-requests-not-standard/</link><pubDate>Wed, 30 Oct 2019 22:32:20 +0000</pubDate><guid>https://liriansu.com/posts/2019-10-30-anecdote-why-requests-not-standard/</guid><description>&lt;p>前几年一次跟耗子哥聊天，&lt;br>
他说：“你终有一天会从 stackoverflow 上找 bugfix,&lt;br>
进化到从 github issue 里找 bugfix.”&lt;br>
一语成谶。&lt;/p>
&lt;h2 id="头部注释">头部注释&lt;/h2>
&lt;p>我非常喜欢&lt;a href="https://www.zhihu.com/question/30137699/answer/476916096">@灵剑 说的这么一段话&lt;/a>：&lt;/p>
&lt;blockquote>
&lt;p>软件维护有两种截然不同的思路：&lt;br>
一种是所有的依赖都追踪最新版，&lt;br>
一旦出最新版立即开始试用；&lt;br>
另一种是所有的依赖都选择一个不会变的固定版本，&lt;br>
能不升级就不升级。&lt;/p>
&lt;/blockquote>
&lt;p>看见软件的新陈代谢，给写代码的我带来了无穷的热爱与动力，&lt;br>
同时也给我带来了很多 github issues&amp;hellip;&lt;/p>
&lt;p>代码是人写的，bug 也是人写的，bugfix 也还是人写的，&lt;br>
github issue 的文字里也充满了各种各样有血有肉的充满既视感的评论。&lt;br>
issue 的文字虽然隔着时间空间上的距离，&lt;br>
但就像 &lt;a href="https://xkcd.com/979/">xkcd 979 - wisdom of the ancients&lt;/a> 表达的那样，&lt;br>
有些情绪就是亘古不变的。&lt;/p>
&lt;p>&lt;img src="https://imgs.xkcd.com/comics/wisdom_of_the_ancients.png" alt="wisdom-of-the-ancients">&lt;/p>
&lt;p>在工作中 debug 的时候，&lt;br>
对于具体的 issue,&lt;br>
同事们都留下过很多精彩的讨论。&lt;/p>
&lt;p>鉴于这样，&lt;br>
我决定开辟一个“轶事”的专栏，&lt;br>
专门来讲一讲那些好玩的 issue.&lt;/p>
&lt;h2 id="为什么-requests-不是-python-标准库">为什么 requests 不是 python 标准库？&lt;/h2>
&lt;blockquote>
&lt;p>原文地址:&lt;br>
&lt;a href="https://github.com/psf/requests/issues/2424">https://github.com/psf/requests/issues/2424&lt;/a>&lt;/p>
&lt;/blockquote>
&lt;p>&lt;a href="https://github.com/kennethreitz">Kenneth Reitz&lt;/a> 是一个业界知名的程序员，&lt;br>
很多人了解他可能是因为&lt;a href="https://zhuanlan.zhihu.com/p/20346580">他从两百多斤的胖子变成一个超帅的玩摄影的程序员&lt;/a>，&lt;br>
其实专业过硬的他是写出过 &lt;a href="https://github.com/psf/requests">python-requests&lt;/a>, &lt;a href="https://github.com/postmanlabs/httpbin">httpbin&lt;/a> 等好用的工具库的。&lt;/p>
&lt;p>requests 这个库重要到什么程度呢？&lt;br>
根据目前可以公开的情报看到，&lt;br>
GitHub 上的引用数高达 &lt;code>389k&lt;/code>，&lt;br>
是 python 语言下引用数最高的库。&lt;/p>
&lt;p>于是很自然的，我就产生了这样的疑问：&lt;br>
“为什么 requests 不是 python 标准库呢？”&lt;br>
作为项目的主开发，&lt;br>
Kenneth 在 2015 年初，&lt;br>
还在 python 3.5 的年代就向社区抛了一个问题：&lt;br>
“假如 requests 要加入 python 3.5 标准库，你们有什么想法吗？”&lt;/p>
&lt;p>的确，一个库进标准库是有利有弊，要经过社区讨论的。&lt;br>
所以其实我的问题应该要改一个字，&lt;br>
从“为什么 requests 不是 python 标准库？”&lt;br>
改成“为什么 requests 不进 python 标准库？”&lt;/p>
&lt;p>整串讨论看下来，基本是有这么几个意见：&lt;/p>
&lt;ul>
&lt;li>优势是
&lt;ul>
&lt;li>降低使用成本：让很多小白也能直接上手用标准库的了。&lt;/li>
&lt;li>扩大使用范围：很多只依赖于标准库的项目，也能用上 requests 了。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>劣势是
&lt;ul>
&lt;li>开发流程问题：标准库的严格流程，跟社区开发的流程完全不一样，最终可能导致开发者流失。&lt;/li>
&lt;li>依赖问题：现有的库依赖了不少证书之类的文件，在进标准库的过程中需要大重构。&lt;/li>
&lt;li>进化速度问题：进了标准库以后，接口跟实现就会固化，很难随着外部世界改变而快速变化到最好的状态。&lt;/li>
&lt;li>其它历史问题：以前的 urllib 库为了兼容其实已经很臃肿了，也是需要重构的。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;p>总的来说，&lt;br>
社区的反对意见跟忧虑会更大一些，&lt;br>
更原汁原味的评论大家可以看一下原串。&lt;/p>
&lt;p>整个讨论中还有几个我感兴趣的点：&lt;/p>
&lt;ul>
&lt;li>@Lukasa 在串首来了个起手式：“先问一下几个大佬，他们的看法是怎么样的。”&lt;br>
然后 at 了 &lt;code>@shazow @kevinburke @dstufft @alex @sigmavirus24&lt;/code> 这五个人。&lt;br>
里面我只知道 alex 是写 &lt;code>cryptography&lt;/code> 的，其它人其实都可以认识一下。&lt;/li>
&lt;li>串讨论到一半的时候 &lt;code>@dcramer&lt;/code> 留了些关于“我只用标准库依赖”的评论，&lt;br>
然后留下一句 &lt;code>not sure what you're all bitching about&lt;/code> 就跑了…&lt;br>
我就不敢这么放肆&amp;hellip;&lt;/li>
&lt;li>Kenneth 在 requests 库的文档中曾写过这么一句话：&lt;br>
&lt;code>Essentially, the standard library is where a library goes to die.&lt;/code>&lt;br>
结果就在讨论过程中多次被揪出来“打脸”质疑了。&lt;br>
（其实还好，设计哲学是可以设计的嘛）&lt;/li>
&lt;li>&lt;a href="https://github.com/psf/requests/issues/5057">今年四月也有个老哥 @4evermaat 抛了这个问题&lt;/a>，&lt;br>
他在看完四年前的讨论以后，留下了这么一句感慨：&lt;br>
&lt;code>I didn't realize there was so much politics in getting a module included in the stdlib.&lt;/code>&lt;/li>
&lt;/ul>
&lt;p>在讨论结束过后四年的现在，&lt;br>
&lt;code>requests&lt;/code> 库依然以一个独立的社区项目生机勃勃地新陈代谢着，&lt;br>
python 3.5 以后也增加了标准库 &lt;code>urllib.request&lt;/code> 支持一部分核心功能。&lt;/p>
&lt;p>代码既是人设计的，&lt;br>
也是给人用的。&lt;br>
它们背后的故事，&lt;br>
也是程序内在逻辑的一部分。&lt;br>
这部分逻辑曾经在一个个讨论串里存活着，&lt;br>
最终也让代码更加鲜活地呼吸着、代谢着、生存了下去。&lt;/p>
&lt;p>（完）&lt;/p></description></item><item><title>没错，DNS TTL 字段就是骗你的</title><link>https://liriansu.com/posts/2019-10-29-stupid-dns-ttl/</link><pubDate>Tue, 29 Oct 2019 21:49:42 +0000</pubDate><guid>https://liriansu.com/posts/2019-10-29-stupid-dns-ttl/</guid><description>&lt;blockquote>
&lt;p>By design,&lt;br>
the Internet core is stupid,&lt;br>
and the edge is smart.&lt;/p>
&lt;/blockquote>
&lt;h2 id="引子">引子&lt;/h2>
&lt;p>前几天在网上冲浪的时候，&lt;br>
看到了一篇讲 DNS 的宝藏文章：&lt;br>
&lt;a href="https://labs.ripe.net/Members/giovane_moura/dns-ttl-violations-in-the-wild-with-ripe-atlas-2">DNS TTL Violations in the Wild&lt;/a>.&lt;/p>
&lt;p>之所以对我来说是宝藏文章，&lt;br>
因为在读了第一段以后，&lt;br>
我就发现了一个我习以为常的认知其实在实际是错误✖的：&lt;br>
&lt;em>业界都会遵守 DNS 的 TTL 超时逻辑。&lt;/em>&lt;/p>
&lt;p>然而实际上是：&lt;br>
&lt;strong>业界都知道 DNS 的 TTL 超时逻辑，但不一定这么实现。&lt;/strong>&lt;/p>
&lt;h2 id="事件">事件&lt;/h2>
&lt;p>前几周我们出了个 Bug,&lt;br>
影响了整个开发、测试环境。&lt;/p>
&lt;p>我们有很大一块的业务是跟微信做各类 py 交易，&lt;br>
&lt;a href="https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/Authorization_Process_Technical_Description.html">微信要求说我们给个回调域名&lt;/a>，&lt;br>
每 10 分钟会推送一个凭证，&lt;br>
我们要用微信最新的凭证去调他们的接口。&lt;/p>
&lt;p>最早我们给微信配的回调域名背后是个 AWS ELB,&lt;br>
这是一个亚马逊云上面的旧版负载均衡；&lt;br>
后来我们打算换成新版负载均衡 AWS ALB。&lt;/p>
&lt;p>这个操作就很简单嘛，&lt;br>
到 DNS 服务商里看了一下，&lt;br>
微信回调的域名解析 TTL 是 600 秒，&lt;br>
又是开发测试环境；&lt;br>
于是我们直接把解析改到了新版负载均衡上，&lt;br>
~~（出于省钱的想法）~~顺手还把旧的负载均衡给删了。&lt;/p>
&lt;p>哦豁。&lt;br>
微信一天都没有给我们推授权凭证。&lt;br>
于是我们开发测试环境的微信功能挂了一天。&lt;/p>
&lt;p>有的时候开发测试环境出问题，&lt;br>
会跟生产环境同样煎熬。&lt;br>
因为你会发现你身边的同事，&lt;br>
每隔 10 分钟就会问你：&lt;br>
“弟啊，微信好了没有？”&lt;/p>
&lt;h2 id="疑问">疑问&lt;/h2>
&lt;p>在改 DNS 的 86400 秒以后，&lt;br>
微信的凭证又成功地持续给我们推送了。&lt;/p>
&lt;p>根据现象判定是 DNS 的问题以后，&lt;br>
一边在心里鄙视微信，&lt;br>
一边也产生了疑问：&lt;br>
“不科学啊，DNS 这么基础的服务，怎么会出 bug 呢？”&lt;/p>
&lt;p>这就回到了本文开头讲的：&lt;br>
业界都知道 DNS 的 TTL 超时逻辑，但不一定这么实现。&lt;/p>
&lt;p>每一条 DNS 记录都由两部分数据组成：&lt;br>
什么域名应该指向什么目的地？&lt;br>
我的有效时间是多久？&lt;br>
而这两部分数据会以互联网特有的树状结构层叠而上，盘织交错。&lt;br>
在终端进行 DNS 寻址时，&lt;br>
链路上的任何一个 DNS 服务器都可以实现一套标准或是非标的逻辑。&lt;/p>
&lt;p>对于 TTL 这个值，&lt;br>
只有三种实现的逻辑：&lt;/p>
&lt;ol>
&lt;li>缓存时间等于 DNS TTL 时间。&lt;/li>
&lt;li>缓存时间小于 DNS TTL 时间。&lt;/li>
&lt;li>缓存时间大于 DNS TTL 时间。&lt;/li>
&lt;/ol>
&lt;h2 id="世界">世界&lt;/h2>
&lt;p>要我来写域名服务器的逻辑的话，&lt;br>
不出意外我会严格按照定义来实现。&lt;br>
当然，根据性能、时间、空间的限制，&lt;br>
最终实现出来会有几秒的误差，&lt;br>
不过这不关键。&lt;/p>
&lt;p>关键的是，&lt;a href="https://mailarchive.ietf.org/arch/msg/dnsop/zRuuXkwmklMHFvl_Qqzn2N0SOGY/?qid=ff8e732c964b76fed3bbf333b89b111f">有不少人觉得 DNS 目前的设计是有缺陷的&lt;/a>。&lt;br>
而作为整个互联网的底层构架，&lt;br>
不论是要提升还是替换 DNS 目前的逻辑，&lt;br>
都是一个非常巨大的工程。&lt;br>
当然，这也更吸引工程师为此献身了。&lt;/p>
&lt;p>于是，当今现实世界里的域名解析，&lt;br>
就不是完全按照“缓存时间等于 DNS TTL 时间”来实现的。&lt;/p>
&lt;ul>
&lt;li>当缓存时间小于 DNS TTL 时间时
&lt;ul>
&lt;li>主要争议点在与这个会给上游服务器带来更大的解析压力&lt;/li>
&lt;li>高频解析也意味着更多的带宽、网费支出&lt;/li>
&lt;li>但这种情况不会伤害终端用户&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>当缓存时间大于 DNS TTL 时间时
&lt;ul>
&lt;li>主要的问题在于，这会让用户访问到错误的服务器&lt;/li>
&lt;li>这不仅会带来逻辑错误，还会有潜在的安全隐患&lt;/li>
&lt;li>在本文最开始出现的问题，其实就是微信的 DNS 链路上出现了缓存过旧的问题&lt;/li>
&lt;li>好处可能就是在解析费上不用交那么多钱了(x&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h2 id="总结">总结&lt;/h2>
&lt;p>总的来说，DNS TTL 是一个在互联网基础设施中广泛使用的约定。&lt;br>
但是现实世界中也会有很多非标的实现。&lt;br>
由于 DNS 的特殊性，每一个非标的域名商都会影响一大片他们能触达的用户。&lt;br>
所以在我们操作 DNS 时，要优雅的解决问题就也得把他们给考虑进来。&lt;/p>
&lt;p>工程上的问题就是这样，&lt;br>
既有理论的优雅，&lt;br>
又有凡人的愚蠢，&lt;br>
也有分布式的智慧。&lt;/p>
&lt;blockquote>
&lt;p>By design,&lt;br>
the Internet core is stupid,&lt;br>
and the edge is smart.&lt;/p>
&lt;/blockquote>
&lt;p>（完）&lt;/p></description></item><item><title>Pythonista 的 Go 之旅</title><link>https://liriansu.com/posts/2019-06-13-go-experience-as-a-pythonista/</link><pubDate>Thu, 13 Jun 2019 01:10:49 +0000</pubDate><guid>https://liriansu.com/posts/2019-06-13-go-experience-as-a-pythonista/</guid><description>&lt;h1 id="背景">背景&lt;/h1>
&lt;p>我们团队后端主要技术栈是 Python,&lt;br>
具体的软工实践在前文 &lt;a href="https://liriansu.com/software-engineering-django">django/python&lt;/a> 里有详细的介绍。&lt;br>
由于平时做公司业务主要写的是 Python,&lt;br>
自己做的项目也是 Python 工具，&lt;br>
所以其实一直想尝试体验一下 Go。&lt;/p>
&lt;p>正好上周有空，&lt;br>
于是体验了一下 Go 的基础设定，&lt;br>
用 Go 写了一个小服务（微信消息推送）。&lt;/p>
&lt;p>这篇文章讲的就是一个 Pythonista 的 Go 萌新之路。&lt;br>
有理解谬误、操作不当的地方，&lt;br>
请各位多指教了。&lt;/p>
&lt;h1 id="语法">语法&lt;/h1>
&lt;p>上手一个语言，&lt;br>
总是习惯性打开 &lt;a href="https://learnxinyminutes.com/docs/go/">learn x in y minutes&lt;/a> 先过一遍语法。&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/slides/golang-experience/reserved_words.png" alt="go keyword">&lt;/p>
&lt;p>Go 的特别之处是它的关键字非常少，&lt;br>
这让 Go 的语法很容易被记下来。&lt;br>
总的来说我觉得这几个语法很好玩。&lt;/p>
&lt;h2 id="循环">循环&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// 直接 for 就可以写死循环
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">for&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Println&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;while true...&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// range 这个关键词用起来很舒服
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#a6e22e">data&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#66d9ef">map&lt;/span>[&lt;span style="color:#66d9ef">string&lt;/span>]&lt;span style="color:#66d9ef">string&lt;/span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;key&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;value&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#a6e22e">key&lt;/span>, &lt;span style="color:#a6e22e">value&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#66d9ef">range&lt;/span> &lt;span style="color:#a6e22e">data&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Println&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;while true...&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="枚举">枚举&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// iota 居然被做成了关键字
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// 这里后面的俩 iota 是可以省略的
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">const&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">Unknown&lt;/span> = &lt;span style="color:#66d9ef">iota&lt;/span> &lt;span style="color:#75715e">// 0
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#a6e22e">Male&lt;/span> = &lt;span style="color:#66d9ef">iota&lt;/span> &lt;span style="color:#75715e">// 1
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#a6e22e">Female&lt;/span> = &lt;span style="color:#66d9ef">iota&lt;/span> &lt;span style="color:#75715e">// 2
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// 也可以满足隔 10 定义枚举的喜好
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// `iota &amp;lt;&amp;lt; 2` 这样位运算定义 1/2/4/8 也是可以的
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">const&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">Unknown&lt;/span> = &lt;span style="color:#66d9ef">iota&lt;/span> &lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#ae81ff">10&lt;/span> &lt;span style="color:#75715e">// 0
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#a6e22e">Male&lt;/span> = &lt;span style="color:#66d9ef">iota&lt;/span> &lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#ae81ff">10&lt;/span> &lt;span style="color:#75715e">// 10
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#a6e22e">Female&lt;/span> = &lt;span style="color:#66d9ef">iota&lt;/span> &lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#ae81ff">10&lt;/span> &lt;span style="color:#75715e">// 20
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="多表达式判断">多表达式判断&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// if 语句会取最后的表达式值，所以这么判断是很常见的
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">f&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">file&lt;/span>.&lt;span style="color:#a6e22e">Open&lt;/span>(&lt;span style="color:#a6e22e">path&lt;/span>); &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">Response&lt;/span>(&lt;span style="color:#ae81ff">400&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span>.&lt;span style="color:#a6e22e">Error&lt;/span>())
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// 这样判断布尔值也是常见的操作
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">data&lt;/span>, &lt;span style="color:#a6e22e">ok&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">json&lt;/span>.&lt;span style="color:#a6e22e">Unmarshal&lt;/span>(&lt;span style="color:#a6e22e">body&lt;/span>); !&lt;span style="color:#a6e22e">ok&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">Response&lt;/span>(&lt;span style="color:#ae81ff">400&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;invalid json body&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="goroutine">goroutine&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// go 的天生并发也是非常优雅的地方
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">sendTemplate&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 这里是耗时很久的网络请求
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">handleRequest&lt;/span>(&lt;span style="color:#a6e22e">ctx&lt;/span> &lt;span style="color:#a6e22e">Context&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">validate&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// sendTemplate()
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#75715e">// ↑ 假如为了速度，我们不能同步发送模板，那么我们用 `go` 这个关键字就可以一键异步 ↓
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">go&lt;/span> &lt;span style="color:#a6e22e">sendTemplate&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h1 id="项目">项目&lt;/h1>
&lt;p>第一章的语法过了以后，&lt;br>
很快就到了第二章：&lt;br>
《如何用 go 起一个项目》&lt;/p>
&lt;p>要写代码，首先就得把文档给翻出来看看。&lt;br>
于是第一站便是&lt;a href="https://golang.org/">官网 golang.org&lt;/a>&lt;/p>
&lt;p>Go 的官网其实非常友好，&lt;br>
从最基础的&lt;a href="https://golang.org/doc/code.html">教你怎么配环境、写初始的项目&lt;/a>，&lt;br>
到 &lt;a href="https://golang.org/doc/effective_go.html">Effective Go&lt;/a> 这种全面长文都浅显到点。&lt;/p>
&lt;p>上手装好语言环境以后，&lt;br>
首先跟 &lt;code>GOPATH&lt;/code> 这个环境变量玩了一下。&lt;br>
不过后来发现 Go 1.12 以后自带 go mod,&lt;br>
只要简单了解一下这个概念就行了。&lt;br>
那我们先放一下，&lt;br>
直接上手感受 Go 的工具链吧。&lt;/p>
&lt;h2 id="工具链">工具链&lt;/h2>
&lt;p>Python 装好以后主要自带的是个 REPL 跟 pip 这个包管理器。&lt;br>
Go 装好以后，会自带包括 fmt/test/vet/mod 等一系列的工具。&lt;/p>
&lt;ul>
&lt;li>&lt;code>go fmt&lt;/code>
&lt;ul>
&lt;li>这个是上手 Go 第一印象最大的工具&lt;/li>
&lt;li>它是一个不支持配置的代码格式化工具，非常严格&lt;/li>
&lt;li>&lt;del>prefer tab over space&lt;/del>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;code>go test&lt;/code>
&lt;ul>
&lt;li>自带 coverage, 很好用&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;code>go vet&lt;/code>
&lt;ul>
&lt;li>似乎是自带的 linter&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;p>玩 &lt;code>go test&lt;/code> 的时候发现它是针对 &lt;code>package&lt;/code> 来做测试的，&lt;br>
而 Go 里面，&lt;br>
&lt;code>package&lt;/code> 的概念也是非常突出。&lt;br>
比如调用包方法的时候是要加包名的，&lt;br>
所以最佳实践里也有“命名不重叠”的规则。&lt;br>
（举个栗子，比如方法应该叫 &lt;code>xml.Parser&lt;/code> 而不是 &lt;code>xml.XMLParser&lt;/code>）&lt;/p>
&lt;h2 id="写业务">写业务&lt;/h2>
&lt;p>由于我们写的是一个对内网以 RESTful 风格提供接口，&lt;br>
然后调用微信发送消息通知用户的这么一个小服务，&lt;br>
按照 Python 的惯性就想找个 &lt;code>django&lt;/code> + &lt;code>wechatpy&lt;/code> 的组合在一周内来完成业务。&lt;br>
简单调研了一圈，选了 &lt;code>gin&lt;/code> + &lt;code>gorm&lt;/code> 两个大的工具。&lt;/p>
&lt;p>Go 的第三方库给我的感觉是非常直白。&lt;br>
因为引入第三方库的方式是 &lt;code>go get -u github.com/gin-gonic/gin&lt;/code>，&lt;br>
直接拉的就是 GitHub master 分支的最新代码，&lt;br>
所以感觉整个第三方的社区是基于分布式共识的，&lt;br>
只有大家都遵守社区规范，&lt;br>
才不会有挖矿代码的出现…（虽然中心化也会有挖矿代码）&lt;/p>
&lt;p>文档的话，调研阶段读的其实都是 GitHub README，&lt;br>
GitHub 是经常逛的网站，&lt;br>
各个库的 README 风格也都是 markdown 风格，&lt;br>
读起来也很轻松。&lt;br>
真正要看 godoc 的地方不多。&lt;br>
因为拉的是源代码，&lt;br>
所以基本上都是直接读源代码，&lt;br>
体验跟 Python 非常像。&lt;/p>
&lt;p>具体业务代码就先略过了，&lt;br>
没有什么特别的。&lt;/p>
&lt;h2 id="部署">部署&lt;/h2>
&lt;p>开始准备部署的时候又有不少好玩的话题。&lt;br>
比如 Go 的多环境配置。&lt;/p>
&lt;p>Python (Django) 的多环境我一直用的是环境变量 + 多配置文件，&lt;br>
Go 的话去看了一下社区，&lt;br>
基本也是类似的原理。&lt;br>
可以用环境变量，&lt;br>
也可以用多配置文件（比如 yaml），&lt;br>
还有一个就是用命令参数（flag 库）。&lt;br>
Go 社区里其实比较推崇用 flag，&lt;br>
因为这样可以把配置跟代码（执行文件）融为一体，&lt;br>
更加利于维护。&lt;br>
不过我最终还是选择了环境变量 + 多配置文件…&lt;/p>
&lt;p>项目的编译、部署我们用的是 GitLab CI/Docker。&lt;br>
也是 ci-build/test/compile/docker-build/deploy 五个套路阶段。&lt;br>
Go 里比较特别的是会大量引用 GitHub 以及 Google 官方提供的代码，&lt;br>
在国内拉的速度比较慢，&lt;br>
所以为了加速构建，&lt;br>
我们也自己搭了相应的加速通道去提升速度。&lt;br>
目前来说，从代码进主干分支，&lt;br>
到自动发版大概耗时不超过 3min。&lt;/p>
&lt;h2 id="性能">性能&lt;/h2>
&lt;p>自己写的小服务上去了，&lt;br>
那首先就要 wrk 一下测一下 QPS 啦。&lt;/p>
&lt;p>Python(Django) 默认的其实是同步模式，&lt;br>
基础支持的 QPS 很低，&lt;br>
我们用 gevent + uwsgi 协程模式特意调优过，&lt;br>
一个获取服务器当前时间的简单接口，&lt;br>
在 1CPU+4G Memory 的小破机器上，&lt;br>
Python(gevent) 的 QPS 大概能到 1000，&lt;br>
而未经调优的 Go(gin) QPS 能到 10000。&lt;br>
真有你的啊，Go。&lt;/p>
&lt;h2 id="社区">社区&lt;/h2>
&lt;p>在玩 Go 的一周中，&lt;br>
其实我真正的有效编码时间不是很长，&lt;br>
大部分时间都徜徉在 Go 的各种社区最佳实践文档里。&lt;/p>
&lt;p>在我眼中，&lt;br>
除去 Go 语言本身的很多闪光点，&lt;br>
Go 的整个语言社区运营也是值得其他语言学习的。&lt;br>
比如上面讲到的官方推的工具链，&lt;br>
这能有效提升所有项目的下限。&lt;br>
Python 去年也刚出了&lt;a href="https://github.com/python/black">一个格式化工具 black&lt;/a>，&lt;br>
自己宣称是 &lt;strong>the uncompromising code formatter&lt;/strong>。&lt;br>
（Python: 别催，在学了在学了）&lt;/p>
&lt;h1 id="感受">感受&lt;/h1>
&lt;p>讲了这么多看似中立，&lt;br>
实际都是感受的发言，&lt;br>
我来集中总结一下我的感受。&lt;/p>
&lt;h2 id="我很菜">我很菜&lt;/h2>
&lt;p>写 Go 的时候我是能直白地感受到自己很菜的。&lt;br>
一块是很多地方我能感知到有语法简化的可能性，&lt;br>
但我的语言表达能力还没达到优化的水瓶。&lt;br>
比如 &lt;a href="https://go.googlesource.com/proposal/+/master/design/go2draft-error-handling-overview.md">Go 2 Draft 里的 check 关键字&lt;/a>，&lt;br>
我隐约感觉好像基于 &lt;code>panic + recover&lt;/code> 也能实现类似的机制，&lt;br>
但真要写又写不出。&lt;br>
而 Python 我就感觉能完全写成 Lisp。&lt;/p>
&lt;p>另一块是库的使用，或者叫“语言生态”。&lt;br>
不论是平时用到的标准库，&lt;br>
还是后端业务要用的各类三方库，&lt;br>
或是工程化用到的单元测试、质量把控的库，&lt;br>
我都只能在用到的时候做现场调研。&lt;/p>
&lt;p>总之因为基础知识缺乏，&lt;br>
加上熟练度不够，&lt;br>
写 Go 的过程就总有一种“我好菜啊，这个都不懂”的奇妙感觉。&lt;/p>
&lt;h2 id="我喜欢-go">我喜欢 Go&lt;/h2>
&lt;p>菜并没阻止我表达喜欢 :)&lt;/p>
&lt;p>Go 身上透露出了非常老派的 KISS 原则，&lt;br>
它甚至很多时候给我的感觉是比 Python 还要简约。&lt;br>
比如最佳实践会跟你说：&lt;br>
“不要过早拆文件，&lt;br>
一个目录十个文件能解决的问题不需要分层。”&lt;/p>
&lt;p>相比 Python 而言，&lt;br>
Go 的执行速度透露着一种不讲道理的快。&lt;br>
Python 深入了解并发模型，&lt;br>
调优 CPU 跟语言参数以后的结果，&lt;br>
还是跟 Go 差了一个量级…&lt;br>
（不过开发速度上 Python 还是巨快…）&lt;/p>
&lt;p>而且，&lt;br>
Go 还有可爱的 &lt;a href="https://github.com/egonelbre/gophers">Gopher&lt;/a> 呀~&lt;/p>
&lt;p>&lt;img src="https://github.com/egonelbre/gophers/raw/master/.thumb/icon/emoji-3x.png" alt="gopher-emoji">&lt;/p>
&lt;h2 id="go-的实践">Go 的实践&lt;/h2>
&lt;p>目前我司后端的主技术栈是 Java 跟 Python，&lt;br>
我主要写的是 Python。&lt;/p>
&lt;p>以我短暂的体验而言，&lt;br>
Go 在关键的高性能服务上会有很好的表现，&lt;br>
但在新业务的原型、Web 层的多业务上，&lt;br>
Python 魔法般的开发速度还是无人能比的（叉腰）&lt;/p>
&lt;p>目前后端的各种流行框架基本都是语言无关的，&lt;br>
我们可以根据不同业务的适用场景来选择合适的技术栈。&lt;/p>
&lt;p>企业在选择技术栈中，&lt;br>
其实也会考虑其它更现实的因素，&lt;br>
比如开发人员的招聘难度，&lt;br>
代码库、技术栈的统一，&lt;br>
大型团队的解耦管理。&lt;br>
这些其实也都是非常有深度的、值得探讨的话题。&lt;/p>
&lt;p>写了一周 Go,&lt;br>
我更坚信自己的理念了：&lt;br>
“工程师是解决问题的人，&lt;br>
技术是解决问题的工具。&lt;br>
软件工程没做好说工具难用，&lt;br>
是何异于：&lt;br>
刺人而杀之曰，非我也，兵也？”&lt;/p>
&lt;h1 id="后续">后续&lt;/h1>
&lt;p>一周的体验卡有点太短了，&lt;br>
非常意犹未尽。&lt;/p>
&lt;p>后续有时间的话，&lt;br>
关于 Go 的这些话题我会继续研究：&lt;/p>
&lt;ul>
&lt;li>产线环境上的服务部署姿势。&lt;/li>
&lt;li>Go 的服务可视化（监控、日志、追踪）&lt;/li>
&lt;li>用黑魔法让语言表达力更高的基础库&lt;/li>
&lt;li>跨语言服务间的交互实践&lt;/li>
&lt;/ul>
&lt;p>欢迎交流，&lt;br>
也对文章里的不当之处作出指正批评。&lt;/p>
&lt;p>（完）&lt;/p></description></item><item><title>密度不高地生活了一下子</title><link>https://liriansu.com/posts/2019-06-11-fuzzy-days/</link><pubDate>Tue, 11 Jun 2019 22:50:03 +0000</pubDate><guid>https://liriansu.com/posts/2019-06-11-fuzzy-days/</guid><description>&lt;p>好久没记录思考了。&lt;br>
虽然陶菲格一直在催我在思想逝去前记下来，&lt;br>
但我总有种感觉：&lt;br>
最近的人生密度不是很大。&lt;/p>
&lt;p>今晚照常以社畜的身份下班回家，&lt;br>
米娅已经刷完日常准备睡觉了。&lt;br>
听着她断断续续哼着耳机里不知道什么歌的旋律，&lt;br>
好久没去唱歌的想法突然从我脑子里游了过去。&lt;/p>
&lt;p>“唉，最近又觉得人生好虚无了。”&lt;/p>
&lt;p>晚上进楼道电梯的时候，&lt;br>
有两只母蚊子跟了上来。&lt;br>
她们绕着裸露在短袖外面的手臂转了好几圈，&lt;br>
靠着敏捷高，&lt;br>
躲开了我好几下拍击。&lt;br>
于是我双手交叉，&lt;br>
假装在电梯里思考人生，&lt;br>
趁蚊子被我的冷静愣住的时候，&lt;br>
嗖一下冲出了停稳的电梯。&lt;/p>
&lt;p>现代人的确太容易陷入集体性情绪了，&lt;br>
而个人的悲叹又显得太无力。&lt;/p>
&lt;p>米娅上周收获了一个她的宝藏节目《乐队的夏天》，&lt;br>
几十只乐队的现场后劲加在一起，&lt;br>
抵得上《波西米亚狂想曲》的后劲。&lt;br>
她昨天晚上突然问我：&lt;br>
“你作为 A 站老用户，&lt;br>
有没有那种自己喜欢了很久的小众爱好，&lt;br>
后来突然火了感觉很挫败的感觉？”&lt;/p>
&lt;p>在“我不是我没有别瞎说”的第一否认力还没生效的时候，&lt;br>
我脑子里闪过了一百个单词。&lt;br>
“有，还不少。”&lt;br>
我还是这么回答了。&lt;/p>
&lt;p>在米娅下一个问题还没问出口之前，&lt;br>
我也提前给了她答案：&lt;br>
“是的，后面我就不喜欢了。”&lt;/p>
&lt;p>最近工作感觉比较无力的一点是，&lt;br>
我真切地感受到了“技术不是瓶颈”在工作中的存在，&lt;br>
有不少同事也因为这点而另谋高就了。&lt;br>
虽然说新陈代谢是组织保持活力的必要成分，&lt;br>
但“生命很大世界更大”这句话也重复的有点疲惫。&lt;/p></description></item><item><title>谈谈《谈 996》</title><link>https://liriansu.com/posts/2019-04-14-meta-996/</link><pubDate>Sun, 14 Apr 2019 15:16:24 +0000</pubDate><guid>https://liriansu.com/posts/2019-04-14-meta-996/</guid><description>&lt;p>很多人会喜欢 Lisp 里的宏 (Macro)。&lt;br>
语言里的宏提供了一种元编程 (Meta-Progamming) 的能力。&lt;br>
假如你用过魔兽世界里的宏，&lt;br>
你也可以想象这里的“元游戏”是什么意思：&lt;br>
它注重的不是游戏本身，&lt;br>
而是对游戏求导所得出的“游戏的本质”。&lt;/p>
&lt;p>今天这篇《谈谈&amp;lt;谈 996&amp;gt;》其实是我想写的一篇方法论的文章，&lt;br>
或者我更喜欢称之为: Meta 文章。&lt;/p>
&lt;h2 id="历史的进程">历史的进程&lt;/h2>
&lt;p>最近因为 &lt;a href="https://github.com/996icu/996.ICU">github/996icu&lt;/a> 项目引出了一系列的事件，&lt;br>
在我看来基本上是像人血馒头一样是可以吃的津津有味的。&lt;/p>
&lt;p>一次大型的社会性事件中，&lt;br>
最好玩的是看人类社会的不同角色对事件本身发表的看法。&lt;br>
而且基本上“屁股决定脑袋”或者说“你会成为你喜欢的人”这种道理都是不变的。&lt;/p>
&lt;p>每当这时候我就会想起筱敏写的那句话：&lt;/p>
&lt;blockquote>
&lt;p>1789年7月14日巴黎人民攻克巴士底狱的当夜，&lt;br>
当路易十六听闻消息时惊慌地问：&lt;br>
“这是一场叛乱吗？”&lt;/p>
&lt;p>他的廷利昂古尔公爵当即回答道：&lt;/p>
&lt;p>“不，陛下，这是一场革命。”&lt;/p>
&lt;/blockquote>
&lt;p>社会是由人类组成的，&lt;br>
所以这个整体有的时候会表现出奇特的单人所不具有的特性，&lt;br>
进而进行组织性的进化与修复。&lt;br>
最终回过头看，&lt;br>
不禁就会发出江学长那样的感慨：&lt;br>
个人的奋斗是很重要，&lt;br>
但也要兼顾历史的进程啊。&lt;/p>
&lt;h2 id="言论管理">言论管理&lt;/h2>
&lt;p>我其实蛮喜欢看一些八卦文章的。&lt;br>
（比如推荐一个博主叫“萝严肃”，&lt;br>
他写的长文都会查不少背景知识）&lt;br>
石原里美在文章里经常被表扬“表情管理”做得很好。&lt;br>
同样地，“言论管理”也是资本家会被重点关注的一处特质。&lt;/p>
&lt;p>带着这点去看各个资本家的行动，&lt;br>
就很有意思了。&lt;/p>
&lt;p>有一部分资本家的言论管理就是少说话，&lt;br>
外界对他们的评价就是“比较技术”。&lt;br>
而很大一部分资本家的发言就很精妙，&lt;br>
他们会为了心中更美好的世界而发言。&lt;/p>
&lt;p>但可惜的是，&lt;br>
人类的悲喜并不相通。&lt;/p>
&lt;p>涉及公益、教育这种大家都认可的话题还好，&lt;br>
但工作这个话题本身就涉及社会性分工，&lt;br>
不同的人会因为不同的事情有不同的感受。&lt;br>
假如资本家在“996工作制度”这个话题上直白的表达“我非常享受工作本身”及其类似的观点，&lt;br>
很自然地会收到无区别的批判，&lt;br>
因为这个时候他的原罪是他的身份。&lt;/p>
&lt;p>当一个人的符号属性重于社会属性时，&lt;br>
他发表的所有言论都应当有明确的导向性目的。&lt;br>
这就是“言论管理”。&lt;/p>
&lt;h2 id="自我认知">自我认知&lt;/h2>
&lt;p>以前上学考试结束以后，&lt;br>
总有人会哀嚎“哎呀考试考砸了完了完了。”&lt;br>
结果最后他成绩非常好。&lt;br>
虽然也&lt;a href="https://www.zhihu.com/question/285977219/answer/574675736">有个说法叫“本质是因为怕被认为无能”&lt;/a>，&lt;br>
但不论如何，&lt;br>
假如你的行为轻信了他人的言论，&lt;br>
就很容易被误导进坑里。&lt;br>
最终导致“其它人都是嘴上喊着成绩差，结果你是真的成绩差。”&lt;/p>
&lt;p>就跟上面一节说的一样，&lt;br>
现在的信息流（包括你正在看到的这篇文章）都充斥着言论管理。&lt;br>
一个信息是否有价值影响个人的行动，&lt;br>
是需要被识别、筛选并取其精华的。&lt;/p>
&lt;p>接下来的这段时间我们会看到更多的关于 996 的言论，&lt;br>
有些会刺耳，有些会很解气。&lt;br>
但是哪些里面蕴含了“建设性意见”，&lt;br>
就需要我们睁大眼睛去辨别了。&lt;/p>
&lt;p>当他们在谈论 996 的时候，&lt;br>
我在思考的是这个谈论本身。&lt;/p>
&lt;p>（完）&lt;/p></description></item><item><title>软件工程实践之 django/python</title><link>https://liriansu.com/posts/2019-04-10-software-engineering-django/</link><pubDate>Wed, 10 Apr 2019 22:09:55 +0000</pubDate><guid>https://liriansu.com/posts/2019-04-10-software-engineering-django/</guid><description>&lt;p>软件工程实践系列文章，&lt;br>
会着重讲述实际的工程项目中是如何协作开发软件的。&lt;br>
本文主要介绍了 django/python 系列的工具链。&lt;/p>
&lt;h2 id="outline">outline&lt;/h2>
&lt;p>本文包括以下内容：&lt;/p>
&lt;ul>
&lt;li>outline&lt;/li>
&lt;li>django: 一个搭建后端服务的工具箱。
&lt;ul>
&lt;li>framework: django vs flask/tornado/spring/laravel&lt;/li>
&lt;li>restful: django/restframework/swagger&lt;/li>
&lt;li>worker: django/uwsgi/gevent/celery/channels&lt;/li>
&lt;li>database: django/mysql/sqlite/migrations&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>python: 一门依赖开发者的语言。
&lt;ul>
&lt;li>developing: gitlab/pipenv/docker&lt;/li>
&lt;li>quality: unittest/pytest/flake8/pylint/yapf&lt;/li>
&lt;li>deploy: fabric/aws/nginx&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>conclusion&lt;/li>
&lt;/ul>
&lt;h2 id="django">django&lt;/h2>
&lt;p>&lt;a href="https://github.com/django/django">django&lt;/a> 是一个大名鼎鼎的后端开发框架，&lt;br>
它自己的口号是 &lt;code>the web framework for perfectionists with deadlines.&lt;/code>&lt;/p>
&lt;p>在我用 django 开发的这几年来，&lt;br>
我觉得它是一个逻辑上自洽，&lt;br>
并且为了逻辑自洽甚至舍弃了一部分功能的框架。&lt;/p>
&lt;h3 id="framework">framework&lt;/h3>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/se/django_vs.png" alt="django-vs">&lt;/p>
&lt;blockquote>
&lt;p>search google for &lt;code>django vs&lt;/code>&lt;/p>
&lt;/blockquote>
&lt;p>讲框架避免不了的是同行竞争，&lt;br>
比如到网上搜一下 &lt;code>django vs ...&lt;/code> 就有一大堆搜索结果。&lt;br>
其实框架之间的比较是很难的，&lt;br>
每种框架都有自己适合的业务场景。&lt;/p>
&lt;p>&lt;img src="https://imgs.xkcd.com/comics/standards.png" alt="xkcd-927">&lt;/p>
&lt;blockquote>
&lt;p>xkcd-927: standards&lt;/p>
&lt;/blockquote>
&lt;p>django 最大的特点就是 &lt;strong>&lt;code>Model&lt;/code> 是一等公民&lt;/strong>。&lt;br>
在 django 中的所有的操作都会跟 &lt;code>Model&lt;/code> 相关，&lt;br>
比如它提供了自带的强大 ORM,&lt;br>
也有一系列挂载在 &lt;code>Model&lt;/code> 上的校验等。&lt;/p>
&lt;p>个人感觉在项目的业务需求达到了某种程度的多样化以后，&lt;br>
基础框架用什么并不重要，&lt;br>
适合开发团队才是最重要的。&lt;/p>
&lt;p>鉴于本文的标题是 django,&lt;br>
所以我们只讲 django。&lt;/p>
&lt;h3 id="restful">restful&lt;/h3>
&lt;p>我参与的项目基本都是前后端分离的项目，&lt;br>
后端提供的接口都是用 &lt;code>djangorestframework&lt;/code> 写的。&lt;br>
虽然像 &lt;code>HATEOAS&lt;/code> 这样的高级属性还没用到，&lt;br>
但接口是遵循 &lt;code>restful&lt;/code> 风格的，&lt;br>
比如像用 http method+status 表达语义，&lt;br>
对资源的定义等。&lt;/p>
&lt;p>接口文档我们选用了 &lt;code>drf-yasg&lt;/code> 来生成符合 &lt;code>swagger&lt;/code> 规范的文档。&lt;br>
曾经我们也试过 &lt;code>django-rest-swagger&lt;/code> 这个库，不过……&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/se/django_rest_swagger.png" alt="django-rest-swagger-readme">&lt;/p>
&lt;blockquote>
&lt;p>another help-wanted project&amp;hellip;&lt;/p>
&lt;/blockquote>
&lt;p>使用现成框架的好处是语言表达力极强，&lt;br>
最终我们实现一个“解密微信提供的手机号”接口的&lt;del>伪&lt;/del>业务代码大概如下：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python3" data-lang="python3">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">WeChatVS&lt;/span>(BaseVS):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">@with_response&lt;/span>(empty&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#66d9ef">True&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">@with_request&lt;/span>(DecryptionSiri)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">@action&lt;/span>(methods&lt;span style="color:#f92672">=&lt;/span>[&lt;span style="color:#e6db74">&amp;#39;post&amp;#39;&lt;/span>], detail&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#66d9ef">True&lt;/span>, url_path&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#39;decryption/phone&amp;#39;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">def&lt;/span> &lt;span style="color:#a6e22e">decrypt_wechat_phone&lt;/span>(self, request, uid):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;&amp;#34;&amp;#34; 解密并修改用户的手机号
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> - https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/getPhoneNumber.html
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> &amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> self&lt;span style="color:#f92672">.&lt;/span>check_account_request(request, uid)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> openid, encrypted_data, initial_vector &lt;span style="color:#f92672">=&lt;/span> self&lt;span style="color:#f92672">.&lt;/span>request_data
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> phone &lt;span style="color:#f92672">=&lt;/span> WeChatManager(openid)&lt;span style="color:#f92672">.&lt;/span>decrypt_safely(encrypted_data, initial_vector)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># TODO(ldsink): 找产品问一下外国手机号怎么处理&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> hutils&lt;span style="color:#f92672">.&lt;/span>check_error(&lt;span style="color:#f92672">not&lt;/span> hutils&lt;span style="color:#f92672">.&lt;/span>is_chinese_phone(phone), &lt;span style="color:#e6db74">&amp;#39;o(╥﹏╥)o 目前只支持国内的手机号&amp;#39;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> self&lt;span style="color:#f92672">.&lt;/span>account&lt;span style="color:#f92672">.&lt;/span>modify(phone&lt;span style="color:#f92672">=&lt;/span>phone)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> self&lt;span style="color:#f92672">.&lt;/span>empty_response()
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>这样的十行代码包含了文档、外链、错误检查、写库，&lt;br>
让写业务代码本身也有种施法的快感。&lt;/p>
&lt;h3 id="worker">worker&lt;/h3>
&lt;p>最开始服务器上我们跑的是 django+uwsgi 的普通模式，&lt;br>
用 &lt;code>wrk&lt;/code> 去压一个小接口，&lt;br>
测试环境 4G 内存的机器 QPS 只有 40 左右。&lt;br>
后来加上了 gevent, monkey patch 一下，改到了协程模式&lt;br>
同样的接口同样的机器 QPS 上升到了大概 600。&lt;br>
调优一下效果会更好。&lt;br>
（需要更高性能的业务可能就根本不用 python 了 Orz）&lt;/p>
&lt;p>celery 充当了我们的定时任务+异步任务框架，&lt;br>
我们也拆分了 读写密集型/计算密集型 的两类队列以处理不同的事情。&lt;br>
对于业务中的即时通知部分，&lt;br>
我们用了 channels 库来实现 web socket 的功能。&lt;/p>
&lt;p>对于这些大型的框架，其实我们选择余地并不大。&lt;br>
比如虽然 django 开发者有说在 3.0 会考虑大幅度重写异步调用，&lt;br>
channels 项目会逐渐弃坑……&lt;br>
但毕竟 &lt;code>perfectionists with deadlines.&lt;/code>&lt;br>
不能说人家功能不完美，我们就不干活了嘛&amp;hellip;&lt;/p>
&lt;h3 id="database">database&lt;/h3>
&lt;p>我们用到的数据库也是 mysql/mongo/redis 这御三家，&lt;br>
所以就是每个选取对应的连接库就是了。&lt;/p>
&lt;p>值得一提的是在单元测试里，&lt;br>
我们用 &lt;code>sqlite(in-memory)&lt;/code> 替代了 mysql 数据库。&lt;br>
sqlite 里缺失了 mysql 的函数的问题，&lt;br>
也可以用 &lt;code>connection.create_function&lt;/code> 的方法来规避掉。&lt;/p>
&lt;p>在上线时，还有一个很好玩的东西是 &lt;code>database migration&lt;/code>，&lt;br>
这个基本上跟“给行驶中的火车换轮子”一样刺激。&lt;br>
详细的细节以后会专门开篇文章讲一下（挖坑预警），&lt;br>
从结果上来说我们做到的是&lt;strong>利用 Django Migration 做到数据库结构变更全兼容&lt;/strong>。&lt;/p>
&lt;h2 id="python">python&lt;/h2>
&lt;p>上面一小节中，我们基本上是走马观花地过完了 django 相关的三方库。&lt;br>
到了真正用 python 开发的时候，&lt;br>
我们遇到的更多的是框架之外的奇遇。&lt;/p>
&lt;p>每门语言都有自己的味道。&lt;br>
我很喜欢 python 的一点是：&lt;br>
这门语言有着非常强的表达张力。&lt;br>
就像上面举的那段典型业务代码一样，&lt;br>
在实际的开发中，&lt;br>
python 是能完美表达开发者心中所想的。&lt;/p>
&lt;p>但假如开发者自己都没想清楚自己要写啥，&lt;br>
这就有点不妙了。&lt;/p>
&lt;p>所以我们有一系列的开发工具来保持清醒。&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/meme/stay_awake.jpg" alt="stay-awake">&lt;/p>
&lt;blockquote>
&lt;p>强制清醒.jpg&lt;/p>
&lt;/blockquote>
&lt;h3 id="quality">quality&lt;/h3>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/se/hax_principles.png" alt="hax-principles">&lt;/p>
&lt;blockquote>
&lt;p>&lt;a href="https://www.zhihu.com/question/300762444/answer/529335326">贺师俊在《如何引导程序员新人按正确的流程开发？》下面一段我很欣赏的回答&lt;/a>&lt;/p>
&lt;/blockquote>
&lt;p>除了开发流程上的类似要求，&lt;br>
我们对代码本身也执行了类似的严格要求：&lt;/p>
&lt;ul>
&lt;li>单元测试覆盖率必须得在 96% 以上 (unittest/pytest/coverage)&lt;/li>
&lt;li>代码的逗号、换行、引号的使用都必须符合规范 (flake8)&lt;/li>
&lt;li>代码强制经过 linter 检验，禁止多种黑魔法 (pylint)
&lt;ul>
&lt;li>代码的各个模块之间必须符合特定的拓扑顺序 (pylint-topology)&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>代码风格（如字典的复制、长列表、换行与空行）强制统一 (yapf)&lt;/li>
&lt;/ul>
&lt;p>其中&lt;strong>单元测试覆盖率必须得在 96% 以上&lt;/strong>值得被单独拎出来表扬一下。&lt;/p>
&lt;p>业务代码的 96% 的覆盖率是什么概念呢？&lt;br>
这意味着代码里只有那种真正的边缘情况是没被测到的。&lt;br>
（比如为了兼容微信 SYSTEM ERROR -1000 写的代码）&lt;/p>
&lt;p>为了达到了这么高的覆盖率，&lt;br>
我们也专门强化过单元测试的表达力，&lt;br>
比如一段测试创建用户接口的&lt;del>伪&lt;/del>代码可能如下：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python3" data-lang="python3">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">def&lt;/span> &lt;span style="color:#a6e22e">test_create_account&lt;/span>(self):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;&amp;#34;&amp;#34; 测试创建用户 &amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">with&lt;/span> self&lt;span style="color:#f92672">.&lt;/span>assert_model_increase(Account, delta&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span>):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> response &lt;span style="color:#f92672">=&lt;/span> self&lt;span style="color:#f92672">.&lt;/span>client&lt;span style="color:#f92672">.&lt;/span>post(self&lt;span style="color:#f92672">.&lt;/span>account_url(), {&lt;span style="color:#e6db74">&amp;#39;username&amp;#39;&lt;/span>: &lt;span style="color:#e6db74">&amp;#39;hulucc&amp;#39;&lt;/span>})
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> self&lt;span style="color:#f92672">.&lt;/span>ok(response, username&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#39;hulucc&amp;#39;&lt;/span>, tags__length&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#ae81ff">0&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">with&lt;/span> self&lt;span style="color:#f92672">.&lt;/span>assert_model_increase(Account, delta&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#ae81ff">0&lt;/span>):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> response &lt;span style="color:#f92672">=&lt;/span> self&lt;span style="color:#f92672">.&lt;/span>client&lt;span style="color:#f92672">.&lt;/span>post(self&lt;span style="color:#f92672">.&lt;/span>account_url(), {&lt;span style="color:#e6db74">&amp;#39;username&amp;#39;&lt;/span>: &lt;span style="color:#e6db74">&amp;#39;hulucc&amp;#39;&lt;/span>})
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> self&lt;span style="color:#f92672">.&lt;/span>bad_request(response, message&lt;span style="color:#f92672">=&lt;/span>AccountErrors&lt;span style="color:#f92672">.&lt;/span>DUPLICATE&lt;span style="color:#f92672">.&lt;/span>value)
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;img src="https://liriansu.com/assets/pics/se/gitlab_ci_sample.png" alt="gitlab-ci-sample">&lt;/p>
&lt;blockquote>
&lt;p>所有这些限制都在 CI 中检查了，不通过的话是不让 merge into master 的&lt;/p>
&lt;/blockquote>
&lt;h3 id="developing">developing&lt;/h3>
&lt;p>我们的合作方式是用 gitlab 作为代码托管平台。&lt;br>
为了团队的开发效率，&lt;br>
我们还自己写了个小机器人来处理各种如分支合并、有效性检查、贴标签之类的杂活。&lt;/p>
&lt;p>gitlab ci 不仅被用来做开发阶段的质量保证，&lt;br>
最终我们的构建上线也走的是 gitlab ci &lt;a href="https://liriansu.com/python-deployment-automation-one-sample">(以前我们用的是 jenkins)&lt;/a>&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/se/gitlab_pr_sample.png" alt="gitlab-pr-sample">&lt;/p>
&lt;p>对于 python 的依赖管理，&lt;br>
我们用的是 pipenv,&lt;br>
&lt;code>pip list&lt;/code> 一下大概有了 181 个库。&lt;br>
(关于 pipenv 的介绍可以参见&lt;a href="https://ldsink.com/archives/the-future-of-python-dependency-management/">《Python 依赖管理的未来 - ldsink》&lt;/a>)&lt;/p>
&lt;p>也因为我们线上用的是 docker,&lt;br>
所以不想装依赖的也可以直接用 docker 的环境开发。&lt;/p>
&lt;h3 id="deploy">deploy&lt;/h3>
&lt;p>部署这一块我们暂时还没上 k8s,&lt;br>
目前走的是 gitlab ci 中调用 fabric + aws(boto3) 直接操作裸 docker 的方式。&lt;br>
aws 的负载均衡器提供了基础的流量切换服务，&lt;br>
我们也是借用了现成的服务达到灰度发布、无缝发布的效果。&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/se/gitlab_ci_deploy.png" alt="gitlab-ci-deploy">&lt;/p>
&lt;blockquote>
&lt;p>用 GitLab CI 部署的步骤图&lt;/p>
&lt;/blockquote>
&lt;h2 id="conclusion">conclusion&lt;/h2>
&lt;p>至此，本文介绍了一遍我们在 Python 业务后端的实践。&lt;/p>
&lt;p>对于高可用、容器化、数据库等屠龙技，&lt;br>
业界其实有非常多的探讨，&lt;br>
大家也很容易找到现成的文章。&lt;/p>
&lt;p>但具体到业务后端的工程化实践，&lt;br>
能借鉴的大型项目并不多。&lt;br>
我读过的也只有&lt;a href="https://github.com/reddit-archive/reddit">两年前的 reddit 代码&lt;/a>跟 &lt;a href="https://github.com/getsentry/sentry">sentry&lt;/a> 这个 django 项目符合要求了。&lt;/p>
&lt;p>总的来说，我们用 django 在开发中遵循的约定跟共识有这些：&lt;/p>
&lt;ul>
&lt;li>做正确的事情。
&lt;ul>
&lt;li>比如我们在讨论过后，一致觉得“线性的 Commit 历史是最干净的”，从当天开始我们的 Commit 历史就是干净的线性历史了。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>自动化一切能自动化的工作。
&lt;ul>
&lt;li>用 swagger 自动化生成文档，用 gitlab ci 自动化质量保证。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>尽可能使用最新的特性，让代码时刻保持崭新。
&lt;ul>
&lt;li>我们每隔一阵就会把所有依赖升到最新的稳定版。&lt;/li>
&lt;li>不过因为这个我们也踩了不少坑。&lt;/li>
&lt;li>不少时候三方库会引入全新的用法，动辄改动 100+ 的文件数。&lt;/li>
&lt;li>这个时候就到了 Vim Macro 展现魔法的时候了。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;p>假如你也在用 Django 作为后端框架的话，&lt;br>
不防尝试一下上面提到的各类工具，&lt;br>
绝对物超所值噢 :)&lt;/p></description></item><item><title>《流浪地球》电影观感</title><link>https://liriansu.com/posts/2019-02-06-wandering-earth/</link><pubDate>Wed, 06 Feb 2019 13:45:34 +0000</pubDate><guid>https://liriansu.com/posts/2019-02-06-wandering-earth/</guid><description>&lt;p>假如你想跟家人在春节去看场电影的话，&lt;br>
非常推荐去看看《流浪地球》。&lt;br>
（本文可能只有轻微剧透。）&lt;/p>
&lt;h2 id="电影">电影&lt;/h2>
&lt;p>电影本身我认为是一个非常成功的类型片，&lt;br>
加上了国产滤镜跟科幻滤镜以后，&lt;br>
口碑在春节档电影里排第一也是可以想象的。&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/wechat/wandering_earth.jpg" alt="comment">&lt;/p>
&lt;p>电影剧情的底子其实跟《钢铁侠》《超人归来》之类的超级英雄电影本质上是一样的：&lt;br>
主角出生 - 锻炼自己 - 遇到低谷 - 组成团队 - 创造奇迹 - 拯救世界。&lt;br>
这样的类型片近十年已经有不少了，&lt;br>
要想在他们中间脱颖而出，&lt;br>
需要能把故事讲好。&lt;/p>
&lt;p>大刘（刘慈欣）就在这里发挥了非常重要的作用了。（我脑补的）&lt;/p>
&lt;p>虽然电影故事是在原作小说一段子情节之上，&lt;br>
原创发挥出的独立故事。&lt;br>
但电影开场的字母上写了“全程监制：刘慈欣”几个字，&lt;br>
整个剧本也透出了一股浓浓的“刘氏直男科幻”的味道。&lt;/p>
&lt;p>无论是最开始的“中国味道赛博朋克”的都市背景，&lt;br>
还是中间提到的“饱和救援”方法论，&lt;br>
甚至是贯穿电影的转折，&lt;br>
都用厚重的真实感冲淡了一部分超级英雄类型片本身的魔幻感。&lt;/p>
&lt;p>进而这又引出了这个电影非常“共产主义”的一部分：&lt;br>
电影里的超级英雄不是个体，&lt;br>
而是人类这个集体。&lt;/p>
&lt;p>之前看过一个说法，&lt;br>
说外国人看三国看到的是那个年代里英雄闪烁，&lt;br>
中国人看三国看到的是刘皇叔山穷水尽也要带上人民。&lt;br>
《流浪地球》也是一样，&lt;br>
虽然电影的镜头跟着主角一行人，&lt;br>
但是我们可以清晰地感知到：&lt;br>
是人类本身，在创造人类自身的历史。&lt;/p>
&lt;p>除了原作者监制、共产主义精神这两点，&lt;br>
《流浪地球》电影里还有一点能让我露出“老母亲式”微笑的：&lt;br>
故事讲得圆。&lt;/p>
&lt;p>整个电影埋了不少伏笔，&lt;br>
虽然有些可能让观众能猜出后面剧情的进程，&lt;br>
但是电影并没有给人一种“穿山甲最后怎么了？”的失落感，&lt;br>
基本埋的伏笔都用上了，&lt;br>
而且还疑似致敬了大刘另一本小说的剧情，&lt;br>
提到了一个彩蛋。&lt;/p>
&lt;p>总的来说，电影本身的原作者监制、共产主义精神、故事讲得圆，&lt;br>
这三点让它成为了一部不错的类型片。&lt;br>
缺点的话其实要讲也有不少，&lt;br>
但在我的滤镜加持下就不提了。&lt;br>
额外提一句，假如是受“战狼PTSD”的影响有点怕吴京的话，&lt;br>
这部片里吴京武戏不多，&lt;br>
可以安心观影。&lt;/p>
&lt;h2 id="感受">感受&lt;/h2>
&lt;p>先打个岔讲个好玩的&lt;br>
我是跟家人一起去看的电影，&lt;br>
去的是一家“4D电影院”。&lt;br>
我们都知道3D是指长宽高，&lt;br>
那多出来的第4D在哪呢？&lt;/p>
&lt;p>电影里冰天雪地吹大风的时候，&lt;br>
电影院的扶手会朝你吹风；&lt;br>
电影里主角开车颠簸的时候，&lt;br>
电影院的椅子会疯狂颠你；&lt;br>
电影里东西砸下来的时候，&lt;br>
电影院的椅背也会猛击你背……&lt;br>
感觉像是去了一场欢乐谷…&lt;/p>
&lt;blockquote>
&lt;p>北京市第三区交通委提醒您：&lt;br>
道路千万条，安全第一条。&lt;br>
行车不规范，亲人两行泪。&lt;/p>
&lt;/blockquote>
&lt;p>回到正题。&lt;/p>
&lt;p>在我眼里这电影还有一点好，&lt;br>
就是它宣扬大爱的方式非常地中国化。&lt;/p>
&lt;p>比如西方人拍的超级英雄电影，&lt;br>
宣扬的大爱其实是“爱能解决一切”，&lt;br>
“任何人通过努力都能做成任何看起来不可能的事”。&lt;br>
郭帆拍的是个啥子捏：&lt;br>
“中国人的爱就是回家过年。”&lt;br>
很难想象外国人会拍出“回家过年吧”的桥段来…&lt;br>
（当时电影院里也给我看的一愣一愣的）&lt;/p>
&lt;p>最后电影结束以后（没有菜单），&lt;br>
字幕放了两首歌，&lt;br>
一首是刘欢的《带着地球去流浪》，&lt;br>
一首是逃跑计划的《夜空中最亮的星》。&lt;/p>
&lt;p>看着结尾电影字幕里飘过的中英文制作组人员，&lt;br>
我有点出神。&lt;/p>
&lt;p>之前看惊奇/漫威的电影，&lt;br>
Mia 跟我都会等到字幕结束。&lt;br>
然后一起指着“哇上面还有 HR 的名字”，&lt;br>
“IT 的名字也能上诶”。&lt;/p>
&lt;p>那个时候我就在想：&lt;br>
外国能批量制造这么多的类型片，&lt;br>
是因为他们背后有强大的电影产业链在支持；&lt;br>
什么时候我们中国也有先行者拍点片，&lt;br>
然后带动一下特效、道具、剧本、投资的相关发展，&lt;br>
即使拍的稍微烂点，&lt;br>
我也愿意当个精神股东支持一下啊。&lt;br>
&lt;del>毕竟我真的很想看以北上广深为背景的超级英雄电影&lt;/del>&lt;/p>
&lt;p>希望“中国科幻电影元年”的说法能在今年敲定下来。&lt;br>
再许个愿吧，&lt;br>
希望大刘的《乡村教师》《球状闪电》也能被拍成电影，&lt;br>
等到相关产业链成熟了，&lt;br>
《三体》三部曲就可以拍它个七八部，&lt;br>
最终组成&lt;del>吴京&lt;/del>大刘电影宇宙！&lt;/p>
&lt;h2 id="更多">更多&lt;/h2>
&lt;p>观影之外的还有几个很好玩的事情。&lt;/p>
&lt;p>一个是去微博、豆瓣、知乎上看看《流浪地球》的口碑/票房发展。&lt;br>
毕竟从票房排片上来说，&lt;br>
小破球早期的目标观众还是泛科幻受众，&lt;br>
但口碑跟中国味是有望给电影带来不少自来水的。&lt;br>
品一品大众舆论也是很好玩的。&lt;/p>
&lt;p>二是电影目测能带动大刘的相关小说销量。&lt;br>
虽然人类在他笔下经常被揉来揉去，&lt;br>
但是他特有的科学与人文结合的方式，&lt;br>
经常会给人一种“科学宗教化”的观感。&lt;br>
大家有兴趣的话也可以去读读他在《三体》之外的一些小说。&lt;br>
（比如《球状闪电》）&lt;/p>
&lt;p>三是过节了，家人在一起要注意安全。&lt;/p>
&lt;p>只有中国人拍的电影，&lt;br>
里面才会加入这样的台词：&lt;/p>
&lt;blockquote>
&lt;p>北京市第三区交通委提醒您：&lt;br>
道路千万条，安全第一条。&lt;br>
行车不规范，亲人两行泪。&lt;/p>
&lt;/blockquote>
&lt;p>（完）&lt;/p></description></item><item><title>如何构建工程师团队</title><link>https://liriansu.com/posts/2019-01-28-developer-team/</link><pubDate>Mon, 28 Jan 2019 23:46:45 +0000</pubDate><guid>https://liriansu.com/posts/2019-01-28-developer-team/</guid><description>&lt;p>“工程师团队”这个话题我一直非常好奇，&lt;br>
我经常会问我的朋友们：&lt;br>
“你们公司这个是怎么样的？”&lt;br>
这篇文章讲的就是我自己对于这个话题的思考。&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/weibo/as_leader.png" alt="pic">&lt;/p>
&lt;h2 id="引子">引子&lt;/h2>
&lt;p>上一篇&lt;a href="https://liriansu.com/about-active-thinking">《积极面思考》&lt;/a>中提到了，&lt;br>
最近写的东西都更偏向于“道”一些。&lt;br>
本文虽然标题是叫“如何构建工程师团队”，&lt;br>
但其实讲的东西基本都是主观的想法，&lt;br>
或者不考虑标题长度的话，&lt;br>
更恰当的标题说不定是：&lt;br>
《我们仍未知道那天苏子岳脑海中幻想的是一个什么样的工程师团队》。&lt;/p>
&lt;p>主要涉及的观点可能包括如下：&lt;/p>
&lt;ul>
&lt;li>自己
&lt;ul>
&lt;li>像游戏主程序员一样工作&lt;/li>
&lt;li>信赖，往往会创造出美好的境界&lt;/li>
&lt;li>永远抱着初心者的空杯心态&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>团队
&lt;ul>
&lt;li>四世三公的三公指的是公平、公正与公开&lt;/li>
&lt;li>用工具践行自动化&lt;/li>
&lt;li>我爸爸是刘备：放权&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>文化
&lt;ul>
&lt;li>&lt;a href="https://liriansu.com/pareto-rule-of-programmers">《程序员的二八定律》&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://liriansu.com/about-active-thinking">《积极面思考》&lt;/a>&lt;/li>
&lt;li>在种田与爆兵中寻找平衡&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>其它的&lt;del>标题党&lt;/del>话题
&lt;ul>
&lt;li>真的是写 PPT 的不如讲 PPT 的，讲 PPT 的不如听 PPT 的吗？&lt;/li>
&lt;li>早上九点上班，晚上九点下班，一周上六天班，好吗？&lt;/li>
&lt;li>&lt;a href="https://liriansu.com/this-is-why-i-dont-give-you-a-job-zh-cn">《为什么我不招你当我的员工》&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://liriansu.com/is-it-possible-to-be-rich-easily-by-programming">《搞 IT 的培训三个月就月入上万？》&lt;/a>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;p>本来这里想用单个词语来概括标题的（就像我以前的说明文那样），&lt;br>
但是想想，危言耸听胡言乱语好像也更加 Drama 一些。&lt;br>
那我们就篡改一下&lt;a href="https://baike.baidu.com/item/%E5%86%99%E7%BB%99%E6%9C%AA%E6%9D%A5%E7%9A%84%E4%BD%A0/20830750">张梅的《写给未来的你》&lt;/a>来引出正文吧：&lt;/p>
&lt;blockquote>
&lt;p>要学会欣赏真，&lt;br>
要在重重面具下看到真。&lt;/p>
&lt;p>世上的圆滑标准很多，&lt;br>
但出类拔萃却极少。&lt;br>
而往往出类拔萃又隐藏在卑琐狂荡之下。&lt;/p>
&lt;/blockquote>
&lt;h2 id="自己">自己&lt;/h2>
&lt;p>不论是构建团队，&lt;br>
还是追求事业，&lt;br>
人总是要先做自己，&lt;br>
以前的人管这叫“修身”，&lt;br>
外国也有部电影《修身客的救赎》就是讲这个的。&lt;/p>
&lt;h3 id="定位">定位&lt;/h3>
&lt;blockquote>
&lt;p>像游戏主程序员一样工作&lt;/p>
&lt;/blockquote>
&lt;p>假如你在一个十人左右的技术团队当领导者，&lt;br>
你希望自己是一个什么样的定位呢？&lt;br>
我会希望我是一个&lt;strong>游戏主程序员&lt;/strong>一样。&lt;br>
我从大学就有这个想法了。&lt;br>
（这句话的目标是澄清我没想蹭螃蟹科技的热点）&lt;/p>
&lt;p>游戏的主程序员要做什么呢？&lt;br>
呃，其实我不知道。&lt;br>
不过有知乎上的顾煜在&lt;a href="https://zhuanlan.zhihu.com/p/20232566">《What makes a good lead programmer》&lt;/a>里说得好：&lt;/p>
&lt;blockquote>
&lt;p>主程序员最常见的相关素质包括：&lt;br>
专业能力过硬、沟通效果良好、管理效率高、擅长目标分解。&lt;/p>
&lt;/blockquote>
&lt;p>主程序员也是从小程序员一路 level up 上来的，&lt;br>
他得解决让各利益相关方达成共识，&lt;br>
让大家在同心追求目标的路上噪音尽可能小。&lt;br>
只要有需要的话，主程序员还可以是所有人的兜底方案，&lt;br>
团队的锅第一个会落在他的头上，&lt;br>
难调的 Bug 最终也会落在他的头上。&lt;br>
能力越大，责任越大，讲的也是这个道理。&lt;/p>
&lt;p>这样做的话，&lt;br>
业务上能不受阻碍地去推进，&lt;br>
技术上没有后顾之忧。&lt;br>
唯一算得上缺点的，&lt;br>
大概是成为主程序员不仅需要付出努力，&lt;br>
也得时刻警醒自己多加思考吧。&lt;/p>
&lt;blockquote>
&lt;p>黄色的树林前有两条路，&lt;br>
很遗憾不能我全都要。&lt;br>
我选择了行人稀少的那一条，&lt;br>
它改变了我的一生。&lt;/p>
&lt;/blockquote>
&lt;h3 id="方式">方式&lt;/h3>
&lt;blockquote>
&lt;p>信赖，往往会创造出美好的境界&lt;/p>
&lt;/blockquote>
&lt;p>我其实一直很关注亚文化圈子。&lt;br>
（这个话题也是我一直想写篇文章聊一聊的）&lt;br>
假如说人跟组织是社会的细胞跟器官，&lt;br>
那么亚文化就像是社会的脉搏一样：&lt;br>
时刻变化，又无比精确地反映着社会的心跳频率。&lt;/p>
&lt;p>如今的亚文化中，&lt;br>
“霸权”大部分情况处在负面的语境中，&lt;br>
而“丧”大部分的语境都承担着正向的情绪宣泄。&lt;br>
随着语言跟文化的解构，&lt;br>
越来越多的人会在跟他人相处中保持安全距离，&lt;br>
不轻易信任别人，也不竭力付出自己。&lt;/p>
&lt;p>听着很有种“囚徒困境”的感觉对吧。&lt;br>
在&lt;a href="https://daily.zhihu.com/story/9362305">“多次重复的囚徒困境”变种实验&lt;/a>中，&lt;br>
最佳策略非常简单：&lt;br>
“一开始默认信任，之后一报还一报。”&lt;/p>
&lt;p>就像超级英雄电影里演绎的一样，&lt;br>
一个团队假如大家单打独斗就很容易被逐个击破。&lt;br>
能获得最终胜利的方法，&lt;br>
都是大家相互信任，然后用 &amp;ldquo;Watch My Back&amp;rdquo; 式的宣言来达成目标。&lt;/p>
&lt;p>从自己信赖别人开始，&lt;br>
往往就能创造出美好的团队信任感。&lt;/p>
&lt;h3 id="心态">心态&lt;/h3>
&lt;blockquote>
&lt;p>永远抱着初心者的空杯心态&lt;/p>
&lt;/blockquote>
&lt;p>最开始钦定“主程序员”的原因，&lt;br>
往往是这货写代码又快又狠，&lt;br>
兄弟们都服他，&lt;br>
于是组织上一研究决定，&lt;br>
他就多了一个“带领大家一起冲”的任务了。&lt;/p>
&lt;p>工程师团队的 Tech Leader 有不少都是那种“兄弟们跟我冲”的类型，&lt;br>
从一线出身的人很容易会有“我行我上”的冲动。&lt;br>
（事实上我也常有……）&lt;br>
但其实这并不科学。&lt;/p>
&lt;p>假如所有的难题都是由主程序员来解决，&lt;br>
那么主程序员的实力就是团队的天花板。&lt;br>
假如是写的死规则，&lt;br>
那么围棋机器人的棋力最高也只能到编码的程序员这，&lt;br>
只有实战跟反馈能锻炼出会“机器学习”的阿法狗。&lt;/p>
&lt;p>团队也是一样，&lt;br>
永远抱着初心者的空杯心态，&lt;br>
就仿佛自己就是最菜的。&lt;br>
毕竟&lt;a href="https://liriansu.com/adult-life">假如自己这样都是最菜的，那么团队得有多强啊&lt;/a>！&lt;/p>
&lt;h2 id="团队">团队&lt;/h2>
&lt;p>去年难得追完了一整部番，&lt;br>
叫&lt;a href="https://www.bilibili.com/bangumi/media/md102632/">《中间管理录·利根川》&lt;/a>，&lt;br>
体裁是很稀少的职场搞笑番。&lt;br>
这番横七竖八地透出了几个歪歪扭扭的字：&lt;br>
逢山开路，遇水造桥。（雾&lt;/p>
&lt;h3 id="氛围">氛围&lt;/h3>
&lt;blockquote>
&lt;p>四世三公的三公指的是公平、公正与公开&lt;/p>
&lt;/blockquote>
&lt;p>先打个岔解释一下，防止有人把上面这句我编的句子当真了。&lt;br>
四世三公讲的是袁绍身出名门、身份高贵，&lt;br>
他往上四辈祖先都是三公：大司马、大司徒、大司空（总之就是很厉害）&lt;/p>
&lt;p>构建团队，在做好自己之外，&lt;br>
确定团队的氛围是非常重要的事情。&lt;br>
往远了说，团队的氛围会决定做事情的效率和效果，&lt;br>
会影响新人的融入、跟其它团队的对接；&lt;br>
往近了说，你要在这样的团队中担当主程的角色。&lt;br>
所以团队的氛围必须是你认为的正确。&lt;/p>
&lt;p>公平、公正跟公开是我认为的正确。&lt;/p>
&lt;p>公平，是指机会均等。&lt;br>
每个人都会有同样的机会、同样的空间去完成他的目标。&lt;br>
公正，是指权责平衡。&lt;br>
每个人因为实力不同，所以承担的任务、期待的产出也是不一样的。&lt;br>
公开，是指信息透明。&lt;br>
每个人都能获取到及时、准确的消息，不会因为内部的消息传达而影响了共识，进而影响到事情的推进。&lt;/p>
&lt;p>其实工程师在这点上要求很低，&lt;br>
在分锅的时候讲清楚&lt;em>是什么&lt;/em>、&lt;em>为什么&lt;/em>，&lt;br>
&lt;em>怎么做&lt;/em>就交给我们去决策，&lt;br>
最终工程师会选择合适的技术与分工方案去完成的。&lt;/p>
&lt;p>听起来，&lt;br>
这个道理也同样适用于&lt;br>
“女朋友该如何使唤男朋友干活”呢。&lt;/p>
&lt;h3 id="流程">流程&lt;/h3>
&lt;blockquote>
&lt;p>用工具践行自动化&lt;/p>
&lt;/blockquote>
&lt;p>人这个芦苇不仅会思想，&lt;br>
还会用工具。&lt;br>
工程师就更加了，&lt;br>
就像&lt;a href="https://liriansu.com/engineer-culture">《工程师文化》&lt;/a>中讲的一样：&lt;br>
工程师文化的其中一条就是用工具解决问题。&lt;/p>
&lt;p>团队的工具暂且不提，&lt;br>
我所见过的优秀的工程师都有一个统一的特征：&lt;br>
擅长使用工具，甚至自己发明工具。&lt;/p>
&lt;p>“&lt;a href="https://liriansu.com/my-programmer-habits">程序员都是懒人&lt;/a>，&lt;br>
但有些懒是能一劳永逸的。&lt;br>
他会写一段能自动泡咖啡的代码脚本，&lt;br>
然后每天都不用动手按下那该死的按钮。”&lt;/p>
&lt;p>工程师的团队也一样需要工具来自动化各种流程。&lt;br>
从最基础的自动化的代码检查，&lt;br>
到自动化的持续集成、自动化的监控，&lt;br>
甚至是自动化的分工、自动化的沟通。&lt;br>
这里的每一项自动化都可以节约对应的人力，&lt;br>
或者从财务的角度：“提高人效。”&lt;/p>
&lt;p>在我理想中的工程师团队里，&lt;br>
还有这么一拨工程师，&lt;br>
他们的任务就是给其它工程师做好用的工具。&lt;br>
可能在一线业务上会少两三个程序员，&lt;br>
但是整个团队的总生产力能大大提升。&lt;/p>
&lt;h3 id="权责">权责&lt;/h3>
&lt;blockquote>
&lt;p>我爸爸是刘备：放权&lt;/p>
&lt;/blockquote>
&lt;p>这句话是“三国杀”游戏里“刘禅”的台词，&lt;br>
传达出了一种生在普通家庭的平凡感。&lt;/p>
&lt;p>就像前面四世三公里聊到的，&lt;br>
公正意味着权责平衡，&lt;br>
这点也是工程师认知中非常重要的一环。&lt;br>
无论是有赞的年会宣言还是罗辑思维的公开信，&lt;br>
我认为都是权责问题上的无奈之举：&lt;br>
因为没能成为一个权责平衡的团队，&lt;br>
所以才要宣扬这个道理。&lt;/p>
&lt;p>四世三公里的公正（权责）值得单独拎出来说，&lt;br>
因为在我的认知中，公正比公平难以执行，&lt;br>
但有的时候更正确。&lt;br>
举个栗子。&lt;/p>
&lt;p>比如一个团队每个季度都要评一次绩效，&lt;br>
然后组织上规定，&lt;br>
每个团队的绩效都得排名，&lt;br>
总有一个人要吃 0 分。&lt;/p>
&lt;p>（看似）公平的办法是什么呢？轮流来。&lt;br>
大家和和气气，轮流吃 0 分，&lt;br>
这次我吃蛋，下次到你家。&lt;br>
公正的办法是什么呢？按表现来。&lt;br>
在最能贴近事实的统计学数据下，&lt;br>
最差的吃 0 分。&lt;br>
假如一直是最差的呢？&lt;br>
那就一直吃 0 分。&lt;br>
当然，假如整个团队做的业务都崩了，那都吃 0 分，或者解散。&lt;/p>
&lt;p>在公正的条件下，放权给每一个人是一个能把事情做好的办法。&lt;br>
我自己做的技术选型，之后重构也是我来。&lt;br>
我搭的基础设施，不好用我修。&lt;br>
我写的流程，在过年期间稳定撑过了高并发，甚至不用触发 on call，我牛逼。&lt;br>
自由触发自主，自主就会自豪。&lt;/p>
&lt;p>一次我跟在拼多多的好友聊天，&lt;br>
他说他最喜欢创业感觉的一点是：&lt;br>
“跟产品经理过了需求，&lt;br>
我说三天能做完。&lt;br>
然后啪，一天做好测试上线了，&lt;br>
我感觉我可太牛逼了。”&lt;/p>
&lt;h2 id="文化">文化&lt;/h2>
&lt;p>假如你们有注意的话，&lt;br>
很多组织或者团队不仅有文化，&lt;br>
还有文化的具象符号。&lt;br>
团队的文化就是团队的灵魂，&lt;br>
团队的灵魂是由团队的领导者所决定的。&lt;/p>
&lt;h3 id="精英">精英&lt;/h3>
&lt;blockquote>
&lt;p>20%的程序员写出了80%的代码。&lt;/p>
&lt;p>—— &lt;a href="https://liriansu.com/pareto-rule-of-programmers">《程序员的二八定律》&lt;/a>&lt;/p>
&lt;/blockquote>
&lt;p>虽然程序员们喜欢把自己比喻成“码农”、“码工”，&lt;br>
职称也是叫“工程师”，&lt;br>
大学里学的也是叫“软件工程”。&lt;/p>
&lt;p>但其实编码跟所有脑力劳动有着一样的特性：&lt;br>
人跟人的产出差别是指数级的。&lt;/p>
&lt;p>诗人李白写的诗，传唱度比一万个末流诗人加起来还要高；&lt;br>
哲学家马克思的思想，影响了整个历史的进程；&lt;br>
自然语言学家刘半农创造的她字，催生了跨越千里的情书；&lt;br>
给顶级程序员一根针，他们就能在刻满一张 4GB 的光盘（梗）。&lt;/p>
&lt;p>不提横向对比，&lt;br>
即使是一个人的产出也会有云泥之别。&lt;br>
一个程序员一天工作 8 小时，&lt;br>
可能他最专注的那 2 小时就做完了一整天的功能，&lt;br>
其他时间他只不过是往里面写新的 bug，&lt;br>
然后再努力找出来修复而已。&lt;/p>
&lt;p>所以一个追求最终生产力的文化，&lt;br>
一定会把提升精英工程师的产出，&lt;br>
提高工程师的有效工作占比放在一个重要的位置。&lt;/p>
&lt;p>比如让谷歌“臭名昭著”的 &lt;code>20% rule&lt;/code>，&lt;br>
官方说法是每个工程师只分配 80% 时间在工作上，&lt;br>
剩下的 20% 的时间去做自己感兴趣的副业。&lt;br>
但其实这反而激发了工程师们的热情，&lt;br>
让一些人付出了 120% 的时间在业务上。&lt;br>
最终可能大部分 20% 的项目都没产生效应，&lt;br>
但是少部分 20% 的项目以及这些项目带来的文化热情传染是有着非常大的价值的。&lt;/p>
&lt;h3 id="上进">上进&lt;/h3>
&lt;blockquote>
&lt;p>从正面去思考问题。&lt;/p>
&lt;/blockquote>
&lt;p>聊完精英这个话题，&lt;br>
很容易想到金字塔模型，&lt;br>
进而会有一个问题：&lt;br>
“那假如少部分工程师做了大部分产出，&lt;br>
剩下的大部分工程师怎么办呢？裁员吗？”&lt;/p>
&lt;p>这个问题问的很有趣。&lt;/p>
&lt;p>我的想法是一个团队在建立的时候，&lt;br>
是会经过一套标准恒定的人才筛选机制的。&lt;br>
这个背景下，从个人角度看来，&lt;br>
我作为团队里产出占比很低的人，&lt;br>
我也很绝望啊…&lt;br>
比如我们公司就有个前端，&lt;br>
他不仅做业务做的又快又猛，&lt;br>
技术问题上他也想法多，&lt;br>
一下就能薅一个 demo 出来。&lt;br>
你猜只能仰望他的我，会怎么想？&lt;/p>
&lt;p>没错，我会希望自己也努力成为这样优秀的人。&lt;/p>
&lt;p>好的文化不仅能催化顶级人才的产出，&lt;br>
还能让有潜力肯努力的优秀人才进化成顶级人才。&lt;br>
十年后二十年后一部分元老承担着公司的运作，&lt;br>
离职的大家也散落在不同的公司，&lt;br>
都是像主程序员一样做着核心的事情。&lt;br>
所谓聚是一团火，散是满天星。&lt;/p>
&lt;p>依靠流程、考核、规定去提升团队统计学意义上的生产力，&lt;br>
并不是从正面去解决问题的办法。&lt;br>
营造一个上进的文化，&lt;br>
就会让大家知道向东流一定能流入大海，&lt;br>
这样才能从根本上解决问题。&lt;br>
从团队的角度来说，&lt;br>
大家的总体生产力更加高了，&lt;br>
事情也更容易做了；&lt;br>
从个人的角度来说，&lt;br>
个人命运跟公司进程结合在了一起，&lt;br>
回报是非常可期的。&lt;/p>
&lt;h3 id="远见">远见&lt;/h3>
&lt;blockquote>
&lt;p>在种田与爆兵中寻找平衡&lt;/p>
&lt;/blockquote>
&lt;p>战略类游戏中策略的选择，&lt;br>
往往会在两个方向中动态地摇摆：&lt;/p>
&lt;ul>
&lt;li>种田。你的经济跟科技都会更好，长期发展更有优势，但是很容易短期内被打爆。&lt;/li>
&lt;li>爆兵。你的战斗力会更强，短期战斗一定会胜利，但是长期看来非常疲软。&lt;/li>
&lt;/ul>
&lt;p>工程师团队做的事情其实本质上也是这两方面：&lt;/p>
&lt;ul>
&lt;li>优化技术基建。&lt;br>
你的一切统计学指标都很好，也能支撑很大流量。&lt;br>
但是占用了太多业务开发的时间，你就没能有很大流量。&lt;/li>
&lt;li>实现业务需求。&lt;br>
你的业务需求做的很快，用户的反馈迅速，他们非常开心。&lt;br>
但是技术债越来越多了，甚至你们还没做安全防护，一被 DDOS 就会挂。&lt;/li>
&lt;/ul>
&lt;p>这两件事情你中有我，我中有你，是动态平衡的。&lt;br>
不论是不做基础建设，或是万般皆下品惟有基建高，&lt;br>
都不是一个很好的情况，&lt;br>
工程师团队文化需要避免走向任何一个极端。&lt;/p>
&lt;p>理想中的距离就是恋爱中的“刚刚好”，&lt;br>
业务需求不会因为工期而挤走技术基建，&lt;br>
技术基建也不会因为想练屠龙技就放弃业务需求。&lt;br>
两方都谦谦有礼，都说着：“你先请”然后让出了自己的位置……&lt;/p>
&lt;p>不，醒醒，这样的情况不会发生。&lt;br>
除非事业发展停滞（公司要凉了啊），&lt;br>
在事业进展飞速的情况下，&lt;br>
业务需求永远都是层出不穷，&lt;br>
这种时候平衡点就化成了战略游戏攻略中的“随机应变”几个字了。&lt;br>
最终，团队会形成一种自调节的文化，&lt;br>
以实现高质量高效率的业务需求，&lt;br>
以及提前准备好足够牢固的基础建设 :)&lt;/p>
&lt;p>活在梦里的感觉，有点真实。&lt;/p>
&lt;h2 id="其它">其它&lt;/h2>
&lt;p>总的来说，&lt;br>
上面的个人、团队、文化是我从不同角度对工程师团队的理解。&lt;br>
但其实对于“道”的理解很多时候都是复杂的，&lt;br>
尤其是评价构建团队依靠的都是后验感知。&lt;/p>
&lt;p>但总的来说，我很喜欢我们目前的团队 :)&lt;br>
而且我们&lt;del>强行&lt;/del>达成了共识：&lt;br>
做对的事情，不论这件事情多难。&lt;/p>
&lt;p>下面是一些有可能相关，&lt;br>
但又不知道怎么去抽象的话题，&lt;br>
就罗列在最后当一点散文的尾巴吧。&lt;/p>
&lt;h3 id="务虚与务实">务虚与务实&lt;/h3>
&lt;p>最近有一句话又因为《新东方》年会的改编歌曲焕发二春了：&lt;/p>
&lt;blockquote>
&lt;p>写 PPT 的不如讲 PPT 的，讲 PPT 的不如听 PPT 的。&lt;/p>
&lt;/blockquote>
&lt;p>Mia 去年升职为 Manager 以后，&lt;br>
也时不时跟我感慨，&lt;br>
她觉得目前工作中，&lt;br>
务虚的部分一下子多了不少，&lt;br>
感觉得更努力才行。&lt;/p>
&lt;p>这很科学。&lt;/p>
&lt;p>人在单打独斗的时候其实不需要太多思考，&lt;br>
依靠直觉去行动就行。&lt;br>
但是一个小队的队长，&lt;br>
就需要一些冠冕堂皇也好推心置腹也好的理由来说服队员们。&lt;br>
阿里巴巴这个级别的公司更是需要公司文化、价值观来维持组织的团结齐心。&lt;/p>
&lt;p>而作为组织文化的实体表现者，&lt;br>
就会有到“越往高处，务虚越多”的感受。&lt;br>
有可能当你成为了一整个公司的领导者，&lt;br>
必须得确保自己的认知是可复用、能推广的，&lt;br>
从而你得务虚再多一点，再多一点，&lt;br>
最终化身成了公司的吉祥物，&lt;br>
然后公司大成功！&lt;/p>
&lt;h3 id="工作制度">工作制度&lt;/h3>
&lt;blockquote>
&lt;p>早上九点上班，晚上九点下班，一周上六天班，真的好吗？&lt;/p>
&lt;/blockquote>
&lt;p>直接的问法是：996 接受吗？&lt;/p>
&lt;p>虽然可以用很多论点去修饰，&lt;br>
但其实我核心的想法就是一条：&lt;br>
我无法接受强制的 996，&lt;br>
但是我是一个会自愿 996 工作的人。&lt;br>
具体的想法就不过多阐述了（现在半夜四点，我有点困意了）&lt;/p>
&lt;p>我认为企业选择 996 的工作制度其实跟人类喜欢喝酒一样，&lt;br>
是市场充分竞争环境下的自然结果。&lt;br>
目前存在的问题是整个工作制度存在恶性竞争，&lt;br>
导致损害社会劳动氛围的可能性。&lt;br>
可以附加一些“额外工作医保要求”跟“高龄员工工时补偿”之类的来进行制度优化。&lt;/p>
&lt;p>加班可以，常态不可以。&lt;br>
自愿可以，强制不可以。&lt;br>
健康可以，挂了就不行。&lt;/p>
&lt;h3 id="招聘">招聘&lt;/h3>
&lt;p>大纲里引用的句子是一篇七八年前的匈牙利网络文章，&lt;br>
当时我看的觉得蛮好玩的，&lt;br>
第一次以企业/资本的视角来看待员工。&lt;/p>
&lt;p>招聘是一个很让人头疼的问题。&lt;/p>
&lt;p>尤其是上面的文章中讲到了，&lt;br>
我的认知给自己立了一个 Flag:&lt;br>
“我只想招优秀的人。”&lt;/p>
&lt;p>两年前写&lt;a href="https://liriansu.com/what-a-hard-backend-interview">《HR就讨厌我们这样的技术》&lt;/a>的时候，&lt;br>
我们招人的标准一句话总结就是&lt;br>
“希望候选人对口（做过 Python 的互联网后端开发），&lt;br>
又希望候选人优秀（有在项目里担当主程序员的潜力）”&lt;/p>
&lt;p>当时招聘季 HR 把上海所有 Python 的简历都刷了一遍，&lt;br>
我们只给了 2% 的最终 offer 率，&lt;br>
于是 HR 锤爆了我们的狗头，&lt;br>
并警告我们：“上海的 Python 候选人池子被打爆了，你们考虑一下怎么办。”&lt;/p>
&lt;p>于是（在引入 Java 技术栈之外）我们思考了“对口+优秀”这个标准之后，&lt;br>
拿掉了“对口”这个需求，&lt;br>
只想招“优秀（有在项目里担当主程序员的潜力）”的人才。&lt;/p>
&lt;p>这个方案十分奏效，&lt;br>
我们去年新加入的队友都非常靠谱。&lt;br>
这也印证了前文对工程师团队文化的思考，&lt;br>
科学。&lt;/p>
&lt;h3 id="绩效">绩效&lt;/h3>
&lt;p>程序员是如今的热门行业，&lt;br>
热门行业的薪酬同样也是热门的话题。&lt;br>
（就像工业革命时的工人待遇一样）&lt;/p>
&lt;p>作为一个好奇宝宝，&lt;br>
我也在&lt;a href="https://liriansu.com/a-chat-with-roommates">《一次有意义的吹B》&lt;/a>，&lt;br>
&lt;a href="https://liriansu.com/is-it-possible-to-be-rich-easily-by-programming">《培训三月，月入上万？&lt;/a>，&lt;br>
&lt;a href="https://liriansu.com/a-chat-with-schoolmates">《公司文化、工资期权、开发体验》&lt;/a>中多次聊到这个话题的细节。&lt;/p>
&lt;p>从更高的认知角度上，&lt;br>
我确认并坚定了我从毕业以来的观点：&lt;/p>
&lt;p>只要维持每年的进步，&lt;br>
人的生命会是指数上升的。&lt;br>
你如今的成就，&lt;br>
不过是你十年后的成就里的繁星一点。&lt;/p>
&lt;p>就像唐代斯在最后赠给马克西米连的“等待与希望”一样。&lt;br>
我的朋友，作为工程师的我想送给你两个词，&lt;br>
它们饱含着“递归”、“复利”乃至“宇宙膨胀”的内在哲学：&lt;br>
思考，坚持。&lt;/p>
&lt;p>（全文完）&lt;/p></description></item><item><title>积极面思考</title><link>https://liriansu.com/posts/2019-01-23-about-active-thinking/</link><pubDate>Wed, 23 Jan 2019 23:25:20 +0000</pubDate><guid>https://liriansu.com/posts/2019-01-23-about-active-thinking/</guid><description>&lt;p>最近半年对方法论的思考比较多，&lt;br>
所以可能写的都跟“术”关系不大，&lt;br>
而更加偏向于“道”一些。&lt;/p>
&lt;h2 id="引子">引子&lt;/h2>
&lt;p>我记得中学历史课本中，&lt;br>
在很前面的显眼位置上，&lt;br>
写着这么一句李世民对魏征的评价：&lt;br>
“夫以铜为镜，可以正衣冠；&lt;br>
以史为镜，可以知兴替；&lt;br>
以人为镜，可以明得失。”&lt;/p>
&lt;p>这句话就像图书馆的闭馆铃声一样，&lt;br>
总会在深夜让我抽离自己的身躯，&lt;br>
以一个更高维的角度看自己、看别人。&lt;/p>
&lt;p>就像在&lt;a href="https://liriansu.com/my-programmer-habits">《写程序的我的性格》&lt;/a>跟&lt;a href="https://liriansu.com/adult-life">《毕业三年的报告》&lt;/a>里面我自己反复念叨的一样，&lt;br>
工作很容易让没有防备的人类变成自我重复的机器。&lt;br>
前阵子跟一个产品的好朋友聊天，&lt;br>
讲到招人的喜好，&lt;br>
他说他只喜欢那种“工作经验大于工龄”的人。&lt;br>
或者换句话说，“工作的效率比大部分人都要高”的人。&lt;/p>
&lt;p>在我看来，成为一个效率比别人高的人并不难。&lt;br>
其中一条很有效的办法，我称之为“积极面思考”。&lt;/p>
&lt;h2 id="什么是积极面思考">什么是积极面思考&lt;/h2>
&lt;p>简单来说，就是从事情的正面去思考问题。&lt;/p>
&lt;p>比如举个有点小众的栗子。&lt;br>
蓝猫的配音演员是葛平，他曾经也陷入过跟六小龄童一样的恶搞文化中心里，&lt;br>
但他既没逃避也没斥责，而是“放下了身段”跟恶搞他的大家玩成了一片。&lt;br>
最终大部分恶搞的同学都“路人转粉”，尊称他为“葛叔”了。&lt;br>
同样的道理，只要六小龄童老师能跟“六学家”们打成一片，他的风评也会再次走高的。&lt;/p>
&lt;p>再举个工作中的栗子。&lt;br>
工作里少不了的事情是协同合作，&lt;br>
而多人协同合作容易导致“因为沟通的问题影响到了事情的进度”。&lt;br>
遇到沟通所产生问题的时候，&lt;br>
不论是文本化记录结果、寻求拍板人甚至是自己多做一点减少沟通的量，&lt;br>
都是有效的正面思考问题产生的行为。&lt;br>
而像分责推锅就并不是从事情的正面去思考问题了。&lt;/p>
&lt;p>当面对问题的时候，能不怕问题，&lt;br>
不用懒政跟拖延去推迟问题的解决时间，&lt;br>
而是从解决问题的根本去思考、行动，&lt;br>
这就是积极面思考。&lt;/p>
&lt;h2 id="为什么要积极面思考">为什么要积极面思考&lt;/h2>
&lt;h3 id="积极面思考是解决问题的捷径">积极面思考是解决问题的捷径&lt;/h3>
&lt;p>我司有一点“中国互联网公司的通病”：微信办公。&lt;br>
之前我还在做B端业务的时候，&lt;br>
我微信里工作群有 300 多个，&lt;br>
基本上是周六正在跟女朋友约会，&lt;br>
然后突然就被拉进了一个微信群处理问题，&lt;br>
因为这点我还成为过电影院里看手机的我眼中的“无素质人群”。&lt;/p>
&lt;p>当时我非常崩溃。&lt;br>
一方面我是作为工程师招进来的，却要做售前、售后、客服的工作；&lt;br>
另一方面由于我平常写代码写的最多，也很好说话，&lt;br>
并不是 Leader 的我充当着实质上的项目经理的角色。&lt;br>
当时有次周六凌晨三点，刚处理完事情的我发现CS同事二狗也在线，&lt;br>
我问他在干什么，他说周六我们的餐饮客户搞活动，他还要录十几个营销活动…&lt;/p>
&lt;p>当然，别看我说的这么崩溃，其实我心里非常愿意呢。&lt;br>
假如一家公司是做企业级服务的，那么只要这家公司想要变得卓越，“客户第一”就一定在公司的核心价值观里。&lt;br>
之前&lt;a href="https://liriansu.com/weekly-wander">《最近跟女朋友的周常》&lt;/a>里也讲到了，“客户第一”是需要公司跟员工一起努力达成的。&lt;br>
所以虽然我一开始奉献出了周末（忙的时候连一周一休都做不到）&lt;br>
但随着操作手册的建立、流程的规范还有持续的功能更新，&lt;br>
后面的事情越来越顺畅了。&lt;/p>
&lt;p>这件事情给我的附加感受是，&lt;br>
我真正地体会到了从开发者、项目管理者、用户的不同角度去看一件事情的全貌。&lt;br>
而且我确认了一个事实：&lt;br>
多方合作中，是能找到共赢点的。&lt;br>
只要想明白了这个点，事情就一定可以迎刃而解。&lt;br>
这就是所谓“积极面思考是解决问题的捷径”。&lt;/p>
&lt;h3 id="积极面思考是正向循环的关键环节">积极面思考是正向循环的关键环节&lt;/h3>
&lt;p>一般语境中，区分内向型人格跟外向型人格主要是用沟通意愿区分的。&lt;br>
但我偏向于另一种区分方法：&lt;br>
外向型人格与人沟通会回复精力；&lt;br>
而内向型人格与人沟通会消耗精力，他们靠独处来回复精力。&lt;/p>
&lt;p>Mia 曾经评论过我，说我有一个内在的自给自足的循环，&lt;br>
是这个自洽的循环给我提供了活下去的勇气（听起来怪怪的&amp;hellip;）&lt;br>
没错，积极面思考在我看来是正向循环的关键环节。&lt;/p>
&lt;p>人的正向循环是依靠认知、行动、反馈的每个环节去自洽地形成的。&lt;br>
其中行动、反馈的过程跟结果都很难去控制，&lt;br>
所以认知就是达成正向循环的关键。&lt;br>
积极面思考会带来更正向的心里暗示，&lt;br>
而积极的行动也会潜移默化地改变所处的环境，&lt;br>
从而最终加大正向反馈的可能性。&lt;/p>
&lt;p>多让座、多说请跟谢谢、礼貌待人其实都可以划入这个理论的范畴里。&lt;/p>
&lt;h3 id="积极面思考能扩大影响力">积极面思考能扩大影响力&lt;/h3>
&lt;p>人类的潜力是无穷的，&lt;br>
然而大部分人类都会浪费它。&lt;br>
Zen of Python 里也说过：&lt;code>Now is better than never.&lt;/code>&lt;br>
正面去思考问题并作出应对可能会比较难，&lt;br>
但不论是个人还是集体，&lt;br>
选择正面去迎接问题是长远的最优解。&lt;/p>
&lt;p>就像 Fate/Zero 小说里的亚历山大大帝一样，&lt;br>
他最充满魅力的一点就是他的王道。&lt;br>
他的伙伴韦伯也因为跟亚历山大的思想交流，&lt;br>
而改变了一生的道路。&lt;/p>
&lt;h2 id="综述">综述&lt;/h2>
&lt;p>总的来说，积极面思考能解决当下的问题，&lt;br>
也能带来长远的进步和影响力。&lt;br>
假如作为读者的你愿意的话，我非常推荐你尝试一下这样思考问题。&lt;/p>
&lt;p>当然啦，光是思考是不够的，也要有对应的行动哦。 :)&lt;/p>
&lt;p>（完）&lt;/p></description></item><item><title>回首看向2018年的OKR</title><link>https://liriansu.com/posts/2019-01-22-my-2018-okr-review/</link><pubDate>Tue, 22 Jan 2019 22:07:02 +0000</pubDate><guid>https://liriansu.com/posts/2019-01-22-my-2018-okr-review/</guid><description>&lt;p>去年默默践行了一年的个人 OKR,&lt;br>
今年年初也是到了回顾的时候了。&lt;/p>
&lt;h2 id="引子">引子&lt;/h2>
&lt;p>去年写&lt;a href="https://liriansu.com/my-2018-okr">《这就是我2018年的OKR》&lt;/a>的时候，&lt;br>
我刚处于一个从各类渠道学到了这个技巧的兴奋期，&lt;br>
所以非常激动地设下了（自以为）很精妙的几个小目标。&lt;/p>
&lt;p>一年下来，我收获不小。&lt;br>
其中感触最深的一点是坚持自我审视对个人成长的有效帮助，&lt;br>
或者换一句话说，叫“坚持的力量”。&lt;/p>
&lt;p>OKR 这种东西，就像小学生对以后职业的幻想一样，&lt;br>
是即美好又容易幻灭的东西。&lt;br>
最关键的并不是目标是怎么定的，&lt;br>
而是定目标的人是如何去认知他的目标的。&lt;/p>
&lt;p>举个栗子，我给自己定下的年度目标有一条是“帮助陌生人 50 次”。&lt;br>
这点让我在路上走路都走不安稳了，一直左顾右盼看看有没有哪个人需要天降帮助的。&lt;br>
（最终顺带完成了不少把垃圾捡起来丢到垃圾桶里的普通成就）&lt;/p>
&lt;h2 id="回顾">回顾&lt;/h2>
&lt;p>去年定下的 OKR 是这样的：&lt;/p>
&lt;ul>
&lt;li>O1. 技术影响力大幅度提升
&lt;ul>
&lt;li>学习/理解/使用/掌握6个技术工具&lt;/li>
&lt;li>成为1k+ star项目的主contributor&lt;/li>
&lt;li>技术文章输出20篇&lt;/li>
&lt;li>自己有233 star以上的代码项目&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>O2. 事业上做出极大贡献
&lt;ul>
&lt;li>团队的OKR完成率在80%以上&lt;/li>
&lt;li>review 10万行代码&lt;/li>
&lt;li>当300场面试官&lt;/li>
&lt;li>成为整个团队top 1%的人&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>O3. 保持幸福度爆满的状态
&lt;ul>
&lt;li>与亲人总语音时间超过1000分钟&lt;/li>
&lt;li>跟女朋友争吵次数小于3次&lt;/li>
&lt;li>帮助陌生人达50人次&lt;/li>
&lt;li>新增500首红心歌曲&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;p>很简单，分三点来看就行了。&lt;/p>
&lt;h3 id="技术影响力">技术影响力&lt;/h3>
&lt;p>技术影响力这点上，其实跟我设想的方向有很大出入，&lt;br>
主要原因是：我 2018 年一整年负责的都是一整个团队，而不仅是只要对自己负责了。&lt;br>
一个很大的区别是以前我可以非常活跃地抢锅，&lt;br>
然后在第一线的业务技术锻炼中获取直接经验，&lt;br>
并且快速升级。&lt;br>
现在很多时候是得适度地分锅，&lt;br>
然后让队友们在第一线的业务技术中去锻炼，&lt;br>
以让不同诉求的同学都能找到个人跟公司的平衡。&lt;br>
于是在目标 (Object) 的方向上产生了偏差，&lt;br>
关键结果 (KeyResult) 上的完成情况就偏差更大了。&lt;/p>
&lt;p>技术工具上我一整年接触的比我想的要多了很多，&lt;br>
不仅对语言框架库 (Python/Django/ZeroMQ) 有了更深入的使用，&lt;br>
还对项目进度合作甚至向上向下的管理有了更进一步的认知。&lt;/p>
&lt;p>而在公众输出上，由于一年的闲暇时间基本都奉献给了我的事业（指工作），&lt;br>
所以开源上今年只自然增长到了 200 个 star，&lt;br>
一年下来文章也只写了 18 篇，&lt;br>
总的来说，这一项给自己打个 70 分吧。&lt;/p>
&lt;h3 id="事业贡献">事业贡献&lt;/h3>
&lt;p>我认为 2018 年在事业上的投入带给我的回报是非常大的。&lt;br>
虽然一整年下来，部门的事业没能坐上火箭，部门的兄弟们也没能升职加薪苟富贵，&lt;br>
不过目前看来，我们的未来仍然是非常可期的。&lt;/p>
&lt;p>从付出的角度上来说，Review 10 万行代码是肯定做到了，&lt;br>
光是近半年自己写的代码就有一万多行。&lt;br>
300 场面试官也已经达成了，&lt;br>
不过这个 KR 其实定的不好，&lt;br>
因为它的实现完全是依靠公司招人的计划以及跟 HR 小姐姐们的努力看简历有关的。&lt;br>
关于团队的部分没办法找到一手数据去查验，&lt;br>
不过我最自豪的一点是我们团队的大家一致保持着非常高的研发标准，&lt;br>
没有破窗效应，而且气氛还很棒，让我很喜欢在这里工作。&lt;/p>
&lt;p>而从收获的角度上来说，我收获最多的就是各类的间接经验。&lt;br>
不仅包括技术选型、团队合作的一些实验、项目管理工具的实验，&lt;br>
还包括我跟听了一整年的产品团队的需求分析、设计回顾甚至是跟创始人的战略制定。&lt;br>
假如以前的我只对“从零到一”很有信心的话，&lt;br>
现在的我对“从一到十”乃至“从十到百”也一样充满着信心了。&lt;/p>
&lt;p>总的来说，我其实在这个目标上付出的最多，&lt;br>
对应的收获也是最大的。&lt;/p>
&lt;h3 id="幸福度">幸福度&lt;/h3>
&lt;p>其实当时 OKR 里面加这一条，&lt;br>
我有种“小意思，加上让大家看看吧”的轻蔑的想法。&lt;br>
人只要知足，就很容易达到幸福的状态。&lt;br>
当然，一年来的事实也验证了我的想法。&lt;/p>
&lt;p>刚开始去实践目标的时候，&lt;br>
我逐渐又意识到了一点：&lt;br>
“人心所想会在潜意识里发出回声。”&lt;/p>
&lt;p>比如我给自己列了一条“与亲人总语音时间超过 1000 分钟”。&lt;br>
这是什么意思呢？&lt;br>
刨去过年，一年大概有 50 周。&lt;br>
假如每周都跟家里打电话的话，&lt;br>
每次通话时间保持到 20 分钟就行了。&lt;br>
于是当时我周常给家里打电话的时候特意留意了一下，&lt;br>
得出了一个让我一愣的结论：&lt;br>
“不去主动接话题的话，跟家里的通话是聊不到 20 分钟的。”&lt;br>
就像鸡汤里说的那样，亲情就是这么遥远又纤细的一根电话绳啊。&lt;/p>
&lt;p>总的来说，幸福度这个目标的完成状况我很满意。&lt;br>
年末我的网易云红心也成功地涨到了 2500，&lt;br>
并且给我一种我把云村听穿了的感觉。&lt;/p>
&lt;h2 id="未来">未来&lt;/h2>
&lt;p>认真地过了一遍去年的 OKR 以后，&lt;br>
感觉时间这种东西，&lt;br>
食用起来的确是非常的美味。&lt;/p>
&lt;p>今年的目标我还没想清楚，&lt;br>
不过有一点应该是不会变的，&lt;br>
多写文章，记录自己的思想，&lt;br>
然后产生白底黑字的回音。&lt;/p>
&lt;p>毕竟永恒的方法，&lt;br>
就是刻在石头上。&lt;/p>
&lt;p>（完）&lt;/p></description></item><item><title>如何搭建个人的舒适工作环境 —— 又名 Surface Pro 使用感言</title><link>https://liriansu.com/posts/2018-12-04-dev-env/</link><pubDate>Tue, 04 Dec 2018 23:16:29 +0000</pubDate><guid>https://liriansu.com/posts/2018-12-04-dev-env/</guid><description>&lt;p>首先感谢 Mia 在预算见底的年底，&lt;br>
卖掉了 iPhone 给我补上了款项…&lt;/p>
&lt;p>这篇文章大概会涉及三个方面：&lt;/p>
&lt;ul>
&lt;li>Surface Pro 体验&lt;/li>
&lt;li>我的开发环境硬件搭配&lt;/li>
&lt;li>我的开发环境软件搭配&lt;/li>
&lt;/ul>
&lt;h2 id="surface-pro-体验">Surface Pro 体验&lt;/h2>
&lt;p>我以前B站就逛逛动画区跟鬼畜区，&lt;br>
前几个月开始逛科技区跟生活区以后，&lt;br>
草单就像猫刨过的卫生纸一样疯狂变长。&lt;/p>
&lt;p>在很多件很有科技感的物件中，&lt;br>
我看中了 Surface Pro。&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/env/sp.jpg" alt="sp">&lt;/p>
&lt;blockquote>
&lt;p>码字时的桌面一览&lt;/p>
&lt;/blockquote>
&lt;p>Surface Pro 是微软出的一款平板电脑。&lt;br>
我看中的是 Surface Pro 6，&lt;br>
硬件参数是 512GB SSD 硬盘 + 16G 内存 + 8代4核i7 CPU (i7-8650U)，没有独立显卡，没有风扇，&lt;br>
除了支持触屏以外，身上的接口包括一个音频口、一个雷电2（兼容 miniDP）接口、一个 USB 3.0 接口、一个 Surface Connect 充电口。&lt;br>
国行官方售价是裸机 14888 RMB，&lt;br>
图里的键盘售价是 788 RMB,&lt;br>
粘在屏幕左边的触控笔是 728 RMB.&lt;/p>
&lt;p>上面数据有点冷冰冰的，&lt;br>
让我们举些具体的栗子：&lt;/p>
&lt;ul>
&lt;li>机身很轻。机身重量是 700g, 背在书包里感觉仅等于背着半本《算法导论》。&lt;/li>
&lt;li>抱着走非常方便。配合 XODO/Bamboo 等触屏应用使用可以完全无纸化办公，连跟候选人聊天都是带着看简历。
&lt;ul>
&lt;li>而且记的笔记天生就是电子版这一点非常开心&lt;/li>
&lt;li>怪不得用 iPad 的@快雪初晴 会整天想写点什么&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>不会想用 Surface 玩大型游戏。没有独显让我连 dota2 都不想装。
&lt;ul>
&lt;li>然而我还是装了 Artifact 跟文明 6。&lt;/li>
&lt;li>玩文明比想象的要流畅很多，标速一百回合内无明显卡顿。&lt;/li>
&lt;li>不过就是比较烫，比得上边充电边阴阳师的小米 MIX 了。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>工作时不会有任何卡顿感。16G 的内存同时开着 Chrome + JetBrains + Music 完全无压力。&lt;/li>
&lt;/ul>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/env/tasks.jpg" alt="task">&lt;/p>
&lt;blockquote>
&lt;p>开发时的常见内存占用&lt;/p>
&lt;/blockquote>
&lt;p>总的来说，购入 Surface 以后，&lt;br>
我用它替换了&lt;a href="https://liriansu.com/my-friend-ldsink">之前用的公司神舟电脑&lt;/a>。&lt;br>
目前还在蜜月期的我回家也会背着这个小本子。&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/env/weibo.jpg" alt="weibo">&lt;/p>
&lt;h2 id="我的开发环境硬件搭配">我的开发环境硬件搭配&lt;/h2>
&lt;p>我对硬件开发环境的需求大概是这样的：&lt;/p>
&lt;ul>
&lt;li>公司和家里都得有舒适的开发环境
&lt;ul>
&lt;li>我回家一般也会写点小代码&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>公司的配置得更好一些
&lt;ul>
&lt;li>工作日我一天大概要睡 8 小时，剩下 12 小时在公司，4 小时在家。&lt;/li>
&lt;li>一周在公司写代码的时间占比更高。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>显示器得多一点，键盘鼠标得满上
&lt;ul>
&lt;li>我不太习惯单屏切多桌面&lt;/li>
&lt;li>俗话说的好：越菜的程序员键盘越大&lt;/li>
&lt;li>来自广东，就是粤菜&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/env/desktop.jpg" alt="desktop">&lt;/p>
&lt;blockquote>
&lt;p>程序员的桌面&lt;/p>
&lt;/blockquote>
&lt;ul>
&lt;li>电脑（主机）：Surface Pro
&lt;ul>
&lt;li>公司的标配是当年的 Mac Pro&lt;/li>
&lt;li>我自己要了个神舟，现在已经还了回去了&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>显示器：Dell U2417H * 3 + 显示器臂
&lt;ul>
&lt;li>公司的标配是俩，自己又补了一个&lt;/li>
&lt;li>显示器臂我买的 乐歌+NewBalance, 感觉 NB 便宜些质量也还行，全买 NB 也 OK&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>键鼠：Cherry 青轴 + 牧马人
&lt;ul>
&lt;li>键帽是一套无刻的高帽，@hulucc 买错了匀给我的，很好用&lt;/li>
&lt;li>牧马人是淘宝活动 5 元买的，因为我用 Vim 所以用的不多，也很好用（滑稽&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>配件：Surface Dock + Bose QC 35II + 小米排插/数据线
&lt;ul>
&lt;li>值得拿出来说的就这几个&lt;/li>
&lt;li>Surface Dock: 官方的拓展坞，只占用一个 Connect 充电口，供给了两个雷电2四个USB一个网口，插拔极度方便！一键下班不是梦&lt;/li>
&lt;li>Bose QC 35II: 属于&lt;a href="https://zhuanlan.zhihu.com/p/20665153">洗碗机类需求&lt;/a>，用了就回不去没降噪耳机的时候了&lt;/li>
&lt;li>小米排插/数据线: 性价比高而且实用，假如是自己买的话强烈推荐（我这是公司配的&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;p>最后是价格环节：&lt;/p>
&lt;ul>
&lt;li>Surface 裸机 + 键盘是必备的，算上笔一整套大概是 16000 左右，京淘等活动期可能会有优惠，学生也可以买官方的九折教育套餐。&lt;/li>
&lt;li>Dell U2417H 是 1.5k 左右，显示器的话看个人偏好。前阵子看到个干货：&lt;a href="https://www.zhihu.com/question/35668312/answer/446745873">《如何选购显示器》&lt;/a>&lt;/li>
&lt;li>键鼠耳机就略过了，Dock 的话官方价要 1.5k, 假如你有多屏需求的话是必买的&lt;/li>
&lt;/ul>
&lt;p>可能整套看起来是很特么贵的，&lt;br>
但是可以一件件地慢慢攒啊 :)&lt;/p>
&lt;h2 id="我的开发环境软件搭配">我的开发环境软件搭配&lt;/h2>
&lt;p>距离我上次写的&lt;a href="https://liriansu.com/windows-dev-env">《搭建舒适的 Windows 开发环境》&lt;/a>已经过去了快两年，&lt;br>
现在再去 review 当时的开发环境，&lt;br>
发现我用的软件基本上都换了一圈…&lt;/p>
&lt;p>不过不论在什么平台开发，&lt;br>
用什么软件提升生产力，&lt;br>
我认为总的原则是不会变的：&lt;br>
&lt;strong>聚焦目标，提升效率，减少重复&lt;/strong>&lt;/p>
&lt;p>两年前的我主要面对的问题，以及解决方案有这么些：&lt;/p>
&lt;ul>
&lt;li>安装软件不方便：用 &lt;code>chocolatey&lt;/code> 去自动化安装&lt;/li>
&lt;li>切换程序/寻找文件不方便：用 &lt;code>wox + everything&lt;/code> 来定位&lt;/li>
&lt;li>需要在类 linux shell 下工作：用 &lt;code>git bash&lt;/code> 作为工作的环境&lt;/li>
&lt;li>有很多一定要在 linux 下才能做的事情：用 &lt;code>virtualbox + vagrant + putty&lt;/code> 的本地虚拟化解决方案&lt;/li>
&lt;li>提升工作体验：使用 &lt;code>网易云音乐 + 有道云笔记 + 有道词典&lt;/code>&lt;/li>
&lt;li>想成为一个有理想有追求的人：用 &lt;code>Vim&lt;/code>&lt;/li>
&lt;/ul>
&lt;p>现在我面对的问题跟解决方案，相较于两年前都有些许不同：&lt;/p>
&lt;ul>
&lt;li>安装软件不方便：&lt;strong>手动安装&lt;/strong>
&lt;ul>
&lt;li>本质上这是 Windows 混乱自由的生态导致的，很多软件都无法被 &lt;code>chocolatey&lt;/code> 支持（比如 Steam&lt;/li>
&lt;li>即使是用 &lt;code>scoop&lt;/code> 或者是 &lt;code>choco&lt;/code> 支持的软件，也会因为每个软件有些微不同的配置，而产生让强迫症不爽的自动化安装体验&lt;/li>
&lt;li>所以现在我选择手动安装所有软件。其实感觉还行，因为电脑里也不会装上千个软件…&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>切换程序/寻找文件不方便：&lt;strong>用 &lt;a href="https://www.listary.com/">&lt;code>listary&lt;/code>&lt;/a>&lt;/strong>
&lt;ul>
&lt;li>&lt;code>listary&lt;/code> 的功能已经完美覆盖了 &lt;code>wox + everything&lt;/code> 了&lt;/li>
&lt;li>对中文的支持也非常好&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/env/hyper.jpg" alt="hyper">&lt;/p>
&lt;ul>
&lt;li>需要在类 linux shell 下工作：&lt;strong>用 &lt;a href="https://hyper.is/">&lt;code>Hyper&lt;/code>&lt;/a>&lt;/strong>
&lt;ul>
&lt;li>&lt;code>git bash&lt;/code> 一点不好的就是它太丑了，我配了好久都没配出好看的感觉&lt;/li>
&lt;li>&lt;code>Hyper&lt;/code> 我用的主题是 &lt;a href="https://github.com/yui540/hyper-akari">&lt;code>hyper-akari&lt;/code>&lt;/a>, 是一个我非常喜欢的 &lt;a href="https://yui540.graphics">CSS 魔法哥&lt;/a>的作品&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>有很多一定要在 linux 下才能做的事情：&lt;strong>那就去 linux 下做吧&lt;/strong>
&lt;ul>
&lt;li>目前做的后端是可以完美跨平台开发测试的&lt;/li>
&lt;li>对于特定的功能会用 fake/mock 给滤掉，不妨碍开发体验&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;p>至于其它的体验上的软件，&lt;br>
就属于见仁见智各取所需的事情啦。&lt;br>
最后附上一些我的小习惯：&lt;/p>
&lt;ul>
&lt;li>统一管理所有软件的配置，都放在了 &lt;a href="https://github.com/LKI/LKI">github.com/LKI/LKI&lt;/a> 里面。&lt;/li>
&lt;li>在统一的 workspace 下放代码 （我用的是 &lt;code>C:\Code&lt;/code>）&lt;/li>
&lt;li>用 &lt;code>ss + Proxifier + SwichyOmega&lt;/code> 实现复杂规则下的科学上网。&lt;/li>
&lt;li>:wink: 用 &lt;code>Vim&lt;/code>&lt;/li>
&lt;/ul>
&lt;p>（完）&lt;/p></description></item><item><title>技术人员要怎么选择自己的职业发展道路</title><link>https://liriansu.com/posts/2018-10-25-company-stategy/</link><pubDate>Thu, 25 Oct 2018 23:35:26 +0000</pubDate><guid>https://liriansu.com/posts/2018-10-25-company-stategy/</guid><description>&lt;blockquote>
&lt;p>这篇文章的灵感来自于最近的一次跟好友聊天。&lt;/p>
&lt;/blockquote>
&lt;p>临近毕业的时候，我要找工作了。&lt;br>
但是当时的我其实非常懵逼：&lt;/p>
&lt;ul>
&lt;li>我没有职业发展规划，我甚至连我想进什么样的公司都没偏好（反正我只能写代码）&lt;/li>
&lt;li>就算我有偏好（比如钱多事少离家近），我也不知道哪个公司符合我的偏好&lt;/li>
&lt;li>即使我知道有这样的公司（比如我想象中的谷歌），我也不一定能进&lt;/li>
&lt;li>网上/生活里别人关于职业发展的说法五花八门（比如写代码是吃青春饭），甚至还互相冲突&lt;/li>
&lt;/ul>
&lt;p>于是我秉承着车到山前必有路的快乐心态，&lt;br>
去了第一家给我发 offer 的公司。&lt;br>
（结果工作出人预料地鱼块，详情参见&lt;a href="https://liriansu.com/adult-life">《前文》&lt;/a>）&lt;/p>
&lt;p>如今的我再回头去审视这种青涩的想法，&lt;br>
我最大的感慨是：&lt;br>
信息量的多寡，的确是决策好坏的决定性因素啊。&lt;/p>
&lt;p>我觉得当时我的懵逼是完全正常，&lt;br>
而且我的决策机制（去第一家合适的）也是没有大问题的。&lt;br>
因为我现在是这么想的：&lt;/p>
&lt;ul>
&lt;li>没有最佳策略，只有你最赞赏的策略&lt;/li>
&lt;li>不仅要靠自我奋斗，还要考虑到历史的进程&lt;/li>
&lt;li>目标往往不是一开始就定死的，而是要不断更新的&lt;/li>
&lt;/ul>
&lt;h2 id="没有最佳策略">没有最佳策略&lt;/h2>
&lt;p>人在面对选择题的时候，&lt;br>
总想找出正确答案。&lt;br>
但不是所有选择都是选择题，&lt;br>
总有选择是没有标准答案的，&lt;br>
这个时候人就会想选C。&lt;/p>
&lt;p>比如职业相关的话题，&lt;br>
总会出现这一类问题：&lt;br>
“是去大厂比较好？还是去创业型公司？”&lt;/p>
&lt;p>的确，在信息量不足的情况下，&lt;br>
这种问题是非常难以回答的。&lt;br>
Richard Liu 有一篇写的蛮好的文章&lt;a href="https://zhuanlan.zhihu.com/p/46702362">《职场抉择：我适合大公司，独角兽，还是幼角兽？》&lt;/a>就是讲这个话题的。&lt;/p>
&lt;p>这几种公司的优点代表了不同的策略：&lt;/p>
&lt;ul>
&lt;li>创业公司：机会极多，非常自由，事情做成的话成就感巨高。适合适应能力强，想独当一面的人。&lt;/li>
&lt;li>独角兽：未来可期，各方面都比较优秀，团队水平会比较高。适合业务能力突出，想快速成功的人。&lt;/li>
&lt;li>大厂：发展稳定，社会影响力大，工作不会侵占过多个人生活。适合在意公私平衡，想稳定工作的人。&lt;/li>
&lt;/ul>
&lt;p>比如有朋友跟我聊过他的跳槽策略，&lt;br>
就是挑着C轮/D轮的独角兽公司去，&lt;br>
只要趋势不变的话，&lt;br>
一两年公司就可以上市，&lt;br>
然后再过两三年期权就可以套现。&lt;br>
这样他就可以用他优秀的工作技能，&lt;br>
获得不错的报酬。&lt;/p>
&lt;p>不过我个人来说不会选择这样的策略。&lt;br>
我认为人类的事业感受可以分为这么六个方面：&lt;/p>
&lt;ul>
&lt;li>报酬：劳动获取的劳动等价物（钱）是否满意？&lt;/li>
&lt;li>业务：对做的事情本身是否有成就感？&lt;/li>
&lt;li>体验：工作的体验（环境/制度）是否舒适？&lt;/li>
&lt;li>发展：工作内容是否稳定？对工作的未来是否有期待？&lt;/li>
&lt;li>生活：与工作交叉的人生（通勤/假期）是否舒服？&lt;/li>
&lt;li>团队：跟一起共事的人是否开心？&lt;/li>
&lt;/ul>
&lt;p>最理想的工作，就是这几个问题的回答都是正面的。&lt;br>
不过很多时候看到这样的问题，&lt;br>
感受到的反而是一种无力感：&lt;br>
我的工作对我影响很大，但很多地方好像无法改变。&lt;/p>
&lt;p>这就对了，就是这样的。&lt;/p>
&lt;h2 id="历史的进程">历史的进程&lt;/h2>
&lt;blockquote>
&lt;p>一个人的命运啊，当然要靠自我奋斗，但是也要考虑到历史的进程。&lt;/p>
&lt;/blockquote>
&lt;p>这句话很多人都听过，是江学长视察联合工程公司的时候说的。&lt;br>
有一个我经常举的栗子，道理也是类似的：&lt;/p>
&lt;p>一个人的发展，其实是乘法原理导致的。&lt;br>
蚍蜉和大树是很好的朋友，&lt;br>
蚍蜉在 Hooli 的广告部门工作，经常划水；&lt;br>
大树在 PiedPiper 的业务部门工作，朝九晚十，一周六天。&lt;br>
一年下来，Hooli 稳定发展，增长了 20%，&lt;br>
广告部门增长更快，增长了 50%，&lt;br>
蚍蜉有点划，其他同事评分都是 A，就他是个 B。&lt;br>
而大树呢，工作认真，贡献突出，个人评分 A++，&lt;br>
但是 PiedPiper 今年业绩一般，只增长了 5%，&lt;br>
大树所在的业务部门更是业绩下滑了 20%。&lt;br>
结果 Hooli 因为发展快速，蚍蜉都成了个小 Manager 开始带人了；&lt;br>
而大树所在的整个业务线都要被砍掉裁员。&lt;/p>
&lt;p>用优雅的数学来归纳这个粗糙的故事就是：&lt;br>
&lt;code>个人的成长 = 个人 * 团队 * 公司 * 历史的进程&lt;/code>。&lt;/p>
&lt;p>就像很多独角兽公司都会引用的那句话：&lt;/p>
&lt;blockquote>
&lt;p>if you&amp;rsquo;re offered a seat on a rocket ship,&lt;br>
you don&amp;rsquo;t ask what seat.&lt;br>
You just get on.&lt;/p>
&lt;p>&amp;ndash; Eric Schmidt&lt;/p>
&lt;/blockquote>
&lt;p>所以假如有机会的话，&lt;br>
在面试一家公司的时候，&lt;br>
去跟你未来的队友们聊一聊吧。&lt;br>
初创公司的话，看看创始人是怎么样的；&lt;br>
公司分了不同的部门以后，看看部门Leader是什么样的人；&lt;br>
扁平化的工作氛围，就跟（潜在）未来的队友们聊聊。&lt;br>
在合适的氛围、优秀的团队里，&lt;br>
个人的成长会有最大的加速度。&lt;/p>
&lt;h2 id="不断更新的目标">不断更新的目标&lt;/h2>
&lt;p>小时候想当科学家，&lt;br>
大学想当CEO，&lt;br>
毕业以后想当CTO，&lt;br>
面试的时候觉得当架构师不错，&lt;br>
入职了以后想想就当个后端吧，&lt;br>
现在觉得写好 Python 业务代码才是真切的目标。&lt;br>
以上就是“更新的目标”的含义了（并不&lt;/p>
&lt;p>认真地讲，&lt;br>
我感觉在工作里除了具体技能的提升，&lt;br>
还有一部分很重要的是&lt;strong>掌握信息量的增多&lt;/strong>。&lt;br>
在信息量不足的时候，&lt;br>
人类是很难做出最佳的选择的。&lt;br>
这也是为什么我们写程序的时候，&lt;br>
总会想问清楚“需求是什么？”“以后业务逻辑可能会怎么变？”&lt;br>
随着信息量的增大，&lt;br>
人类总可以做出合适的决策。&lt;/p>
&lt;p>所以其实接触工作的过程，&lt;br>
其实也是一个人不断扩充信息量，&lt;br>
然后根据掌握的信息，&lt;br>
不断修正目标的过程。&lt;/p>
&lt;h2 id="总结">总结&lt;/h2>
&lt;p>所以对于主题“技术人员要怎么选择自己的职业道路”，&lt;br>
这篇文章客套地讲了一些虚的道理：&lt;/p>
&lt;ul>
&lt;li>选择合适的策略来找到心仪的公司&lt;/li>
&lt;li>注意工作的团队也是非常重要的&lt;/li>
&lt;li>在信息量增大时，及时更新目标&lt;/li>
&lt;/ul>
&lt;p>emmmmmm, 感觉这里的道理有点太虚了。&lt;br>
那我们就在接下来的文章里讲一些具体的干货吧 XD&lt;br>
祝大家都能找到自己心仪的事业，并且为之奋斗一生~&lt;/p>
&lt;p>（完）&lt;/p></description></item><item><title>2018 QCon 第一天早上参会有感</title><link>https://liriansu.com/posts/2018-10-18-qcon-2018-shanghai/</link><pubDate>Thu, 18 Oct 2018 18:54:24 +0000</pubDate><guid>https://liriansu.com/posts/2018-10-18-qcon-2018-shanghai/</guid><description>&lt;p>其实这次的 QCon 一共有三天，&lt;br>
但是我只去了半天。&lt;/p>
&lt;p>前几个月 QCon 临近，&lt;br>
老大豪气干云地一挥：&lt;br>
“今年我们买票去听 QCon！”&lt;br>
于是我们非常开心地到网站上一看，&lt;br>
一张票几千人民币…&lt;br>
……&lt;br>
预算不多的我们只能在力所能及的范围内买一些票，&lt;br>
然后把每张票拆成好几块，&lt;br>
让尽可能多的同学都去感受一下“全球软件开发大会”的氛围。&lt;br>
（QCon 的中文名真的是叫这个！）&lt;/p>
&lt;p>这次我就去听了个早上，&lt;br>
在主会场彭蕾/臧秀涛致辞以后，&lt;br>
听了三场讲师的分享。&lt;/p>
&lt;h1 id="java-api-design-best-practices">Java API Design Best Practices&lt;/h1>
&lt;p>第一场本来是个老外讲 Go 的，&lt;br>
但好像路上堵车没能来得及到会场，&lt;br>
所以临时换了个讲 Java 的老外。&lt;/p>
&lt;p>这位老哥叫 Jonathan，&lt;br>
呆的公司一路是 Sun/Oracle/Microsoft，&lt;br>
介绍完自己以后，&lt;br>
PPT 突然切到了 &amp;lt;Effective Java (3rd)&amp;gt;,&lt;br>
然后 Jonathan 吹了一波：&lt;br>
“这可是写 Java 的程序员都必看的一本书！”&lt;/p>
&lt;p>然后话题逐渐切入正轨，Jonathan 提出了好的 API 会有的几个特质：&lt;/p>
&lt;ul>
&lt;li>易懂的 (Understandable)&lt;/li>
&lt;li>稳定的 (Consistent)&lt;/li>
&lt;li>合适的 (Fit for purpose)&lt;/li>
&lt;li>文档好 (Well documented)&lt;/li>
&lt;li>节制的 (Restrained)&lt;/li>
&lt;li>可进化 (Evolvable)&lt;/li>
&lt;/ul>
&lt;p>然后 Jonathan 用具体的例子穿插着讲了一下他对这几个特质的理解。&lt;/p>
&lt;p>我听下来感觉抛去具体的语法例子，&lt;br>
优秀的 API 特质都是共通的，&lt;br>
就像之前写的&lt;a href="https://liriansu.com/api-design-in-python">《优雅的 Python 接口设计》&lt;/a>一样。&lt;/p>
&lt;p>最后 Jonathon 又吹了一波 &lt;!-- raw HTML omitted -->，&lt;br>
并且还极力宣传说：“你们这些只看过第二版的，记得买第三版看看啊…”&lt;br>
简直让人怀疑这本书给他分成了（x&lt;/p>
&lt;h1 id="腾讯微服务架构的过去现在与未来">腾讯微服务架构的过去、现在与未来&lt;/h1>
&lt;p>休息了一会儿，就到了腾讯讲师刘昕的回合了。&lt;/p>
&lt;p>虽然话题是微服务框架，&lt;br>
但是感觉大部分时间刘昕都在宣传自家框架 &lt;a href="https://github.com/tarscloud">Tars (github.com/TarsCloud)&lt;/a>&amp;hellip;&lt;/p>
&lt;p>不过整体讲的逻辑还是很清晰的：&lt;/p>
&lt;ul>
&lt;li>最早遇到了业务逻辑复杂、代码质量难控、运营管理混乱、监控体系缺失的问题。&lt;/li>
&lt;li>后来在“大系统小做”的指导思想下，逐步开始统一框架。&lt;/li>
&lt;li>框架是首先实现了服务调用+服务治理的基础功能。&lt;/li>
&lt;li>然后提升了性能+易用性。&lt;/li>
&lt;li>现在还引入了容器化+高拓展性（其实到这一步就可以开源推广了）&lt;/li>
&lt;/ul>
&lt;p>刘昕用的 PPT 里有两个很好玩的数据。&lt;br>
一个是 51% 都考虑往 Cloud Native 的架构转。&lt;br>
这个数据引出的话题是一个很不错的话题，&lt;br>
让 AWS 重度用户很想说些什么，&lt;br>
感觉下次可以专门码一篇文章。&lt;/p>
&lt;p>还有一个是用 服务治理/多语言 的不严谨划分成的四象限：&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/micro_services.jpg" alt="MS">&lt;/p>
&lt;p>非常有趣。&lt;/p>
&lt;p>最后刘昕还花了不少时间讲了一下 TARS 支持的多门语言。&lt;br>
听了以后我很佩服（然后选择了 service mesh&amp;hellip;）&lt;/p>
&lt;h1 id="the-past-present-and-future-of-go-2">The Past, Present, and Future of GO 2&lt;/h1>
&lt;p>休息了一会儿后，本应第一个开讲的 David Chaney 终于来啦。&lt;br>
（@hulucc 问：他跟 Go 啥关系啊？&lt;br>
@紫月酥 答：应该就像 @jkzing 跟 VueJS 的关系一样，是核心 Contributor。）&lt;/p>
&lt;p>一开始 David 讲了很多历史，&lt;br>
比如 Go 诞生的初衷，&lt;br>
Go 从小长大一路走过的路，&lt;br>
软工和编码的区别，&lt;br>
Go 多个版本的更新，&lt;br>
现在用 Go 的公司/团队/项目之类的…&lt;br>
听得我感觉又是一个典型的布道师，&lt;br>
就当是给纯萌新科普 Go 了…&lt;/p>
&lt;p>然后！&lt;br>
David 突然又介绍了一波 gopher 这个萌物：&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/gopher.jpg" alt="gopher">&lt;/p>
&lt;p>（感觉全场一下子就四老外兴奋.jpg起来了）&lt;/p>
&lt;p>在漫长的铺垫以后，&lt;br>
David 终于讲到了 Go 面临并且要解决的三个大的问题：&lt;/p>
&lt;ul>
&lt;li>依赖管理 (Dependency management)&lt;/li>
&lt;li>错误处理 (Error handling)&lt;/li>
&lt;li>泛型 (Generics)&lt;/li>
&lt;/ul>
&lt;p>听到这里，我一拍大腿：&lt;br>
“对对对！我当时就是因为这个弃坑的！”&lt;/p>
&lt;p>随之 David 不紧不慢地用各种小例子给出了目前的解决方案：&lt;/p>
&lt;ul>
&lt;li>Go 1.11 里已经可以用 go modules 来管理依赖了。（初见的我有种 node_modules 的熟悉即视感）&lt;/li>
&lt;li>Go 2 里会引入 check/handle 等语法糖来处理错误，本质上还是要第一时间让程序员自己处理错误的&lt;/li>
&lt;li>Go 2 里会有泛型，目前可能会引入 contract。（但具体怎么搞，我感觉我这里没太听明白，之后得去深入看看）&lt;/li>
&lt;/ul>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/generic_dilemma.jpg" alt="generic">&lt;/p>
&lt;p>而后 David 还特别强调了一下，&lt;br>
Go2 和 Go1 只是大版本不一样，&lt;br>
“是不会像 Python3 或者 Perl6 那样滴…”&lt;/p>
&lt;h1 id="感想">感想&lt;/h1>
&lt;p>主会场第一天上午到此就全部结束了。&lt;br>
整体下来，我感觉对眼界增长大于技术收获。&lt;br>
可以知道同僚都在朝着什么方向去深耕也是非常不错的收获。&lt;/p>
&lt;p>2018年的最后一个季度肯定会再次把 Go 给捡起来认真玩一下…&lt;br>
（不过没有参数默认值真的写起来很难受啊.jpg）&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/qcon.jpg" alt="qcon">&lt;/p>
&lt;p>（完）&lt;/p></description></item><item><title>优雅的 Python 接口设计</title><link>https://liriansu.com/posts/2018-09-21-api-design-in-python/</link><pubDate>Fri, 21 Sep 2018 20:57:46 +0000</pubDate><guid>https://liriansu.com/posts/2018-09-21-api-design-in-python/</guid><description>&lt;p>今天跟&lt;a href="https://github.com/hulucc">@hulucc&lt;/a> 日常写码吹比，&lt;br>
讲到了选第三方库的原则说：&lt;br>
“我其实发现我现在选库不太 care 他源码是怎么实现的，&lt;br>
但是我非常喜欢那些 api 设计得巨科学的库。”&lt;/p>
&lt;h2 id="科学的-api">科学的 API&lt;/h2>
&lt;p>API 设计的科学大概是什么样的呢？&lt;br>
比如举一个有名的例子就是 &lt;a href="https://github.com/requests/requests">requests&lt;/a> 这个库。&lt;/p>
&lt;blockquote>
&lt;p>Requests is one of the most downloaded Python packages of all time,&lt;br>
pulling in over 11,000,000 downloads every month.&lt;/p>
&lt;/blockquote>
&lt;p>这个库的 API 用起来大概是这样的：&lt;/p>
&lt;pre tabindex="0">&lt;code>&amp;gt;&amp;gt;&amp;gt; response = requests.get(&amp;#39;https://api.github.com/user&amp;#39;, auth=(&amp;#39;user&amp;#39;, &amp;#39;pass&amp;#39;))
&amp;gt;&amp;gt;&amp;gt; response.status_code
200
&amp;gt;&amp;gt;&amp;gt; response.headers[&amp;#39;content-type&amp;#39;]
&amp;#39;application/json; charset=utf8&amp;#39;
&amp;gt;&amp;gt;&amp;gt; response.encoding
&amp;#39;utf-8&amp;#39;
&amp;gt;&amp;gt;&amp;gt; response.raise_for_status()
&lt;/code>&lt;/pre>&lt;p>这里设计的所有 Python 程序语言都是见文知意的英文人类语言，&lt;br>
&lt;code>requests.get&lt;/code> 中的 &lt;code>requests&lt;/code> 不仅是包名，&lt;br>
还化身成了代码语义的一部分。&lt;br>
返回的 &lt;code>response&lt;/code> 就是一个典型的 HTTP 协议对象，&lt;br>
只要对 HTTP 协议有一定了解的程序员，&lt;br>
基本上不用看文档都能猜到它的主要属性和相关作用。&lt;br>
对应还有便捷的 &lt;code>.raise_for_status()&lt;/code> 和 &lt;code>.json()&lt;/code> 这样的常用方法。&lt;br>
这就是科学的 API 给我的感受。&lt;/p>
&lt;p>当然，库的作者（也就是那个帅哥 &lt;a href="https://github.com/kennethreitz">Kenneth Reitz&lt;/a>）也清楚自己的代码接口优雅，&lt;br>
他的个人签名也是这么说的：&lt;/p>
&lt;blockquote>
&lt;p>I wrote @requests: HTTP for Humans.&lt;br>
The only thing I really care about is interface design.&lt;br>
&amp;ndash; Kenneth Reitz&lt;/p>
&lt;/blockquote>
&lt;h2 id="不科学的-api">不科学的 API&lt;/h2>
&lt;p>大部分开源高星项目的接口都是比较优雅的，&lt;br>
那么不科学的 API 大概是什么样子呢？&lt;br>
唔，我的话，翻一翻自己两三年前的代码，&lt;br>
就满是不科学的 API 实现了。&lt;/p>
&lt;p>最早接触 &lt;code>**kwargs&lt;/code> 这个东西的时候，&lt;br>
我非常喜欢用这个语法，&lt;br>
比如我常常会写这么一种函数：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">Record&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">def&lt;/span> &lt;span style="color:#a6e22e">create&lt;/span>(&lt;span style="color:#f92672">**&lt;/span>kwargs):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> now &lt;span style="color:#f92672">=&lt;/span> kwargs&lt;span style="color:#f92672">.&lt;/span>get(&lt;span style="color:#e6db74">&amp;#39;now&amp;#39;&lt;/span>, datetime&lt;span style="color:#f92672">.&lt;/span>datetime&lt;span style="color:#f92672">.&lt;/span>now())
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> key &lt;span style="color:#f92672">=&lt;/span> kwargs&lt;span style="color:#f92672">.&lt;/span>get(&lt;span style="color:#e6db74">&amp;#39;key&amp;#39;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> value &lt;span style="color:#f92672">=&lt;/span> kwargs&lt;span style="color:#f92672">.&lt;/span>get(&lt;span style="color:#e6db74">&amp;#39;value&amp;#39;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">...&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>这样写的好处是看起来灵活的一比，实现起来爽。&lt;br>
以后假如要加参数，&lt;br>
往往只要在 &lt;code>record.create&lt;/code> 里面加一个新的 &lt;code>kwargs.get&lt;/code> 就行了。&lt;br>
然而在大部分情况，这样的实现只会把参数给隐式化：&lt;br>
记不住参数调用 &lt;code>record.create&lt;/code> 的时候还得进函数看实现；&lt;br>
而且万一把 &lt;code>value&lt;/code> 拼错成了 &lt;code>valeu&lt;/code>，&lt;br>
函数是会像某些语言一样正常运行的！&lt;br>
然后会在后面某个地方报错，&lt;br>
这样就很难方便找出根源了。&lt;/p>
&lt;p>后来我大部分情况会这么写：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">Record&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">def&lt;/span> &lt;span style="color:#a6e22e">create&lt;/span>(now&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#66d9ef">None&lt;/span>, key&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#66d9ef">None&lt;/span>, value&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#66d9ef">None&lt;/span>):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> now &lt;span style="color:#f92672">is&lt;/span> &lt;span style="color:#66d9ef">None&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> now &lt;span style="color:#f92672">=&lt;/span> datetime&lt;span style="color:#f92672">.&lt;/span>datetime&lt;span style="color:#f92672">.&lt;/span>now()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">...&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>这样的显式调用强制要求参数的正确性，&lt;br>
虽然实现起来要写的参数多了，&lt;br>
但是调用和阅读的时候更加明确。&lt;/p>
&lt;pre tabindex="0">&lt;code>&amp;gt;&amp;gt;&amp;gt; import this
The Zen of Python, by Tim Peters
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren&amp;#39;t special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you&amp;#39;re Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it&amp;#39;s a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let&amp;#39;s do more of those!
&lt;/code>&lt;/pre>&lt;p>后来我看到 &lt;code>The Zen of Python&lt;/code> 的这句 &lt;code>Explicit is better than implicit&lt;/code> 总会想到这个例子。&lt;br>
（关于 Python 接口参数设计的，有一篇我觉得说的很好的知乎文章：&lt;br>
&lt;a href="https://zhuanlan.zhihu.com/p/25017419">《Python函数接口的一些设计心得 - 灵剑》&lt;/a>）&lt;/p>
&lt;h2 id="例子">例子&lt;/h2>
&lt;p>&lt;code>The Zen of Python&lt;/code> 里还有非常多珠玑可以挖掘。&lt;br>
比如在做的一个项目 &lt;a href="https://github.com/zaihui/hutils">hutils&lt;/a>，&lt;br>
想着把公司里各种 Python Web 中常用到的函数抽出来做个基础库，&lt;br>
结果写的时候 80% 的时间都在想怎么让 API 变的更科学。&lt;/p>
&lt;p>比如我们写后端的时候，&lt;br>
经常会遇到要转化框架错误类的情况：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">def&lt;/span> &lt;span style="color:#a6e22e">service_call&lt;/span>(&lt;span style="color:#f92672">...&lt;/span>):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">try&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> external_service&lt;span style="color:#f92672">.&lt;/span>call()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">except&lt;/span> ExternalServiceError &lt;span style="color:#66d9ef">as&lt;/span> ex:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> log_error(ex)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">raise&lt;/span> APIError(&lt;span style="color:#e6db74">&amp;#39;Error calling external service&amp;#39;&lt;/span>)
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>对应的，我们会有个这样的装饰器来封装错误处理：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">@contextlib&lt;/span>&lt;span style="color:#f92672">.&lt;/span>contextmanager
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">def&lt;/span> &lt;span style="color:#a6e22e">catches&lt;/span>(&lt;span style="color:#f92672">*&lt;/span>exceptions,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> raise_to: &lt;span style="color:#a6e22e">BaseException&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">None&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> raise_from: Callable[[&lt;span style="color:#a6e22e">Exception&lt;/span>], &lt;span style="color:#a6e22e">BaseException&lt;/span>] &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">None&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> log&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#66d9ef">False&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ignore&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#66d9ef">False&lt;/span>):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">try&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">yield&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">except&lt;/span> exceptions &lt;span style="color:#66d9ef">as&lt;/span> ex:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> log:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> log_error(ex)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">not&lt;/span> ignore:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> raise_from:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">raise&lt;/span> raise_from(ex)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">else&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">raise&lt;/span> raise_to &lt;span style="color:#75715e"># pylint: disable=raising-bad-type&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>有了封装的装饰器以后，&lt;br>
简单的错误转化就可以跟业务代码相分离：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">@catches&lt;/span>(ExternalServiceError, raise_to&lt;span style="color:#f92672">=&lt;/span>APIError(&lt;span style="color:#e6db74">&amp;#39;Error calling external service&amp;#39;&lt;/span>), log&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#66d9ef">True&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">def&lt;/span> &lt;span style="color:#a6e22e">service_call&lt;/span>(&lt;span style="color:#f92672">...&lt;/span>):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> external_service&lt;span style="color:#f92672">.&lt;/span>call()
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>但是这样的装饰器实现会在 Code Review 阶段就会被像 &lt;a href="https://github.com/hulucc">@hulucc&lt;/a> 这样的铁血队友锤回来，&lt;br>
这样的 API 实现有几个不够科学的地方：&lt;/p>
&lt;ul>
&lt;li>&lt;code>raise_to&lt;/code> 和 &lt;code>raise_from&lt;/code> 有重叠之处，&lt;br>
而且调用者不注意的话会触发 &lt;code>raise None&lt;/code> 的问题，&lt;br>
连 &lt;code>pylint&lt;/code> 都注意到了。&lt;br>
应当使用类型判断来合并参数。&lt;/li>
&lt;li>这样错误转化，原错误类的堆栈信息会丢失。&lt;br>
应当使用 &lt;code>raise ... from ...&lt;/code> 的语法来保留堆栈信息。&lt;/li>
&lt;li>&lt;code>transfer&lt;/code>/&lt;code>ignore&lt;/code>/&lt;code>retry&lt;/code> 其实是相对独立的逻辑，&lt;br>
混合处理当然可以，&lt;br>
不过最好的情况是逻辑拆分，独立处理。&lt;/li>
&lt;/ul>
&lt;p>一波讨论以后，&lt;br>
顺带顺手支持 &lt;code>catches(Exception, raises=raise_api_error)&lt;/code> 的快捷写法，&lt;br>
装饰器的实现就改成了这样子。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">@contextlib&lt;/span>&lt;span style="color:#f92672">.&lt;/span>contextmanager
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">def&lt;/span> &lt;span style="color:#a6e22e">catches&lt;/span>(&lt;span style="color:#f92672">*&lt;/span>exceptions, raises: Union[&lt;span style="color:#a6e22e">BaseException&lt;/span>, Callable[[&lt;span style="color:#a6e22e">Exception&lt;/span>], &lt;span style="color:#a6e22e">BaseException&lt;/span>]], log&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#66d9ef">False&lt;/span>):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> exceptions &lt;span style="color:#f92672">=&lt;/span> exceptions &lt;span style="color:#f92672">or&lt;/span> (&lt;span style="color:#a6e22e">Exception&lt;/span>,)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">try&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">yield&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">except&lt;/span> exceptions &lt;span style="color:#66d9ef">as&lt;/span> ex:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> callable(raises):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> raises &lt;span style="color:#f92672">=&lt;/span> raises(ex)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> log:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> log_error(__name__, raises)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">raise&lt;/span> raises &lt;span style="color:#f92672">from&lt;/span> ex
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>感觉更加优雅了呢。&lt;/p>
&lt;h2 id="结语">结语&lt;/h2>
&lt;p>Python 因为语法及其灵活，&lt;br>
所以其实接口的设计是全看程序员的设计水平的。&lt;br>
但往往科学又优雅的实现就像 &lt;code>There should be one-- and preferably only one --obvious way to do it&lt;/code> 这句话说的一样，&lt;br>
是万中取一的。&lt;/p>
&lt;p>不仅要实现功能，&lt;br>
还要优雅，不要污。&lt;br>
看来写程序的确是要想得多，&lt;br>
怪不得程序员会头发少呀 :)&lt;/p>
&lt;p>（完）&lt;/p></description></item><item><title>毕业三年的报告</title><link>https://liriansu.com/posts/2018-09-09-adult-life/</link><pubDate>Sun, 09 Sep 2018 19:46:37 +0000</pubDate><guid>https://liriansu.com/posts/2018-09-09-adult-life/</guid><description>&lt;p>前阵子在知乎上看到一个问题，&lt;br>
叫&lt;a href="https://www.zhihu.com/question/31907973">《读研三年与工作三年的人有哪些差别》&lt;/a>。&lt;br>
我的思绪突然被唤醒了：&lt;br>
对哦，原来我已经毕业了三年了。&lt;/p>
&lt;blockquote>
&lt;p>注意，本文有一万字，可能要读个半小时？&lt;/p>
&lt;/blockquote>
&lt;p>我跟小米娅的工作习惯都比较类似，&lt;br>
前阵子闲聊的时候我们算了一下：&lt;br>
正常的朝九晚六加双休，&lt;br>
一周是工作 40 小时；&lt;br>
不过因为我们两个人基本上下班以后还会看工作相关的事情，&lt;br>
平均下来工作日会多工作 2 小时，&lt;br>
周末还会有一天干职业相关的事情，&lt;br>
所以满打满算可以说一周工作 60 小时。&lt;br>
嚯。也就是说我们工作两年，就有四年工作经验了。&lt;br>
赚翻了耶。&lt;/p>
&lt;p>当然了，这个工作经验 buff 只是说着玩的。&lt;br>
认真地说，要算工作经验的话，&lt;br>
我更愿意从 2014年7月7日 算起，&lt;br>
那是作为实习生的我第一份工作的 First Day（定语真多）。&lt;/p>
&lt;h2 id="实习">实习&lt;/h2>
&lt;h3 id="通勤">通勤&lt;/h3>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/adult/2014-07-07.png" alt="pic1">&lt;/p>
&lt;p>我们大学的设定是大四一年是给你实习的，&lt;br>
然后我因为硬学习成绩不算好，&lt;br>
考不动研也想早点致用，&lt;br>
所以抱着找一份实习工作，&lt;br>
然后毕业以后转正成为正式工的想法。&lt;/p>
&lt;p>当时 &lt;a href="lazy-coding-thinking">QAD(一家美资跨国软件公司)&lt;/a> 跑来学校校招，&lt;br>
我就去参加了面试。&lt;br>
面试的流程是笔试 + 群面 + 单面，&lt;br>
跟 NIMO (交大网管部) 的面试流程极为相似。&lt;/p>
&lt;p>&lt;del>所以我熟练地就通过了。（并没有）&lt;/del>&lt;br>
我其实填完了姓名和手机就愣住了，&lt;br>
因为第三个空叫“目标职位”，&lt;br>
有 SE, QA 和 BA 个选项可以勾选。&lt;br>
我便举手问了负责发试卷的 HR 小姐姐 Gloria，&lt;br>
Gloria 跟我说你软件学院的就填 SE 吧，&lt;br>
其它两个不用填，我就顺从地填了 SE。&lt;/p>
&lt;p>后来我才知道要填职位是因为公司分工所致的：&lt;/p>
&lt;ul>
&lt;li>QAD 在全球各个地方都设有研发中心，中国的研发中心设在上海。&lt;/li>
&lt;li>当然了，上海其实不止有研发，还有销售、售后等等部门。&lt;/li>
&lt;li>研发部门正式的说法叫 Research and Development, 写作 R&amp;amp;D, 读作 R and D。&lt;/li>
&lt;li>R&amp;amp;D 按照业务团队拆分成了好几个小组，我在的组是 Release Foundation, 中文意思大概是基础组件组，人多的时候大概有 20 个人。&lt;/li>
&lt;li>R&amp;amp;D 里每个组都是具有独立作战能力的，从技术选型、前端、后端到测试都是自己组内搞定。&lt;/li>
&lt;li>所以其实我们组内就两种职位：SE(开发) 和 QA(测试)，BA 是更一线的业务相关开发组才会设立的职位。&lt;/li>
&lt;/ul>
&lt;p>在实习了一个月以后终于搞明白了公司分工这个问题，&lt;br>
我很是兴奋，因为我觉得这是公司的脉络。&lt;br>
一个公司能成长到跨国的程度，&lt;br>
那公司组织结构什么的肯定是科学的！&lt;br>
学到了，以后有一天我开跨国公司了，&lt;br>
我也这么搞！&lt;br>
我很开心地这么想着。&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/adult/2014-07-07-2.png" alt="pic2">&lt;/p>
&lt;p>后来我才知道还有是按职能分工的制度。&lt;br>
不过我一直沿用了跟别人介绍公司时，&lt;br>
先介绍公司业务范围、&lt;br>
再介绍公司分工组成、&lt;br>
最后介绍团队相关技术内容的套路。&lt;br>
因为我就很吃这样的套路呀 :)&lt;/p>
&lt;h3 id="通勤-1">通勤&lt;/h3>
&lt;p>不过实习的时候有一点我很困扰的是，&lt;br>
公司在浦东陆家嘴软件园，&lt;br>
学校在闵行。&lt;br>
算上走路每天单程得两小时，&lt;br>
来回四小时就没了。&lt;/p>
&lt;p>有些同学选择了在公司旁边合租了个房间。&lt;br>
不过我看了一下我的实习工资，&lt;br>
感觉付费上班有点亏，&lt;br>
就约着同在一家公司实习的李超一起每天 06:45 起床，&lt;br>
06:50 出门赶在 09:00 前到公司。&lt;/p>
&lt;p>公司的学长学姐发现我们俩居然选择了每天四小时的通勤，&lt;br>
就开玩笑跟我们说：“你们这样肯定受不了的，两个月内你们肯定会租房，或者要么就离职了…”&lt;br>
感谢这个反向 flag,&lt;br>
实习的一年就算被挤扁在 5 号线的门上，&lt;br>
我也是坚持四小时地铁来回。&lt;br>
并且我还在地铁上补完了想看的动漫和想读的书。&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/adult/2014-07-29.png" alt="pic3">&lt;/p>
&lt;p>《代码大全 (Code Complete)》这本书的中文版和英文版都是在地铁上读完的，&lt;br>
直至今日想起来也清楚地记得，&lt;br>
身边全是上班的社畜只能举起手机仰头读书，&lt;br>
而被书里讲的一段代码陋习深深地震撼到的感觉。&lt;/p>
&lt;h3 id="菜鸟">菜鸟&lt;/h3>
&lt;p>面试的时候，我问 Joe 说组里的开发环境是怎么样的？&lt;br>
Joe 跟我说：“我们开发语言是 Perl 和 PHP，平常都是在 Linux 上用 Vim 开发。你接触过么？”&lt;br>
我尴尬地挠了挠头：“Perl/PHP 只听过，Linux 和 Vim 都只是在课上碰过，根本不了解。”&lt;br>
Joe 安慰道：“没事，写写就熟了。我们每个人都会有一个 Mentor 的。”&lt;/p>
&lt;p>噢 0w0，有 Mentor 啊，那我安心了，我心想。&lt;br>
在网管部我们也有 Mentor 这样的师徒制度，&lt;br>
一个明确的求助对象对新手来说是非常大的心理安慰，&lt;br>
当然最终的修行还是得靠个人的。&lt;/p>
&lt;p>入职的第一天我早到了一个小时，8 点就来了。&lt;br>
结果前台 MM 还没上班，&lt;br>
我站在门外等了十分钟等到了给我开门的扫地阿姨…&lt;br>
道谢以后找到了挂着我工牌的座位，&lt;br>
然后发现我身后已经坐着一个看起来快 30 岁的工程师了。&lt;br>
看了看他的工牌是叫 Justin Zhang,&lt;br>
我十分好奇地问他：“Justin 你好，我叫 Lirian，中文名是苏子岳。你是我的 Mentor 吗？”&lt;br>
Justin 若有所思地回答：“算……是吧？”&lt;br>
（实际上就是的）&lt;/p>
&lt;p>在做完了公司给新人的反腐败、反性侵等在线课程以后（没错…）&lt;br>
我摩拳擦掌地问 Justin 有啥我可以做的么，&lt;br>
Justin 说：“你去了解一下 Vim 吧。”&lt;br>
Emmmmmm, 还没理解这个任务的时候，&lt;br>
Justin 就打开了一个 Vim 的页面：&lt;br>
“我给你展示一下我们平常是怎么看代码、写代码的。”&lt;br>
然后 Justin 便向我展示了一下 Nerdtree/CTags 等各式功能，&lt;br>
并且帮我装上了他的配置 &lt;a href="https://github.com/schnell18/dotvim">(schnell18/dotvim)&lt;/a>…&lt;/p>
&lt;p>于是接下来的几天，我除了公司的新手村任务，&lt;br>
还开心地到处看 Vim 相关的资料（没错，我甚至连 vimtutor 都还没跑。）&lt;br>
越看我越觉得 Vim 这个东西，&lt;br>
真的是像 Justin 说的一样：&lt;br>
“Vim 是一个非常强大的工具，你学 Vim 可能要一个月，但是你用就能用一辈子。”&lt;br>
一开始不熟练的时候，&lt;br>
我经常地就是 jjjjjjjjj 或者 i→→→→→→→→→ 这样操作，&lt;br>
不过由于 Justin 时不时会站在我身后帮我 Review 代码，&lt;br>
在压力和自尊心下，我就改成了 }} 或者 f2$ 这样的操作了…&lt;/p>
&lt;p>我的 Mentor Justin 是一个代码洁癖非常重的工程师。&lt;br>
当时我们的项目管理是用 git + gitolite 管理的，&lt;br>
每次我们提交代码的时候，&lt;br>
Justin 都会用 git diff + vimdiff 来逐行 review 我们的代码。&lt;br>
有的时候需要在命令行敲命令，&lt;br>
Justin 也会站在我身后跟我讲一遍我要敲的命令。&lt;br>
并且以此我从 Justin 那学到了各种符号的英文说法，&lt;br>
比如 横杠 (dash), 反引号 (quote) 等等…&lt;br>
（不过最开始每次 Justin 跟我说 git rev dash list 的时候我都会一愣并且反应半天）&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/adult/2014-08-27.png" alt="pic4">&lt;/p>
&lt;h3 id="忧虑">忧虑&lt;/h3>
&lt;p>慢慢地，我习惯了用 Putty + Vagrant 搭开发环境，&lt;br>
用 Vim + Git 去编辑提交代码，&lt;br>
用 Perl 语言去解决业务问题。&lt;br>
但随着学到的东西越多，&lt;br>
我开始越来越担心自己不能变得杰出。&lt;/p>
&lt;p>那阵子上下班看了不少技术相关的文章/书籍，&lt;br>
其中有两个思想异常地打动我，&lt;br>
一个出自《代码大全》：&lt;/p>
&lt;blockquote>
&lt;p>关于程序员的经验：&lt;/p>
&lt;p>人们还荒唐地强调程序员有多少经验。&lt;br>
“我们需要有五年以上C语言编程经验的程序员”就是愚蠢的说法。&lt;br>
如果程序员过了前一两年还没有学好C语言，那么再加三年也没有意义。&lt;br>
这种“经验”和工作效能关系不大。&lt;/p>
&lt;/blockquote>
&lt;p>我当时看到了这句话，&lt;br>
回头想了一下自己这两周的工作，&lt;br>
发现我其实只是在单纯地挥发自己已有的知识！&lt;br>
我并不想工作三年以后，&lt;br>
成为那种实际只有一年工作经验然后重复了两年的人类。&lt;/p>
&lt;p>还有一个是我在上班路上想明白的。&lt;/p>
&lt;p>我玩竞技游戏会非常累，因为我很想赢。&lt;br>
我想赢也不是因为我多么享受胜利的感觉，&lt;br>
而是我害怕我努力却没有回报的付出回报不对等的挫败感。&lt;br>
所以很多时候我做事情不会尽力，&lt;br>
因为这样即使打团打输了，&lt;br>
我也有理由想：“not my fault，我只出了八成力。”&lt;/p>
&lt;p>但是还没毕业的我又想，&lt;br>
假如我真的选择了一条我不能尽力尽兴的人生道路，&lt;br>
那当我回首往事的时候，我怎会不因虚度年华而悔恨，也不因碌碌无为而羞愧呢？&lt;/p>
&lt;p>于是我在自己的心理暗示环节中，&lt;br>
加入了“比你聪明的人也有比你努力的啊”这一个鸡汤环节。&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/adult/2015-01-27.png" alt="pic5">&lt;/p>
&lt;h2 id="转正">转正&lt;/h2>
&lt;h3 id="现实问题">现实问题&lt;/h3>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/adult/2015-07-05.png" alt="pic6">&lt;/p>
&lt;p>在实习了一年以后，&lt;br>
我顺利地转正了。&lt;br>
我遇到了一个小难题：薪资。&lt;br>
当然，这里说难题并不是说公司为难我或者我不满意什么的。&lt;br>
首先我其实不太在意刚毕业的薪酬，因为我总觉得以后有一天我创造的价值会比我刚毕业一年的薪水还要多；&lt;br>
其次公司也不会压任何员工薪资，给的都是统一水平线的 offer。&lt;/p>
&lt;p>薪资的难题难在我隐隐感觉有点不够用。&lt;br>
大学时候我一个月生活费大概是一千多一些，&lt;br>
非常够用了。&lt;br>
毕业以后假如我要在公司附近租一个带厨房的一室户，&lt;br>
每个月大概要 3500，扣除这么多房租和其它杂项我每个月能剩两千多一些。&lt;/p>
&lt;p>当然了，正常的社会人肯定不会花这么多的占比来租房的。&lt;br>
但我想着我不烟不酒，不买衣服不吃大餐不社交，&lt;br>
回家要么看看技术博客要么玩玩游戏，&lt;br>
而且我女朋友也不是物质狂，&lt;br>
送不了贵的礼物就送点有心意的礼物…&lt;br>
讲道理省省也差不多够用？&lt;br>
于是我果断花了一半的月可支配收入在房租上…&lt;/p>
&lt;p>后来毕业快一年了，&lt;br>
我爸问我：“&lt;br>
你妈妈毕业以后住在外公那里，&lt;br>
毕业工作的一年钱基本全都存下来了，&lt;br>
后来我们结婚你外公还把存的工资都发给你妈妈了。&lt;br>
你这实习加工作两年了，总是存了点钱吧？”&lt;br>
我：“……存了存了…哦我要去洗衣服了，先挂了，886”&lt;/p>
&lt;p>那年我弟高考完去武汉读大学，&lt;br>
我打算送一个最新的 iphone 给他。&lt;br>
当时我去读大学的时候，&lt;br>
我舅送了我一部手提电脑 (Lenovo Y470),&lt;br>
收到礼物后，我心中充满了可支配的自由喜悦之情，&lt;br>
在 QQ 空间发了一条“我有自己的电脑了！开心的要哭了！”&lt;br>
我妈看到以后狠狠地批评了我：“有个电脑就这么没出息吗？快把这条状态删了。”&lt;br>
我：“……”&lt;br>
所以我弟上大学的时候，&lt;br>
我决定也让他体验一下这种可支配的自由喜悦 :)&lt;/p>
&lt;p>在认真算了一下最新 iphone 的价格，&lt;br>
以及我几个月的财政状况以后，&lt;br>
我连续两个月都厚颜无耻地拉着女朋友去吃社会食堂，&lt;br>
并且只点一个荤菜，然后蹭女朋友的青菜。&lt;br>
在吃了两个月的社会食堂以后，&lt;br>
我成功地爱上了掌中宝这道菜。&lt;br>
有一说一，掌中宝是真的好吃。&lt;/p>
&lt;h3 id="last-day">Last Day&lt;/h3>
&lt;p>从实习到转正还有一件对我来说感受很深的事情，&lt;br>
就是 Justin 离职去了平安好医生了。&lt;/p>
&lt;p>外企有一个充满仪式感的离职 Last Day,&lt;br>
在这天你可能会拿着一张 Checklist 一个个地做过去，&lt;br>
然后跟平常一起工作的同事聊聊工作上或者生活上的事情，&lt;br>
再发一封带有你个人联系方式的邮件给全上海再抄送平常对接的各种外国同事，&lt;br>
最后在所有 Checklist 都做完以后早点下班，&lt;br>
结束你在这家公司几年的雇员生涯，开始下一段的工作和人生。&lt;/p>
&lt;p>我看文学作品，&lt;br>
最受不了两种剧情：&lt;br>
一种是美人、英雄迟暮；&lt;br>
一种是再见难的离别。&lt;/p>
&lt;p>直到今天我也能想起 Justin 的 Last Day，&lt;br>
他早上正常地早到了快一个小时，&lt;br>
也正常地处理了事情，&lt;br>
中午组里的同事们正常地在楼下吃了个送别饭，&lt;br>
期间大家聊着以前、以后的事情。&lt;br>
下午四点多，&lt;br>
Justin 背着他的包，&lt;br>
声音不是很大地说了声：“我走了。”&lt;br>
然后大家都站了起来跟 Justin 告别，&lt;br>
在走道的 Justin 也停了下来，&lt;br>
笑容也一直停在了他的脸上，&lt;br>
直到转身离去。&lt;br>
我幽幽地感慨了一句：“Justin 要是再多站两分钟我感觉我都要哭出来了…”&lt;br>
顿时大家都忍不住笑了，&lt;br>
冲散了那股忧郁的离别气息。&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/adult/2015-04-30.png" alt="pic7">&lt;/p>
&lt;p>其实大部分人都不会一辈子只做一份工作，&lt;br>
在 21 世纪的上海也是如此。&lt;br>
所以其实在职场的大家，&lt;br>
也很清楚身边的同事在某一天，&lt;br>
可能会因为各种各样的事情而选择离开。&lt;br>
大家对离职的同事也会抱着祝福的心情，&lt;br>
毕竟世界很大，生命更大，&lt;br>
总有机会再见的。&lt;/p>
&lt;p>后来 Justin 走后的黄桃季节，&lt;br>
我们还是成功地照例蹭到了 Justin 渠道的美味黄桃 :)&lt;/p>
&lt;h3 id="本职工作">本职工作&lt;/h3>
&lt;p>在 Justin 走后，&lt;br>
我逐渐接手了整个项目。&lt;br>
随着新的一年校招，&lt;br>
新的实习生们也来到了公司，&lt;br>
我也变成了一个勤奋的小哥哥 (@Ray) 的 Mentor，&lt;br>
我便像当时 Justin 教我一样教他 Vim、Review 他的代码。&lt;/p>
&lt;p>在跟他交流的过程中，&lt;br>
恍惚间我看到了一年前我的影子，&lt;br>
间接地我对自己的理解更加深入了。&lt;br>
我好像很模糊地抓住了“该怎么样请教别人才能学的更快”、&lt;br>
“工作里要怎么发挥自主性比较合适”这样的概念。&lt;/p>
&lt;p>具体在业务开发里，&lt;br>
因为团队人员配置一直比较科学，&lt;br>
而且大家效率都比较高，&lt;br>
所以我们比预期项目进度早了两个月就开发完了 Perl 的版本。&lt;br>
然后这里我很开心地找到了一个可以写到简历上的事情。&lt;/p>
&lt;p>我很早就感觉到了项目会提早做完，&lt;br>
所以心里一直有个想法在摇曳：&lt;br>
“能不能用 Java 重写一遍这个 Perl 的命令行工具？”&lt;/p>
&lt;p>当时用 Perl 是因为这个命令行工具初版用的是 Perl，&lt;br>
加上 Perl 本身非常适合命令行的文本处理，&lt;br>
以及我们组的开发对 Perl 非常擅长。&lt;br>
但是 Perl 的缺点也很明显：&lt;br>
这不是主流语言，很难招有经验的人，&lt;br>
新手又容易因为学这个看不到前途就加大离职风险，&lt;br>
而且部署上 Perl 的部署跟系统关系挺大，&lt;br>
我们还踩过一个 prelink 跟 Perl 冲突的坑。&lt;br>
相比而言 Java 可能在文本处理上弱了，&lt;br>
但是在人员招聘、部署上会方便很多。&lt;/p>
&lt;p>不过做工程项目，遇到的很大问题就是性价比。&lt;br>
我们 Perl 版本的项目写了快一年，&lt;br>
算上单元测试代码量好像是五万行左右，&lt;br>
上线时间还有两个月，&lt;br>
看起来是不太可行的。&lt;br>
但是我们却把这件事情给做成了。&lt;/p>
&lt;p>整个事情主要是因为当时我的 Manager: Joe 的魄力。&lt;br>
（就是上文实习时候面试我的那个人！）&lt;br>
我中间跟 Joe 讲过 Perl vs Java 的话题，&lt;br>
他首先非常认可我的观点，&lt;br>
并且跟我说关于工程项目上的问题他都可以想办法搞定。&lt;/p>
&lt;p>于是我决定先自己在业余时间尝试用 Java 重写整个项目，&lt;br>
就算最后没用上也算是我练 Java 了。&lt;br>
那阵子晚上去社会食堂吃完饭加送女朋友上地铁以后，&lt;br>
我走路回家洗个澡就又赶回公司码代码。&lt;br>
因为熟悉逻辑加只是纯重构，还能抽象类加精简代码，&lt;br>
一个多月的时候我把整个项目的骨架加基本的单元测试都实现了。&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/adult/2015-11-12.png" alt="pic8">&lt;/p>
&lt;p>后来一天 Joe 一看骨架都做好了，&lt;br>
于是很兴奋地拉上我们认真地合计了一下，&lt;br>
算了一下投入产出比，&lt;br>
归纳出来了 8 条英文的 &amp;ldquo;why should refactor from Perl to Java&amp;rdquo;。&lt;br>
最终 Joe 在跟各方协调沟通以后，&lt;br>
不仅用 Java 重写这个方案通过了，&lt;br>
我们还多了两个月的开发时间！（协商延期）&lt;br>
于是 Joe 又从组里其他项目抽调了好几个队友来一起开发到最终上线 :)&lt;/p>
&lt;h3 id="外国队友">外国队友&lt;/h3>
&lt;p>因为我们的命令行工具最终部署是各种外国程序员用的，&lt;br>
所以上线前我的组织任务就是跟外国的队友接洽。&lt;br>
对接最多的时候是连续两周每天早上 09:00 ~ 11:00 都要在线跟外国同事 (@Mythily) 语音会议，&lt;br>
然后她会共享她的屏幕，&lt;br>
我看着她的 Terminal 跟她讲解各种命令 or 文档。&lt;/p>
&lt;p>这个时候我突然就明白了为什么 Justin 会跟我说 &amp;ldquo;git rev dash list&amp;rdquo; 这样全英文的命令行读法，&lt;br>
因为我跟 Mythily 也只能这样说，&lt;br>
我又不可能跟外国人说 &amp;ldquo;ls 空格 -l 回车&amp;rdquo; ……&lt;/p>
&lt;p>可惜由于学艺不精，&lt;br>
我很多时候也只能：&lt;br>
&amp;ldquo;emmm, let me send you the command line in chat&amp;rdquo;&lt;br>
&amp;ldquo;yeah yeah yeah, space&amp;rdquo;&lt;br>
&amp;ldquo;no no no, dash, yeah git dash&amp;rdquo;&lt;/p>
&lt;p>不过还好 Mythily 是印度同事，&lt;br>
我们两个对有口音的英语的理解能力都超强，&lt;br>
沟通也很顺畅。&lt;/p>
&lt;p>有的时候做完了一天该做的任务我们还会闲聊一会，&lt;br>
一次她还开心地跟我科普了一个印度传统节日叫 Diwali,&lt;br>
并且邀请我什么时候可以趁 Diwali 去印度玩。&lt;br>
我也礼貌地邀请她在 Spring Festival 的时候来中国玩，&lt;br>
展现了一定的大国风范。&lt;/p>
&lt;h3 id="业余技术">业余技术&lt;/h3>
&lt;p>讲了很多工作上的事情，&lt;br>
一方面是因为真的上班在工作，&lt;br>
下班在思考，&lt;br>
睡前都在想代码要怎么写才比较优雅；&lt;br>
另一方便是真的穷，&lt;br>
平常的消遣就是看看 YYF 或者刷刷技术博客。&lt;/p>
&lt;p>技术类博客有个网站我很喜欢，叫 &lt;a href="https://coolshell.cn/haoel">酷壳 coolshell&lt;/a>。&lt;br>
酷壳的博主陈皓的状态就是我理想中的状态：&lt;br>
连续十几年都在技术的一线工作，&lt;br>
对语言、工具、架构、文化都有自己独到而优秀的理解，&lt;br>
对普通程序员有着不俗的影响力、引导着他们变得优秀，&lt;br>
至今仍奋斗在一线。&lt;/p>
&lt;p>受着这样的博客启发，&lt;br>
我也决定&lt;a href="https://liriansu.com/why-im-blogging">开始自己写博客&lt;/a>。&lt;br>
不过一开始没啥好写的，&lt;br>
我就&lt;a href="https://liriansu.com/vagrant-up-but-mount-no-device-zh">列了一些解决bug的流程&lt;/a>…&lt;/p>
&lt;p>在写博客的过程中，我发现这是个很好的进步途径：&lt;br>
写博客不仅可以督促我苟日新、日日新、又日新，&lt;br>
还能时常提醒我去看看别人是怎么发现问题、认知问题、解决问题的。&lt;br>
至少这不会让我变得与行业脱离太多，&lt;br>
也说不定可以避免一年经验重复N年的问题。&lt;/p>
&lt;h2 id="变化">变化&lt;/h2>
&lt;h3 id="打击">打击&lt;/h3>
&lt;p>有一天在黄浦江边上跑步的时候，&lt;br>
我突然接到了 Justin 的电话。&lt;br>
在聊了一下近况以后，&lt;br>
Justin 邀请我去他现在的公司平安好医生面试。&lt;br>
我思考了一下，&lt;br>
觉得去互联网公司试试也是不错，&lt;br>
而且 Justin 已经去当了前哨了，&lt;br>
公司应该是不错的，&lt;br>
我就高兴地去面试了。&lt;/p>
&lt;p>然后崩了…&lt;/p>
&lt;p>我去面的是 Java 后端，&lt;br>
于是面试官就问了我一些很平常的 Spring 框架/Java 线程池/GC/进程分析之类的，&lt;br>
结果我全都不会。&lt;br>
面试官也很无奈，&lt;br>
他就问我：“那你觉得你擅长一些什么？”&lt;br>
我弱弱的回答：“Vim？”&lt;br>
面试官想了想，问我：“把光标移到屏幕中间是哪个快捷键？”&lt;br>
我一愣，然后回答：“不知道……”&lt;br>
（后来查了以后才知道是 &lt;code>M&lt;/code>，我居然真的从来没用过…）&lt;/p>
&lt;p>后来我回来认真复盘过，&lt;br>
觉得面试我主要有几个问题：&lt;br>
一是的确菜，很多都不懂，不会不学不练；&lt;br>
二是过于自信没有准备，有些套路问题是可以先学习的；&lt;br>
三是没意识到写命令行的 Java 技术栈和写后端的 Java 技术栈是不一样的。&lt;br>
再加上面试没问算法题，&lt;br>
也没办法靠硬知识加分…&lt;/p>
&lt;p>不过最终还是给我发了 offer，&lt;br>
只吃薪酬上比较尴尬，&lt;br>
是跟我当前工作没有涨幅的 offer。&lt;br>
问了一下 HR，说是因为我是毕业没满一年，&lt;br>
所以是按应届生来的。&lt;br>
我心有不甘，不过非常理解。&lt;br>
虽然我没面过别人，不过换我面一个问题都回答不上来的人，&lt;br>
能发 offer 已经算给推荐人很大面子啦。&lt;/p>
&lt;p>面对着这份 offer，我开始纠结了。&lt;br>
理论上平薪跳槽不科学，&lt;br>
但是这可是互联网公司诶，火热的行业诶；&lt;br>
而且还有已知的大腿 Justin,&lt;br>
我跟着学总行了吧？&lt;br>
不过这么离开 QAD 总是心有不甘，&lt;br>
当时项目还没彻底完工，&lt;br>
而且不算实习的话工作还没满一年，&lt;br>
组里队友其实都很好…&lt;br>
emmm 纠结。&lt;/p>
&lt;p>一般来说英雄电影里，&lt;br>
低落时总有前辈站出来给出指导意见。&lt;br>
于是我尝试在微博上私信给左耳朵耗子，&lt;br>
并且得到了他的回复。&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/adult/2016-03-14.png" alt="pic9">&lt;/p>
&lt;p>然后我晚上跟皓哥电话聊了快两个小时。&lt;br>
电话里，他讲了他在亚马逊、阿里、自己创业的三段不同的经验，&lt;br>
以及他年轻时候类似的烦恼，&lt;br>
甚至还讲到他写代码解决问题时的方法思路以及对应的人生观。&lt;br>
皓哥给的建议是具体的，&lt;br>
那天晚上听在我耳中的却是非常理想主义的两个字：格局。&lt;/p>
&lt;p>人生在世近百年，&lt;br>
作为工程师会解决无数的问题，&lt;br>
所以有的时候眼前的问题放得更长远会有更好的解决方法。&lt;br>
挂了电话以后，&lt;br>
我心中想起了一句俗话：“莫欺少年穷。”&lt;br>
于是最后我在跟 Justin 提前沟通好以后，&lt;br>
跟 HR 小姐姐婉拒了这份 offer。&lt;/p>
&lt;p>（然后我每天都给自己打两升鸡血！）&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/adult/2016-06-26.png" alt="pic10">&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/adult/2016-07-04.png" alt="pic11">&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/adult/2016-07-11.png" alt="pic12">&lt;/p>
&lt;h3 id="普通的一天">普通的一天&lt;/h3>
&lt;p>后来有一天，百姓网的 HR (@PP) 从我 GitHub 翻到了邮件，&lt;br>
发了封邮件要到我的微信，&lt;br>
然后约了个早上的面试。&lt;br>
在拼多多的基友 FM 也问我要不要去面面，&lt;br>
我就也顺便约了个同天下午的面试。&lt;/p>
&lt;p>早上去浩然面完百姓，&lt;br>
中午找 ldsink 在学校门口吃了个面，&lt;br>
吃完以后 ldsink 还顺路带我去他公司转了转。&lt;br>
刚走到凯利大厦时，一个同事跟 ldsink 打了下招呼，&lt;br>
我好奇地问：“这是谁啊？”&lt;br>
ldsink 说是一个销售同事。&lt;br>
我顿时感到十分惊讶：“你们这么热情的么？开发和销售都这么熟？”&lt;/p>
&lt;p>到了公司里逛了一圈，&lt;br>
感觉这个小公司的确小的比较明显，&lt;br>
人也少装修也比较裸，&lt;br>
不过见到了 Eason Jiang 的前室友，&lt;br>
一个同济大学的瘦子，&lt;br>
世界真小啊。&lt;/p>
&lt;p>晚上去拼多多面完以后，&lt;br>
跟 FM 还有 FHN 在公司旁边的面馆吃了碗面，&lt;br>
吃完都七点多了准备回家。&lt;br>
突然微信上 ldsink 问我吃完了吗，&lt;br>
他还说公司同事都没下班呢，&lt;br>
给我留了份盒饭，邀请我去一起吃…&lt;br>
我心想公司盒饭哪有外面面馆的面好吃，&lt;br>
不过还是跑过去了。&lt;/p>
&lt;p>结果发现我去是面试的！&lt;br>
我两周前发给周丞的简历都打印好了…&lt;br>
第一个面试官是个看起来就事业有成的后端，&lt;br>
做了两道算法题聊了聊天就没了；&lt;br>
第二个面试官就是上文的同济瘦子，&lt;br>
啥都没问，纯吹比，我给他看了看我业余写的前端玩具，&lt;br>
他给我介绍了下产品相关就没了…&lt;br>
然后我坐着稍微等了一下，&lt;br>
公司的 CEO 居然专门从外面赶回公司来见我，&lt;br>
然后他问了一下我的技术理想，&lt;br>
我跟他说了一下就开始互膜起来了（还是带身体动作的那种互膜…）&lt;/p>
&lt;p>回家以后我打电话跟女朋友说了下今天面试的情况，&lt;br>
并且我还猜测地跟她说：“假如都给我发 offer 的话，我应该会去再惠，这家公司给我的感觉很舒服。”&lt;/p>
&lt;p>后来我的确去了再惠，&lt;br>
并且和一帮很强的队友一起共事。&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/adult/2016-12-13.png" alt="pic13">&lt;/p>
&lt;blockquote>
&lt;p>当你老了，回顾一生，就会发觉，&lt;br>
什么时候出国读书，&lt;br>
什么时候决定做第一份职业，&lt;br>
什么时候选定了对象而恋爱，&lt;br>
什么时候结婚，其实都是命运的巨变。&lt;/p>
&lt;p>只是当时站在人生的三岔路口，眼见风云千樯，&lt;br>
你作出选择的那一日，在日记上，相当沉闷和平淡，&lt;br>
当时还以为是生命中最普通的一天。&lt;/p>
&lt;/blockquote>
&lt;h2 id="新的开始">新的开始&lt;/h2>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/adult/2016-11-25.png" alt="pic14">&lt;/p>
&lt;h3 id="自由">自由&lt;/h3>
&lt;p>在16年11月底，我从一家外企来到了一家A轮的互联网公司。&lt;br>
在逐渐熟悉了业务和技术以后，&lt;br>
我突然意识到了很多以前习以为常的东西其实是每个公司都不一样的。&lt;br>
其中让我感触最深的就是公司制度。&lt;/p>
&lt;p>比如说工作范畴。&lt;/p>
&lt;p>在外企的时候其实是定时定量的。&lt;br>
我做的事情是组里分配的，做快做慢都是这么多，&lt;br>
组里的事情是部门分到每个 Manager 上的，&lt;br>
基本上也是合理分配相对固定的。&lt;br>
但是在互联网公司的工作是全凭主动性的。&lt;br>
不仅你做得快那么你要做的事情会更多（当然做的慢绩效就差），&lt;br>
而且很多事情都是可以砍掉的！&lt;br>
很可能大家一讨论，发现有更科学的方法去实现，整个东西都不用做了。&lt;/p>
&lt;p>这样最直观的感受就是身边的同事 ownership 都巨高。&lt;br>
因为他做的事情是他参与思考讨论的，&lt;br>
所以大家的热情都非常高，&lt;br>
我第一次发现有这么多在家里都会工作的家伙…而他们居然都在我的公司里？？？&lt;/p>
&lt;p>还有像新人培训。&lt;/p>
&lt;p>QAD 有为期一个月多的新人培训，&lt;br>
期间除了业务培训，还有英文邮件、工作礼仪等等培训。&lt;br>
再惠技术部门的新人培训就只有一天，&lt;br>
一开始连 Mentor 机制也没，&lt;br>
就是靠招进来的都是大佬、大佬会自救自己想办法这么支撑下去的。&lt;br>
不过后来逐渐有 Buddy (就是Mentor) 机制，&lt;br>
以及有一系列完善的新手村任务熟悉业务了。&lt;/p>
&lt;p>还有就是招聘。&lt;/p>
&lt;p>在 QAD 招人的话我没参与过，&lt;br>
不清楚具体的情况，&lt;br>
不过基本上是 Manager 决定。&lt;br>
而我来再惠的第二周就让我跟着去面试了。&lt;br>
我很快发现相比于“挑选下属”的面试感觉，&lt;br>
再惠的面试其实是让我们“挑选队友”。&lt;br>
CEO/CTO 的最终面是质量把关，&lt;br>
前面的同事面试其实非常关键，&lt;br>
从不同角度去面试候选人才能保证永远招 A 类人。&lt;/p>
&lt;p>当然，我们录用率只有 4% 这点也被 HRMM 们多次批评过，&lt;br>
不过反过来说，我们离职率也只有 0% 呀。&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/adult/2017-03-21.png" alt="pic15">&lt;/p>
&lt;h3 id="技术相关">技术相关&lt;/h3>
&lt;p>虽然之前轻描淡写地讲了讲技术，&lt;br>
不过其实我在来再惠之前完全没接触过正规的 Python Web 后端开发。&lt;br>
我大概菜到一个什么程度呢？&lt;br>
就是假如津铭（上文提到的看起来事业有成的后端）当时面试的时候问我这些问题：&lt;br>
HTTP的请求方法每个有什么含义?/virtualenv是干什么的?/uwsgi是干什么的?&lt;br>
我一个都答不上来…&lt;/p>
&lt;p>菜，得认。&lt;br>
所以我那阵子每天回家都跟女朋友说：&lt;br>
“我好菜啊，队友好强啊，&lt;br>
但我真的好开心啊，感觉啥都能学到，&lt;br>
而且他们下班也会写代码，&lt;br>
感觉找到同类了啊，不过感觉再也追不上他们了啊”&lt;/p>
&lt;p>但我很快发现原本会绑住我的缚仙索不存在了：&lt;br>
我入职以后马上就有了各种测试环境的权限。&lt;br>
uwsgi配置搞不懂？那就去测试环境玩一下。&lt;br>
因为搞不懂而玩坏了？没事很快就会被前端爸爸找上门暴打一顿然后强制搞懂的。&lt;br>
恍惚间有一种刚玩dota时，选了个火枪然后很快懂了全英雄技能的感觉。&lt;/p>
&lt;p>那阵子的周末我基本上也在写公司相关的代码。&lt;br>
因为周末不会有测试环境被搞挂或者是冲突的问题，&lt;br>
所以我可以放肆地试错，然后学到各种经验。&lt;/p>
&lt;p>有了这段经验以后，&lt;br>
我十分确定一个事实：&lt;br>
尽可能地放权给程序员，&lt;br>
优秀的人会像李洛克解开了负重一样腾飞的。&lt;/p>
&lt;h3 id="生活相关">生活相关&lt;/h3>
&lt;p>在再惠的工作内容其实我写了很多别的文章去讲，比如：&lt;br>
&lt;a href="https://liriansu.com/my-work">《我的工作》&lt;/a>&lt;br>
&lt;a href="https://liriansu.com/engineer-culture">《为什么我喜欢工程师文化》&lt;/a>&lt;br>
就不过多阐述了。&lt;/p>
&lt;p>换工作这个节点对我还有一层意义，&lt;br>
就是我跟女朋友合租了。&lt;/p>
&lt;p>我爸妈都是老师，&lt;br>
小时候放学回家会听见他们聊各种学生、备课、科目组、考试的事情，&lt;br>
他们不仅生活上是温馨恩爱的夫妻，&lt;br>
工作上也会互相倾听给出建议，&lt;br>
这让我很是向往。&lt;br>
所以跟女朋友合租最让我开心的一点，&lt;br>
其实是下班回家以后可以瘫着，&lt;br>
要么听女朋友讲 HR 的职业生涯和各种破事，&lt;br>
要么跟女朋友讲工程师的发展规划和各种破事。&lt;/p>
&lt;p>不过想了想，&lt;br>
关于女朋友我也专门写过&lt;a href="https://liriansu.com/my-little-mia">《我的女友小米娅》&lt;/a>，&lt;br>
感觉也没什么特别可以说的。&lt;/p>
&lt;p>哎，高产的烦恼。&lt;/p>
&lt;h2 id="结尾语">结尾语&lt;/h2>
&lt;p>坐在电脑前，&lt;br>
认真地想了一下毕业三年所做的各种各样的事情，&lt;br>
让我感受最深的并不是什么实在的事情，&lt;br>
而是我思想的进步。&lt;/p>
&lt;p>对人友善、&lt;br>
用控制变量法研究问题、&lt;br>
换位思考这种从小就学的普适性的东西其实是非常正确并且有用的方法论。&lt;/p>
&lt;p>希望这个世界会在你我的努力下，&lt;br>
越来越美好 :)&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/adult/2018-01-01.jpg" alt="pic16">&lt;/p></description></item><item><title>公司文化、工资期权、开发体验——一线程序员的喜怒哀乐</title><link>https://liriansu.com/posts/2018-08-11-a-chat-with-schoolmates/</link><pubDate>Sat, 11 Aug 2018 23:55:50 +0000</pubDate><guid>https://liriansu.com/posts/2018-08-11-a-chat-with-schoolmates/</guid><description>&lt;p>我有一群中学时学计算机奥赛的最好的朋友，&lt;br>
毕业以后我们散落在各个公司写码，&lt;br>
大家心照不宣地约定着“分开打钱，有事TP”，&lt;br>
时不时地就会聚在一起吃个饭。&lt;/p>
&lt;blockquote>
&lt;p>Disclaimer:&lt;br>
本文内容涉及大量个人感想，&lt;br>
记忆内容有模糊，&lt;br>
一切内容真实性不保证，&lt;br>
有任何问题由作者本人背锅。（没错就是他，快喷）&lt;/p>
&lt;/blockquote>
&lt;h2 id="一友情">（一）友情&lt;/h2>
&lt;p>Mia 有空的时候也会参加我们的季度聚会，&lt;br>
她和 YJ 的女朋友阿张是我们一堆男生聚会时的唯二妹子。&lt;br>
除了感慨：“程序员的手是好看啊。”&lt;br>
Mia 跟我也感慨过：&lt;br>
“我觉得你们这样真的很难得。&lt;br>
从初一初二就认识，&lt;br>
然后之后一直保持联系，&lt;br>
毕业以后也从事着一样的行业。&lt;br>
我觉得你们之间充满了共同话题。”&lt;br>
“对啊，日漫里面这就叫命运的羁绊。”&lt;/p>
&lt;p>我们一帮队友里，&lt;br>
有毕业去了谷歌英国，如今已经找到真爱的队友；&lt;br>
也有毕业进华为，一直在出国的单身队友；&lt;br>
有一路深造还在读书的队友，&lt;br>
还有先后从微软、网易、依图跳入拼多多怀抱的队友们。&lt;/p>
&lt;p>大部分时候我们会找个粤菜馆子吃点上海肠粉，&lt;br>
用来下饭的话题会从忍者村大战3v3经典对决，&lt;br>
聊到广东回南天和上海梅雨天的气候差别。&lt;br>
这次的聚会发起于刚从国外出差回来的华为小员工 enye。&lt;br>
就像以前的宿舍吹比一样，&lt;br>
这次的聊天吹比也让我颇有想法。&lt;/p>
&lt;h2 id="二-公司文化">（二） 公司文化&lt;/h2>
&lt;p>我们问 enye 他这次休息几天，&lt;br>
enye 说他请的三四天年假，可以休息九天。&lt;br>
众人：？？？啥操作？？？&lt;br>
enye 解释道华为有个约定，&lt;br>
就是出国回来默认有一天可以倒时差，&lt;br>
他就顺势请了一波连起来的假，以玩代休了。&lt;/p>
&lt;p>enye 又讲到他其实有过想跳槽，&lt;br>
大家问起原因，&lt;br>
enye 感慨道：“我存不下钱啊。”&lt;br>
因为工作性质，enye 要走遍世界各个国家，&lt;br>
他又忍不住在知乎上关注了美食和旅行的话题，&lt;br>
也难怪存不住钱。&lt;/p>
&lt;p>大家笑了一波他这第一世界的烦恼以后，&lt;br>
他又讲到：&lt;br>
“其实在我司，我难受的还有一种焦虑感。”&lt;br>
在 enye 的感受里，&lt;br>
华为是极度狼性文化的，&lt;br>
假如员工到了 35/40 的年纪还没有一定成就，&lt;br>
就会被淘汰掉。&lt;br>
enye 还举了个例子：&lt;br>
他认识的当时跟他同期进去的人，&lt;br>
现在已经全部受不了走人了，&lt;br>
而 enye 一直是 top performance 的，&lt;br>
他也感觉自己到 35/40 岁的时候不一定能做到高位。&lt;/p>
&lt;p>听完以后我不禁感慨道：&lt;br>
华为毕竟是华为啊。&lt;br>
拼多多的早期员工 FM 也说道：&lt;br>
我们公司各种方面都非常想学华为。&lt;br>
我问 FM，你们拼多多也是狼性文化的么？&lt;br>
FM 点了点头，并举了个例子：&lt;br>
他们目前做的很多事情都是朝令夕改的，&lt;br>
比如对接京东、对接微信的组，&lt;br>
开发已经开发好了，&lt;br>
但是过两周，对不起，业务上合同没谈下来，&lt;br>
整个组都给我解散，&lt;br>
大家做的东西都白做了。&lt;br>
大家沉默了一会，感觉没什么能说的，&lt;br>
就念了念阿里的咒语：“拥抱变化，拥抱变化。”&lt;/p>
&lt;p>我又接着问 FM：“那开发量上，你们忙吗？”&lt;br>
在两个组的 FM 和 Freedom 同时给出了不同的答案。&lt;br>
感觉很忙的 Freedom 说，&lt;br>
他们做的是公司的数据分析层 (hadoop + flink)。&lt;br>
公司人多了一倍的同时，他们组一个人没多，&lt;br>
每天忙的一笔。&lt;br>
FM 就附言说，像 Freedom 的组其实是特例，&lt;br>
拼多多大部分组已经慢下来了，&lt;br>
现在分工细了，花在沟通上的时间多了很多。&lt;br>
举个夸张的例子，以前一个组三天就能做完的东西，&lt;br>
现在可能两个组要做三周。&lt;/p>
&lt;p>“那听起来有点划，&lt;br>
你们还是 996 周日加班么？”&lt;br>
“对啊！”&lt;br>
FM 又感慨道，其实感觉现在的工作量可以不 996 了。&lt;br>
比如他现在带的组包括实习生有 6 个人，&lt;br>
很多时候大家的活都不是饱和的。&lt;/p>
&lt;p>讲到工作时间的问题又有个例子。&lt;br>
说拼多多上市的第二天他们开了员工大会，&lt;br>
两千多人在一个大会场里席地而坐，&lt;br>
老大们拿了张纸条出来，&lt;br>
说：“我们来回答一些大家关心的问题吧。”&lt;br>
然后读到：“我们现在人多位子挤，会不会搬新办公室？&lt;br>
我们会不会每两周多休息一天，引入单双休制度？&lt;br>
我们会不会每人发股票？”&lt;br>
台下的员工们非常兴奋，&lt;br>
每听到一个问题都热烈地鼓一次掌，&lt;br>
单双休的问题最是热烈。&lt;br>
然后老大们给出了素质三连：“不会，不会，不会。”&lt;br>
听完这个故事，在场众人又流下了沉默的无奈的泪水。&lt;/p>
&lt;p>作为局外人的我叹了口气：&lt;br>
讲道理全中国我只听过你们这一家这个量级的公司，&lt;br>
是全公司 996 的，其它顶多是分团队或者短暂的。&lt;br>
感觉单双休这个问题，&lt;br>
只有你们老大黄铮发言，&lt;br>
真正官方给意见才行。&lt;br>
不过话又说回来，&lt;br>
你们招人的时候给的钱估计是按 996 给的，&lt;br>
现在换成 995 了，&lt;br>
除非你们愿意降薪 16.6%，&lt;br>
要不公司肯定是亏的。&lt;br>
Freedom 又补充道：&lt;br>
对啊，现在其实有很多组的人是自己固定请事假，&lt;br>
然后达到手动降薪单双休的效果。&lt;/p>
&lt;p>大家又扯了一波单休和双休的本质区别，&lt;br>
总结出了一条真理，叫：&lt;br>
公司文化完全取决于老大，对小团队也是如此。&lt;br>
因为很多事情是只能由老大拍板的。&lt;/p>
&lt;p>讲着讲着，我又想了想我司。&lt;br>
很多方面上，拼多多给我的即视感跟我司非常像，&lt;br>
要总结一句可以是：“当下中国快速发展的互联网创业公司大抵如此，很多制度难以跟上。”&lt;br>
但另一方面，我又觉得很多事情我司的操作性比拼多多要强。&lt;br>
拼多多发展的比我司快很多，&lt;br>
所以很多基建、文化很难同步赶上，&lt;br>
但我司首先是有双休，&lt;br>
然后文化上内部的宣传也比拼多多好些。&lt;br>
讲着讲着，Freedom 想起了他毕业后去网易的事情，&lt;br>
笑着补充了一句：“其实公司文化这个东西，&lt;br>
对刚毕业的应届生影响很大的。&lt;br>
很多人对职场一辈子的感知都起源于最初的印象。”&lt;/p>
&lt;p>是啊，就像小王子感慨的那样：&lt;br>
沙漠的美，源于它之中隐藏的甘泉。&lt;/p>
&lt;h2 id="三工资期权">（三）工资期权&lt;/h2>
&lt;p>讲到拼多多上市的员工大会，&lt;br>
我又问了一个敏感话题下的不敏感问题：&lt;br>
“你们上市以后，期权兑换股权的方式是怎么样的？”&lt;br>
得到的回答是标准的美国科技公司的做法，&lt;br>
跟网上的说法是一样的。&lt;br>
比如拿硅谷里的 PiedPiper 公司举个虚假的栗子：&lt;/p>
&lt;ul>
&lt;li>公司还没上市，是没有股票，只有期权的
&lt;ul>
&lt;li>理论上，等上市了，期权可以用来换成股票&lt;/li>
&lt;li>但期权也不是免费的，需要用&lt;em>行权价&lt;/em>购买&lt;/li>
&lt;li>一般来说&lt;em>行权价&lt;/em>比较低。举个栗子，相比于上市股票每股10USD，行权价可能是每股0.5USD。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>PiedPiper 刚创业的时候发出了 20% 的期权。
&lt;ul>
&lt;li>CEO 自己出的钱，出了 Idea，贡献了自己的住处，一个拥有 10%。&lt;/li>
&lt;li>其它 5 个早期员工每人拥有 2%。&lt;/li>
&lt;li>所有事情 CEO 拍板。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>剩下的 80% 大家设立了为期 4 年的期限均摊。
&lt;ul>
&lt;li>这样即使第一年某个早期员工走了，他也只有 2% 的期权，不会占着茅坑不拉屎。&lt;/li>
&lt;li>之后来的新人也是 4 年领完所有期权。&lt;/li>
&lt;li>大家努力干活，一条心做好产品。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>过了三个月，产品原型出了，算了一波市场以后，公司估值 80 万，投资人 A 投了 80 万。
&lt;ul>
&lt;li>本来公司估值是 40 万，期权已经分出去了 20%，投资人给两倍钱就是要 40% 的期权。&lt;/li>
&lt;li>但是投资人说：这样，公司估值给你做翻倍，但是我想现在分完期权，等不及 4 年了。&lt;/li>
&lt;li>公司缺钱投放产品，同意了。于是 CEO+众人 拿了 80 万现金和 50% 的期权，投资人 A 拿了 50% 期权。&lt;/li>
&lt;li>投资人 A 占得期权比高，不过公司还是 CEO 拍板，只不过每个月都要跟投资人 A 开一下例会，说一下拿着钱干什么去了。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>产品投放以后，效果很好，一年后，公司招了人，估值 300 万，又从投资人 B 那融了 200 万现金。
&lt;ul>
&lt;li>因为之前期权分完了，所以现在新资金来了，大家的期权都被稀释了，大概比例是
&lt;ul>
&lt;li>CEO 15%，五个早期员工 3%，投资人 A 30%，投资人 B 40%。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>现在 CEO 每个月要跟投资人 A 和投资人 B 开例会，有的时候要按投资人的想法来做事情。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>随着公司的发展，引入了更多资金，甚至公司准备上市了。
&lt;ul>
&lt;li>多个投资人和专业经理人组成了董事会，大部分公司业务方向由董事会决定，CEO 成为了真正的首席执行官。&lt;/li>
&lt;li>为了写清楚募股书，公司停止了对新同事的期权发放。&lt;/li>
&lt;li>为了避免公司上市后现金流损失，董事会建议 PiedPiper 设定了一个为期 5 年的期权兑换时间。&lt;/li>
&lt;li>因为后来发的很多是子公司的期权，所以董事会对不同子公司制定了从 5:1 到 10:1 不等的期权股票兑换比例。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;p>（扯的例子有点长，而且都是个人猜想，可能很多不准确）&lt;br>
FM 主要讲了一点，&lt;br>
就是拼多多的期权兑换方式是 4 年拉满期权，兑换现金的时间还要 3 年。&lt;br>
这一听大家就都很蛋疼，&lt;br>
不约而同地说道：“那 FM 你这就肯定不能跳槽了啊，要不亏的一笔。”&lt;/p>
&lt;p>为了量化这个亏有多少，&lt;br>
我们又猜想了一组虚假的数字：&lt;br>
假设有 100k 股期权，&lt;br>
每股行权价是 0.1 美元,&lt;br>
上市发行价是 20.5 美元,&lt;br>
期权股票兑换比例是 5:1，&lt;br>
期权交税比例是 40%，&lt;br>
期权发放时间和兑换时间都是 4 年；&lt;br>
那么公司上市成功了以后，&lt;br>
你可以换到的现金是 (100k / 5) * 20.5 - 100k * 0.1 = 400k (美元)&lt;br>
你本质上这 8 年的工作相当于每年年薪多了 400k / 8 = 50k (美元) 约等于 350k (人民币)。&lt;br>
也就是说跟着公司创业成功的你，&lt;br>
相当于每年多了 35 万人民币的年薪。&lt;/p>
&lt;p>听起来很多，&lt;br>
那么我们再算下数学期望。&lt;br>
假设创业成功上市是九死一生的，&lt;br>
也就是概率是 10%（很高了！）&lt;br>
那么你在不知道公司未来的情况下，&lt;br>
创业公司的大饼 buff 其实等于 3.5 万的年薪，&lt;br>
约等于 3000 元的月薪。&lt;/p>
&lt;p>一顿瞎比分析以后，&lt;br>
大家又总结了一波：&lt;br>
“大部分情况下，你能拿多少的数学期望是恒定的。&lt;br>
不论你在小厂、中厂还是大厂。”&lt;/p>
&lt;p>不过讲到这里，&lt;br>
我不禁又跟 FM/Freedom 吐槽：&lt;br>
“你们拼多多实属异类，给的钱是真的多。”&lt;br>
之前金三银四的时候，&lt;br>
我们发 offer 的好几个人都直接去了拼多多，&lt;br>
一问为什么，offer 开的价格接近我们开的两倍，&lt;br>
真的夸张。&lt;/p>
&lt;p>不过我司有个好处，&lt;br>
就是绝对保证公平，&lt;br>
比如我是觉得我们公司没有任何倒挂的情况。&lt;br>
（倒挂：指的是因为行情变化，导致实力差距较大的同学因为入职时间先后，导致薪酬反转的一种现象）&lt;br>
互联网行业因为很吃研发水平，&lt;br>
所以导致优秀人才的薪酬是在逐年上涨的，&lt;br>
市场涨幅比公司涨幅高的结果是很多情况下同是毕业入公司，&lt;br>
16 年毕业的工作一年的老同学比 17 年刚毕业的同学薪酬还低。&lt;br>
知乎上还有个很火爆的 600W 阅读的问题《为何公司宁愿给新人开高工资，却不愿意给知根知底的老员工涨薪？》就是讲这个的。&lt;/p>
&lt;p>讲到倒挂，Freedom 就很痛苦地回忆道：&lt;br>
“我感觉当时我在的组，我的绩效是 271 里的 2，但是回报却是 1，很不公平。”&lt;br>
271 讲的是大部分公司激励制度是会按正态分布，&lt;br>
给表现最优秀的 20% 人最好的奖励，&lt;br>
让表现最差的 10% 吃屎（或者政治正确的说法叫给工作建议），&lt;br>
剩下的 70% 彼此彼此。&lt;br>
不同 Leader 的政策是不一样的：&lt;br>
有些 Leader 喜欢让大家轮流吃屎，&lt;br>
好处是大家和谐，&lt;br>
另外的 Leader 会让最差的吃屎，&lt;br>
很多情况下固定就是那个人一直在吃；&lt;br>
还有些 Leader 会有新手保护，&lt;br>
刚毕业的、刚加入团队的新同学最开始是不会吃屎的。&lt;br>
不过大家又吐槽，假如就按 dps 算的话，&lt;br>
新人是应该吃屎啊，我们也是在吃屎中成长的呀。&lt;/p>
&lt;p>一边说着，新上的油条肠粉又被大家瓜分干净了。&lt;/p>
&lt;h2 id="四-开发体验">（四） 开发体验&lt;/h2>
&lt;p>讲钱相关的话题总有一种大人的感觉，&lt;br>
庸俗又真实。&lt;br>
为了让话题不这么沉重，&lt;br>
在思考职业发展的 enye 又问：&lt;br>
“不考虑钱的话，去早期公司、中期公司、大公司有什么异同吗？”&lt;br>
“不考虑钱的话，”我想了想，说道，&lt;br>
“我非常、非常喜欢优秀的小厂的工作环境。”&lt;/p>
&lt;p>一方面是开发体验极好。&lt;br>
我们在只有几个人的时候，&lt;br>
虽然技术有分工、分前端和后端，&lt;br>
但是每个人都是业务全栈的，&lt;br>
也就是任何人能做任何事情，&lt;br>
数据流向数据存储数据格式？你的锅。&lt;br>
业务代码增删改查400/500？你的锅。&lt;br>
发版部署服务分布依赖关系？还是你的锅。&lt;br>
而且每次改动都是很快见效，&lt;br>
反馈效应极强。&lt;br>
FM 默默点头：&lt;br>
那个时候没什么沟通成本，&lt;br>
我说两天能做完，&lt;br>
然后两天就肝出来了，&lt;br>
你觉得我很牛逼，&lt;br>
我也觉得自己很牛逼啊！&lt;/p>
&lt;p>另一方面，就像 FM 说的，&lt;br>
是沟通成本的问题。&lt;br>
我问 FM：“你有没有感觉你们人多了以后，扯皮非常严重”&lt;br>
FM 说有，并且举了一个具体的例子：&lt;br>
他们研发因为人很多，&lt;br>
很多人都彼此不认识，&lt;br>
所以并不知道谁是组长谁有拍板的权利。&lt;br>
然后业务问题很多都是模棱两可的，&lt;br>
时不时就有人对业务问题产生了分歧，&lt;br>
然后 argue 了很久也没能拍板，&lt;br>
导致很多时间都花在了沟通上。&lt;/p>
&lt;p>讲到这个话题，&lt;br>
大家共鸣非常强，&lt;br>
工作既涉及开发又设计产品经理还涉及客户关系维护的 enye 非常激动地说：&lt;br>
“你知道为什么吗？这就是屁股决定脑袋！”&lt;br>
很多时候双方互相冲突的观点其实都是正确的，&lt;br>
问题是出在两个人的屁股都是朝着自己的方向的。&lt;br>
就算你到了高层也是一样，都是做着决策层的需求，&lt;br>
但是你们 KPI 不一样，团队也是不一样的，&lt;br>
自然就难避免扯皮了。&lt;/p>
&lt;p>聊到这里，我又想起了 OKR 整套方法论里面很重要的一个概念叫“校准”。&lt;br>
就是说大的任务被拆分时，&lt;br>
第一要保证的是它们的方向一定得是一致的，&lt;br>
不能有互相冲突的地方。&lt;br>
方法论里都这么讲了，&lt;br>
那反过来说这个问题其实是广泛存在的。&lt;/p>
&lt;p>讲着讲着，FM 就老气横秋地说道：&lt;br>
“所以其实作为研发，跟产品、运维、市场这些人搞好关系是很重要的。&lt;br>
即使是工作里，大家假如不作为伙伴互相看待的话，其实非常蛋疼的。”&lt;br>
众纷纷点头认可。&lt;/p>
&lt;p>扯了这么多，&lt;br>
我发现偏离了一开始的主题，&lt;br>
就补充道：&lt;br>
其实小厂好还是大厂好，&lt;br>
我感觉是不仅看人，还看团队的，&lt;br>
我是非常喜欢目前的团队氛围。&lt;br>
举个栗子，&lt;br>
我们前携程队友，&lt;br>
他来了我司以后感慨：&lt;br>
“卧槽原来还有这样的地方啊，&lt;br>
我以前在大公司学到的扯皮的那么一套居然都用不上了！”&lt;br>
众笑。&lt;/p>
&lt;h2 id="五-感情生活">（五） 感情生活&lt;/h2>
&lt;p>几个上世纪出生的男生聚在一起，&lt;br>
就聊起了 PLMM 的话题。&lt;br>
大家发现在场的 5 人里有 4 人是单身的，&lt;br>
并且有小伙伴都进入了“还是琪亚娜比较可爱”的佛系状态里，&lt;br>
不仅唏嘘了一下。&lt;/p>
&lt;p>最后，大家纷纷给下周一就又要去西班牙的 enye 头上插满了 flag:&lt;br>
“下次来上海，要带着妹子来。”&lt;/p>
&lt;p>（完）&lt;/p></description></item><item><title>为什么我喜欢工程师文化</title><link>https://liriansu.com/posts/2018-07-26-engineer-culture/</link><pubDate>Thu, 26 Jul 2018 22:38:44 +0000</pubDate><guid>https://liriansu.com/posts/2018-07-26-engineer-culture/</guid><description>&lt;p>Mia 公司的母公司是 3G资本，&lt;br>
她前几天突然好奇公司的文化是怎么样的，&lt;br>
就去找了相关资料读了一遍。&lt;/p>
&lt;p>然后 Mia 惊奇地跟我说：&lt;br>
“我发现 3G资本 对人才的要求特别神奇。&lt;br>
三个关键词是 smart, poor, desire to be rich&amp;hellip;”&lt;br>
空气中顿时充满了快活的笑声。&lt;/p>
&lt;p>后来我又想，&lt;br>
我司有什么企业文化呢？&lt;br>
假如要我来说的话，&lt;br>
大概就是 &lt;code>工程师文化&lt;/code> 吧。&lt;/p>
&lt;h1 id="工程师文化">工程师文化&lt;/h1>
&lt;p>看美剧的时候，&lt;br>
我们会发现美国人一楼总有一个车库，&lt;br>
车库的工具箱里装着各种各样祖传的实用工具，&lt;br>
Mickey/Rick/Baymax 都是从车库里走出来的。&lt;/p>
&lt;p>软件工程师的工程师文化跟这个场景也很像：&lt;/p>
&lt;ul>
&lt;li>在实践中学习&lt;/li>
&lt;li>用工具解决问题&lt;/li>
&lt;li>自主决策&lt;/li>
&lt;/ul>
&lt;p>我很喜欢这样的工程师文化。&lt;br>
具体来说，&lt;br>
我们举一个B轮公司的研发部门为例子，&lt;br>
也就是我目前在的公司：&lt;br>
再惠（上海）网络科技有限公司。&lt;/p>
&lt;h2 id="在实践中学习">在实践中学习&lt;/h2>
&lt;p>我司有一份文档，&lt;br>
叫 &lt;code>the Hitchhiker's Guide to ZaiHui Dev&lt;/code>，&lt;br>
俗称“新手村任务”，&lt;br>
这个文档大概长这样子：&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/engineer/guide.png" alt="guide">&lt;/p>
&lt;p>文档里的章节包括搭建开发环境、&lt;br>
熟悉基础业务、参与合作流程、认识基础架构、&lt;br>
还有名为 DLC 的包括权限、队友、小脚本等附录。&lt;/p>
&lt;p>除了这一套完善的文档以外，&lt;br>
每个人还配有一名 buddy，&lt;br>
就像老刺客带新刺客一样，&lt;br>
新同学在万物皆虚万事皆允的路上不管有任何问题，&lt;br>
都是可以抓着 buddy 问个透彻的。&lt;/p>
&lt;p>比如其中后端的新手村任务大概长这样子（节选）：&lt;/p>
&lt;ul>
&lt;li>玩 API
&lt;ul>
&lt;li>本地跑一个 server，尝试用接口获取 id=1 的商户信息&lt;/li>
&lt;li>尝试用测试环境的登录接口，拿到自己的 key&lt;/li>
&lt;li>想办法给所有测试环境添加自己的权限账号&lt;/li>
&lt;li>通过调用 api 的方式修改自己库里的用户名&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>玩 DB
&lt;ul>
&lt;li>在测试环境入个会&lt;/li>
&lt;li>在代码里找到“阿瓦达索命”相关功能，注销掉自己的账号&lt;/li>
&lt;li>研究发验证码的代码 (pin.py) 到测试环境给自己设一个永久验证码&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>写 Bug
&lt;ul>
&lt;li>尝试搞挂&amp;lt;惠吧烤鱼&amp;gt;这个公众号，让微信提示“该公众号无法提供服务”（记得修！不然测试爸爸要叫！）&lt;/li>
&lt;li>尝试不用 random 库，写一个有几率会挂的 ut&lt;/li>
&lt;li>写一个循环引用，让所有 ut 都挂&lt;/li>
&lt;li>尝试去测试环境改一下代码，然后搞坏该环境的发版（期待结果是在 pull_new_code 的时候报错）&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;p>一般来说，&lt;br>
有 python 经验的同学可以在一周左右做完新手村任务，&lt;br>
了解我们的主要业务和后端的大致实现框架。&lt;br>
刚毕业的同学也可以在整套流程中认识到 RESTful/MySQL/Git/Jenkins 等开发流程。&lt;/p>
&lt;p>对应的，我们还践行 DevOps 的原则，&lt;br>
就是 &lt;code>Eat your own dog food&lt;/code>。&lt;br>
不仅包括开发+架构设计+环境搭建一体化，&lt;br>
还包括可以瞎比玩别人的测试环境，&lt;br>
一个环境我搞挂了就得我来修，&lt;br>
不修的话就会被拿刀抵在背上来修（并不）…&lt;/p>
&lt;h2 id="用工具解决问题">用工具解决问题&lt;/h2>
&lt;p>截止到目前（2018年7月）为止，&lt;br>
我司技术部门（各端研发+测试）一共不到60人，&lt;br>
对应我们年费制的数千家商户，&lt;br>
平均下来每个人支持了100家商户。&lt;/p>
&lt;blockquote>
&lt;p>这么想想敏俊（96年的刚毕业小帅哥）也支持了100家商户，&lt;br>
想想也为他感到有点小激动…&lt;/p>
&lt;/blockquote>
&lt;p>这里就是我们用的大量工具起到了杠杆的作用，&lt;br>
放大了每个工程师的生产力。&lt;/p>
&lt;p>当时我被面试的时候，&lt;br>
谢老板的一句话给我印象很深：&lt;br>
“能用工具解决的问题，&lt;br>
我们是不会让工程师上的。”&lt;/p>
&lt;p>具体来说，&lt;br>
我们看一个典型开发流程所要经历的一些步骤。&lt;/p>
&lt;h3 id="迭代">迭代&lt;/h3>
&lt;p>我司一直跑的是敏捷开发，&lt;br>
早期用的是 Trello。&lt;br>
那时不仅产品不多，&lt;br>
产品经理也不多。&lt;/p>
&lt;p>后来队友逐渐在增加，&lt;br>
就尝试用了 Jira。&lt;br>
Jira 的好处是它功能强大可配置，&lt;br>
配套的 Confluence 等设施完善。&lt;br>
但是因为配置起来比较繁琐，&lt;br>
也没有让我们自己反复调整的时间，&lt;br>
大部分队友也就不太适应 Jira。&lt;/p>
&lt;p>后来一直到现在我们在用 Teambition。&lt;br>
目前每个产品线有自己的敏捷面板，&lt;br>
每两周一次迭代，周一计划会，下周五回顾会。&lt;br>
每天早上晨会，大家除了过一下昨天的进度和今天的计划，&lt;br>
还会主要把一些小的疑问/困难放在晨会里说出来，&lt;br>
10 个人的晨会大概 10 分钟就结束了，效率巨高。&lt;/p>
&lt;p>前几天面试的时候，&lt;br>
一个唯品会的小姑娘好奇地问我：&lt;br>
“你们的迭代是两周定时的么？”&lt;br>
我意识到其实不同团队对迭代的执行细节不一样，&lt;br>
就跟她解释了一下我们对迭代的理解：&lt;br>
“其实迭代就像地铁班车，&lt;br>
我们是写死两周一班车，&lt;br>
这个迭代能做完什么就做完什么。&lt;br>
车又不等人，做不完的下个迭代再做就行啦。”&lt;/p>
&lt;h3 id="vcs">VCS&lt;/h3>
&lt;p>我们用的版本控制工具是私有部署的 GitLab EE。&lt;br>
除了 Repository，&lt;br>
还用上了里面的 Merge Request/CI/CD/Docker Registry/Wiki 等功能。&lt;/p>
&lt;p>比如举我们的机器人 KevinBot 为例，&lt;br>
假如想要给 Kevin 加一个新功能大概流程是这样的：&lt;/p>
&lt;ul>
&lt;li>fork 项目到本地开发&lt;/li>
&lt;li>push 到自己的 repo，提一个 merge request&lt;/li>
&lt;li>触发了 CI 检查
&lt;ul>
&lt;li>flake8 检查一波有没有语法问题，比如用了双引号、忘了写逗号&lt;/li>
&lt;li>django 检查一下有没有 migration 上的问题&lt;/li>
&lt;li>跑完全部 ut，看看单元测试能不能过&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>跪求 code owner 来 review 自己的代码
&lt;ul>
&lt;li>会有线上评论，不好解释的会线下解释一波&lt;/li>
&lt;li>有问题就打回去改了，重新 push&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>approve + merge&lt;/li>
&lt;li>自动触发了 docker 的自动构建&lt;/li>
&lt;li>构建完成以后自动触发了发版，kevin 机器人发版完成&lt;/li>
&lt;/ul>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/engineer/review.png" alt="review">&lt;/p>
&lt;p>整个过程中 contributor 需要 fork + coding + merge request，&lt;br>
code owner 需要 review + approve + merge，&lt;br>
剩下的单元测试、镜像构建、版本更新都是一条流水线做完的~&lt;/p>
&lt;blockquote>
&lt;p>于是小机器人就更新了一个又一个并不实用的好玩功能&lt;/p>
&lt;/blockquote>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/engineer/alias.png" alt="alias">&lt;/p>
&lt;h3 id="监控">监控&lt;/h3>
&lt;p>我们的监控系统分为几块。&lt;br>
所有监控的告警我们用的是邮件 + 微信机器人。&lt;br>
机器状态的监控我们用了云平台的自带功能 AWS CloudWatch，&lt;br>
业务的状态、日志监控我们用了 ELK 整套系统，&lt;br>
还有最直接实用的错误监控我们用的是 Sentry。&lt;/p>
&lt;p>比如说一年前每周都有好几个发版夜的时候，&lt;br>
大家都是一边看着 Jenkins console log，&lt;br>
一边看着 Sentry 看看会不会蹦出来一些 error log。&lt;br>
有的话当然就火线编程了！&lt;br>
（于是当时就有这样的九核围观的梗：&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/engineer/fire.jpg" alt="fire">&lt;/p>
&lt;p>后来我们终于迎来了正规军测试小伙伴的加入，&lt;br>
Sentry 依然还是我们在测试环境用的一个非常有效的 debug 手段，&lt;br>
不论是 error 还是 warning，&lt;br>
Sentry 上的每一个错误都有几率被抓起来吊着锤。&lt;/p>
&lt;p>有一次 Sentry 变慢了一些，&lt;br>
都被敏锐的旭总察觉到了事情并不简单，&lt;br>
从而牵扯出了一桩案件：&lt;a href="https://liriansu.com/solve-a-sentry-case">《破案·Sentry迷云》&lt;/a>&lt;/p>
&lt;h2 id="自主决策">自主决策&lt;/h2>
&lt;p>上面讲的这些工程师文化的方方面面，&lt;br>
各个优秀的团队都绝对也一样有这样的工程师团队。&lt;br>
但唯有一点，&lt;br>
我是觉得只有我司是特别的。&lt;/p>
&lt;p>套用一段之前在高德干活的拉总讲的话：&lt;br>
“我以前在高德，做的事情是领导分给我的。&lt;br>
我的领导呢，做的事情也是他的领导分给他的。&lt;br>
所有人要做的业务、要使用的技术都是相对固定的。&lt;br>
但是在再惠，根本就是怎么好怎么来。&lt;br>
而且实话说，我以前根本没有想象过，工作能这么开心！”&lt;/p>
&lt;p>拉总总是这么睿智（棒读）。&lt;/p>
&lt;p>政治老师说过，&lt;br>
我们答题要用总分总的形式容易得高分。&lt;/p>
&lt;p>看来工程师文化令人喜欢的一个原因，&lt;br>
就是工程师们也十分令人喜欢呀。&lt;/p>
&lt;p>（完）&lt;/p></description></item><item><title>最近跟女朋友的周常</title><link>https://liriansu.com/posts/2018-06-05-weekly-wander/</link><pubDate>Tue, 05 Jun 2018 00:22:48 +0000</pubDate><guid>https://liriansu.com/posts/2018-06-05-weekly-wander/</guid><description>&lt;p>最近因为加班有点多，&lt;br>
经常打断二人世界，&lt;br>
导致女朋友有点不开心。&lt;/p>
&lt;p>（一）&lt;br>
前几个月的时候周常去觅食，&lt;br>
去的店家是港式风格装修的。&lt;br>
米娅正很开心地跟我讨论着墙纸上的 sasa 店面，&lt;br>
我眼角瞥见了桌上有一张二维码。&lt;/p>
&lt;p>“哇你看，他们家也有微信点餐。&lt;br>
我这几个月加班都在做这个！&lt;br>
你等我下我拍照发群里，&lt;br>
看看人家做的跟我们做的体验相比如何…”&lt;/p>
&lt;p>顿时米娅跟我聊天的兴致全无了。&lt;/p>
&lt;p>上周末的时候，&lt;br>
吃饭过程中又接了个语音，&lt;br>
然后我跟米娅说，&lt;br>
吃完饭我下午要去公司。&lt;/p>
&lt;p>米娅就很好奇地问了我一句：&lt;br>
“你们公司出 bug 都是你修吗？”&lt;/p>
&lt;p>我安慰米娅说：&lt;br>
“有些别的同事也要周末修 bug 的啦。”&lt;/p>
&lt;p>（二）&lt;/p>
&lt;p>第二天晚上跟米娅吃完饭出去散步消食，&lt;br>
不知不觉又聊到了加班这个话题。&lt;br>
出于“爱一个人就想跟他分享全部”的道理，&lt;br>
我不禁又跟米娅喋喋不休我的工作起来。&lt;/p>
&lt;p>“我跟你说，我感觉每个人的属性真的是不一样的。”&lt;/p>
&lt;p>米娅捧哏：“嗯？”&lt;/p>
&lt;p>“比如说我们公司吧。&lt;br>
因为工作制度是 965 + 弹性时间，&lt;br>
所以每个人的方差其实很大。&lt;br>
有些同事就是按时上班按时下班好好工作，&lt;br>
也有些同事跟我一样就是加班划水。”&lt;/p>
&lt;p>“噢，也就是说你们真的有人是不加班的咯？”&lt;/p>
&lt;p>“对啊当然。&lt;br>
你看加班这个属性，&lt;br>
其实不是跟公司绑定的而是跟我绑定的，&lt;br>
我在 QAD 不也晚上洗完澡回去干活么…”&lt;/p>
&lt;p>“噢…”&lt;/p>
&lt;p>（三）&lt;/p>
&lt;p>不过讲到这个，&lt;br>
我又想起上次看到的一个很好玩的说法：&lt;br>
“离职爆破半径。”&lt;br>
于是我想办法用人话跟米娅 demo 了一下：&lt;/p>
&lt;p>“虽然说每个人都是平等的，&lt;br>
但人和人之间真的差别还是蛮大的。”&lt;/p>
&lt;p>“怎么讲？”&lt;/p>
&lt;p>“比如说你看我们现在几十个人，&lt;br>
少几个人好像没啥问题。&lt;br>
但其实我拍脑袋可以数出几个人，&lt;br>
只要他们一瞬间全部离职，&lt;br>
我们的事情就会崩。”&lt;/p>
&lt;p>“啊？为什么啊。”&lt;/p>
&lt;p>“因为我们目前很多事情其实不是靠制度在维护的，&lt;br>
真的是靠优秀的人在顶着。&lt;br>
而且因为这些人太优秀了，&lt;br>
所以很多制度上的事情感觉还没有做的必要，&lt;br>
非常地‘以人为本’。”&lt;/p>
&lt;p>（四）&lt;/p>
&lt;p>“比如说我给你举个具体的例子，&lt;br>
就是 support。”&lt;/p>
&lt;p>“嗯好~”&lt;/p>
&lt;p>“我们公司是做 B 端产品的嘛，&lt;br>
也就是说商户其实才是我们的根本。&lt;br>
所以我个人非常信奉&lt;strong>客户第一&lt;/strong>，&lt;br>
跟 QAD 讲的那个 Customer First 的 Core Value 是一样的道理。&lt;br>
不过像这句话，&lt;br>
我从来不会在同事的面前提。”&lt;/p>
&lt;p>“啊，为啥？”&lt;/p>
&lt;p>“因为我觉得这个问题很敏感。&lt;br>
比如说个具体的，&lt;br>
我们目前是没有 technical support 部门的，&lt;br>
也就是说有任何搞不定的技术问题，都得 R&amp;amp;D 上，去解决问题。”&lt;/p>
&lt;p>“啊？你们 service 的同事呢？他们不是要负责上门安装么？”&lt;/p>
&lt;p>“对，我司分工里这叫 Customer Success。&lt;br>
他们其实也蛮苦逼，要负责 service + support 的工作。&lt;br>
不过他们不懂技术，所以我刚才说我们是没有 technical support 的。”&lt;/p>
&lt;p>“噢噢。”&lt;/p>
&lt;p>“这个没什么好或者不好，&lt;br>
这个是我们目前的现状。&lt;br>
但是问题是我们招人的时候，&lt;br>
或者说公司战略上不会明确这么一件事情：&lt;br>
就是技术的工作职责里包括支持。&lt;br>
这个其实就很崩，&lt;br>
人的屁股不同就会决定思想的不一样，&lt;br>
所以这里很多东西是纯靠我们的责任感去维持。”&lt;/p>
&lt;p>“那为什么你们公司不设 technical support 呢？”&lt;/p>
&lt;p>“唔，这个我就说不上话了。&lt;br>
我猜这个是公司成长之路上的阵痛吧。”&lt;/p>
&lt;p>（五）&lt;/p>
&lt;p>米娅想起了上次看到优衣库招聘启事上写的：&lt;br>
“我们是一家信奉实力主义至上的公司”&lt;br>
不禁感慨道：“那有家庭的人估计不能在这样的公司里工作。”&lt;/p>
&lt;p>“是啊，而且我们还有那种结了婚但是工作巨努力的同事…&lt;br>
简直可怕…”&lt;/p>
&lt;p>米娅又想到了什么，问：&lt;br>
“对了，那旭总是单身？”&lt;/p>
&lt;p>我：“大概……是吧……”&lt;/p>
&lt;p>讲到此处，&lt;br>
我和米娅才发现已经不知不觉走到了日月光。&lt;br>
只见门口的公交车站广告牌处，&lt;br>
一个“大满足”的杨洋正在笑容满面地看着我们。&lt;/p>
&lt;p>“走，原路返回，回家。”&lt;/p>
&lt;p>（完）&lt;/p></description></item><item><title>我的一点强迫症</title><link>https://liriansu.com/posts/2018-05-07-my-coding-ocd/</link><pubDate>Mon, 07 May 2018 22:07:44 +0000</pubDate><guid>https://liriansu.com/posts/2018-05-07-my-coding-ocd/</guid><description>&lt;p>每个程序员都有他自己的强迫症。&lt;br>
一旦被戳中了，&lt;br>
就不禁心里暗暗会喊一声“舒服”。&lt;/p>
&lt;h1 id="正确使用空格">正确使用空格&lt;/h1>
&lt;blockquote>
&lt;p>有研究显示，&lt;br>
打字的时候不喜欢在中文和英文之间加空格的人，&lt;br>
感情路都走得很辛苦，&lt;br>
有七成的比例会在 34 岁的时候跟自己不爱的人结婚，&lt;br>
而其余的三成最后只能把遗产留给自己的猫。&lt;br>
毕竟爱情跟书写都需要适时地留白。&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://github.com/vinta/pangu.js">vinta/pangu.js&lt;/a>&lt;/li>
&lt;/ul>
&lt;/blockquote>
&lt;p>现代社会的程序员总是要接触英文，&lt;br>
而很多时候我们会在中文中夹杂英文。&lt;/p>
&lt;p>这种时候假如见到不留白的字我就会很难受：&lt;/p>
&lt;pre tabindex="0">&lt;code>错误：我今天带GF去吃了KFC的嫩牛五方。
正确：我今天带 GF 去吃了 KFC 的嫩牛五方。
&lt;/code>&lt;/pre>&lt;h1 id="正确使用全半角符号">正确使用全半角符号&lt;/h1>
&lt;p>当时在微信公众号的文档 JSON 样例数据里，&lt;br>
发现了全角双引号的我，&lt;br>
就像初中时回宿舍路上，&lt;br>
在马路中央见到了一直死老鼠的阿锋一样惊恐。&lt;/p>
&lt;p>中文使用全角符号，&lt;br>
英文使用半角符号并留白，&lt;br>
连接处使用全角符号。&lt;/p>
&lt;pre tabindex="0">&lt;code>错误：你们搞信息竞赛(OI)的有句话叫&amp;#34;code is cheap，show me your boyfriend。&amp;#34;
正确：你们搞信息竞赛（OI）的有句话叫“code is cheap, show me your boyfriend.”
&lt;/code>&lt;/pre>&lt;h1 id="文本文件以换行符结尾">文本文件以换行符结尾&lt;/h1>
&lt;p>&lt;code>No newline at end of file&lt;/code> 这句话就像是“你房间没锁门”一样令人惊悚。&lt;/p>
&lt;p>不过专业地说，&lt;br>
&lt;a href="https://stackoverflow.com/questions/729692">在 POSIX 标准里行的定义&lt;/a>是：&lt;/p>
&lt;blockquote>
&lt;p>3.206 Line&lt;br>
A sequence of zero or more non-&amp;lt;newline&amp;gt; characters plus a terminating &amp;lt;newline&amp;gt; character.&lt;/p>
&lt;/blockquote>
&lt;h1 id="使用正确的词描述事情">使用正确的词描述事情&lt;/h1>
&lt;blockquote>
&lt;p>你们这样&lt;strong>地&lt;/strong>热情，&lt;br>
但还是要提高自己&lt;strong>的&lt;/strong>知识水平，&lt;br>
识&lt;strong>得&lt;/strong>唔识得啊？&lt;/p>
&lt;/blockquote>
&lt;p>古人有一句话，&lt;br>
叫“学好的地得，走遍天下都不怕”。&lt;/p>
&lt;p>这么想来，&lt;br>
那个苍蝇问的那句话还是颇有思想性的：&lt;br>
“假如当时我们把屎叫做饭会怎么样？”&lt;/p></description></item><item><title>如何带节奏</title><link>https://liriansu.com/posts/2018-04-13-make-your-impact/</link><pubDate>Fri, 13 Apr 2018 22:44:45 +0000</pubDate><guid>https://liriansu.com/posts/2018-04-13-make-your-impact/</guid><description>&lt;p>3月份我司周常分享轮到我的时候，&lt;br>
我讲了这个话题。&lt;br>
就像学好了“meta编程”就可以编的一手好程序，&lt;br>
我想着假如大家能掌握“meta分享”的技巧，&lt;br>
那日后我们的内部分享便会是盛宴不断了。&lt;/p>
&lt;p>本文语气更贴近 presentation,&lt;br>
文学性会欠缺一些。&lt;/p>
&lt;h2 id="背景">背景&lt;/h2>
&lt;p>今天的主题是“如何带节奏”，&lt;br>
我们也可以说“如何说服一个团体”，&lt;br>
或者叫“如何增加你的影响力”。&lt;/p>
&lt;p>所以很显然，&lt;br>
这次我要讲的东西很虚，&lt;br>
基本上全部都是鸡汤。&lt;br>
关于鸡汤类的文章/分享，&lt;br>
有一句话，叫：&lt;/p>
&lt;blockquote>
&lt;p>甲之砒霜，乙之蜜糖&lt;/p>
&lt;/blockquote>
&lt;p>这句话出处我没太找到，&lt;br>
大概就是评价杨玉环的。&lt;br>
说到杨贵妃，古典四大美人之一，&lt;br>
她对于皇帝来说就是蜜糖，&lt;br>
但是对于劳苦大众来说就是砒霜。&lt;br>
这句话你也可以管它叫“千人千面”、“萝卜青菜”、“哈姆雷特和林黛玉”，&lt;br>
意思都是一样的。&lt;/p>
&lt;blockquote>
&lt;p>朝闻道，夕死可矣&lt;/p>
&lt;/blockquote>
&lt;p>这句话意思其实就等同于“纸上得来终觉浅”。&lt;br>
很多时候我们看文章、听分享得来的道理，&lt;br>
觉得蛮普通的。&lt;br>
等到真正践行的时候，&lt;br>
会发现这个道理的确科学啊。&lt;/p>
&lt;p>回到这句话，&lt;br>
意思就是你今天早上听了这个分享，&lt;br>
到晚上你就会发出“すごい”的感慨。&lt;br>
（众人愣，后笑）&lt;/p>
&lt;blockquote>
&lt;p>喜欢就会放肆，但爱就会克制&lt;/p>
&lt;/blockquote>
&lt;p>这句话出自韩寒的《后会无期》，&lt;br>
他前阵子发了条微博：&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/toocold.jpg" alt="toocold">&lt;/p>
&lt;p>大概我今天讲的也会是这样的。&lt;/p>
&lt;p>所谓“古来圣贤皆寂寞，惟有饮者留其名”。&lt;br>
虽然我觉得今天讲的是我的肺腑之言，&lt;br>
但大家也就选自己信的部分听就行了。&lt;/p>
&lt;h2 id="理论">理论&lt;/h2>
&lt;p>好了，背景介绍完了。&lt;br>
我们来讲“如何带节奏”的理论。&lt;br>
光是理论很干涩啊，&lt;br>
我们来想一个例子：&lt;br>
你在玩一个网络游戏（比如山口山），&lt;br>
你加入了一个很强大的组织（比如全服第一的阴阳寮），&lt;br>
你想在里面的主力阵容里有一席之地，&lt;br>
甚至最后可以带团，&lt;br>
那你应该怎么做呢？&lt;/p>
&lt;p>大概的大纲是下面的四步：&lt;/p>
&lt;ul>
&lt;li>打入内部&lt;/li>
&lt;li>建立人设&lt;/li>
&lt;li>注意技巧&lt;/li>
&lt;li>不忘初心&lt;/li>
&lt;/ul>
&lt;h2 id="打入内部">打入内部&lt;/h2>
&lt;p>首先世界上每个组织都有自己一套的行为方式，&lt;br>
比如开源项目有自己的代码风格，&lt;br>
每个公司有自己的文化，&lt;br>
一个公会也可能有自己的副本时间表。&lt;br>
所以第一步就是：要多观察。&lt;br>
这里有一句话，叫：&lt;/p>
&lt;h3 id="新潜三">新潜三&lt;/h3>
&lt;p>也就是“萌新要首先潜水三个月”的意思。&lt;/p>
&lt;p>潜水三个月并不是说你这几个月不说话，&lt;br>
而是你在适当参与互动的前提下，&lt;br>
你可以有比较多的时间注意下像&lt;br>
“组织有什么黑话？”&lt;br>
“组织里哪个人是可以开玩笑的？”&lt;br>
“哪种说话方式可以让大家最舒服？”&lt;br>
“大家是以冲排名为目标，还是以休闲为目标？”&lt;/p>
&lt;p>讲到这里还能引出一个问题，叫：&lt;/p>
&lt;blockquote>
&lt;p>如何跟青少年沟通？&lt;/p>
&lt;/blockquote>
&lt;p>我从之前到现在一直觉得这很扯：&lt;br>
只要多跟他们聊天，&lt;br>
跟他们玩一样的游戏，&lt;br>
跟他们上一样的网站，&lt;br>
自然就知道“现在的年轻人”在想什么。&lt;br>
很多人既不想跟小孩子玩到一起，&lt;br>
又想跟小孩子有共同语言，&lt;br>
这肯定是不科学的。&lt;br>
比如后面我们要讲到的局座、葛平等人，&lt;br>
就是这点做的非常棒的。&lt;/p>
&lt;h3 id="不拉踩">不拉踩&lt;/h3>
&lt;p>这个就是字面意思，&lt;br>
任何时候我们做人，&lt;br>
不能“拉一踩一”。&lt;/p>
&lt;p>比如玩游戏，&lt;br>
一个团里可能会有固定队伍，&lt;br>
我们一定不能说因为我们想顶替掉现在的T，&lt;br>
就只跟奶搞好关系，说“那个T怎么怎么样”。&lt;br>
这样为了短期回报，&lt;br>
而丢掉长期发展的操作是很伤的。&lt;br>
我们要带的是长远的节奏，不在一朝一夕。&lt;/p>
&lt;blockquote>
&lt;p>早期A/B站的故事&lt;/p>
&lt;/blockquote>
&lt;p>这点俊儒也是A岛丧尸所以可能知道的清楚一些，&lt;br>
你们大部分人应该只知道B站很好。&lt;br>
不过其实当初B站创立的时候有一波不太和谐的操作，&lt;br>
具体的情况我也不能断定，&lt;br>
不过在我眼里就是有“拉自己踩隔壁”的嫌疑。&lt;br>
（不过运营、资本、大小姐什么的就是后话了）&lt;/p>
&lt;h3 id="不ky">不KY&lt;/h3>
&lt;p>KY 这个词，源自日语的“空気を読めない”，&lt;br>
翻译过来就是“不会读空气”。&lt;br>
比如举个例子，&lt;br>
我们公司玩 dota2 的人挺多的，&lt;br>
假如大家正在兴冲冲地讨论新出的英雄，&lt;br>
然后我说一句：“只有我觉得 dota1 比 dota2 好玩么？”&lt;br>
这就是 KY。&lt;br>
就算我内心真是这么想的，&lt;br>
但我也得在合适的空气（气氛）中说出来。&lt;/p>
&lt;blockquote>
&lt;p>杠精&lt;/p>
&lt;/blockquote>
&lt;p>前阵子有这么一个词，&lt;br>
指的是那些“喜欢抬杠到成了精”的人。&lt;br>
比如我今天发了一条朋友圈，&lt;br>
说“哇我用 python flask 写了个小服务器好开心”，&lt;br>
然后评论就说：“为什么不用 java? java 效率更高”。&lt;br>
或者微博上的 @新垣结衣新闻社 又发了 gakki 的九宫美图，&lt;br>
粉丝们都在舔屏幕的时候，&lt;br>
有人在下面评论：“就我觉得新垣结衣不是很漂亮吗？”&lt;/p>
&lt;p>这样的事情不仅会破坏气氛，&lt;br>
还会减你自己的群地位。&lt;br>
尽量忍住别做这样的事情。&lt;/p>
&lt;h3 id="不冲突">不冲突&lt;/h3>
&lt;p>字面意思，别跟别人怼起来就行了。&lt;/p>
&lt;p>不过讲道理这条其实有点难，&lt;br>
我见过不少组织因为核心成员怼起来就散了的。&lt;/p>
&lt;h3 id="game">Game&lt;/h3>
&lt;p>分享到这里，&lt;br>
组织了一波现场小游戏：&lt;br>
&lt;code>每个人都讲一句 KY 的话，其他人来点评够不够 KY&lt;/code>&lt;/p>
&lt;p>因为在场的都是平常互黑的研发同事，&lt;br>
所以场面异常火爆。&lt;br>
（场面火爆++）&lt;/p>
&lt;h2 id="建立人设">建立人设&lt;/h2>
&lt;p>下面的一些话写的有点中二，多见谅啊。&lt;/p>
&lt;p>我说的人设这个词，&lt;br>
对应到英文可以是 &lt;code>stereotype&lt;/code>&lt;br>
也就是“刻板印象”。&lt;br>
可能这个词词义本身是带贬义的，&lt;br>
不过我们要知道这是事实就存在的一种设定。&lt;/p>
&lt;p>比如我刚来公司的时候，&lt;br>
跟大家没有共同经历，&lt;br>
所以你们认识我肯定就是从我的一些人设开始的：&lt;br>
交大毕业的、柳老板的室友、广东人。&lt;br>
所以我黑一下复旦，黑一下柳老板，黑一下福建人都是非常“符合人设”的举动。&lt;/p>
&lt;p>这里首先要说到的第一个人性的弱点就是：&lt;/p>
&lt;h3 id="凡人皆愿掌控世界">凡人皆愿掌控世界&lt;/h3>
&lt;p>比如前阵子我搬家，&lt;br>
我发现人类有一点是很好玩的（用轻蔑的语气说的，众笑）。&lt;br>
就是很多人没有活在真实的世界里，&lt;br>
我觉得他们仅仅活在自己的三观里。&lt;br>
比如我搬家的时候会接触不少的人，&lt;br>
每个人都会问一个问题，&lt;br>
叫：“你这房子借的多少钱？”&lt;br>
（提问：为什么是“借”？答：上海人好像是这么说的）&lt;br>
我每次都会说：“一般价格啦。”&lt;br>
注意这里我并没有直接回答他们的问题，&lt;br>
然后有些人就会说：“哦，三四千吧。”&lt;br>
也有些人会说：“五六千要的。”&lt;br>
这里他们的问题其实并不是想要一个真实的回答，&lt;br>
他们只是想用各种各样的方式加强自己的信心：&lt;br>
“嗯，如我所想。”&lt;/p>
&lt;p>凡人总是想掌握世界运行的规律，&lt;br>
愚蠢的人类啊喵。（众笑）&lt;/p>
&lt;p>不过这里虽然我们说凡人怎么怎么样，&lt;br>
但其实我们也是凡人。&lt;br>
假如不自知的话，&lt;br>
我们也容易陷入到这样的弱点里，&lt;br>
你去了解的不是事情的事实，&lt;br>
而是一直在加强心中的那个设定。&lt;br>
（比如有些面试官只凭第一印象去决定面试结果）&lt;/p>
&lt;p>所以这里有个很重要的：&lt;/p>
&lt;blockquote>
&lt;p>空杯心态&lt;/p>
&lt;/blockquote>
&lt;p>比如张总（正在认真听的张总一惊），&lt;br>
经过 GitHub 统计他是全国 Python 第一的程序员（众笑），&lt;br>
他不仅代码厉害，别人夸他的时候他还膜回去，&lt;br>
这就是典型的空杯心态。（众笑，张总：不敢当不敢当）&lt;/p>
&lt;p>这种空杯心态不难达成，但是反过来就不一定了。&lt;br>
比如我苏子岳，讲真大学时候没学过《计算机网络》，&lt;br>
来我司面试的时候真的是连 Get/Post 的区别都分不清，&lt;br>
假如当时拿这个来面我，我肯定会挂。&lt;br>
所以假如当时别人说我“哎呀，你网络基础不行”的时候，&lt;br>
我不控制自己的话就很容易生气：&lt;br>
因为我的确网络基础不行啊！&lt;/p>
&lt;p>所以不仅要在满了的时候保持空杯心态，&lt;br>
你杯子是空的时候更要意识到这个事实，&lt;br>
保持空杯心态。&lt;/p>
&lt;h3 id="吾等只知千人千面">吾等只知千人千面&lt;/h3>
&lt;p>上一节讲的是凡人，&lt;br>
这一节讲的是我们。&lt;br>
恕我直言，&lt;br>
在座的各位都是……&lt;br>
精英！（众笑）&lt;/p>
&lt;p>听到这种好话，&lt;br>
我们肯定很开心，&lt;br>
不过稍一思索我们就会知道：&lt;br>
我们没有什么不同，我们就是凡人。&lt;/p>
&lt;p>这就是一个人设里面很 trick 的东西：&lt;br>
语言里经常会说“我们怎么怎么样”，&lt;br>
但其实我是我，你是你，两个人是截然不同的人。&lt;/p>
&lt;p>作为一个集体，&lt;br>
可能是普通的，&lt;br>
但只要细颗粒地去看，&lt;br>
每个人都是截然不同的人设，&lt;br>
每个人的形象都是不一样的。&lt;/p>
&lt;h3 id="环顾周围已经如此">环顾周围已经如此&lt;/h3>
&lt;p>上一节讲得有点虚了，&lt;br>
我们来看一下周围，&lt;br>
或者说大家都认识的人里有哪些是有“典型人设”的人吧。&lt;/p>
&lt;blockquote>
&lt;p>高晓松&lt;/p>
&lt;/blockquote>
&lt;p>一方面，我在公众场合发言，&lt;br>
讲道理我应该注意观点理中客。&lt;br>
不过另一方面，我讲话只代表我个人的想法。&lt;/p>
&lt;p>我觉得高晓松某些程度上跟罗振宇是很像的，&lt;br>
两个人都是因为一定的特质受部分人群的喜欢，&lt;br>
但其实我们要知道他们被喜欢的是人设。&lt;br>
比如知乎上会有“高晓松讲的东西不对啦，&lt;br>
罗振宇的60s语音是提前录好的啦”之类的讨论，&lt;br>
大部分时候这种事情都不会影响他们的公众人设。&lt;/p>
&lt;blockquote>
&lt;p>葛平&lt;/p>
&lt;/blockquote>
&lt;p>（此处给不懂葛平老师的人放了一下原版，&lt;br>
经典作《循环》，&lt;br>
还有葛平老师自己唱的循环）&lt;/p>
&lt;p>跟局座一样，&lt;br>
葛平也是在年过半百的时候突然被安上了“奇怪的”人设。&lt;br>
但是他们都非常开心地接受了自己的人设，&lt;br>
并且有的时候还会大方地拿自己的人设开玩笑。&lt;br>
很多年轻人一开始只是想恶搞一下他们，&lt;br>
结果最后却真的被他们的人格魅力所吸粉了。&lt;/p>
&lt;h3 id="自然反复迟早身陷">自然反复迟早身陷&lt;/h3>
&lt;p>讲这么一长串，&lt;br>
我想表达的内容就是“人设”这个现象是自然存在的。&lt;br>
只要利用好人设这一点，&lt;br>
就可以迷惑大部分的凡人。&lt;/p>
&lt;p>那怎么建立这点人设呢？&lt;br>
比如会有个老梗说雷锋把好事都写到日记里。&lt;br>
从我的角度来看，&lt;br>
假如一个人假如能360度地维持人设一辈子，&lt;br>
那他就是这样的人。&lt;/p>
&lt;p>对于大部分普通人，&lt;br>
他的人设是什么样，&lt;br>
基本上就是取决于他这个人本来就是什么样。&lt;/p>
&lt;p>当你凝视深渊的时候，&lt;br>
深渊也在凝视着你。&lt;br>
你无法抵抗。&lt;/p>
&lt;h3 id="game-1">Game&lt;/h3>
&lt;p>讲完了人设这么一节，&lt;br>
在场的各位又玩了一次游戏，&lt;br>
叫“每个人讲三个自己的人设。”&lt;/p>
&lt;p>这个环节也是非常火爆，&lt;br>
通常是一个人没讲自己的人设，&lt;br>
大家都争先恐后地帮他回答了。&lt;/p>
&lt;p>不过中间发生了一件蛮好玩的事情，&lt;br>
拉总讲到自己一个人设是“内向”（众笑）&lt;br>
后来拉总跟我聊天的时候，&lt;br>
聊到动情处，&lt;br>
拉总说他自己其实对陌生人是不会很热情的，&lt;br>
很多人觉得他很外向，&lt;br>
但其实他觉得自己在这环节里讲的“内向”才是他的性格。&lt;br>
我不禁陷入了思考。&lt;/p>
&lt;p>这样的游戏环节蛮好的，&lt;br>
不仅能侧面佐证一下分享内容，&lt;br>
还能引起了真真切切的思考，&lt;br>
十分科学。&lt;/p>
&lt;h2 id="注意技巧">注意技巧&lt;/h2>
&lt;p>下一章主题叫“注意技巧”。&lt;br>
现在我们打入内部，有了自己的人设，&lt;br>
面临的就是各种各样具体的事情了。&lt;br>
我们接下来来看一些具体的“术”，&lt;br>
这一部分实操性比较强。&lt;/p>
&lt;p>比如一个小栗子就是我在讲的时候啊，&lt;br>
汤总听得都很认真，&lt;br>
他一边听还一边默默地点头表示认可。（众笑）&lt;br>
有个说法是在会议室里，&lt;br>
一个人默默点头是可以增加群体的认同感的，&lt;br>
俗称就可以叫“托”。&lt;br>
汤总：我不是，我没有，别瞎说啊！（众笑）&lt;/p>
&lt;h3 id="逻辑">逻辑&lt;/h3>
&lt;p>说回正题。&lt;br>
从我的角度来看，&lt;br>
跟别人沟通中讲逻辑是很重要的。&lt;br>
我这个人并不要求别人讲逻辑，&lt;br>
但我一定要讲逻辑，&lt;br>
逻辑清晰的话比较容易把事情说清楚，&lt;br>
各种意义上都会减少误会。&lt;br>
比如说：&lt;/p>
&lt;blockquote>
&lt;p>知之为知之&lt;/p>
&lt;/blockquote>
&lt;p>这点其实是很平常的道理，&lt;br>
但大家可以观察到很多人是做不到的。&lt;br>
这点跟上面的空杯心态有一定重合，&lt;br>
就不讲了。&lt;br>
跟大家讲一个实用的小技巧。&lt;/p>
&lt;blockquote>
&lt;p>FFC (Fact, Feeling, Compare)&lt;/p>
&lt;/blockquote>
&lt;p>人性的弱点之一是：&lt;br>
人被表扬就会开心。&lt;br>
所以我们想影响一个人，&lt;br>
很好的一个切入点就是去表扬他。&lt;br>
这个 FFC 原则，&lt;br>
就是我们表扬别人时可以具体用到的原则。&lt;/p>
&lt;p>比如说今天女朋友给我做了一餐饭，&lt;br>
我可以这么去说：&lt;br>
“今天的罗宋汤颜色好鲜艳，闻起来很香！&lt;br>
（这是 Fact, 事实）&lt;br>
光是看我都看饿了，我觉得你做饭超厉害的！&lt;br>
（这是 Feeling, 感受）&lt;br>
以前我都不会主动吃番茄的，只有你做的我才喜欢吃！&lt;br>
（这是 Compare, 对比）”&lt;br>
这么讲完以后，&lt;br>
女朋友会很开心，&lt;br>
然后明天我也能喝到她给我做的汤了（众笑）&lt;/p>
&lt;p>这个原则很好记，&lt;br>
等下的游戏环节我们就会玩“用 FFC 表扬一个队友”，&lt;br>
大家可以想想。&lt;br>
一般来说，&lt;br>
关于表扬别人还有一个说法，&lt;br>
叫：&lt;/p>
&lt;blockquote>
&lt;p>表扬要公开表扬，&lt;br>
批评最好私下批评。&lt;/p>
&lt;/blockquote>
&lt;p>很简单，&lt;br>
我今天跟张总一个人说“你是全中国 Python 第一的程序员”（众笑）&lt;br>
张总就是单份的开心。&lt;br>
但我今天在大家面前说“张总是全中国 Python 第一的程序员”&lt;br>
在场有 N 个人，&lt;br>
张总就会获得 N 份快感（众笑）&lt;br>
超捧场的张总：我好有快感啊（众狂笑）&lt;/p>
&lt;h3 id="逆向">逆向&lt;/h3>
&lt;p>刚才我们讲的是正面的东西。&lt;br>
有的时候一样东西反过来看又是别样的风景。&lt;br>
比如我很喜欢的一个作家叫“蔡智恒”，&lt;br>
他网名叫“痞子蔡”，&lt;br>
就是写《第一次的亲密接触》的那个人。&lt;br>
他一本书里讲到过这么一个故事：&lt;/p>
&lt;blockquote>
&lt;p>右边的石头&lt;/p>
&lt;/blockquote>
&lt;p>就说一个旅人在爬山，&lt;br>
一路上很累，但风景也很好。&lt;br>
走啊走啊他来到了一个岔路口，&lt;br>
路的左边是一条一眼望得到底的平坦的路，&lt;br>
路的右边是一块很难爬上去的石头。&lt;br>
他这时候想了，&lt;br>
我是走左边的、风景平常的山路，&lt;br>
还是试着去爬爬右边的石头呢？&lt;br>
最后他选择了走平坦的路。&lt;br>
但他一路上都忍不住想：&lt;br>
“假如我当初爬过了右边的石头，&lt;br>
又会是什么样的风景呢？”&lt;/p>
&lt;p>这个套路其实就叫“心结”&lt;br>
很多影视剧/动漫里面都会用，&lt;br>
比如男主小时候有一件blabla的什么事情，&lt;br>
影响了他的一辈子。&lt;/p>
&lt;p>这点对于推进波澜曲折的剧情是很棒啦。&lt;br>
但我觉得作为活着的一个人，&lt;br>
根本不要去在意什么右边的石头，&lt;br>
既然选择了左边的路，&lt;br>
就一条路走到黑。&lt;/p>
&lt;p>（讲到这里，突然觉得不知道怎么讲下去了）&lt;br>
呃，我们的分享主题好像是“如何带节奏”对吧，&lt;br>
咋就被我讲到了个人三观了捏？（众笑）&lt;br>
不管了，我 PPT 都写好了，继续讲。&lt;/p>
&lt;blockquote>
&lt;p>半满杯子&lt;/p>
&lt;/blockquote>
&lt;p>这个故事你们大概听过。&lt;br>
就是一个装了一半水的杯子，&lt;br>
乐观主义者看了觉得还有一半水呢，&lt;br>
悲观主义者看了觉得只剩一半水了，&lt;br>
工程师看了觉得这杯子容积是额定大小的两倍。&lt;/p>
&lt;p>这个经典故事说明的道理也很简单：&lt;br>
看问题的角度会改变问题。&lt;br>
我们不会说“当乐观主义者是对的”或者“不能当悲观主义者”，&lt;br>
假如我们想能站在更高的位置去看事情、做事情，&lt;br>
我们就得能在不同的角度去观察一件事情。&lt;/p>
&lt;blockquote>
&lt;p>站在人群中&lt;/p>
&lt;/blockquote>
&lt;p>这个用西方的一套说，&lt;br>
可能叫“众生平等”。&lt;br>
不过从我的角度来说，&lt;br>
就是我们平常思考问题，&lt;br>
一定一定不能把人分贵贱，&lt;br>
把人分三六九等。&lt;br>
因为这会阻碍我们换位思考，&lt;br>
让我们“逆向”的思考只会在我们“平级”之间流转。&lt;/p>
&lt;p>比如靖哥哥，我觉得他牛逼，&lt;br>
他讲的我信，我只想跟他交流问题。&lt;br>
但强哥是产品转来的，&lt;br>
我觉得他是个菜逼，他说啥我都不信。（众笑）&lt;br>
例子可能有点夸张了，&lt;br>
但这样你们一听就会觉得不妥，&lt;br>
对吧。&lt;/p>
&lt;p>苏轼有一句话，&lt;br>
叫“吾上可陪玉皇大帝，下可以陪卑田院乞儿（，眼前见天下无一个不好人）”&lt;br>
这句话我就很喜欢。&lt;/p>
&lt;h2 id="空杯">空杯&lt;/h2>
&lt;p>又讲到空杯了，&lt;br>
这里可以讲一个故事&lt;/p>
&lt;blockquote>
&lt;p>苏格拉底&lt;/p>
&lt;/blockquote>
&lt;p>这个故事比较经典，&lt;br>
大意是说有人问神谕：&lt;br>
“全雅典最聪明的人是谁啊？”&lt;br>
神谕说是苏格拉底。&lt;br>
苏格拉底听到了这句话以后大吃一惊，&lt;br>
他说：“不对啊，我觉得我非常无知。”&lt;br>
最后他发现，&lt;br>
正是他清楚自己的无知，&lt;br>
这一点比很多人都要厉害。&lt;/p>
&lt;p>对应自己的弱点，&lt;br>
还有一种我们经常会遇到的情况是人生的逆境。&lt;br>
这里有个词，叫“逆商”。&lt;br>
所谓智商、情商、逆商，&lt;br>
智商是怎么处理逻辑问题，&lt;br>
情商是怎么处理人际问题，&lt;br>
逆商大概就是怎么面对逆境了。&lt;/p>
&lt;p>我们人类没办法在瞬间改变环境，&lt;br>
所以很多时候面临逆境，&lt;br>
本质上就是处理我们跟自己的关系。&lt;br>
湖南人有一句话说得好，&lt;br>
叫“霸得蛮，耐得烦”，&lt;br>
大概就是“坚韧不拔”的意思吧。&lt;/p>
&lt;blockquote>
&lt;p>满谦&lt;/p>
&lt;/blockquote>
&lt;p>空杯还有一点，&lt;br>
就是满谦……&lt;br>
（写文章跟分享的时候差了几周，&lt;br>
所以本来好像这里才是将上面的例子的…&lt;br>
不过这并不重要了，过。）&lt;/p>
&lt;h2 id="不忘初心">不忘初心&lt;/h2>
&lt;p>收一下，&lt;br>
我们讲了这么多关于“如何带节奏”的东西，&lt;br>
假如你回去试着去用的话，&lt;br>
你会发现一点：&lt;br>
“最开始你能带节奏的人，都是你身边的人。”&lt;/p>
&lt;p>举个例子，比如何总2016年写过一篇博客，&lt;br>
里面有一句话，叫“2017年要监督女朋友培养正确价值观”，&lt;br>
这就说明他是很能带他女朋友节奏的。&lt;/p>
&lt;p>除了伴侣之间，父母子女之间也很容易带节奏。&lt;br>
再举个例子，我经常会跟女朋友一起看各种访谈之类的，&lt;br>
有的时候里面的人就会说：&lt;br>
“我现在怎么怎么样，&lt;br>
是因为小时候我父母怎么怎么样，&lt;br>
给我造成了永久的伤害。”&lt;/p>
&lt;p>所以假如你有带节奏的能力，&lt;br>
你一定要记住两句话：&lt;/p>
&lt;ul>
&lt;li>别忘了你要带什么节奏&lt;/li>
&lt;li>别忘了你自己是什么样的人&lt;/li>
&lt;/ul>
&lt;p>比如回到最开始，&lt;br>
我们在玩网络游戏，&lt;br>
我们加入了一个很强大的组织，&lt;br>
我们的目的是什么？&lt;br>
没错，我们的目的是想在团里排进主力阵容，&lt;br>
甚至是当团长。&lt;/p>
&lt;p>这就是我们最开始的“初心”。&lt;/p>
&lt;h1 id="实践">实践&lt;/h1>
&lt;p>道理讲了很多，&lt;br>
剩下的都是实际去试了。&lt;/p>
&lt;p>The Zen of Python 里有一句话，&lt;br>
最后送给大家：&lt;/p>
&lt;pre tabindex="0">&lt;code>&amp;gt; Now is better than never.
&amp;gt;
&amp;gt; --- The Zen of Python, by Tim Peters
&lt;/code>&lt;/pre>&lt;p>（完）&lt;/p>
&lt;blockquote>
&lt;p>本文 slides 地址为 liriansu.com/slides/influence&lt;/p>
&lt;p>所有内容为各种杂谈经作者二次消化完成&lt;/p>
&lt;/blockquote></description></item><item><title>破案·Sentry迷云</title><link>https://liriansu.com/posts/2018-03-22-solve-a-sentry-case/</link><pubDate>Thu, 22 Mar 2018 20:14:08 +0000</pubDate><guid>https://liriansu.com/posts/2018-03-22-solve-a-sentry-case/</guid><description>&lt;p>作为程序员，&lt;br>
日常开发中经常会出现一些“不科学”的事情，&lt;br>
这种时候也是“破案”的好时机：&lt;br>
让我们来用科学，解释不科学。&lt;/p>
&lt;h2 id="起">起&lt;/h2>
&lt;p>又是平凡的一天，&lt;br>
坐成一排的程序员们正在噼里啪啦地写代码。&lt;br>
不知不觉间 deadline 逼近了，&lt;br>
想到这点，&lt;br>
大家不禁紧张地噼里啪啦地写代码。&lt;/p>
&lt;p>突然，&lt;a href="https://github.com/MIA503">旭总&lt;/a>眉头一皱，发现事情并不简单：&lt;br>
“我总感觉这几天 Sentry 的响应速度变慢了。”&lt;/p>
&lt;blockquote>
&lt;p>Sentry, 英文单词直译是哨兵（漫威宇宙里最强者之一）。&lt;br>
也是一个非常好用的异常监控/收集/管理软件，&lt;br>
官网可以参见 sentry.io&lt;/p>
&lt;p>我司用 Sentry 做了各端的错误收集，&lt;br>
大家养成了一出错先看 Sentry 堆栈分锅的习惯。&lt;/p>
&lt;/blockquote>
&lt;p>于是紫月就例行公事地看了一眼 Sentry Stats,&lt;br>
紫月觉得事情很简单：&lt;br>
“拉总你看看你的推送啊！”&lt;/p>
&lt;blockquote>
&lt;p>&lt;a href="https://lxkaka.wang/">拉总&lt;/a>，绰号来源于 ID: lxkaka.&lt;br>
因为跟我们支付供应商拉卡拉 (lakala) 巨像而得名。&lt;/p>
&lt;p>拉总在我司做后端，&lt;br>
负责过会员数据、平台监控、推送系统的实现。&lt;/p>
&lt;/blockquote>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/cases/sentry_stats.jpg" alt="stats">&lt;/p>
&lt;p>跑过来看着紫月屏幕里 Sentry Stats 的数据，&lt;br>
拉总感到一脸懵逼：&lt;br>
“不应该啊，推送系统怎么能报这么多错呢？”&lt;/p>
&lt;h2 id="承">承&lt;/h2>
&lt;p>回到座位的拉总研究了一会儿，&lt;br>
惊呼道：&lt;br>
“我们是不是换过测试环境的 MongoDB 地址啊？”&lt;/p>
&lt;p>旭总一脸鄙视：&lt;br>
“没换，要换也是两个月以前换的。”&lt;/p>
&lt;p>紫月笑着调戏拉总：&lt;br>
“不会你的代码跪了两个月才发现吧？”&lt;/p>
&lt;p>拉总赶快说：&lt;br>
“不可能不可能，我再看看。”&lt;/p>
&lt;p>过了十分钟，&lt;br>
拉总二脸懵逼地站起来了，&lt;br>
十分迷惑地 Pub 了一句：&lt;br>
“这不科学啊，测试环境是好的啊。”&lt;/p>
&lt;p>于是大家凑在一起，&lt;br>
整理出了目前几个已知事实：&lt;/p>
&lt;ul>
&lt;li>Sentry 不停地在接受测试环境的推送系统 (zaihui-push) 的报错。&lt;/li>
&lt;li>报错内容是 MongoDB 访问地址不对。&lt;/li>
&lt;li>两个月以前我们换过测试环境的 MongoDB 。&lt;/li>
&lt;li>但是代码级别上，测试环境用的 MongoDB 配置是正确的。&lt;/li>
&lt;/ul>
&lt;p>也就是说：&lt;br>
我们以为我们代码是正确的，&lt;br>
但是监控观察到代码一直在报错！&lt;/p>
&lt;p>这很 (bu) 神 (ke) 奇 (xue) 。&lt;/p>
&lt;p>于是我们决定破案一下。&lt;/p>
&lt;p>首先，拉总检查了一下测试环境的正确性。&lt;br>
拉总把推送系统的 docker 都关了，&lt;br>
但 Sentry 还是一直收到报错，&lt;br>
这说明&lt;strong>报错源不是测试环境&lt;/strong>。&lt;/p>
&lt;p>&lt;a href="https://github.com/hulucc">俊儒&lt;/a>指出 Sentry 说不定可以看到源 IP，&lt;br>
于是紫月尝试观测了一下，&lt;br>
IP 是没观测到，但是观测到了 Server Name。&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/cases/sentry_tags.jpg" alt="tags">&lt;/p>
&lt;p>&lt;code>ea064a694da5&lt;/code> 这个12位的16进制数字是典型的 Docker Container ID ！&lt;/p>
&lt;p>所以大家马上想到了暴力的破解方法：&lt;br>
把内网的所有 Docker Container ID 都找出来。&lt;/p>
&lt;blockquote>
&lt;p>我司的测试/生产环境都在内网环境中，&lt;br>
只能通过入口机器 (gateway) ssh 到机器上。&lt;br>
为了方便运维，&lt;br>
内网机器都在 ssh config 里配上了名称。&lt;/p>
&lt;/blockquote>
&lt;p>于是紫月在入口机上执行了一段 bash 脚本，&lt;br>
把所有内网上的 Docker Container ID 都找了出来：&lt;/p>
&lt;pre tabindex="0">&lt;code>cat ~/.ssh/config | grep -G &amp;#39;^Host&amp;#39; | cut -d&amp;#39; &amp;#39; -f2 | xargs -I{} ssh {} &amp;#34;docker ps&amp;#34; &amp;gt;&amp;gt; dockers_container.log
&lt;/code>&lt;/pre>&lt;p>命令跑完以后，&lt;br>
我们打开输出文件，&lt;br>
激动地发现：&lt;br>
&lt;strong>报错源不在内网里&lt;/strong>！&lt;/p>
&lt;h2 id="转">转&lt;/h2>
&lt;p>一下子事情僵住了，&lt;br>
大家的头绪离散到了好几个方面：&lt;/p>
&lt;ul>
&lt;li>能不能模拟 MongoDB 的地址，然后抓包请求？&lt;/li>
&lt;li>能不能在 Sentry 信息中翻到 IP 地址？&lt;/li>
&lt;li>能不能通过 Docker Container ID 找到对应的机器？&lt;/li>
&lt;/ul>
&lt;p>经过思考以后，&lt;br>
大家总结出破案的关键在于整个网络调用：&lt;br>
我们只要捋一遍服务器的网络关系、调用路径，&lt;br>
就可以找到破案点！&lt;/p>
&lt;p>问题一下子就定位到了内部系统的 Load Balancer 上。&lt;/p>
&lt;blockquote>
&lt;p>我司隔离了生产环境和内部系统（比如 GitLab/Sentry 等）&lt;br>
类似于生产环境的入口机器 (gateway)&lt;br>
我们内部系统的流量入口也是我们用 nginx 自己搭的。&lt;/p>
&lt;/blockquote>
&lt;p>于是我们登上了内部系统的 nginx,&lt;br>
找到了 nginx access log,&lt;br>
整个文件大概有10万行。&lt;/p>
&lt;pre tabindex="0">&lt;code>...
42141 59.78.3.25 - - [22/Mar/2018:22:09:07 +0800] &amp;#34;POST /api/450/store/ HTTP/1.1&amp;#34; 200 41 &amp;#34;-&amp;#34; &amp;#34;raven-python/6.3.0&amp;#34; &amp;#34;-&amp;#34;
42142 59.78.3.20 - - [22/Mar/2018:22:09:07 +0800] &amp;#34;POST /api/355/store/?sentry_version=7&amp;amp;sentry_client=raven-js%2F3.22.3&amp;amp; HTTP/1.1&amp;#34; 200 41 &amp;#34;Mozilla/5.0 (Linux; Android 8.0; DUK-AL20 Build/HUAWEIDUK-AL20; wv) Mobile Safari/537.36 MicroMessenger/6.6.5.1280&amp;#34; &amp;#34;-&amp;#34;
42143 59.78.3.24 - - [22/Mar/2018:09:33:08 +0800] &amp;#34;POST /api/452/store/ HTTP/1.1&amp;#34; 400 62 &amp;#34;-&amp;#34; &amp;#34;SharpRaven/2.2.0.0&amp;#34; &amp;#34;-&amp;#34;
...
&lt;/code>&lt;/pre>&lt;p>问题又来了：&lt;br>
要怎么在这数万行形态各异的 log 中，&lt;br>
找到哪一条是推送系统的报错，&lt;br>
从而找到报错源的 IP 呢？&lt;/p>
&lt;p>可以通过 Sentry Endpoint,&lt;br>
也可以通过 Raven 的版本。&lt;br>
比如上述 log 中的三条信息，&lt;br>
分别是 Python/JavaScript/C# 向 Sentry 发送的错误信息。&lt;/p>
&lt;p>推送系统用的包是 [raven==6.3.0][ravern],&lt;br>
于是我们就从中晒出来了真正的 IP：&lt;br>
59.78.3.25 ！&lt;br>
（本条 IP 已打码）&lt;/p>
&lt;p>大家兴奋地都站了起来。&lt;br>
因为不是自己推送系统环境没配对之类的锅，&lt;br>
拉总也如释重负/火上浇油地喊道：&lt;br>
“破案了破案了！快看看这个IP是谁的！”&lt;/p>
&lt;h2 id="合">合&lt;/h2>
&lt;p>上网定位了一下，&lt;br>
发现这个 IP 是上海市的，&lt;br>
俊儒怀疑道：&lt;br>
“这怕不是就是我司办公室的流量出口？”&lt;/p>
&lt;p>于是我们查了一下我们现在的出口 IP：&lt;/p>
&lt;pre tabindex="0">&lt;code>&amp;gt; curl -s httpbin.org/ip
{
&amp;#34;origin&amp;#34;: &amp;#34;59.78.3.25&amp;#34;
}
&lt;/code>&lt;/pre>&lt;p>顿时空气有点寂静，&lt;br>
因为目前的事实是这样的：&lt;/p>
&lt;ul>
&lt;li>拉总确认过他开发的推送系统没有报错。&lt;/li>
&lt;li>大家追溯下来，报错源就在我们办公室。&lt;/li>
&lt;li>报错源藏在某个人电脑的 docker 里面。&lt;/li>
&lt;/ul>
&lt;p>那么问题来了：&lt;br>
究竟哪个人会 clone 推送系统的代码，&lt;br>
并且在自己的电脑上用 docker 跑起来呢？&lt;br>
那就只可能是开发者&lt;strong>拉总本人&lt;/strong>。&lt;/p>
&lt;p>大家围到了紧张的拉总的身后，&lt;br>
看着他敲下了 &lt;code>docker ps&lt;/code> 命令：&lt;/p>
&lt;pre tabindex="0">&lt;code>&amp;gt; docker ps
CONTAINER ID IMAGE ...
ea064a694da5 zaihui-push ...
&lt;/code>&lt;/pre>&lt;p>破案了！&lt;/p>
&lt;p>拉总想了想，猜测说：&lt;br>
他大概是几天前本机调试了一下推送，&lt;br>
忘了关了。&lt;/p>
&lt;p>那么真的如他所说是几天前吗？&lt;br>
大家打开了 Sentry：&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/cases/sentry_frequency.jpg" alt="frequency">&lt;/p>
&lt;p>数据无情地还原了真相：&lt;br>
两个月以前就开始报错了，&lt;br>
也就是按旭总的记忆，&lt;br>
从我们换了测试环境的 MongoDB 开始。&lt;/p>
&lt;p>看着最后原来是拉总自己电脑搞的乌龙，&lt;br>
大家也是爆笑了一圈，&lt;br>
旭总顺带还调侃拉总：&lt;br>
“你的 Mac 电脑也是牛逼啊，开着几个 docker 都不卡的。”&lt;/p>
&lt;p>后来看着 Sentry 的错误频率图，&lt;br>
大家又疯狂地笑了一圈拉总：&lt;br>
“拉总，这个 Sentry 报错早十晚八，做五休二，&lt;br>
可真能反映你的上班时间~”&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/cases/sentry_hours.jpg" alt="hours">&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/cases/sentry_weeks.jpg" alt="weeks">&lt;/p>
&lt;p>事情的最后，&lt;br>
紫月从柳总桌子上翻出了门把手的“拉”和“推”两个字，&lt;br>
放在了拉总的桌子上：&lt;br>
“拉总，好吧，经此一役，&lt;br>
你也是我们的推总了。”&lt;/p>
&lt;p>（完）&lt;/p></description></item><item><title>链家小哥问我：听说搞IT的培训三个月就可以月入上万，是真的吗？</title><link>https://liriansu.com/posts/2018-03-12-is-it-possible-to-be-rich-easily-by-programming/</link><pubDate>Mon, 12 Mar 2018 23:22:10 +0000</pubDate><guid>https://liriansu.com/posts/2018-03-12-is-it-possible-to-be-rich-easily-by-programming/</guid><description>&lt;p>我想了想，&lt;br>
说：&lt;br>
是的。&lt;/p>
&lt;p>（一）&lt;/p>
&lt;p>前几天跟女朋友去租房子，&lt;br>
因为我们一对情侣租的是两居室，&lt;br>
链家小哥自然就问一居室的考不考虑。&lt;/p>
&lt;p>本着知道业务需求，&lt;br>
才能实现的更好的原则，&lt;br>
我就跟他说了下我是程序员，&lt;br>
有的时候晚上想工作到比较晚，&lt;br>
作息上会跟女朋友错开，&lt;br>
所以会住两居室的原因。&lt;/p>
&lt;p>小哥听说我是程序员以后很好奇，&lt;br>
问：“你们程序员是干什么的啊？”&lt;/p>
&lt;p>我想了想，跟他说：&lt;br>
“比如你们上传房间照片用的网站，&lt;br>
就是你们程序员开发的。&lt;br>
比如你手机上的App时不时要更新，&lt;br>
这些也是程序员做的。&lt;br>
比如微信、王者荣耀、或者说你手机系统，&lt;br>
都是程序员做的。”&lt;/p>
&lt;p>小哥更好奇了：&lt;br>
“那你们这算是搞IT的咯。&lt;br>
我听我朋友说，&lt;br>
你们搞IT的，&lt;br>
培训三个月，&lt;br>
就可以找到月收入一万的工作，&lt;br>
是真的吗？”&lt;/p>
&lt;p>（二）&lt;/p>
&lt;p>小哥看我一脸懵逼的样子，&lt;br>
他就跟我说：&lt;br>
“年后我接待的客户全部都是搞IT的。&lt;br>
前阵子有个湖南那边的应届生来上海，&lt;br>
两个人租了九千块钱的房子。&lt;br>
刚过完年的时候，&lt;br>
也是有一对情侣，&lt;br>
男的比女的大不少，&lt;br>
也是搞IT的，&lt;br>
两个人也是租了七、八千。&lt;br>
前阵子还有一个客户，&lt;br>
一个人租了五千，&lt;br>
刚租了一个月，&lt;br>
（押金都不要了）&lt;br>
就去了杭州阿里巴巴那边上班…”&lt;/p>
&lt;p>我：“呃。。。”&lt;br>
=_=&lt;/p>
&lt;p>我想了想，&lt;br>
看小哥这么好奇的样子，&lt;br>
也出于我跟小哥交换行业知识，&lt;br>
小哥说不定也会跟我说怎么租房子便宜的私心，&lt;br>
我认真地解释道：&lt;br>
“你说的，培训三个月，&lt;br>
月入上万是肯定有几率存在的情况。&lt;/p>
&lt;p>我们这行可能会被叫做“搞IT的”，&lt;br>
这其实是一个很大的职业范围，&lt;br>
这里会有各种各样的情况。&lt;/p>
&lt;p>比如可能是有些有钱的企业在搞信息化，&lt;br>
这样的企业缺乏的不是技术上多么专业的人才，&lt;br>
而是各方面都很优秀的人。&lt;br>
有可能你本来跟人沟通啊、合作意识啊、业务能力啊都很不错，&lt;br>
然后你去认真参加了一个培训，&lt;br>
你获得了“搞IT”这项技能，&lt;br>
就像参加了英语培训、参加了挖掘机培训一个道理。”&lt;/p>
&lt;p>小哥想了想，&lt;br>
他说是这样的。&lt;/p>
&lt;p>（三）&lt;/p>
&lt;p>小哥说链家正在改革，&lt;br>
所有人都是无底薪，&lt;br>
单纯靠提成维持生活。&lt;/p>
&lt;p>“你知道吗，&lt;br>
我16年刚来上海的时候，&lt;br>
只要穿个西装打个领带，&lt;br>
站在街上就会有人问我买房…”&lt;br>
小哥怀念当年的情景，说道：&lt;br>
“我们很多同事，&lt;br>
高中没毕业，&lt;br>
08年、10年就做这行了。&lt;br>
早就在老家买房买车，&lt;br>
现在也在店里干活。”&lt;/p>
&lt;p>对口相声讲究一人逗一人捧，&lt;br>
于是我感慨道：“这么厉害的吗。”&lt;/p>
&lt;p>小哥也感慨道：&lt;br>
“是啊。&lt;br>
不过我们现在每天晚上都睡不着觉，&lt;br>
每天一起来就只有出账，&lt;br>
没有入账，&lt;br>
你懂这种感觉吗？&lt;br>
我就想了解下互联网行业怎么样，&lt;br>
有机会的话回老家做。&lt;br>
现在什么最火？&lt;br>
就是互联网。&lt;br>
现在这个时代就是互联网加的时代。”&lt;/p>
&lt;p>我被小哥振聋发聩、洞悉行业、实事求是的发言折服了，&lt;br>
不知道说啥能接上话题。&lt;/p>
&lt;p>（四）&lt;/p>
&lt;p>不知道说啥的时候就切回主题。&lt;br>
主题是啥？&lt;br>
主题是培训。&lt;br>
好，那我们继续跟小哥说培训的话题。&lt;/p>
&lt;p>知道了小哥其实有点认真考虑培训的话题，&lt;br>
我想了想，&lt;br>
给他又讲了下我知道的内容：&lt;/p>
&lt;p>“唔，我把我知道的都跟你说说吧，&lt;br>
不过因为我自己不是做培训的，&lt;br>
所以我说的可能都不对。&lt;/p>
&lt;p>首先，认真参加IT培训肯定是能找到工作的。&lt;br>
就像你说的，现在是‘互联网+’的时代，&lt;br>
这个社会对IT人才的缺口很大，&lt;br>
比如刚才看到的电子锁，&lt;br>
比如这两年出现的共享单车，&lt;br>
比如人人都在用的移动支付，&lt;br>
这里都是自动化，都需要工程师。&lt;/p>
&lt;p>其次，找到什么样的工作不一定。&lt;br>
因为‘搞IT的’做的事情其实很广。&lt;br>
这个我具体阐述不来，&lt;br>
但你要知道很多时候‘搞IT’面对的是机器，&lt;br>
是传统意义上很枯燥的工作。&lt;br>
不适应的话，很多人都会干的很痛苦。&lt;/p>
&lt;p>最后，培训本身来说，效果是因人而异的。&lt;br>
有些人可能培训了几个月，&lt;br>
他就学到了很多，&lt;br>
打开了一扇门。&lt;br>
但有些人可能培训了几个月，&lt;br>
他唯一学到的，&lt;br>
就是自己不适合‘搞IT’。&lt;/p>
&lt;p>所以说，因为不了解你的具体情况，&lt;br>
这件事情我没办法给你具体的帮助。”&lt;/p>
&lt;p>小哥听完以后，&lt;br>
陷入了信息量带来的卡顿中。&lt;br>
我又想了想，&lt;br>
给了个实操上的建议：&lt;/p>
&lt;p>“讲道理你想了解这方面的东西的话，&lt;br>
我建议是这样的。&lt;br>
你问问看你老家那边，&lt;br>
或者有没有认识的亲近的IT朋友，&lt;br>
他们肯定更了解你、更了解你老家的具体情况，&lt;br>
他们给的建议，&lt;br>
肯定更能执行下来。&lt;br>
”&lt;/p>
&lt;p>（五）&lt;/p>
&lt;p>跟链家小哥聊了一路以后，&lt;br>
我回家也不禁一屁股陷进了“行业选择”这个话题里。&lt;/p>
&lt;p>我想我自己选择行业的那一时刻，&lt;br>
发生在我爸给我填志愿的那一刻。&lt;/p>
&lt;p>当时高三保送生考试去考清华，&lt;br>
考前要填三个志愿专业。&lt;br>
填志愿的时候特开心，&lt;br>
就像已经考上了一样。&lt;br>
当时很喜欢看讲建筑的《筑梦天下》和讲汽车的《Top Gear》，&lt;br>
清华的一二三志愿填的就是建筑学、土木工程、汽车工程。&lt;/p>
&lt;p>后来考华约，我懒得又填一遍交大的志愿，&lt;br>
就让我爸帮我代劳。&lt;br>
我爸看了看表格，跟我说：“交大可以填五个志愿诶。”&lt;br>
应该是正在玩游戏的我说：“你看着填就行了。”&lt;br>
于是我爸对应的就给我填了建筑、土木、汽车工程、计算机科学、软件工程。&lt;br>
我看了看五个志愿，跟我爸说：&lt;br>
“我感觉中学已经写了六年程序了，&lt;br>
我以后大概不会想写程序的。”&lt;br>
就把第四志愿的计算机科学换成了英语系。&lt;/p>
&lt;p>结果后来交大分专业的老师，&lt;br>
可能看我是学OI的，&lt;br>
就直接给我分到了第五志愿：软件工程了。&lt;br>
到今天我一直很感谢这位老师没有纵容我的小任性。&lt;/p>
&lt;p>有的时候我会跟队友感慨：&lt;br>
其实科班生的几年学习，&lt;br>
最大的作用是让你知道自己喜不喜欢这个行业。&lt;br>
幸运的同学就会明确这一点，&lt;br>
并且在自己大学的行业上一直做下去；&lt;br>
也有的同学学完四年，&lt;br>
就知道自己并不喜欢这个专业/行业，&lt;br>
就会立刻转行。&lt;/p>
&lt;p>就像链家小哥问的那样：&lt;/p>
&lt;p>“听说搞IT的培训三个月就月入上万，&lt;br>
是真的吗？”&lt;/p>
&lt;p>假如再问我一次，我会跟他说：&lt;/p>
&lt;p>“可以是真的。”&lt;/p>
&lt;p>假如再要我多说一句的话，我会说：&lt;/p>
&lt;p>“只要你坚持在你喜欢的行业工作下去，&lt;br>
你可能会遇到困难、遭受挫折，&lt;br>
但你终有一天会因为自己的勤奋、勇敢而获得更好的生活。”&lt;/p>
&lt;p>希望小哥能找到他喜欢的事业，&lt;br>
并且为之奉献一生。&lt;/p>
&lt;p>（完）&lt;/p></description></item><item><title>我的好友柳宁宁</title><link>https://liriansu.com/posts/2018-03-03-my-friend-ldsink/</link><pubDate>Sat, 03 Mar 2018 20:39:48 +0000</pubDate><guid>https://liriansu.com/posts/2018-03-03-my-friend-ldsink/</guid><description>&lt;p>柳宁宁真名其实不叫柳宁宁，&lt;br>
我帮他解释真名都是某个朝代的某个职位。&lt;br>
但柳宁宁的快递名都叫“柳宁宁”，&lt;br>
以致于我的快递名叫“柳宁宁的同桌”。&lt;/p>
&lt;p>柳宁宁和我是大学室友，&lt;br>
后来是工作伙伴。&lt;br>
因为在我司互膜文化盛行，&lt;br>
基本上互称不是X总X神就是X老板，&lt;br>
所以后来我称呼柳宁宁都是叫柳总。&lt;br>
硬生生地把大学几年的称呼都扭过来了，&lt;br>
现在我叫柳总真名反而不太适应。&lt;/p>
&lt;p>柳总真名不叫柳宁宁。&lt;br>
不过他很喜欢柳这个姓，&lt;br>
于是有时需要录测试数据，&lt;br>
他不是录“蜜汁服务员柳宁宁”，&lt;br>
就是录“柳纯”。&lt;/p>
&lt;p>柳总对隐私安全很重视。&lt;br>
柳总有一段时间把他所有不玩的账号都注销掉了，&lt;br>
但是有些网站没有提供注销功能（比如新浪微博），&lt;br>
他就很烦。&lt;br>
之前我在知乎上写文章经常会提到柳总的真名，&lt;br>
他的队友发现以后就吐槽了一波柳总，&lt;br>
于是柳总就拜托我把文章里的真名换成了化名。&lt;br>
我有些换成了柳宁宁，&lt;br>
有些换成了柳纯，&lt;br>
有些换成了ldsink。&lt;br>
后来柳总盯着搜索出来的五六篇文章，&lt;br>
感慨道：“这么多文章，简直像是女朋友…”&lt;/p>
&lt;p>柳总的ID是ldsink。&lt;br>
GitHub/ldsink或者是ldsink.com都是柳总。&lt;br>
柳总说这个名字是 LinuxDeepin Sink 的缩写，&lt;br>
以及 Deepin 是一款很棒的 Linux 发行版，&lt;br>
Sink对应他的名字。&lt;br>
果然柳总是 Deepin 的真爱。&lt;/p>
&lt;p>柳总现在基本只用Deepin。&lt;br>
（除了打dota2的时候）&lt;br>
我司程序员标配Mac电脑，&lt;br>
但只有8GB的默认内存和IOS的默认系统有时就不那么方便。&lt;br>
在柳总建议下和预算允许的范围内，&lt;br>
我换了一个神舟电脑+俩16G内存条，&lt;br>
他换了一个戴尔本子+俩8G内存条。&lt;br>
后来我的神舟天天蓝屏，&lt;br>
柳总嘿嘿一笑：“我猜是内存的原因，不如我们换一下”。&lt;br>
换了以后用着俩8G内存条神舟电脑的我果然不蓝屏了。&lt;br>
围观了事件全过程的张总惊呼：&lt;br>
“这就是柳总的内存转移之术！”&lt;/p>
&lt;p>柳总是一个ACG御宅。&lt;br>
虽然广义上的说法可以介绍说柳总是动漫宅，&lt;br>
但其实我觉得他算是ACG Otaku，&lt;br>
也就是“在动画、漫画、游戏界都很沉迷的御宅族”的说法。&lt;br>
去年（17年）柳总发起了一波《刀剑神域：序列之争》观影活动，&lt;br>
同时表露了他作为松岗爱衣催婚协会会员的激动心情。&lt;br>
大学时期有一阵他手机铃声是石头门的OP《Hacking to the Gate》，&lt;br>
短信通知铃声是香菜的嘟嘟噜，&lt;br>
于是我总是瞅着他忘了开静音的上课时间戳他微信消息。&lt;/p>
&lt;p>柳总是一个萝莉控。&lt;br>
他大概很吃萝莉音，&lt;br>
大学夜聊的时候，&lt;br>
讲到“你最看重女生身上什么特质”这个话题时，&lt;br>
柳总曾顺带讲过声音是很重要的特质：&lt;br>
“好的脸蛋总会衰老，&lt;br>
好的性格也许会变，&lt;br>
但是好的声音永远都是这么好听呀~&lt;br>
你看那些声优都是怪物~”&lt;/p>
&lt;p>柳总是OI保送的交大。&lt;br>
柳总是雅礼中学毕业的，&lt;br>
我以前也到长郡中学读过一阵书，&lt;br>
有的时候就会聊到以前保送以后的放浪生活。&lt;br>
柳总说他们那个时候会集体去网吧，&lt;br>
打野的打野，打中路的打中路，好不快活。&lt;/p>
&lt;p>柳总打dota，本名是先知。&lt;br>
读大学认识了室友以后第一件事就是互相报兴趣爱好，&lt;br>
柳总、郁翔和我都打dota，&lt;br>
小赖也有一阵被我们带的打起了dota。&lt;br>
柳总的本名是先知，&lt;br>
擅长的技巧是高台打野，&lt;br>
然后飞到中路gank影魔，&lt;br>
或者是出了大根以后电影魔，&lt;br>
或者是出了资源以后沉默影魔。&lt;br>
在11平台打天梯那阵，&lt;br>
在我们的分工之下，&lt;br>
柳总还用起了聊天流，&lt;br>
一边高台打野，&lt;br>
一边跟敌方影魔聊人生。&lt;/p>
&lt;p>柳总有不少关系很铁的朋友。&lt;br>
以前大学的时候分分钟就可以靠柳总拉起五人黑，&lt;br>
（不保证黑店质量）。&lt;br>
有一次我们宿舍三人再加一个柳总好友四排，&lt;br>
一把游戏输了以后，&lt;br>
我感慨道“柳总你这朋友是有点菜啊”，&lt;br>
然后一看游戏的得分面板：&lt;br>
该玩家（柳总朋友）蓝猫英雄评分1分（正常分数是1000~3000分），&lt;br>
本场比赛-0分。&lt;br>
郁翔：-_-&lt;br>
我：=_=&lt;br>
柳总：+_+&lt;br>
后来我们也常常拉他一起开黑，&lt;br>
然后在“赢一场就睡”的flag下玩了一晚上。&lt;/p>
&lt;p>柳总十分愿意分享他的知识。&lt;br>
大学夜聊的时候，&lt;br>
讲到“要怎么避孕”这个话题时，&lt;br>
因为郁翔和小赖都缺乏相关安全知识，&lt;br>
于是柳总兴致勃勃地给大家讲解了一波“安全期与避孕药”，&lt;br>
后来我们还拆了一个六盒装的杜蕾斯，&lt;br>
用了两个装些水玩了一下，&lt;br>
最后四个每人分了一个放抽屉里。&lt;br>
想着第二天阿姨清垃圾，&lt;br>
看到男生宿舍里突然出现的用过的杜蕾斯…&lt;br>
大家纷纷没心没肺地笑了起来…&lt;br>
毕业的时候宿舍四人清理抽屉，&lt;br>
都发现几年的一个过期杜蕾斯…&lt;/p>
&lt;p>柳总还很有销售的天赋。&lt;br>
现在办公室里很多队友拿的是小米手机，&lt;br>
用的是小米插头，&lt;br>
测体温的是iHealth体温计，&lt;br>
都是拜柳总安利所赐。&lt;br>
柳总安利一样东西的手法异常纯熟：&lt;br>
介绍产品：“这个XX就可以买，功能有XX，是XX出的，解决了XX问题…”&lt;br>
打压竞品：“那个XX特别贵，没有XX功能，你看XX用的效果根本不好…”&lt;br>
瞬间到货：“我昨天刚买了这个XX，你要不要，你要的话我这个就给你…”&lt;br>
货款两清：“你扫我的付款码就好了，你看，再惠茶餐厅，多方便（笑眯眯）…”&lt;/p>
&lt;p>柳总是金牛座的，对钱很有概念。&lt;br>
虽然柳总应该不太信星座。&lt;br>
柳总大学的时候就开始炒股了，&lt;br>
选课的时候还跟水哥发起过一波《证券投资学》的选修。&lt;br>
柳总对信用卡也颇有研究，&lt;br>
去年成功拉了好几个刷卡送星巴克的小伙伴入坑。&lt;br>
以至于后来我司做支付的时候，&lt;br>
大家都觉得这功能应该归属于柳总，&lt;br>
后来“代金券能不能叠加”这个月经锅也就自然而然地被柳总接下了。&lt;/p>
&lt;p>靖哥哥只服柳总。&lt;br>
（语文老师说要有侧面描写，&lt;br>
想了想，就拿靖哥哥当靶子吧。）&lt;br>
靖哥哥是我司前端大佬，&lt;br>
不仅负责写一些JS文件（棒读），&lt;br>
还要负责前端整套服务器的搭建。&lt;br>
因为本身是大佬，&lt;br>
所以靖哥哥一直很屌，&lt;br>
除了跟柳总交流的时候。&lt;br>
每次靖哥哥都是鬼鬼祟祟地从走道走过来，&lt;br>
然后问柳总：“大佬，小弟问个问题，blabla…”&lt;br>
（不过每次在支付相关的问题上，&lt;br>
他们两个互怼的都很凶就是了）&lt;/p>
&lt;p>柳总难以忍受落后的技术。&lt;br>
在之前的&lt;a href="https://liriansu.com/py2-to-py3">《我们是怎么升级到Python3的》&lt;/a>一文中就讲过，&lt;br>
柳总充当了升级Python3整件事情的推动者，&lt;br>
把分锅、背锅以及一些大家不想做的锅相关的事情都做了。&lt;br>
发现了Git的Commit可以签名以后，&lt;br>
柳总又很开心地把他自己的Commit都签名了一波，&lt;br>
看着GitHub/GitLab上绿绿的认证标签，&lt;br>
柳总很是开心。&lt;/p>
&lt;p>柳总其实是一个很内敛的人。&lt;br>
我想他大概会喜欢“木秀于林，风必摧之；堆出于岸，流必湍之；行高于人，众必非之。”这句话。&lt;br>
柳总虽然也很喜欢吃瓜（看戏），&lt;br>
但他一般不会直接表露他对事情的看法，&lt;br>
除非他忍不住了。&lt;br>
所以有的时候要逗柳总讲话，&lt;br>
就可以贱兮兮地发表一些有争议的观点，&lt;br>
比如“我觉得kafka是个解耦神器，什么场景都可以用”…&lt;/p>
&lt;p>柳总也是懒人。&lt;br>
比如租房子，&lt;br>
柳总选自如是因为简单方便。&lt;br>
比如工具箱，&lt;br>
柳总把所有他常做的运维操作都&lt;a href="https://github.com/ldsink/toolbox">记成了脚本&lt;/a>。&lt;br>
比如答疑解惑，&lt;br>
假如别人有什么操作想问柳总的话，&lt;br>
柳总肯定第一反应是丢一个文档/脚本让他自己跑。&lt;br>
不过有些事情柳总也是很勤奋，&lt;br>
他的博客ldsink.com从14年开始一直保持着大概一月一更的频率。&lt;/p>
&lt;p>柳总很白。&lt;br>
字面意义上的。&lt;br>
柳总以前也胖过一段时间，&lt;br>
有一次去面试候选人，&lt;br>
几轮面完以后谢老板出来笑着跟柳总说：&lt;br>
“刚才那个候选人说：‘前面那个白白胖胖的面试官很厉害啊！’”&lt;br>
受了很大刺激的柳总后面的两个月晚饭只吃沙拉…&lt;/p>
&lt;p>柳总想笑的时候是忍不住的。&lt;br>
前阵子柳总又玩起了阴阳师，&lt;br>
然后一天晚饭的时候，&lt;br>
我眼睁睁地看他抽到了SSR·彼岸花。&lt;br>
然后柳总一副啊呀我真开心，&lt;br>
啊呀我要低调，&lt;br>
啊呀我不能在别人面前晒卡，&lt;br>
啊呀但我真的很开心&lt;br>
的复杂的开心表情。&lt;br>
这样的表情在大家围观紫光阁地沟油事件的时候也同样地发生过…&lt;/p>
&lt;p>柳总和我虽然在同一家公司共事，&lt;br>
但其实任何时候我们两人聊天基本上不讲工作相关的事情。&lt;br>
反而聊的是“啥时候去交大办校友卡”，&lt;br>
“你搬家找房子怎么找”，&lt;br>
“XX银行卡真的福利很好你办一张呗，不用的话也可以给我”，&lt;br>
“你旧号不玩了的话，求给我登一下，好带我刷御魂”之类的琐事…&lt;/p>
&lt;p>大概是一种“你的后背交给我了”的安心感吧。&lt;/p>
&lt;p>这就是我的好友，柳宁宁。&lt;/p></description></item><item><title>Git的理念</title><link>https://liriansu.com/posts/2018-02-10-philosophy-of-git/</link><pubDate>Sat, 10 Feb 2018 16:01:31 +0000</pubDate><guid>https://liriansu.com/posts/2018-02-10-philosophy-of-git/</guid><description>&lt;p>本文尝试介绍一下Git的过人之处。&lt;br>
目标读者是想了解Git，&lt;br>
或者对软件设计有兴趣的人。&lt;/p>
&lt;p>Git作为一个极其灵活的工具，&lt;br>
从修改单机游戏数据文件的版本管理，&lt;br>
到多人协作一起堆屎的协作开发，&lt;br>
使用起来都是十分趁手。&lt;/p>
&lt;p>那么Git灵活的奥秘在哪呢？&lt;br>
大概是因为Git设计正交、实现扎实吧。&lt;/p>
&lt;h2 id="总览">总览&lt;/h2>
&lt;p>Git里面的术语/命令很多，&lt;br>
但是它们可以归并成几个大类，&lt;br>
每个大类的概念都是正交的，&lt;br>
也就是说交叉概念很少，&lt;br>
不会有模糊的概念定义。&lt;br>
基于这样的设计，&lt;br>
Git与之对应地实现了一套扎实的命令系统。&lt;/p>
&lt;blockquote>
&lt;p>Git里的概念有些难以准确翻译，&lt;br>
本文涉及概念词的地方尽量用术语表达 。&lt;/p>
&lt;/blockquote>
&lt;p>比如经常用到的概念会有这些：&lt;/p>
&lt;ul>
&lt;li>Line Diff&lt;/li>
&lt;li>Commit&lt;/li>
&lt;li>Branch&lt;/li>
&lt;li>Repository&lt;/li>
&lt;li>Remote&lt;/li>
&lt;/ul>
&lt;h2 id="line-diff">Line Diff&lt;/h2>
&lt;p>Git实现版本控制的方法是根据Line Diff，&lt;br>
推算出每个Commit具体改了哪些东西，&lt;br>
然后用多个Commit（实则是多份Line Diff）构建出所有历史。&lt;/p>
&lt;p>这个基于Line Diff的先天设计决定了Git的一些特性：&lt;/p>
&lt;ol>
&lt;li>
&lt;p>可以存储所有历史。&lt;br>
我们常听到“Git是一个分布式的版本控制系统”，&lt;br>
这个指的就是Git不需要中心化的服务器，&lt;br>
你就可以做完所有操作。&lt;br>
因为本地存着所有的Line Diff，&lt;br>
所以“查看昨天被改过的文件名列表”这个操作完全可以离线完成。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>对二进制文件不友善。&lt;br>
二进制文件是没法强行比Line Diff的。&lt;br>
所以假如用Git管理二进制文件，&lt;br>
Git只会显示一个&lt;code>Binary File Differ&lt;/code>。&lt;br>
再把上面一条“存储所有历史”给叠加上，&lt;br>
就会出现今天提交了一个200M的文件，&lt;br>
明天后天我都修改覆盖了这个文件，&lt;br>
最后整个目录就有600M大了…&lt;br>
（也就是说一般不用Git来管理二进制大文件）&lt;/p>
&lt;/li>
&lt;li>
&lt;p>能检测文件重命名。&lt;br>
假如在一个Commit中，&lt;br>
从Line Diff的视角看，&lt;br>
删除的文件和增加的文件相似度很高，&lt;br>
Git就会判定这是一个重命名的操作。&lt;/p>
&lt;/li>
&lt;/ol>
&lt;h2 id="commit">Commit&lt;/h2>
&lt;p>Line Diff组成了Commit，&lt;br>
Commit是大部分Git操作的最小单位。&lt;br>
这个词既是动词，也是名词。&lt;/p>
&lt;p>一个Commit包含了多种信息：&lt;/p>
&lt;ul>
&lt;li>SHA hash：是根据line diff + 精确到秒的时间戳生成的一串唯一标识符&lt;/li>
&lt;li>Author：写Line Diff的人&lt;/li>
&lt;li>Committer：一个隐藏的属性，代表Commit的人&lt;/li>
&lt;li>Date：包括AuthorDate和CommitDate&lt;/li>
&lt;li>Message：Commit文本描述，Git会取Message第一行作为Subject，所以一般会遵循&lt;a href="https://www.ruanyifeng.com/blog/2016/01/commit_message_change_log.html">一定规范&lt;/a>&lt;/li>
&lt;li>Line Diffs：改动了哪些内容&lt;/li>
&lt;/ul>
&lt;p>这里还可以说的概念包括RootCommit、MergeCommit，&lt;br>
不过它们特殊之处不影响实际使用，&lt;br>
所以跳过它们，继续往下说。&lt;/p>
&lt;h2 id="branch">Branch&lt;/h2>
&lt;p>多个Commit会组成一个Branch，&lt;br>
最初的Branch默认叫master（主干分支）。&lt;/p>
&lt;p>Branch和Commit在很多命令里都是可以作为等价的操作对象的。&lt;br>
举个例子：&lt;/p>
&lt;p>小成写了一天代码，&lt;br>
他在wechat这个分支上commit了很多次，&lt;br>
快下班了，小成想回顾一下今天的改动。&lt;br>
假设他的log长这样子：&lt;/p>
&lt;pre tabindex="0">&lt;code>&amp;gt; git log --oneline --graph
* f01c8d1 (HEAD -&amp;gt; wechat) refactor: improve project layout
* 2f9c867 feat: add rest api to create card
* 5d5242b feat: custom wechat card background
* 873e6ca fix: wechat card slow query
* 0dd06a9 fix: 500 when user unsubscribe
* fb91f98 (origin/master, master) feat: implement wechat card
* 176b4f0 feat: implement membership level
* 2727226 migration: add Settings.enable_level
...
&lt;/code>&lt;/pre>&lt;p>那么以下命令是完全等价的：&lt;/p>
&lt;pre tabindex="0">&lt;code># 查看从master到wechat的diff
&amp;gt; git diff master..wechat
# 查看从master到当前的diff（HEAD代表当前位置，也就是wechat分支）
&amp;gt; git diff master..HEAD
# 查看从master到当前的diff（HEAD是默认值，可省略）
&amp;gt; git diff master
# 查看master的commit到当前的diff
&amp;gt; git diff fb91f98
# 查看五个Commit以前倒当前的diff（master分支在五个Commit以前）
&amp;gt; git diff HEAD~5
&lt;/code>&lt;/pre>&lt;p>所以也可以说“Branch是特殊的Commit”。&lt;br>
理解了这一点以后，&lt;br>
再去看大部分的Git命令，&lt;br>
发现它们都是&lt;code>git &amp;lt;operation&amp;gt; &amp;lt;range&amp;gt; -- &amp;lt;files&amp;gt;...&lt;/code>这样的形式。&lt;/p>
&lt;p>比如查看今天发布哪些内容就是&lt;code>git diff master..release&lt;/code>，&lt;br>
把某个文件回滚到200个Commit以前就是&lt;code>git checkout HEAD~200 -- some/path/some/file.txt&lt;/code>，&lt;br>
查看单个文件的改动历史就是&lt;code>git log -- some/path/some/file.txt&lt;/code>&lt;/p>
&lt;h2 id="repository">Repository&lt;/h2>
&lt;p>Repository包含了所有的操作历史。&lt;br>
&lt;code>git init&lt;/code>命令可以初始化一个Repository。&lt;/p>
&lt;p>一个Git Repository结构可能是这样的：&lt;/p>
&lt;pre tabindex="0">&lt;code>- .git/
- hooks/
- objects/
- refs/
- HEAD
- config
- ForgiveDB/
- README.md
- requirements.txt
&lt;/code>&lt;/pre>&lt;p>这里的&lt;code>.git&lt;/code>目录就存储着上面讲的Line Diff、Commit、Branch的所有历史，&lt;br>
就像上面二进制大文件的那个例子，&lt;br>
这里可能存了几百M的文件历史。&lt;/p>
&lt;h2 id="remote">Remote&lt;/h2>
&lt;p>Remote就是放在别的地方的Repository。&lt;br>
同一个Repository可以添加多个Remote。&lt;/p>
&lt;p>除了&lt;code>push/pull/fetch&lt;/code>这些基本操作以外，&lt;br>
关于Remote还有一个很骚的设定：&lt;br>
Git支持本地Remote。&lt;/p>
&lt;p>比如样例的命令如下：&lt;/p>
&lt;pre tabindex="0">&lt;code># 假设在服务器上的 /home/lirian/chinese-calendar 路径下有一个 Repository
&amp;gt; cd /home/lirian
# 把它 clone 到某一个地方
&amp;gt; git clone chinese-calendar /opt/git/repo/chinese-calendar --bare
# 同个服务器上的另一个用户就可以 clone 这个 Repository
&amp;gt; cd /home/ldsink &amp;amp;&amp;amp; git clone file:///opt/git/repo/chinese-calendar &amp;amp;&amp;amp; git remote -v
origin file:///opt/git/repo/chinese-calendar (fetch)
origin file:///opt/git/repo/chinese-calendar (push)
&lt;/code>&lt;/pre>&lt;p>这样的设计之下，&lt;br>
Remote/Repository是完全分离的，&lt;br>
不会因为断网就修改不了历史。&lt;br>
我们甚至可以把Remote当成一种特殊的Branch，&lt;br>
比如&lt;code>fork - pull request&lt;/code>就是这种模式的一种应用。&lt;/p>
&lt;h2 id="尾言">尾言&lt;/h2>
&lt;p>文中讲到的不少例子有一些浅尝辄止，&lt;br>
读者有兴趣的话可以尝试思考实现一下这几个拓展问题：&lt;/p>
&lt;ul>
&lt;li>关于Line Diff：改动的两个文件相似度多高，Git才会识别为重命名呢？&lt;/li>
&lt;li>关于Commit：如何修改Commit的Author？GitHub上能看出来Committer么？&lt;/li>
&lt;li>关于Branch：如何删除远程分支？&lt;code>git stash&lt;/code>产生的Commit可以像Branch一样操作么？&lt;/li>
&lt;li>关于Repository：删除分支以后，Git目录会变小吗？&lt;/li>
&lt;li>关于Remote：文中用到的&lt;code>--bare&lt;/code>参数是什么意思？&lt;/li>
&lt;/ul>
&lt;p>Git的设计理念中还有很强大的一部分是它关于历史（History）的管理，&lt;br>
那又是一个值得细说的话题。&lt;/p>
&lt;p>总的来说，笔者眼中Git是一个科学且强大的工具。&lt;br>
Git优秀的原因在于它：&lt;/p>
&lt;ul>
&lt;li>正交的设计：术语定义清晰，重叠概念少，表现张力强大。&lt;/li>
&lt;li>扎实的实现：二级术语丰富，命令参数完善，贴合实际应用场景。&lt;/li>
&lt;/ul>
&lt;p>（完）&lt;/p></description></item><item><title>这就是我2018年的OKR</title><link>https://liriansu.com/posts/2018-01-25-my-2018-okr/</link><pubDate>Thu, 25 Jan 2018 23:27:28 +0000</pubDate><guid>https://liriansu.com/posts/2018-01-25-my-2018-okr/</guid><description>&lt;p>前阵子听了一位老师关于OKR很详尽的讲解，&lt;br>
受益匪浅。&lt;/p>
&lt;h2 id="引子">引子&lt;/h2>
&lt;p>当时老师开题的时候，&lt;br>
举了“打地鼠”和“灭火”当例子。&lt;br>
以下是经过回忆加工的原话：&lt;/p>
&lt;blockquote>
&lt;p>假如让你想一想，&lt;br>
去年一整年你做的三件最主要的事情是什么，&lt;br>
你能数的起来吗？&lt;/p>
&lt;p>很多人是数不起来的。&lt;/p>
&lt;p>因为很多时候没有目标，没有计划，&lt;br>
我们做事情就容易像打地鼠一样：&lt;br>
一会儿冒出来这个事情，很紧急，就先做这个；&lt;br>
又一会儿冒出来那个事情，很有前途，又做那个。&lt;/p>
&lt;p>或者换个比喻，&lt;br>
假如我们要穿过一片到处都着火的地方，&lt;br>
才能到达目的地。&lt;br>
那其实只要规划好了，&lt;br>
我们只要扑灭我们路途上的火就行了。&lt;br>
其他烧着的火呢？&lt;br>
烧就让它烧吧。&lt;/p>
&lt;/blockquote>
&lt;p>（当时这段话产品经理小鱼表示感触很深，学到了）&lt;/p>
&lt;p>通过这个小故事，&lt;br>
其实就想说明定目标本身是很有意义的。&lt;/p>
&lt;p>那具体目标怎么定呢？&lt;br>
当然就是OKR了。&lt;/p>
&lt;h2 id="okr">OKR&lt;/h2>
&lt;p>&lt;a href="https://liriansu.com/okr">其实上次跟小米娅聊天的时候&lt;/a>，&lt;br>
就学到了OKR相关的知识。&lt;/p>
&lt;p>这次听老师又讲了一遍，&lt;br>
对两部分印象很深刻。&lt;/p>
&lt;p>一部分是OKR本身的特性：&lt;/p>
&lt;p>OKR 全称是 &lt;code>Objectives and Key Results&lt;/code> （目标和关键结果）&lt;br>
可以对标 KPI (Key Performance Indicator - 关键绩效指标)&lt;/p>
&lt;p>KPI会直接跟绩效考核挂钩，&lt;br>
而OKR一定不直接跟绩效考核挂钩。&lt;/p>
&lt;p>当时讲到这里，&lt;br>
我听到了一句受震撼很大的话：&lt;br>
&lt;strong>工作的奖赏就是工作本身&lt;/strong>&lt;/p>
&lt;p>这种就属于我明白，&lt;br>
但是以前没能用语文直白表达出来，&lt;br>
结果被别人抢先说出来的道理。&lt;/p>
&lt;p>很科学。&lt;/p>
&lt;p>印象很深刻的第二部分是OKR的特性：&lt;/p>
&lt;ul>
&lt;li>目标 (O) 要是一定时间内，定性的，鼓舞人心的，可以达成的。&lt;/li>
&lt;li>关键结果 (KR) 要是定量的，陈述事实的，有挑战性的。&lt;/li>
&lt;/ul>
&lt;p>呃，这个要举例子就举的多了，&lt;br>
懒得写就不写了…&lt;br>
自己看看就行。&lt;/p>
&lt;h2 id="我的2018年度okr">我的2018年度OKR&lt;/h2>
&lt;p>经历了好几天的思考，&lt;br>
我定下的OKR如下：&lt;/p>
&lt;ul>
&lt;li>O1. 技术影响力大幅度提升
&lt;ul>
&lt;li>学习/理解/使用/掌握6个技术工具&lt;/li>
&lt;li>成为1k+ star项目的主contributor&lt;/li>
&lt;li>技术文章输出20篇&lt;/li>
&lt;li>自己有233 star以上的代码项目&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>O2. 事业上做出极大贡献
&lt;ul>
&lt;li>团队的OKR完成率在80%以上&lt;/li>
&lt;li>review 10万行代码&lt;/li>
&lt;li>当300场面试官&lt;/li>
&lt;li>成为整个团队top 1%的人&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>O3. 保持幸福度爆满的状态
&lt;ul>
&lt;li>与亲人总语音时间超过1000分钟&lt;/li>
&lt;li>跟女朋友争吵次数小于3次&lt;/li>
&lt;li>帮助陌生人达50人次&lt;/li>
&lt;li>新增500首红心歌曲&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;p>嗯！大概就是这样。&lt;/p>
&lt;p>从今天开始，计时开始啦~&lt;/p></description></item><item><title>我的女友小米娅</title><link>https://liriansu.com/posts/2018-01-13-my-little-mia/</link><pubDate>Sat, 13 Jan 2018 08:06:16 +0000</pubDate><guid>https://liriansu.com/posts/2018-01-13-my-little-mia/</guid><description>&lt;p>小米娅本名叫吴莹莹，&lt;br>
不过她很喜欢Mia这个英文名和对应的中文名米娅。&lt;br>
不过注册微信公众号的时候，&lt;br>
“小米娅”已经被注册了，&lt;br>
于是最后纠结了好一会儿，&lt;br>
她选择了“一只米娅”这个听起来很精灵的名字。&lt;/p>
&lt;p>认识小米娅的契机是因为我们一个公司，&lt;br>
她当HR，&lt;br>
所有人都认识HR。&lt;/p>
&lt;p>印象中的小米娅就是身着深色系衣服，&lt;br>
气质高冷，&lt;br>
讲话信息量很高，&lt;br>
有种魔道中人的感觉。&lt;/p>
&lt;p>公司要选年会主持人，&lt;br>
惯例是抓两个在职员工和两个实习生。&lt;br>
还是实习生的小米娅和我便被抓了壮丁。&lt;/p>
&lt;p>由于要一起对串词，&lt;br>
得想办法活跃气氛，&lt;br>
我就有合适的理由讲一大坨电波系的冷笑话。&lt;br>
小米娅听了以后问：&lt;br>
这笑点在哪？&lt;br>
……&lt;/p>
&lt;p>后来我发现小米娅和我是下班顺路的。&lt;br>
我回交大要两小时地铁，&lt;br>
她回华理也要一小时地铁。&lt;br>
于是那之后每天下班，&lt;br>
HR办公室门口就站了一个我&amp;hellip;&lt;/p>
&lt;p>有的时候小米娅会提很重的包下班，&lt;br>
（很直男的）我觉得女人都是弱鸡，&lt;br>
就想抢着帮她提。&lt;br>
小米娅都很礼貌地拒绝了我，&lt;br>
并顺便教了我一个道理：&lt;br>
女生的包，很多时候是整体搭配的装饰，&lt;br>
不可以因为大男子主义作祟而抢包哦。&lt;/p>
&lt;p>小米娅的idol是林志炫，&lt;br>
而且小米娅会真的去追星，&lt;br>
不过小米娅心中，&lt;br>
林志炫作为老一辈艺术家，&lt;br>
她追星的心态更多是敬仰之情。&lt;br>
作为新垣结衣老公之一的我自愧不如。&lt;/p>
&lt;p>小米娅人生唯一一次提前交卷，&lt;br>
就是为了去赶火车，&lt;br>
为了去听林志炫的演唱会。&lt;br>
演唱会结束以后小米娅和几个粉丝杀到了林志炫的酒店，&lt;br>
在大家一起拍合照的环节，&lt;br>
身材纤细的小米娅硬是挤到了第一排，&lt;br>
挽住了林志炫的手臂，&lt;br>
留下了一张小米娅跟她idol最亲密的照片。&lt;/p>
&lt;p>小米娅自豪地把照片给我看，&lt;br>
我看着上面她一头红发惊呆了：&lt;br>
“你那时候怎么这么杀马特？”&lt;br>
“哦，大学的时候想染头发就去染了。”&lt;/p>
&lt;p>小米娅做事有的时候很随性，&lt;br>
我很喜欢。&lt;br>
上周我们在家吃饭，&lt;br>
讲到洗碗真特么麻烦，&lt;br>
突然灵感一闪：&lt;br>
“饭堂用的铁盘子洗起来很方便！”&lt;br>
“那个沃尔玛有卖！”&lt;br>
于是我们决定就用饭堂铁盘子吃饭了。&lt;br>
可能以后朋友圈晒厨艺的时候，&lt;br>
会有点怪。&lt;/p>
&lt;p>说回杀马特。&lt;br>
小米娅染了红发以后去初中接她妹妹放学，&lt;br>
她妹妹的同学都惊呆了。&lt;br>
她妹妹倒是很淡定：&lt;br>
“我姐真帅！”&lt;br>
不过后来小米娅要实习面试了，&lt;br>
为了稳妥，头发还是染了回来。&lt;/p>
&lt;p>我经常会求小米娅：&lt;br>
“你啥时候染个头发呗…我光看照片就觉得老帅了…”&lt;br>
小米娅：&lt;br>
“不染，滚”&lt;/p>
&lt;p>小米娅大学是学德语的。&lt;br>
她跟我讲大学去德国交流，&lt;br>
然后周末去了周边玩耍，&lt;br>
科隆大教堂真壮丽云云。&lt;br>
我说：科隆大教堂！我以后也想爬！&lt;br>
小米娅：？？？&lt;/p>
&lt;p>小米娅知道我很喜欢玩游戏，&lt;br>
我跟她讲了很多刺客信条/Dota/文明/游戏厂商的故事。&lt;br>
作为交流，&lt;br>
小米娅也跟我讲了很多生活大爆炸/哈利波特/神探夏洛克/柯南的故事。&lt;/p>
&lt;p>不过虽然小米娅看柯南，&lt;br>
但她不是二次元（此处有争议，我想不到一个既合适又中庸的词）&lt;br>
本来想拿South Park/Rick and Morty/Fate这些动画安利她，&lt;br>
但小米娅不吃安利。&lt;br>
最终小米娅从头到尾看完的一部动画就是《好想告诉你》。&lt;/p>
&lt;p>小米娅是人生第一次恋爱，&lt;br>
大概她从《好想告诉你》里找到了跟《冰果》一样的蔷薇色的世界吧。&lt;/p>
&lt;p>不过这里比较烦的是她有时会缠着我，&lt;br>
要我讲以前的恋爱故事。&lt;br>
我又不能不讲，&lt;br>
于是我每次只能用教科书上的讲故事方式，&lt;br>
从背景，到发展，讲到矛盾点，最后再总结经验教训。&lt;/p>
&lt;p>15年以后小米娅和我都转正工作了，&lt;br>
她成了HR，要看很多简历。&lt;br>
于是每次我跟她讲了很多什么叫科班出身，&lt;br>
什么是软件工程，&lt;br>
Java和JavaScript是什么关系，&lt;br>
数据库是什么概念。&lt;/p>
&lt;p>后来我去面试的时候，&lt;br>
一个面试官问我问题：&lt;br>
“假设我不太懂技术，&lt;br>
你能不能用通俗的语言解释一下，&lt;br>
什么是软件工程？”&lt;/p>
&lt;p>我讲完以后面试官又很好奇的问我：&lt;br>
“我觉得你讲得非常好啊，&lt;br>
你平常会思考这些问题吗？”&lt;br>
我便跟面试官吹捧了一下我的女朋友。&lt;/p>
&lt;p>工作里小米娅经常要帮外国人招人。&lt;br>
有一次一个老外要招Linux初级运维，&lt;br>
这个老外跟小米娅说他最近很忙，&lt;br>
没时间面试，要小米娅帮他做电话面试。&lt;br>
于是那阵子我被小米娅问了一万个问题…&lt;br>
后来成功招到人了，&lt;br>
老外非常开心地发了一封感谢信给中国区所有HR。&lt;br>
（虽然这么说，但是我们是小厂，一共四个）&lt;/p>
&lt;p>作为HR，&lt;br>
小米娅还会接触到很多敏感信息，&lt;br>
主要是薪酬。&lt;br>
不过小米娅非常有职业操守，&lt;br>
她从来不会跟我透露任何敏感信息，&lt;br>
即使后来小米娅和我都到了不同的公司。&lt;/p>
&lt;p>当然，我也很有职业操守。&lt;br>
我也不会把公司代码给小米娅看的。&lt;/p>
&lt;p>小米娅现在的公司是家外企，&lt;br>
特别狼性文化。&lt;br>
就是那种你干得好，你牛逼，&lt;br>
你干不好，你走人的公司。&lt;/p>
&lt;p>小米娅和我都不太喜欢这种非常有侵略性的文化。&lt;br>
不过小米娅刚入职没半年，&lt;br>
好像就要当主管了……&lt;/p>
&lt;p>平常小米娅和我都很忙，&lt;br>
小米娅7点起床，8点出门，&lt;br>
我9点起床，9点出门。&lt;br>
晚上小米娅8点到家，还要做饭，&lt;br>
我10点回家，要洗她不想洗的碗…&lt;br>
（不过最近小米娅特别勤奋，&lt;br>
都自己洗碗了）&lt;/p>
&lt;p>平常住在一起，&lt;br>
小米娅不喜欢洗碗，&lt;br>
我不喜欢洗/晾/收衣服，&lt;br>
分工明确。&lt;br>
不过我们都喜欢干活的时候外放歌曲，&lt;br>
于是家里有时响起林志炫的歌声，&lt;br>
有时响起《电音之王》……&lt;/p>
&lt;p>小米娅和我租的是两室一厅，&lt;br>
虽然是情侣，&lt;br>
但平常都是各睡各的。&lt;br>
她心安理得地大字型霸床，&lt;br>
我也心安理得地听歌写程序到夜深。&lt;/p>
&lt;p>小米娅收到的第一个礼物是一个特别可爱的，&lt;br>
摸起来像柴犬，看起来也像柴犬的粉色小熊玩偶。&lt;br>
小米娅和我都十分喜欢这个玩偶，&lt;br>
于是我们决定给它取个名字，&lt;br>
一番讨论以后，&lt;br>
这只小粉熊就叫“吴建国”了。&lt;/p>
&lt;p>小米娅的理想之一是环游世界，&lt;br>
她在旅行之前会做极其详尽的攻略。&lt;br>
就像 @苍南派 说的一样：&lt;br>
两个人旅游，通常是一个人负责订来回车票酒店民宿景点门票计划好目的地路线行程衔接整体开销查看好天气情况帖子攻略网友好差评想好怎么看怎么玩怎么吃，另一个负责当弱智。&lt;/p>
&lt;p>我就是那个开心的弱智…&lt;/p>
&lt;p>这么说来，&lt;br>
小米娅好像快醒了。&lt;br>
这次小米娅的故事就先讲到这里吧，&lt;br>
下次见~&lt;/p></description></item><item><title>我是怎么实现《用弹幕玩GBA游戏》的</title><link>https://liriansu.com/posts/2018-01-06-play-gba-with-danmaku/</link><pubDate>Sat, 06 Jan 2018 18:58:33 +0000</pubDate><guid>https://liriansu.com/posts/2018-01-06-play-gba-with-danmaku/</guid><description>&lt;p>大概是大二的时候，&lt;br>
我在TwitchTV上看到了一个极其精彩的Idea。&lt;/p>
&lt;h2 id="背景">背景&lt;/h2>
&lt;p>&lt;a href="https://www.twitch.tv/">TwitchTV&lt;/a>是外国的一个主要做游戏直播网站，&lt;br>
观众可以打开网页观看游戏直播，&lt;br>
每个人都能随时发弹幕表达自己的想法。&lt;br>
&lt;a href="https://zh.moegirl.org/zh-hans/%E5%BC%B9%E5%B9%95">&lt;em>弹幕是啥？&lt;/em>&lt;/a>&lt;/p>
&lt;p>依赖于发弹幕万人同屏的这个设定，&lt;br>
TwitchTV做了一个很好玩的功能，&lt;br>
就是“几千人玩操纵同一个角色，玩同一个游戏。”&lt;br>
&lt;a href="https://en.wikipedia.org/wiki/Twitch_Plays_Pok%C3%A9mon">&lt;em>详情可以参见Twitch Plays Pokemon这个维基词条&lt;/em>&lt;/a>&lt;/p>
&lt;p>当时看到这个消息，&lt;br>
我也去玩了一下，&lt;br>
感受是：特别好玩！！！&lt;/p>
&lt;p>几千个人同屏玩游戏的话，&lt;br>
最大的感受就是&lt;strong>混乱&lt;/strong>，&lt;br>
这也是最棒的体验。&lt;br>
大部分玩家是冲着通关的目标去玩的，&lt;br>
所以总体看来，角色的行为是有目标性的。&lt;br>
但是也会有一部分玩家以捣乱为乐，&lt;br>
在一些精细操作的时候（比如收服Pokemon的时候）&lt;br>
就会额外混乱。&lt;/p>
&lt;p>最终整个游戏（或者说社会实验）在混乱中前行，&lt;br>
经过了16个日夜，&lt;br>
最终打过了四大天王，&lt;br>
完成了通关壮举。&lt;/p>
&lt;p>OK，前面都是背景介绍，&lt;br>
那么看到这么好玩的一个东西，&lt;br>
我的心痒了很久：&lt;br>
我也想实现一个类似的功能！&lt;/p>
&lt;h2 id="实现">实现&lt;/h2>
&lt;p>就像把大象塞冰箱里需要拆解步骤，&lt;br>
为了实现“用弹幕玩同屏GBA游戏”这一点，&lt;br>
我们主要要做的事情有如下几点：&lt;/p>
&lt;ol>
&lt;li>申请一个直播间&lt;/li>
&lt;li>获取直播间的弹幕&lt;/li>
&lt;li>实现从弹幕到键位的映射&lt;/li>
&lt;li>用程序操纵GBA模拟器&lt;/li>
&lt;/ol>
&lt;p>当然，我们这个拆分非常的粗略，&lt;br>
而且会有很多具体的问题，&lt;br>
我们一个一个地来看。&lt;/p>
&lt;h3 id="申请一个直播间">申请一个直播间&lt;/h3>
&lt;p>我要没记错的话（&lt;em>懒得去查资料验证了&lt;/em>）&lt;br>
TwitchTV的同屏玩游戏功能应该是官方实现的，&lt;br>
不是某一个主播或者是我这样的第三方程序员实现的。&lt;br>
平台自己实现的话会有非常多的自主权，&lt;br>
而且可以给到游戏本身的推广，&lt;br>
一波活动推出去不论是效果还是效果都会更好。&lt;/p>
&lt;p>但是毕竟人微言轻，&lt;br>
我们普通人类还是要从头开始，&lt;br>
从申请直播间开始。&lt;/p>
&lt;p>申请直播间的话主要是涉及到直播平台的选择，&lt;br>
因为我一直都是A/B站用户，&lt;br>
所以直播平台基本上就是斗鱼&lt;a href="https://www.zhihu.com/question/27088840">（A站生放送）&lt;/a>和B站直播之间选一个。&lt;/p>
&lt;p>最终我两年前注册了一个斗鱼直播间&lt;br>
（打个广告，从来不播的直播间：&lt;a href="https://www.douyu.com/lisp">douyu.com/lisp&lt;/a>）&lt;/p>
&lt;p>第一步算是做完了。&lt;/p>
&lt;h3 id="获取直播间的弹幕">获取直播间的弹幕&lt;/h3>
&lt;p>这个是个非常interesting的问题。&lt;br>
首先他受前置问题的影响，&lt;br>
带来的现实问题是&lt;strong>每个直播平台获取弹幕的难度是不一样的&lt;/strong>。&lt;/p>
&lt;p>斗鱼和B站直播相比，&lt;br>
看斗鱼的人肯定是更多的，&lt;br>
但是受氛围和观众群体的影响，&lt;br>
&lt;a href="https://github.com/feisuzhu/vim-bilibili-live">会为B站写插件的程序员&lt;/a>更多_CITATION NEEDED_。&lt;/p>
&lt;p>但毕竟我们在上一个步骤选择了斗鱼，&lt;br>
还是得从一而终。&lt;br>
于是两年前我就在知乎关注了&lt;a href="https://www.zhihu.com/question/29027665">《如何获取斗鱼直播间的弹幕信息？》&lt;/a>这个问题，&lt;br>
顺便学习了一波socket相关知识（对，这句话反映了我的真实水平&amp;hellip;）&lt;/p>
&lt;p>当时没有一套好用的库，&lt;br>
我又懒得自己钻研，&lt;br>
所以就卡在这里了。&lt;/p>
&lt;p>后来我&lt;a href="https://liriansu.com/how-i-use-github">在GitHub闲逛的时候&lt;/a>，&lt;br>
发现itchat的作者写了一个包，&lt;br>
支持获取各大直播平台的弹幕，&lt;br>
感觉就是我要的轮子！&lt;br>
&lt;a href="https://github.com/littlecodersh/danmu">于是我点了一个star先马克着&lt;/a>。&lt;/p>
&lt;p>今天是2018年1月，&lt;br>
这个库最近的更新是2017年5月，&lt;br>
有大半年没更新代码了。&lt;br>
正式采用之前我试了一下，&lt;br>
斗鱼的弹幕是没问题的，&lt;br>
不过B站的弹幕因为是直接&lt;a href="https://github.com/littlecodersh/danmu/blob/master/danmu/Bilibili.py">解析网页原文拿ROOMID&lt;/a>的，&lt;br>
已经失效了。&lt;br>
又因为这个库（或者说littlecoder这个人）不是很Pythonic，&lt;br>
于是我心中又暗立一个flag，&lt;br>
fork了这个项目，&lt;br>
想着啥时候摸鱼摸够了就去改进一波。&lt;/p>
&lt;p>于是最终我采用了danmu这个库，&lt;br>
几行代码就成功地获取了斗鱼弹幕，&lt;br>
大概代码（伪）如下：&lt;/p>
&lt;pre tabindex="0">&lt;code>import danmu
client = danmu.DanMuClient(&amp;#39;https://www.douyu.com/lisp&amp;#39;)
@client.danmu
def receive(message):
print(&amp;#39;[{}] {}&amp;#39;.format(message[&amp;#39;NickName&amp;#39;], message[&amp;#39;Content&amp;#39;]))
client.start()
&lt;/code>&lt;/pre>&lt;h3 id="实现从弹幕到键位的映射">实现从弹幕到键位的映射&lt;/h3>
&lt;p>这个没什么可以说的，&lt;br>
就是业务逻辑/苦力活。&lt;br>
简单。跳过。&lt;/p>
&lt;h3 id="用程序操纵gba模拟器">用程序操纵GBA模拟器&lt;/h3>
&lt;p>好，这里首先有个坑。&lt;br>
我们回忆一下，&lt;br>
最开始我们的目标其实是“实现用弹幕玩GBA游戏”，&lt;br>
现在的这个小步骤被回归成了“用程序操纵GBA&lt;strong>模拟器&lt;/strong>”。&lt;br>
这模拟器的需求是哪冒出来的？&lt;/p>
&lt;p>嗨呀，这个是有苦衷的。&lt;/p>
&lt;p>首先，我对GBA的回忆除了实体机，&lt;br>
有一半都是&lt;a href="https://en.wikipedia.org/wiki/VisualBoyAdvance">&lt;code>VisualBoyAdvance.exe&lt;/code>&lt;/a>这个模拟器给的。&lt;br>
还有就是理论上我们也可以实现Web版的，&lt;br>
或者自己撸一个GBA模拟器，&lt;br>
但那样又相当于额外的工作量了。&lt;br>
所以基于“把我不会的目标拆成我能做到的小步骤”&lt;br>
和“鲁迅说过，不要重复造轮子”这两个设定，&lt;br>
我就把“用程序玩GBA游戏”拆分成了“用程序操纵GBA模拟器”+“用GBA模拟器玩GBA游戏”（现成的）这两个任务了。&lt;/p>
&lt;p>OK，我们来现实地看第一点：&lt;br>
“怎么用程序操纵GBA模拟器”。&lt;/p>
&lt;p>在我的脑海中，&lt;br>
假如用Python来实现，&lt;br>
基本上这个就是Python调用windows库 + windows库给程序传递信号 + 程序接收信号达成效果，&lt;br>
这样一套combo下来就行了。&lt;/p>
&lt;p>虽然我平常开发环境是windows，&lt;br>
但其实我对windows的接口是一窍不通（暴露水平 x2）&lt;br>
不过不懂可以问啊！&lt;br>
于是前几天我问了一下身边的windows大拿hulucc，&lt;br>
他表示&lt;a href="https://msdn.microsoft.com/en-us/library/system.windows.forms.sendkeys(v=vs.110).aspx">windows有个叫sendkey的API&lt;/a>可以做这个，&lt;br>
不过只能操纵active window。&lt;br>
后来他又查了一下，&lt;br>
跟我说Python里有个&lt;code>pywin32&lt;/code>的库可以调用windows接口，&lt;br>
又发了一篇文章 &lt;a href="https://code.tutsplus.com/tutorials/how-to-build-a-python-bot-that-can-play-web-games--active-11117">How to Build a Python Bot That Can Play Web Games&lt;/a>&lt;br>
给我参考。&lt;/p>
&lt;p>学习了这么一大段以后，&lt;br>
我十分感动，&lt;br>
然后自己找了个另外的库&lt;a href="https://github.com/boppreh/keyboard">keyboard&lt;/a>（雾）&lt;/p>
&lt;p>事实是后来我回来研究了一下，&lt;br>
用windows接口肯定能达到我的目的，&lt;br>
但是问题是&lt;a href="https://stackoverflow.com/questions/4863056/how-to-install-pywin32-module-in-windows-7">pywin32或者是类似的pypiwin32这俩包没有合适的pip release要手动安装&lt;/a>，&lt;br>
这让我很不舒服。&lt;br>
刚好google的同时，&lt;br>
我搜到了另外一个python库&lt;a href="https://github.com/boppreh/keyboard">&lt;code>keyboard&lt;/code>&lt;/a>，&lt;br>
它的主页长得还蛮好看的，&lt;br>
也能达到我的需求，&lt;br>
不错，就这个了。&lt;/p>
&lt;p>于是实现了接收弹幕+发送按键的代码（伪）就大概长这样子：&lt;/p>
&lt;pre tabindex="0">&lt;code>import danmu
import keyboard
import constants
client = danmu.DanMuClient(&amp;#39;https://www.douyu.com/lisp&amp;#39;)
@client.danmu
def receive(message):
print(&amp;#39;[{}] {}&amp;#39;.format(message[&amp;#39;NickName&amp;#39;], message[&amp;#39;Content&amp;#39;]))
content = message[&amp;#39;Content&amp;#39;] # 主要是新增了这行和下面的if
if content in constants.valid_keystrokes:
keyboard.send(content)
client.start()
&lt;/code>&lt;/pre>&lt;h3 id="一个小坑">一个小坑&lt;/h3>
&lt;p>这里还遇到了一个小坑，&lt;br>
简单来说就是VisualBoyAdvance这款GBA模拟器（以下简称VBA）&lt;br>
它应该是通过监控键盘事件来转化键位的。&lt;br>
（此句描述不够专业）&lt;/p>
&lt;p>转化成代码语言就是&lt;code>keyboard.send(content)&lt;/code>这行代码对VBA不起作用。&lt;br>
经过思考加尝试以后，&lt;br>
最终使用了&lt;code>keyboard.press(content)&lt;/code> + &lt;code>time.sleep(0.02)&lt;/code> + &lt;code>keyboard.release(content)&lt;/code>三个combo达成了效果。&lt;/p>
&lt;p>最终不禁要感慨一下：&lt;br>
上面这段描述里的&lt;strong>经过思考加尝试&lt;/strong>，&lt;br>
就是写程序这件事情最痛苦也是最美好的所在了。&lt;/p>
&lt;h2 id="总结">总结&lt;/h2>
&lt;p>上面讲的比较零碎，&lt;br>
总结下来：&lt;/p>
&lt;p>为了做到 “用弹幕玩GBA游戏” 这个事情，&lt;br>
被拆分细化完成的任务有这些：&lt;/p>
&lt;ul>
&lt;li>注册直播间，选了斗鱼。&lt;/li>
&lt;li>获取直播间弹幕，平常关注一波信息，最终用了danmu这个库。&lt;/li>
&lt;li>实现业务逻辑。&lt;/li>
&lt;li>用程序操纵GBA模拟器来玩GBA游戏，使用了keyboard库发送键位信息。&lt;/li>
&lt;/ul>
&lt;p>最终的成品在我的GitHub上：&lt;a href="https://github.com/LKI/danmaboy">LKI/danmaboy&lt;/a>这个项目，&lt;br>
有效代码就100行，就在&lt;a href="https://github.com/LKI/danmaboy/blob/master/danmaboy/__init__.py">danmaboy/__init__.py&lt;/a>一个文件内。&lt;/p>
&lt;p>一下午就写完了，&lt;br>
不过中途摸鱼思考的时间用了几年（惭愧）&lt;/p>
&lt;p>下午写代码的时候我还做了一个尝试，&lt;br>
就是开着直播写代码，&lt;br>
不过因为没人看（现实的原因），&lt;br>
所以总体感受跟小黄鸭编程差不多，&lt;br>
写一会儿，就紧张地想一下思路，&lt;br>
效果意外的不错。&lt;/p>
&lt;p>最终成品出来以后，&lt;br>
试着在直播间里跑了一下，&lt;br>
&lt;del>创业失败&lt;/del>遇到了一个基石上的失误：&lt;/p>
&lt;p>&lt;strong>因为是游戏，所以普通的弹幕延迟在这个项目上会放大到极度影响游戏体验&lt;/strong>&lt;/p>
&lt;p>基本上就是发一条弹幕，&lt;br>
15秒以后才会有对应的游戏变动，&lt;br>
别说TwitchTV那样的效果了，&lt;br>
就是基本的自己玩玩都玩不动…&lt;/p>
&lt;p>叹气。&lt;/p>
&lt;p>不过好歹是我心里很多idea之一了，&lt;br>
这篇文章也算是给这个项目画个句号吧。&lt;/p>
&lt;p>我的心中还有很多未竟的事业，&lt;br>
有兴趣的话，&lt;br>
欢迎和我交流噢~&lt;/p>
&lt;p>下次见。&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/screen.png" alt="screen">&lt;br>
&lt;em>直播时的画面截图&lt;/em>&lt;/p></description></item><item><title>一种简单的鉴权方式：JWT</title><link>https://liriansu.com/posts/2017-12-09-jwt/</link><pubDate>Sat, 09 Dec 2017 20:07:17 +0000</pubDate><guid>https://liriansu.com/posts/2017-12-09-jwt/</guid><description>&lt;p>这是一篇关于 &lt;a href="https://jwt.io/">JWT(JSON Web Token)&lt;/a> 的简短介绍。&lt;/p>
&lt;h2 id="什么是jwt">什么是JWT&lt;/h2>
&lt;p>JWT, 全称是JSON Web Token，&lt;br>
是一种易于使用、无状态的鉴权(&lt;a href="https://en.wikipedia.org/wiki/Authorization">Authorization&lt;/a>)方式。&lt;br>
简单的来说，就是&lt;br>
&lt;strong>Server端把JSON数据经过加密做成token，以授权给Client端&lt;/strong>。&lt;/p>
&lt;p>多说无益，上代码，举个栗子。&lt;/p>
&lt;p>当Client端登录完成以后，&lt;br>
Server端要返回一个7天有效的token，&lt;br>
那么对应的Python的样例代码会是这样的：&lt;br>
（&lt;a href="https://github.com/jpadilla/pyjwt">使用了PyJWT包：&lt;code>pip install pyjwt&lt;/code>&lt;/a>）&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">import&lt;/span> time
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">import&lt;/span> jwt
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>exp &lt;span style="color:#f92672">=&lt;/span> int(time&lt;span style="color:#f92672">.&lt;/span>time()) &lt;span style="color:#f92672">+&lt;/span> &lt;span style="color:#ae81ff">86400&lt;/span> &lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#ae81ff">7&lt;/span> &lt;span style="color:#75715e"># 失效时间&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>user &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#39;liriansu&amp;#39;&lt;/span> &lt;span style="color:#75715e"># 用户表示&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>key &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#39;hunter2&amp;#39;&lt;/span> &lt;span style="color:#75715e"># 密钥&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>payload &lt;span style="color:#f92672">=&lt;/span> {&lt;span style="color:#e6db74">&amp;#39;exp&amp;#39;&lt;/span>: exp, &lt;span style="color:#e6db74">&amp;#39;user&amp;#39;&lt;/span>: user} &lt;span style="color:#75715e"># JSON 数据&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>token &lt;span style="color:#f92672">=&lt;/span> jwt&lt;span style="color:#f92672">.&lt;/span>encode(payload, key)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>print(token)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># token可能会长这样子&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.e30.EoKoMCjq_zGqUg5HDfqw4EN7EiG6gMjkUZle0uGJDGU&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>&lt;a href="https://liriansu.com/hunter2-meme">关于hunter2也有个梗：弱密码hunter2&lt;/a>&lt;/p>
&lt;/blockquote>
&lt;p>然后Client端每次在authorization header或者是query string里带上token。&lt;br>
Server端收到请求的时候，&lt;br>
用&lt;code>payload = jwt.decode(token, key)&lt;/code>验证权限就行了。&lt;br>
验证通过以后，payload中就是整个JSON数据。&lt;br>
理论上你可以往token payload里塞任何_非敏感_数据。&lt;/p>
&lt;p>所以综合来说，&lt;br>
假如使用JWT作为鉴权方式，&lt;br>
有以下几个特性：&lt;/p>
&lt;ol>
&lt;li>Client端不用管任何加密/解密，只用存token，在请求里面带上就行了。&lt;/li>
&lt;li>Server端可以实现不依赖外部存储鉴权，所有的数据都丢在token里。&lt;/li>
&lt;li>也就是说鉴权这一步不需要File/MySQL/Redis之类的数据库，也能知道用户身份。&lt;/li>
&lt;li>因为token带失效时间，所以需要在失效前/后再刷新token。&lt;/li>
&lt;/ol>
&lt;p>好了，以上就是关于JWT的所有描述了。&lt;br>
本次的简单介绍就到此结束。（雾）&lt;br>
（不过&lt;a href="https://liriansu.com/hawk-authentication">上次关于Hawk的介绍&lt;/a>大概就是这样的）&lt;/p>
&lt;h2 id="关于jwt的更多说明">关于JWT的更多说明&lt;/h2>
&lt;blockquote>
&lt;p>讲了这么多，实质上就是用个JSON数据当token，&lt;br>
这破token真的安全吗？能伪造吗？&lt;/p>
&lt;/blockquote>
&lt;p>emmmmmm, 好问题（表示这个问题很尖锐，难以正面回答，准备迂回）&lt;br>
JWT使用很广泛，久经考验，大家都在用（表现了我也不懂，应该不会有问题吧？的一种从众心理）&lt;/p>
&lt;p>认真地发表一下个人意见：&lt;br>
首先token/key泄漏了，&lt;br>
后果基本是跟其它鉴权方式一样严重。&lt;br>
其次JWT可以选择合适的加密方式，&lt;br>
加上合适的key是基本伪造不了的。&lt;br>
还有就是在JWT之外，&lt;br>
一定要用HTTPS！&lt;br>
不用JWT相当于没有门禁，&lt;br>
&lt;a href="https://www.zhihu.com/question/52790301/answer/173452126">不用HTTPS基本是不穿内裤了&lt;/a>。。。&lt;/p>
&lt;blockquote>
&lt;p>我想了解更详细的JWT生成/验证过程&lt;/p>
&lt;/blockquote>
&lt;p>具体说明请参照来源 &lt;a href="https://tools.ietf.org/html/rfc7519">RFC7519 - JSON Web Token (JWT)&lt;/a>&lt;/p>
&lt;p>简单的来说，JWT是由以下三部分组成的：&lt;/p>
&lt;ol>
&lt;li>第一部分指定了加密算法(alg)和token类型(typ)。&lt;/li>
&lt;li>第二部分就是我们定义的payload。&lt;/li>
&lt;li>第三部分是由加密算法产生的签名。&lt;/li>
&lt;/ol>
&lt;p>获取了三部分数据以后，&lt;br>
分别用base64加密，&lt;br>
把最末的等号去掉，&lt;br>
再用小数点连在一起，&lt;br>
就是一个token了。&lt;br>
验证的话，基本就是把这个过程反过来。&lt;/p>
&lt;blockquote>
&lt;p>我去，那token里的信息就是明文的啊？&lt;/p>
&lt;/blockquote>
&lt;p>是的。&lt;br>
所以token里不要带任何敏感信息。&lt;/p>
&lt;p>&lt;a href="https://tools.ietf.org/html/rfc7519">文档上把payload里带的信息叫&lt;code>Claim&lt;/code>&lt;/a>，&lt;br>
有这么几个可选的&lt;code>Claim&lt;/code>：&lt;/p>
&lt;ul>
&lt;li>
&lt;p>&lt;strong>iss&lt;/strong>: Issuer, 签发方。&lt;br>
比如这个token是微信签发的，&lt;br>
那么可以是&lt;code>{'iss': 'wechat'}&lt;/code>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>aud&lt;/strong>: Audience, 接收方。&lt;br>
比如王者荣耀想用微信登录，&lt;br>
那么可以是&lt;code>{'aud': 'king-of-glory'}&lt;/code>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>exp&lt;/strong>: Expiration Time, 失效时间。&lt;br>
使用的是整形Unix时间戳，&lt;br>
关于时间戳可以看看&lt;a href="https://zhuanlan.zhihu.com/p/31829454">《互联网上的日期和时间》&lt;/a>&lt;/p>
&lt;/li>
&lt;/ul>
&lt;p>&lt;a href="https://tools.ietf.org/html/rfc7519">RFC7519&lt;/a>里面还有一点很好玩，&lt;br>
就是上面每一个&lt;code>Claim&lt;/code>最后都加了一句&lt;code>Use of this claim is OPTIONAL&lt;/code>&lt;br>
（&lt;a href="https://tools.ietf.org/html/rfc2119">RFC2119还定义过啥叫OPTIONAL&lt;/a>）&lt;/p>
&lt;p>也就是说我们可以往payload里丢任何东西。&lt;br>
只要符合这种加密/解密/鉴权的方式，&lt;br>
我们都可以说“我们用了JWT”。&lt;/p>
&lt;blockquote>
&lt;p>那token会不会很大？&lt;/p>
&lt;/blockquote>
&lt;p>有可能会。&lt;/p>
&lt;p>所以payload里的东西能少则少，&lt;br>
看文档里，连&lt;code>issuer -&amp;gt; iss&lt;/code>, &lt;code>audience -&amp;gt; aud&lt;/code>这种地方都给省了好几个字符。&lt;/p>
&lt;p>还有就是传输JWT的时候，&lt;br>
相较于放query string里，&lt;br>
更推荐放在Request Headers里面。&lt;/p>
&lt;h2 id="与其他鉴权方式的对比">与其他鉴权方式的对比&lt;/h2>
&lt;p>详尽的比较超越了本文的范畴，&lt;br>
&lt;em>（写这句话好爽，可以少查一万个资料）&lt;/em>&lt;br>
下面就用个简单的表格来对比一下_我了解的_几种鉴权方式吧：&lt;br>
&lt;a href="https://tools.ietf.org/html/rfc7519">JWT&lt;/a>, &lt;a href="https://tools.ietf.org/html/rfc6749">OAuth&lt;/a>, &lt;a href="https://tools.ietf.org/html/rfc6265">Session&lt;/a>, &lt;a href="https://liriansu.com/hawk-authentication">Hawk&lt;/a>&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>&lt;/th>
&lt;th>JWT&lt;/th>
&lt;th>OAuth&lt;/th>
&lt;th>Session&lt;/th>
&lt;th>Hawk&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>易用性&lt;/td>
&lt;td>容易，就一个token&lt;/td>
&lt;td>麻烦，要用Refresh Token刷Access Token&lt;/td>
&lt;td>容易，用Cookie就行&lt;/td>
&lt;td>麻烦，每个请求都要单独计算header&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>泛用性&lt;/td>
&lt;td>各种场合都适用&lt;/td>
&lt;td>带三方授权的场合特别适用&lt;/td>
&lt;td>还行吧&amp;hellip;&lt;/td>
&lt;td>能用header的都适用&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>安全性&lt;/td>
&lt;td>跟别的方案差不多，key泄漏了就完蛋了&lt;/td>
&lt;td>Auth Server安全就行，&lt;del>我才不管Client&lt;/del>其它的跟别的方案差不多&lt;/td>
&lt;td>还行吧&amp;hellip;&lt;/td>
&lt;td>&lt;a href="https://liriansu.com/hawk-authentication">我！能！防！中间人攻击！&lt;/a>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>接受度&lt;/td>
&lt;td>有一定安全度，client端很喜欢，用的还是很多的&lt;/td>
&lt;td>繁琐和安全的折中方案，很多大厂都用&lt;/td>
&lt;td>真的广&amp;hellip;&lt;/td>
&lt;td>目前只听说了我司在用Hawk&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h2 id="其它感受">其它感受&lt;/h2>
&lt;ul>
&lt;li>
&lt;p>JWT全称叫JSON Web Token,&lt;br>
小心别写了类似&lt;code>jwt_token&lt;/code>这样的变量名了（语义重复）。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;a href="https://tools.ietf.org/html/rfc7519">RFC7519还定义了JWT读起来是类似于jot的发音&lt;/a>。&lt;br>
然而实际中交流都会说JWT（怕听不懂）。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>JWT说是说用同一个key就行了，&lt;br>
不过我们在项目实际中还是根据不一样的user用了不一样的key。&lt;br>
（同时也用了数据库）&lt;/p>
&lt;/li>
&lt;li>
&lt;p>假如payload里带了失效时间，&lt;br>
理论上JWT签发后是不会失效的，&lt;br>
也就是Server端管理不了这些token。&lt;br>
（所以可以加个数据库来管）&lt;br>
（好像变复杂了）&lt;/p>
&lt;/li>
&lt;li>
&lt;p>用JWT想做“记住登录状态”这个功能的话，&lt;br>
可以设定token失效期比如是7天，&lt;br>
然后用户每天登录的时候刷一次token。&lt;br>
这样除非用户一周内都没登录，&lt;br>
才会请求重新登录。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>我对互联网安全的认知是真的有限，&lt;br>
经常看文档，&lt;br>
一句话学到三四个新的词。&lt;br>
还是要多学习一个啊。&lt;br>
所谓&lt;code>苟日新，日日新，又日新&lt;/code>是也。&lt;/p>
&lt;/li>
&lt;/ul></description></item><item><title>视差</title><link>https://liriansu.com/posts/2017-12-04-your-own-sight/</link><pubDate>Mon, 04 Dec 2017 22:29:14 +0000</pubDate><guid>https://liriansu.com/posts/2017-12-04-your-own-sight/</guid><description>&lt;p>蚍蜉和大树是很好的朋友，&lt;br>
蚍蜉常常站在大树头上跟大树聊天。&lt;/p>
&lt;p>两只生物从诗词歌赋谈到人生理想，&lt;br>
无话不谈，谈了又谈，&lt;br>
所有的观点都无比契合。&lt;/p>
&lt;p>这一天他们看着遥远的天空，&lt;br>
蚍蜉不禁感慨道：“天真的蓝啊。”&lt;/p>
&lt;p>出生在悬崖边上的大树一动不动，仿佛出了神：&lt;br>
“是啊，这天空的蓝，比海面的蓝更宁静。”&lt;/p>
&lt;p>看着视野远方的海天分界线，蚍蜉也不禁感慨道：&lt;br>
“对啊，海洋的蓝深邃，天空的蓝给我一种忧伤的感觉。”&lt;/p>
&lt;p>大树摇了摇身上的叶子：&lt;br>
“我倒觉得春天的时候，叶子的颜色才更忧伤。&lt;br>
天空的蓝给我一种生机盎然的感觉，我很向往。”&lt;/p>
&lt;p>蚍蜉觉得很奇怪：&lt;br>
“不对呀，春天的绿叶才是生机盎然吧。”&lt;/p>
&lt;p>大树笑了：&lt;br>
“你可不能把生物规律加到颜色感觉上，&lt;br>
绿色本来就是忧郁的，&lt;br>
尤其是春天叶子新芽的那一抹淡绿。”&lt;/p>
&lt;p>蚍蜉没有说话，想了想，提了个问题：&lt;br>
“那大树，你能不能描述一下你眼中的绿色是什么？”&lt;/p>
&lt;p>“绿色啊，就是春天万物生长时候的颜色啊。&lt;br>
比如绿叶衬红花，老树发绿芽，&lt;br>
这阵子在我们这跑来跑去的那个年轻人，&lt;br>
帽子也是绿的。”&lt;/p>
&lt;p>“唔，我不是问绿色在现实生活中的投影。&lt;br>
我想知道你是怎么看绿色这种颜色本身的，&lt;br>
更重要的：你对这个颜色的&lt;strong>感觉&lt;/strong>。”&lt;/p>
&lt;p>大树侧着脑袋想了想，说：&lt;br>
“其实吧，我看到绿色，&lt;br>
会有种很平静，很忧伤的感觉。&lt;br>
就有一种我整棵树都会沉浸在绿色里，&lt;br>
随着我越沉越深，我整个颜色也越来越淡。&lt;br>
深色的绿色就会有一种特别深邃的感觉，&lt;br>
就像这个颜色本身就是自然赋予的，&lt;br>
深不见底，吞没灵魂。”&lt;/p>
&lt;p>随着大树讲下去，&lt;br>
蚍蜉的眼神变得越来越锋利了：&lt;br>
“大树，我觉得，&lt;strong>我们看到的颜色不一样&lt;/strong>。”&lt;/p>
&lt;p>还沉浸在颜色感觉中的大树一愣：&lt;br>
“怎么不一样了？”&lt;/p>
&lt;p>“我跟你讲一下我眼中的绿色吧，”&lt;br>
蚍蜉想了想，描述道：&lt;br>
“绿色给我一种生机勃发的感觉，&lt;br>
我指的是光看到这个颜色，&lt;br>
就觉得它里面蕴含着生命的能量，&lt;br>
看到它会感觉特别平静。&lt;br>
这种平静跟蓝色不一样，&lt;br>
蓝色是让你没有想法，&lt;br>
绿色会让你觉得生命本身就是这么美好，&lt;br>
会被温柔地环绕。”&lt;/p>
&lt;p>大树仿佛意识到了什么，&lt;br>
缓慢地说道：&lt;br>
“我觉得，你描述的是蓝色。”&lt;/p>
&lt;p>蚍蜉点了点头：&lt;br>
“对，刚才我也觉得你描述的是我眼中的蓝色。”&lt;/p>
&lt;p>大树沉思了一下：&lt;br>
“有趣，这么看来，我们眼中的蓝绿色其实根本是反的。”&lt;/p>
&lt;p>“是的。但是我看到这个颜色，我叫它绿色，&lt;br>
你看到这个颜色，你也叫它绿色。&lt;br>
完全一致。”&lt;/p>
&lt;p>“对。我小时候知道这是绿色，是家人教我的，&lt;br>
想必你也是这么认识颜色的。&lt;br>
假如我们不交流对颜色本身的看法，&lt;br>
我们就永远不会发现我们眼中的蓝、绿色其实是非常不一样的。”&lt;/p>
&lt;p>“这就是&lt;strong>视差&lt;/strong>。&lt;br>
不止蓝、绿色，说不定我们眼中的世界都是非常不一样的。”&lt;/p>
&lt;p>小云、庄子、惠子三个人讨论完了这个故事，&lt;br>
击掌而笑。&lt;/p>
&lt;p>庄子感慨道：&lt;br>
“妙啊，我得把这个故事写下来。”&lt;/p>
&lt;p>惠子想了想，评论道：&lt;br>
“这样写的话，太直白了。&lt;br>
怕是读者只会看字面的意思。”&lt;/p>
&lt;p>小云笑着拍了一下惠子：&lt;br>
“放心，庄子这个人可是狡猾得很，&lt;br>
他肯定会彻底换一个故事皮的。”&lt;/p>
&lt;p>庄子也笑了：&lt;br>
“既然小云你这么说我狡猾，&lt;br>
那我可就要把故事里的你换成一条鱼了。”&lt;/p>
&lt;p>惠子担心地问：&lt;br>
“这样会不会被读者曲解了故事的意思啊？”&lt;/p>
&lt;p>“没关系。&lt;br>
这也是&lt;strong>视差&lt;/strong>。”&lt;/p></description></item><item><title>Python项目自动化部署之一：举个栗子</title><link>https://liriansu.com/posts/2017-11-23-python-deployment-automation-one-sample/</link><pubDate>Thu, 23 Nov 2017 16:49:57 +0000</pubDate><guid>https://liriansu.com/posts/2017-11-23-python-deployment-automation-one-sample/</guid><description>&lt;p>本文主要讲述一下我司&lt;br>
（&lt;a href="https://www.zhihu.com/question/19596230/answer/152193862">一个成长中的创业公司&lt;/a>）&lt;br>
目前的代码发布流程用到了哪些工具。&lt;/p>
&lt;h2 id="发布工具jenkinsjenkins">发布工具：&lt;a href="https://jenkins.io/">Jenkins&lt;/a>&lt;/h2>
&lt;p>我们用的发布工具是&lt;a href="https://stackshare.io/jenkins">很多公司都在用&lt;/a>的&lt;a href="https://jenkins.io/">Jenkins&lt;/a>。&lt;br>
举个&lt;del>栗子&lt;/del>图，&lt;br>
在Jenkins Server上可以一键发布后端服务器代码：&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/zaihui_jenkins.jpg" alt="jenkins-demo">&lt;/p>
&lt;p>按下 Build按钮 以后，&lt;br>
发生的事情如下：&lt;/p>
&lt;ul>
&lt;li>在 Jenkins服务器 上触发预先配置的 Bash脚本
&lt;ul>
&lt;li>git命令获取到最新的代码版本，切换合适的分支&lt;/li>
&lt;li>&lt;del>执行代码风格检测和单元测试&lt;/del>自从使用了付费版GitLab后，本功能已切换至GitLab CI了&lt;/li>
&lt;li>安全检查通过以后，使用fab命令部署代码&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h2 id="发布命令fabricfabric">发布命令：&lt;a href="https://github.com/fabric/fabric">Fabric&lt;/a>&lt;/h2>
&lt;p>这里的fab命令用的就是&lt;a href="https://github.com/fabric/fabric">Python的Fabric库&lt;/a>，&lt;br>
这个库类似&lt;a href="https://github.com/ansible/ansible">ansible&lt;/a>，&lt;br>
主要包含两套功能：&lt;/p>
&lt;ul>
&lt;li>
&lt;p>&lt;strong>本地命令集成&lt;/strong>。&lt;br>
这点大概跟 Java 的 &lt;a href="https://ant.apache.org/">&lt;code>ant&lt;/code>&lt;/a>, &lt;a href="https://gradle.org/">&lt;code>gradle&lt;/code>&lt;/a>,&lt;br>
或者是 JS 的 &lt;a href="https://www.npmjs.com/">&lt;code>npm run&lt;/code>&lt;/a> 有类似功能。&lt;br>
都是可以把数个操作集成到一条简单的工作流命令里。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>远程ssh工具&lt;/strong>。&lt;br>
&lt;a href="https://github.com/fabric/fabric">Fabric&lt;/a>里基于&lt;a href="https://en.wikipedia.org/wiki/Secure_Shell">ssh&lt;/a>，&lt;br>
实现了一套方便的远程命令接口，&lt;br>
比如这么一段代码就可以把配置上传到远程服务器：&lt;/p>
&lt;/li>
&lt;/ul>
&lt;pre tabindex="0">&lt;code>from fabric.api import * # NOQA
# 不用试了，这里的两个都是假的domain，对应放上ssh的host/user即可
env.hosts = [&amp;#39;www.kezaihui.com&amp;#39;, &amp;#39;zaihuiwebserver-814613977.cn-north-1.elb.amazonaws.com.cn&amp;#39;]
env.user = &amp;#39;saber&amp;#39;
def update_supervisor_config():
put(&amp;#39;./supervisor/*.conf&amp;#39;, &amp;#39;/etc/supervisor/conf.d/&amp;#39;, use_sudo=True)
run(&amp;#39;supervisorctl update&amp;#39;, use_sudo=True)
&lt;/code>&lt;/pre>&lt;p>但&lt;a href="https://github.com/fabric/fabric">Fabric&lt;/a>有个比较蛋疼的地方就是它只支持&lt;a href="https://docs.python-guide.org/en/latest/starting/which-python/">Python2&lt;/a>，&lt;br>
假如要用&lt;a href="https://docs.python-guide.org/en/latest/starting/which-python/">Python3&lt;/a>的话，&lt;br>
可以使用&lt;a href="https://github.com/fabric/fabric">Fabric&lt;/a>的一个fork分支&lt;a href="https://github.com/mathiasertl/fabric/">Fabric3&lt;/a>，&lt;br>
&lt;a href="https://github.com/mathiasertl/fabric/">Fabric3&lt;/a>与&lt;a href="https://github.com/fabric/fabric">Fabric&lt;/a>大部分功能等价。&lt;/p>
&lt;p>只想用里面本地命令集成这部分功能的话，&lt;br>
还有一个库叫&lt;a href="https://www.pyinvoke.org/">Invoke&lt;/a>也提供了类似的功能。&lt;br>
这个库主要是名字特别帅，&lt;br>
&lt;a href="https://dota2.gamepedia.com/Invoker">dota2里面的卡尔就叫Invoker（祈求者）&lt;/a>。&lt;/p>
&lt;h2 id="进程管理supervisorsupervisor">进程管理：&lt;a href="https://supervisord.org/">Supervisor&lt;/a>&lt;/h2>
&lt;p>在正式环境中，&lt;br>
为了保证服务器进程的鲁棒性，&lt;br>
我们使用了 &lt;a href="https://supervisord.org/">supervisor&lt;/a> 来监控进程状态。&lt;/p>
&lt;p>一个简单的 nginx supervisor 的配置会长这样子：&lt;/p>
&lt;pre tabindex="0">&lt;code>[program:nginx]
command=/usr/sbin/nginx
autostart=true
autorestart=true
stdout_logfile=/var/log/supervisor/nginx.log
stderr_logfile=/var/log/supervisor/nginx_error.log
&lt;/code>&lt;/pre>&lt;p>把配置文件放到 &lt;code>/etc/supervisor/conf.d/nginx.conf&lt;/code> 以后，&lt;br>
就可以使用一系列命令把服务起起来：&lt;/p>
&lt;pre tabindex="0">&lt;code>$ supervisorctl update # supervisorctl 是 supervisor 的命令行工具，更新一波配置
nginx STARTING pid 1000, uptime 0:00:00
$ supervisorctl status # 查看进程状态
nginx RUNNING pid 1000, uptime 0:12:34
$ kill -9 1000 # 模拟各种波动，干掉 nginx 进程
$ supervisorctl status # 再次查看进程状态，可以发现 supervisor 自动重启了
nginx STARTING pid 1020, uptime 0:00:00
&lt;/code>&lt;/pre>&lt;h2 id="总结">总结&lt;/h2>
&lt;p>负责发版的工程师，&lt;br>
可能只在页面上点下了 &lt;code>Build&lt;/code> 的一个按钮，&lt;br>
实际上的流程是这样的：&lt;/p>
&lt;ul>
&lt;li>Jenkins 触发了配置好的 Bash脚本。&lt;/li>
&lt;li>里面 Bash 脚本跑了 fab 命令。&lt;/li>
&lt;li>fab 命令执行了代码上传的工作，本质上是通过 ssh 执行命令。&lt;/li>
&lt;li>最终用 supervisor 开启/重启了进程服务。&lt;/li>
&lt;li>发版完成。&lt;/li>
&lt;/ul>
&lt;p>以上大概就是我司目前自动化部署的简陋介绍。&lt;br>
升级之路漫漫，&lt;br>
还是有很多东西要学习/实践/掌握的呀。&lt;/p>
&lt;blockquote>
&lt;p>&lt;a href="https://liriansu.com/python-deployment-automation-one-sample">原文链接&lt;/a>，&lt;a href="https://liriansu.com/about/">作者 @苏子岳&lt;/a>&lt;/p>
&lt;p>本文版权属于再惠研发团队，欢迎转载，转载请保留出处。&lt;/p>
&lt;/blockquote></description></item><item><title>怎么使用搜索引擎</title><link>https://liriansu.com/posts/2017-11-19-how-to-google/</link><pubDate>Sun, 19 Nov 2017 21:52:07 +0000</pubDate><guid>https://liriansu.com/posts/2017-11-19-how-to-google/</guid><description>&lt;p>我就是这么用的。&lt;/p>
&lt;p>平常学习/工作过程中，&lt;br>
我经常提问和被提问，&lt;br>
有时会很惊讶地发现：&lt;br>
似乎我十分擅长回答别人的问题。&lt;/p>
&lt;p>于是我自豪地内省了一下，&lt;br>
发现了“表面上擅长回答问题”的原因：&lt;br>
我很擅长利用搜索引擎。&lt;/p>
&lt;p>于是我又灰溜溜地自省了一下，&lt;br>
发现了“擅长利用搜索引擎”的原因：&lt;br>
我掌握了一些小技巧。&lt;/p>
&lt;p>我决定把这些小技巧给记下来。&lt;br>
熟练学习、理解、运用、掌握以后，&lt;br>
相信你也能成为一个优质的谷歌UI的。&lt;/p>
&lt;h2 id="不用百度尽量用谷歌">不用百度，尽量用谷歌&lt;/h2>
&lt;p>在大陆的人类中，&lt;br>
使用最广的搜索引擎应该就是百度了。&lt;/p>
&lt;p>但我不喜欢用百度，&lt;br>
一些主观的原因主要如下：&lt;/p>
&lt;ul>
&lt;li>
&lt;p>口碑不好，可被替代。&lt;br>
因为种种原因（假药/推广/泄露用户信息），&lt;br>
百度的搜索口碑不好；&lt;br>
而且友商搜狗(sogou.com)也能顶替搜索功能。&lt;br>
那我更愿意选择口碑好的产品。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>内容更新不及时。&lt;br>
举个栗子，GitHub Issue里的最新内容，&lt;br>
百度就很少收录[CITATION NEEDED]。&lt;br>
而很多代码里的一些冷门报错，&lt;br>
收录的就更少了。&lt;/p>
&lt;/li>
&lt;/ul>
&lt;p>个人来说，我推荐能访问谷歌搜索的友人，&lt;br>
都可以使用谷歌搜索。&lt;br>
虽然谷歌的中国本土化做的不一定好，&lt;br>
但是像“怎么判断煤气泄漏”&lt;br>
“大哥喝冰阔落是什么梗”&lt;br>
“一点点哪个味道比较好喝”都是可以搜到合适的答案的。&lt;/p>
&lt;p>访问不到谷歌的大陆人类，&lt;br>
也可以使用必应、搜狗等代替。&lt;br>
我个人平常会用搜狗。&lt;/p>
&lt;p>假如程序员朋友，&lt;br>
想了解“不用百度搜索”的更多信息，&lt;br>
可以读一下&lt;a href="https://coolshell.cn/articles/9308.html">酷壳的倡议：《“作环保的程序员，从不用百度开始”》&lt;/a>&lt;/p>
&lt;h2 id="找到x问题">找到X问题&lt;/h2>
&lt;p>我之前一直以为XYZ问题是个广泛使用的说法了，&lt;br>
没想到居然好像是我先提这个说法的。&lt;/p>
&lt;p>XYZ问题的描述是&lt;a href="https://liriansu.com/x-y-z-question">“有的时候我们想解决的是X问题， 但是我们却纠结于Y问题， 最后却陷入了Z问题的陷阱里。”&lt;/a>&lt;br>
归纳一下就是：&lt;strong>找到问题的根源&lt;/strong>&lt;/p>
&lt;p>比如&lt;a href="https://liriansu.com/x-y-z-question">文章里提到的打字机效果&lt;/a>，&lt;br>
就是搜索X问题一个很好的例子。&lt;/p>
&lt;p>再比如平常写代码会遇到的第三方库报错的问题，&lt;br>
程序报的错一般都比较原始：&lt;br>
比如&lt;code>channel 0: open failed: administratively prohibited&lt;/code>这种。&lt;br>
有的时候看到报错，&lt;br>
我们会不自觉地先思考几步，&lt;br>
觉得可能是SSH channel遇到了权限问题，&lt;br>
然后我们就搜索了&lt;code>linux ssh channel permission&lt;/code>，&lt;br>
结果答案就海了去了。&lt;br>
这里最好的做法是直接用裸的报错信息去搜，&lt;br>
因为原始报错信息就是描述根源问题的最准确描述。&lt;/p>
&lt;h2 id="用正交的搜索词">用正交的搜索词&lt;/h2>
&lt;p>其实上一节我们搜&lt;code>linux ssh channel permission&lt;/code>的时候，&lt;br>
我们已经用了正交搜索词的技巧了。&lt;br>
这里借用数学术语正交，&lt;br>
说的是几个搜索词之间尽量&lt;strong>相互独特，互不关联&lt;/strong>。&lt;/p>
&lt;p>比如假如没有文化的我，&lt;br>
忘了朱自清先生的名篇叫什么名字，&lt;br>
可以搜“父亲 橘子 不要动”，&lt;br>
就能搜到《背影》一文。&lt;br>
&lt;del>（其实会搜到梗/段子/表情包）&lt;/del>&lt;/p>
&lt;p>比如我知道DC漫画跑得快的是闪电侠，&lt;br>
忘了漫威那边跑得快的是谁，&lt;br>
那显然我们搜“跑得快 一日千里 到过很多地方”这样相近的词语是搜不出快银的，&lt;br>
我们要用“漫威 跑得快 对标闪电侠”当关键词来搜索，&lt;br>
就可以得出合适的结果了。&lt;/p>
&lt;h2 id="理解结果">理解结果&lt;/h2>
&lt;p>搜索引擎大部分时候不会给出确切的答案，&lt;br>
给出的会是一个网页。&lt;br>
假如搜的是报错的话，&lt;br>
很多时候会给出一个问答论坛页面，&lt;br>
或者是讨论过程。&lt;/p>
&lt;p>这就要求我们能从一整个页面中抽出对我们有用的关键信息，&lt;br>
而且有的时候还要分辨谬误信息，&lt;br>
这里就是经验发挥作用的地方了。&lt;br>
你只要去尝试下载一个中文盗版软件，&lt;br>
就可以掌握“抽出有用信息”的技巧。&lt;/p>
&lt;p>假如是写程序的搜索的话，&lt;br>
你得了解Stack Overflow/GitHub Issue的一些基本方法：&lt;br>
比如Stack Overflow上高赞很多都是好几年前的答案，&lt;br>
要注意语言/库的版本；&lt;br>
以及GitHub Issue emoji最多的答案一般都有用等经验论。&lt;/p>
&lt;p>还有很多时候可能你是一个搜索引擎UI，&lt;br>
你要负责把结果二次解释给其他人。&lt;br>
那首先确保你解决的是&lt;a href="https://liriansu.com/x-y-z-question">&lt;strong>X问题&lt;/strong>&lt;/a>的基础上，&lt;br>
最有用的就是&lt;strong>换位思考&lt;/strong>，&lt;br>
确定对方的立场/理解力/需求，&lt;br>
再用对方能接受的语言讲述给他。&lt;/p>
&lt;h2 id="总结">总结&lt;/h2>
&lt;ul>
&lt;li>不用百度，尽量用谷歌。&lt;/li>
&lt;li>找到X问题。&lt;/li>
&lt;li>用正交的搜索词。&lt;/li>
&lt;li>理解结果。&lt;/li>
&lt;/ul>
&lt;p>只要做到这几条，&lt;br>
你就是一个合格的搜索引擎UI了。&lt;/p>
&lt;p>再佐以温和的态度，&lt;br>
良好的伪装，&lt;br>
以及不会被看透的高深。&lt;/p>
&lt;p>恭喜你，你就成为了他人眼中的大佬了！&lt;br>
（撒花）&lt;/p></description></item><item><title>程序员之逻辑</title><link>https://liriansu.com/posts/2017-10-31-programmers-logic/</link><pubDate>Tue, 31 Oct 2017 22:05:35 +0000</pubDate><guid>https://liriansu.com/posts/2017-10-31-programmers-logic/</guid><description>&lt;p>我有时会突然意识过来，&lt;br>
写程序这件事情给我带来了深远的影响。&lt;/p>
&lt;blockquote>
&lt;p>利益相关：&lt;br>
以下皆为本人自身想法，&lt;br>
与广大的可爱的程序员们不一定有关。&lt;/p>
&lt;/blockquote>
&lt;p>苏·格拉底曾经说过：&lt;br>
“一个人要先不断地剖析自己，&lt;br>
再不断地剖析自己，&lt;br>
最后不断地剖析自己，&lt;br>
他才是个伟大的人。”&lt;/p>
&lt;blockquote>
&lt;p>苏·格拉底：&lt;br>
我不是，&lt;br>
我没有，&lt;br>
别瞎说啊。&lt;em>（否认三连）&lt;/em>&lt;/p>
&lt;/blockquote>
&lt;blockquote>
&lt;p>苏格拉底：&lt;br>
别乱在外国人名中间打点。&lt;/p>
&lt;/blockquote>
&lt;p>在此，我就记录一下平常生活中的小事，&lt;br>
这样说不定可以窥斑见豹。&lt;/p>
&lt;h2 id="0">0&lt;/h2>
&lt;p>跟计算机打交道久了，&lt;br>
非常清楚程序都是按照流程来的。&lt;br>
所有所谓的 Bug 都是某个地方的计算机逻辑，&lt;br>
没有跟人类逻辑匹配上所导致的。&lt;br>
所以现在修 Bug 的时候，&lt;br>
虽然也会像以前一样高呼着“这不科学”，&lt;br>
但其实我心里知道，&lt;br>
这很科学，&lt;br>
而且外国古人不是说嘛：&lt;br>
&lt;code>Where there's a bug, there's a fix.&lt;/code>&lt;/p>
&lt;p>人类也是一样的。&lt;/p>
&lt;p>我们做的所有决定，&lt;br>
所有结果，&lt;br>
都是由一个决策树生成的，&lt;br>
这棵树或深或浅。&lt;/p>
&lt;p>我今天心情好，&lt;br>
突然坐到奶茶店里喝了一杯奶茶。&lt;br>
在旁边分手的小情侣，&lt;br>
用苹果电脑办公的小哥，&lt;br>
几个叽叽喳喳的大妈，&lt;br>
都像是钱钟书说的一样。&lt;br>
不过都是电台换台，&lt;br>
东一句西一句听得零碎，&lt;br>
但他们都是有自己完整的故事的。&lt;/p>
&lt;p>所以看事情，&lt;br>
知道了来龙去脉以后，&lt;br>
我总忍不住感慨一句：&lt;br>
&lt;strong>这很科学&lt;/strong>。&lt;/p>
&lt;h2 id="1">1&lt;/h2>
&lt;p>乌托邦世界里，&lt;br>
大家都很科学。&lt;br>
然而实际生活中，&lt;br>
总会有取舍。&lt;/p>
&lt;p>比如 &lt;code>Vim vs Emacs&lt;/code>,&lt;br>
&lt;code>PC vs 主机&lt;/code>,&lt;br>
&lt;code>青轴 vs 红轴&lt;/code>&lt;br>
等等话题，&lt;br>
现世中的我们总要做出选择。&lt;br>
而事实告诉我，&lt;br>
因为某一时刻，&lt;br>
我们的用户习惯、&lt;br>
用户量、&lt;br>
团队氛围、&lt;br>
外部环境总是固定的，&lt;br>
所以虽然没有最优解，&lt;br>
但我们&lt;strong>一定可以选择更优解&lt;/strong>。&lt;/p>
&lt;p>比如&lt;a href="https://www.zhihu.com/question/56236190">阿里编码规范里写到的&lt;code>超过三个表禁止 join&lt;/code>&lt;/a>，&lt;br>
我非常理解这里的道理，&lt;br>
但是我自己做项目的时候恕做不到。&lt;br>
或者说按网上一部分的说法，&lt;br>
&lt;em>好的男朋友要清楚包括口红色号在内的很多信息&lt;/em>，&lt;br>
那我更愿意尊重独立个体，&lt;br>
毕竟想了解&lt;em>dota新版本具体改动内容&lt;/em>的人也是少数…&lt;/p>
&lt;p>拿&lt;a href="https://en.wikipedia.org/wiki/Editor_war">最开始的 &lt;code>Vim vs Emacs&lt;/code> 这个经典话题&lt;/a>来举例子，&lt;br>
在两边都用过以后，&lt;br>
的确知道为什么说&lt;em>一个是编辑器之神，一个是神用的编辑器&lt;/em>了。&lt;br>
但具体到每个人的每个编辑环境，&lt;br>
总会选择一种搭配方式，&lt;br>
让他陷入最舒服的境地中。&lt;/p>
&lt;h2 id="01">01&lt;/h2>
&lt;p>&lt;code>万物科学&lt;/code> 和 &lt;code>最优解&lt;/code> 这两点叠加起来，&lt;br>
有一个结论就是永远要保持开放性的心态。&lt;br>
假如我们秉持着&lt;br>
&lt;em>世界上，15岁之前出现的都是已有的平凡事物，15到30岁出现的都是改变世界的发明，30岁以后出现的都是什么垃圾玩意啊。&lt;/em>&lt;br>
这样的心态，&lt;br>
那我们就会早早地陷入 &lt;a href="https://en.wikipedia.org/wiki/Local_optimum">local optima&lt;/a>.&lt;/p>
&lt;p>举个栗子。&lt;br>
业务代码写多了，&lt;br>
&lt;del>人&lt;/del>我就容易陷入套路代码的惰性里。&lt;br>
前阵子和产品经理讨论一个需求的实现，&lt;br>
说到一个点，&lt;br>
我很自然地说：“这实现不了。”&lt;br>
但产品经理又好奇地/疑惑地/质疑地多问了一句：&lt;br>
“为什么呢？”&lt;br>
那一刻我心中一愣，&lt;br>
对啊，为什么呢？&lt;br>
于是后续展开了更深刻的讨论。&lt;/p>
&lt;p>总的来说，&lt;br>
我&lt;strong>十分敬重学习能力&lt;/strong>，&lt;br>
我也十分喜欢/敬仰那些学习能力很强的人。&lt;/p>
&lt;p>在面试时跟候选人聊天的时候，&lt;br>
我很喜欢问一个问题，是：&lt;br>
&lt;em>能不能讲一下，你做过的项目里，你最喜欢的一个？&lt;/em>&lt;br>
有些同学会突然激动起来，&lt;br>
抓着你讲一个完整的故事。&lt;br>
比如最开始是某某原因，&lt;br>
然后本来是想怎么样的，&lt;br>
后来又因为什么样的原因，&lt;br>
学到了什么什么。&lt;br>
在这样的交流里，&lt;br>
不仅我能学到不少东西，&lt;br>
我也能看到他身上的成就和成长。&lt;/p>
&lt;h2 id="11">11&lt;/h2>
&lt;p>所以我很愿意&lt;strong>当一个好奇宝宝&lt;/strong>。&lt;/p>
&lt;p>就好像萌新三连说的那样：&lt;/p>
&lt;blockquote>
&lt;p>啥百度啊？&lt;br>
百度啥啊？&lt;br>
咋百度啊？&lt;/p>
&lt;/blockquote>
&lt;p>最后再附带 combo 技：&lt;/p>
&lt;blockquote>
&lt;p>大佬你到底会不会啊？&lt;/p>
&lt;/blockquote>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/meme/moe_combo.png" alt="combo">&lt;/p>
&lt;p>有的时候很多问题，&lt;br>
虽然我心里已经有一个大概率确定的答案，&lt;br>
但我也一样会问出来：&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://liriansu.com/girls-stockings">“丝袜，裤袜，打底裤有什么区别？”&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://liriansu.com/what-is-cash-cow">“现金牛是什么梗？”&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://liriansu.com/pronunciations">“Vim, Tmux, Zsh怎么读？”&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://liriansu.com/why-i-hate-smoking">“为什么烟不算毒品？”&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>所谓&lt;em>活到老，学到老&lt;/em>嘛（关谷语气）&lt;/p>
&lt;h2 id="100">100&lt;/h2>
&lt;p>对了，还有一点。&lt;br>
我称其为&lt;strong>对高信息量有好感&lt;/strong>。&lt;/p>
&lt;p>这点平常可能不会太在意，&lt;br>
但是简历/面试里面会很明显：&lt;br>
同样是讲三句话，&lt;br>
有些人就讲了很多有用信息，&lt;br>
有些人就像啥都没讲一样。&lt;/p>
&lt;p>在《狼人杀》里面这点也会很明显，&lt;br>
很多高玩会频繁用“发金水”“警徽流”“丢水包”等新手听不太懂的词，&lt;br>
这会增加他的发言信息量，&lt;br>
让发言听起来更靠谱。&lt;br>
而很多说：“啊，今天死的是XXX，所以大概女巫XXX，希望XXX”的人，&lt;br>
都被“这货发言信息量真少”给放逐了。&lt;/p>
&lt;p>这也是很多亚文化(&lt;a href="https://en.wikipedia.org/wiki/Meme">meme&lt;/a>)&lt;br>
好玩的地方。&lt;br>
同样的话语组成部分，&lt;br>
用独特的方式表达出来，&lt;br>
就会传达出微妙差异而信息量丰富的感觉。&lt;/p>
&lt;p>假如我写代码的时候，&lt;br>
能写出表达精简，&lt;br>
边界完备，&lt;br>
“信息量很高”的代码。&lt;br>
那不需要队友在Code Review时喊666，&lt;br>
我自己已经一蹦三尺高，&lt;br>
开心地像见了新垣结衣一样了。&lt;/p>
&lt;h2 id="-1">-1&lt;/h2>
&lt;p>其实边写还能边想到很多，&lt;br>
不过&lt;a href="https://en.wikipedia.org/wiki/Fermat%27s_Last_Theorem">&lt;del>这本书边上的空白太小了写不下&lt;/del>&lt;/a>&lt;br>
我想去玩游戏了…&lt;/p>
&lt;p>所以简单综述一下：&lt;/p>
&lt;ul>
&lt;li>信奉万物皆科学&lt;/li>
&lt;li>相信一定存在最优解&lt;/li>
&lt;li>喜欢学习能力强的人&lt;/li>
&lt;li>好奇心旺盛&lt;/li>
&lt;li>对高信息量有好感&lt;/li>
&lt;/ul>
&lt;p>这大概就是，&lt;br>
我作为程序员的逻辑的一小部分吧。&lt;/p></description></item><item><title>消逝的此刻</title><link>https://liriansu.com/posts/2017-10-26-carpe-diem/</link><pubDate>Thu, 26 Oct 2017 17:48:42 +0000</pubDate><guid>https://liriansu.com/posts/2017-10-26-carpe-diem/</guid><description>&lt;p>前几天 Reddit 上有个赞的很多的&lt;br>
Shower Thought:&lt;/p>
&lt;blockquote>
&lt;p>One of the most bittersweet feelings has to be&lt;br>
when you realise how much you&amp;rsquo;re going to miss a moment,&lt;/p>
&lt;p>while you&amp;rsquo;re still living it.&lt;/p>
&lt;/blockquote>
&lt;p>我很喜欢这个说法。&lt;/p>
&lt;p>跟女朋友聊到高中的时候，&lt;br>
她跟我讲过她有这么一种感觉：&lt;br>
“高三的时候因为学习压力重，&lt;br>
大家都很辛苦。&lt;br>
我虽然也很辛苦，&lt;br>
但我一点也没有不开心。&lt;br>
因为当时的我很清晰地知道：&lt;br>
这就是我的过一天少一天的高中生活了。”&lt;/p>
&lt;p>真是一个很美妙，&lt;br>
又很轻小说的描述。&lt;br>
时间真奇妙。&lt;/p>
&lt;p>五岁的某一天晚上，&lt;br>
我突然清楚了一件事情：&lt;br>
人类，是会死的。&lt;/p>
&lt;p>在那之前，&lt;br>
我只是知识性地接受了这个事实，&lt;br>
但那天晚上，&lt;br>
仿佛有个打印机把这个事实印进了我心里。&lt;br>
巨大的恐惧包围了我。&lt;/p>
&lt;p>随着时间的流逝，&lt;br>
那个夜晚在生命中也渐行渐远。&lt;br>
但随着我思考的越多，&lt;br>
死亡带来的孤独感就越重。&lt;/p>
&lt;p>有几个坚固的事实矗立在我眼前：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>我们微不足道&lt;/strong>。&lt;/li>
&lt;/ol>
&lt;p>我很喜欢 Fate系列 动画作品的一个原因就是：&lt;br>
它把各个年代的英雄带来到了同一个时空里，&lt;br>
并且把他们的观念冲突展示出来。&lt;/p>
&lt;p>有一次韦伯心情低落的时候，&lt;br>
亚历山大大帝指着世界地图笑着跟他说：&lt;br>
“你看，我当时征服的世界，&lt;br>
不过在地图上是这么一小块。&lt;br>
那在地图上，你有多大？我又有多大？&lt;br>
我们不过是世界的沧海一粟而已。”&lt;/p>
&lt;p>时间总会前进。&lt;br>
即使我能改变人类，&lt;br>
那我也只能改变几十年的人类。&lt;/p>
&lt;ol start="2">
&lt;li>&lt;strong>我们总会死&lt;/strong>。&lt;/li>
&lt;/ol>
&lt;p>那假如我能功在当代，利在千秋呢？&lt;br>
功在当代，利在千秋又与我何干。&lt;/p>
&lt;p>《狮子王》里，&lt;br>
穆法沙带着小辛巴到草原上玩。&lt;br>
那天晚上夜空闪亮，&lt;br>
穆法沙就跟辛巴讲了一个故事：&lt;br>
“我们狮子族有一个传说，&lt;br>
就是我们每一个逝去的祖先，&lt;br>
都会化成天空中的一个星星。&lt;br>
每当你抬头看夜空，&lt;br>
发现星星在闪烁的时候，&lt;br>
那都是我们的祖先在看着你。”&lt;/p>
&lt;p>在其它的传说、宗教、神话里，&lt;br>
总有类似的说法。&lt;/p>
&lt;p>没办法改变命运，&lt;br>
我们只能改变自己的思想了。&lt;br>
真是愚蠢的人类啊喵。&lt;/p>
&lt;ol start="3">
&lt;li>&lt;strong>我们只能自己思考&lt;/strong>。&lt;/li>
&lt;/ol>
&lt;p>小学时候看了很多《儿童文学》。&lt;br>
里面有一篇短篇小说我额外喜欢，&lt;br>
故事大纲是一个程序员创造了一个网游世界，&lt;br>
他爱上了里面虚拟的NPC，&lt;br>
结果最后他发现他也是被创造出来的NPC。&lt;/p>
&lt;p>这个故事跟《楚门的世界》、《沙耶之歌》异曲同工，&lt;br>
就像以前BBS上流传的一句话：&lt;br>
“在网上，没人知道你是一只狗。”&lt;/p>
&lt;p>难怪人类会在大刘的《乡村教师》里被评为5B级文明：&lt;/p>
&lt;blockquote>
&lt;p>“上尉。你是个白痴吗？！”&lt;br>
舰队统帅大怒，&lt;br>
“你是想告诉我们，&lt;br>
一种没有记忆遗传，&lt;br>
相互间用声波进行信息交流，&lt;br>
并且是以令人难以置信的每秒1至10比特的速率进行交流的物种，&lt;br>
能创造出5B级文明？！&lt;br>
而且这种文明是在没有任何外部高级文明培植的情况下自动进化的？！”&lt;/p>
&lt;p>“但，阁下，确实如此。”&lt;/p>
&lt;p>“但在这种情况下，&lt;br>
这个物种根本不可能在每代之间积累和传递知识，&lt;br>
而这时文明进化所必须的！”&lt;/p>
&lt;p>“他们有一种个体，&lt;br>
有一定数量，&lt;br>
分布于这个种群的各个角落，&lt;br>
这类个体充当两代生命体之间知识传递的媒介。”&lt;/p>
&lt;p>“听起来像神话。”&lt;/p>
&lt;p>“不，”&lt;br>
参议员说：&lt;br>
“在银河文明的太古时代，&lt;br>
确实有过这个概念，&lt;br>
但即使在那时也极其罕见，&lt;br>
除了我们这些星系文明进化史的专业研究者，&lt;br>
很少有人知道。”&lt;/p>
&lt;p>“你是说那种在两代生命体之间传递知识的个体？”&lt;/p>
&lt;p>“他们叫教师。”&lt;/p>
&lt;/blockquote>
&lt;p>存活到现在，&lt;br>
我可能有四分之一的空闲时间都在思考这类问题。&lt;br>
高一的时候跟物理老师也探讨过。&lt;br>
（高中物理老师是个老厉害的人，&lt;br>
十八岁前他就读完了大学，&lt;br>
三十多岁就教了二十多年物理了…）&lt;/p>
&lt;p>不过当时的他也没办法说服我，&lt;br>
主要是几个问题过于终极：&lt;br>
“人类为什么要活着？&lt;br>
世界终究会毁灭的话，人类有意义吗？&lt;br>
即使我是特殊的人类，我能做出什么不同的事情吗？”&lt;/p>
&lt;p>假如你能针对这几个问题，&lt;br>
给我你的回答的话，&lt;br>
那我知道有一家很好吃的蛋糕店，&lt;br>
我请你吃。&lt;/p>
&lt;p>希望世界和平。&lt;br>
Carpe Diem.&lt;/p></description></item><item><title>怎么写Bug</title><link>https://liriansu.com/posts/2017-09-20-how-to-write-bugs/</link><pubDate>Wed, 20 Sep 2017 19:49:38 +0000</pubDate><guid>https://liriansu.com/posts/2017-09-20-how-to-write-bugs/</guid><description>&lt;p>时至今日，&lt;br>
笔者已经有十年以上的写Bug经验了。&lt;br>
是时候给各位想写Bug但还不够熟练的同学们，&lt;br>
分享一些写Bug的心得了。&lt;/p>
&lt;h2 id="概述">概述&lt;/h2>
&lt;p>诚实地说，&lt;br>
写Bug本身并不是一件很光荣的事情。&lt;br>
但是写了一个很隐蔽/影响很大/看起来像是Feature的Bug，&lt;br>
然后再修复它，&lt;br>
就是一件伟大的事情了。&lt;br>
往往在你的行云流水般的bugfix代码下，&lt;br>
&lt;a href="https://github.com/MrMEEE/bumblebee-Old-and-abbandoned/commit/a047be85247755cdbe0acce6#diff-1">还能收获围观群众的666666惊呼&lt;/a>。&lt;/p>
&lt;p>总的来说，&lt;br>
写Bug的技巧可以分为下面几个维度：&lt;/p>
&lt;ul>
&lt;li>开发功能
&lt;ul>
&lt;li>测试是懦夫的行为&lt;/li>
&lt;li>不要让外界发现Bug&lt;/li>
&lt;li>Warning? 不存在的&lt;/li>
&lt;li>复制别人的代码&lt;/li>
&lt;li>遵循历史规律，不轻易改变&lt;/li>
&lt;li>用中间状态完成功能&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>培养习惯
&lt;ul>
&lt;li>所有情况下都拥抱变化&lt;/li>
&lt;li>配置个性化的开发环境&lt;/li>
&lt;li>少做自动化的无用功&lt;/li>
&lt;li>同时开展多个工作&lt;/li>
&lt;li>信任他人的实现&lt;/li>
&lt;li>永远充满自信&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>与人交流
&lt;ul>
&lt;li>永远只实现90%的方案&lt;/li>
&lt;li>永远只实现100%的方案&lt;/li>
&lt;li>Code Review时也不解释自己的代码&lt;/li>
&lt;li>为Bug的合理性辩护&lt;/li>
&lt;li>适当指责别人写的不好&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>后期维护
&lt;ul>
&lt;li>当权责分明的人&lt;/li>
&lt;li>信奉无知即无罪&lt;/li>
&lt;li>分担权责到用户和运营上&lt;/li>
&lt;li>多写代码，生产力=破坏力&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;p>下面就让笔者依次为你讲解具体的写Bug技巧。&lt;/p>
&lt;h2 id="开发功能">开发功能&lt;/h2>
&lt;h3 id="测试是懦夫的行为">测试是懦夫的行为&lt;/h3>
&lt;p>Bug的天敌之一就是完善的测试，&lt;br>
为了写更多的Bug，&lt;br>
我们需要减少测试的量。&lt;br>
但是不写测试道义上说不过去，&lt;br>
所以我们要合理用一些话术来解释：&lt;/p>
&lt;ul>
&lt;li>这个功能很简单，不用写测试。&lt;/li>
&lt;li>这个功能太复杂，不想写测试。&lt;/li>
&lt;li>这个功能是临时上的，不写测试了。&lt;/li>
&lt;li>这个功能我们写不了测试。&lt;/li>
&lt;li>放心吧，我写的代码稳得一笔，包准没有Bug。&lt;/li>
&lt;/ul>
&lt;p>更高级的做法是自己开发功能的时候，&lt;br>
先手动测试保证完善了。&lt;br>
但是几个月以后，&lt;br>
别人再改动相关代码的时候，&lt;br>
就神不知鬼不觉地写了几个Bug进去了。&lt;/p>
&lt;h3 id="不要让外界发现bug">不要让外界发现Bug&lt;/h3>
&lt;p>Bug是十分引人讨厌的，&lt;br>
基本上被发现了都会被修复。&lt;br>
那针对这个，&lt;br>
我们有两种操作可以做：&lt;/p>
&lt;ol>
&lt;li>
&lt;p>&lt;strong>让Bug不被发现&lt;/strong>。&lt;br>
编码过程中，&lt;br>
多用&lt;code>catch Exception { ignore(); }&lt;/code>这样的操作，&lt;br>
或者就把Bug的信息记到一个没人看的日志文件里面。&lt;br>
这样前一个操作做错了，&lt;br>
后面的操作还能接着做下去，&lt;br>
说不定就像小学数学题一样：&lt;br>
过程是错的，结果却是对的呢？&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>让Bug不被修复&lt;/strong>。&lt;br>
这个其实很简单，&lt;br>
只要我们写一个基于概率性假设的Feature就行了。&lt;br>
比如经典的&lt;code>race condition&lt;/code>，&lt;br>
在高并发的情况下同时改某一个变量，&lt;br>
或者是npm的包不锁死版本，&lt;br>
然后不同时间依次部署在多个环境上…&lt;/p>
&lt;/li>
&lt;/ol>
&lt;h3 id="warning-不存在的">Warning? 不存在的&lt;/h3>
&lt;p>代码里面有Warning是极其正常的事情，&lt;br>
我们只要保证代码能编译运行就行了。&lt;br>
IDE的大部分灰色/黄色/下划线都是一些强迫症程序员做的功能，&lt;br>
我们应当关掉IDE的这些警告。&lt;/p>
&lt;p>还有Lint工具，&lt;br>
更多是用来检查拼写的。&lt;br>
每个人的代码习惯都不一样，&lt;br>
我们应当尊重个人差异，&lt;br>
只要有习惯不一致的地方，&lt;br>
就应当关掉Linter对应的检查。&lt;/p>
&lt;h3 id="多复制别人的代码">多复制别人的代码&lt;/h3>
&lt;p>程序员业界有一句流传两百多年的俗话，叫：&lt;br>
“不要重复造轮子”。&lt;/p>
&lt;p>所以我们应当多复制现成的代码，&lt;br>
这样一个Bug就会被复制成了两个。&lt;br>
而且以后新版本里，那部分代码的Bug被修复了，&lt;br>
但肯定没人会发现我们也复制了一份代码，&lt;br>
这里还有一个Bug。&lt;/p>
&lt;p>当我们要定制化部分第三方依赖库里的代码时，&lt;br>
少用继承和组合，&lt;br>
多用复制和粘贴，&lt;br>
然后在我们需要的地方加上定制化的改动就行了。&lt;/p>
&lt;h3 id="遵循历史规律不轻易改变">遵循历史规律，不轻易改变&lt;/h3>
&lt;p>很多时候以前的代码写成这样是有原因的。&lt;br>
中国有句老话叫“萧规曹随”，&lt;br>
写程序里的意思就是“之前的代码就是这么实现的，我也应该要这么写”。&lt;/p>
&lt;p>这样虽然我们只能在新的业务里引进新的Bug，&lt;br>
但是旧的业务的Bug我们可以继承过来呀。&lt;br>
而且把这一条技巧和上一条技巧结合起来就更佳了，&lt;br>
“复制以前的历史代码”，&lt;br>
是大大减少写Bug的工作量的一条捷径。&lt;/p>
&lt;h3 id="用中间状态完成功能">用中间状态完成功能&lt;/h3>
&lt;p>工作中写的代码大体上会分为技术代码和业务代码两部分。&lt;br>
业务代码很不好玩，&lt;br>
而且会有一个明确的deadline。&lt;/p>
&lt;p>这个时候我们就要心中冥想“这个我要快点写完”，&lt;br>
口中默念“这个很容易实现”，&lt;br>
一边解释“先猥琐一点实现了，后面再整理一下”，&lt;br>
再依靠我们的编程素养三下五除二地解决问题。&lt;/p>
&lt;p>虽然这样写出来的Bug生命周期不会太长，&lt;br>
但是万一后面大家都很忙，忘了这里有个中间状态，&lt;br>
那一些Bug的生命就会很长了！超棒！&lt;/p>
&lt;h2 id="培养习惯">培养习惯&lt;/h2>
&lt;h3 id="所有情况下都拥抱变化">所有情况下都拥抱变化&lt;/h3>
&lt;p>现代软件开发世界里有一个真理，&lt;br>
叫**“需求一直是变化的”**。&lt;br>
根据逻辑学来看：&lt;/p>
&lt;ul>
&lt;li>因为需求一直是变化的，&lt;/li>
&lt;li>又因为代码是要实现需求的，&lt;/li>
&lt;li>所以代码也一直是变化的。&lt;/li>
&lt;/ul>
&lt;p>我们写出一个又一个新的Bug就有了坚实的理论基础。&lt;/p>
&lt;p>而且这里还有一个酷炫小技巧就是，&lt;br>
最开始的系统设计一般都是简单的，&lt;br>
最开始的时间也是很充裕的，&lt;br>
但是往往变化的时间会比较急促。&lt;br>
所以只要我们大胆拥抱变化，承诺“这周内都能实现”，&lt;br>
这里就会有一个很小但充裕的时间让我们发挥，&lt;br>
写出一些别人根本设计不出来的Bug。&lt;/p>
&lt;h3 id="配置个性化的开发环境">配置个性化的开发环境&lt;/h3>
&lt;p>开发环境永远，永远不要跟生产环境保持一致：&lt;br>
因为生产环境一般来说是Linux，Linux太无趣了。&lt;br>
我们应当用一些像Windows/MacOS这样不区分大小写的宽松的系统，&lt;br>
来当我们的开发环境。&lt;/p>
&lt;p>用自己的电脑开发的时候，为了自己心情愉悦，&lt;br>
可以在全局装一些好看的字体、很好用的第三方库，&lt;br>
然后适当地在代码中引用这些定制化的很棒的工具。&lt;br>
同时测试时永远用最新版的软件，&lt;br>
比如浏览器、客户端、代码版本等。&lt;/p>
&lt;p>当别人疑惑地报了个疑似Bug的问题时，&lt;br>
你可以自豪地回复：“我这是好的。”&lt;/p>
&lt;h3 id="少做自动化的无用功">少做自动化的无用功&lt;/h3>
&lt;p>假如一个自动化程序有Bug，&lt;br>
那这个Bug被修复以后就很难被重新引入。&lt;/p>
&lt;p>但是假如我们每次做一些数据上的操作，&lt;br>
都直接调用代码，&lt;br>
或者是写一些一次性的脚本来“自动化”这个操作，&lt;br>
那我们每次都有机会引入全新的Bug。&lt;/p>
&lt;p>虽然手动操作会耗费我们更多的时间，&lt;br>
但是它能带来更多Bug的可能性呀~&lt;/p>
&lt;h3 id="同时开展多个工作">同时开展多个工作&lt;/h3>
&lt;p>厉害的人永远不会只在一个项目上留下他的Bug。&lt;/p>
&lt;p>我们也要当这样的人，&lt;br>
所以就像“能力越强，责任越大”说的一样，&lt;br>
在同一时刻我们要敢于承担多个任务。&lt;br>
这里的任务可大可小，&lt;br>
但是每个任务都要是不同方面的，&lt;br>
假如不仅是紧急的任务，&lt;br>
还时不时会有利益相关的人来催一下就更好了。&lt;/p>
&lt;p>这样我们在完成多个任务的时候，&lt;br>
还可以充分体验“上下文切换”的快感，&lt;br>
然后在多个项目上都留下了自己的印记。&lt;/p>
&lt;h3 id="信任他人的实现">信任他人的实现&lt;/h3>
&lt;p>正如小学、初中、高中每几年都要学一遍的《珍珠鸟》讲的那样：&lt;/p>
&lt;blockquote>
&lt;p>信赖，往往创造出美好的境界。&lt;/p>
&lt;/blockquote>
&lt;p>作为单纯可爱的程序员，&lt;br>
我们也要信任他人。&lt;br>
信任用户这么聪明，肯定能看得懂报错，&lt;br>
信任产品经理给的需求，肯定简单，&lt;br>
信任设计师给的图，肯定容易实现；&lt;br>
信任前端传入的数据，肯定是合法的，&lt;br>
信任传入合法数据时，后端的接口肯定不会报错；&lt;br>
信任测试过的代码，上线了肯定没问题，&lt;br>
信任第三方的库，小版本肯定不会改兼容性，&lt;br>
信任这么贵的服务，效果肯定比MySQL好。&lt;/p>
&lt;p>而且就算这种时候出了Bug，&lt;br>
我们也可以解释呀~&lt;br>
又不是我们的问题，&lt;br>
这个Bug，写的精妙吧。&lt;/p>
&lt;h3 id="永远充满自信不用写注释">永远充满自信，不用写注释&lt;/h3>
&lt;p>&lt;a href="https://liriansu.com/pareto-rule-of-programmers">世界上20%的程序员&lt;/a>，&lt;br>
写出了80%的&lt;del>程序&lt;/del>Bug。&lt;br>
一般来说，看到这篇文章的程序员，&lt;br>
应该都是属于top 20%。&lt;/p>
&lt;p>虽然说三年前的代码我不一定想的起来，&lt;br>
但是一年前的代码自己应该看得懂，&lt;br>
所以一般情况知道是自己维护的话，&lt;br>
就不用写多少注释了。&lt;/p>
&lt;p>而且像我们这种英文很好的人，&lt;br>
写注释肯定是用英文的。&lt;br>
不过又担心看代码的人英文不一定好，&lt;br>
所以还是不写注释了。&lt;/p>
&lt;p>基于自信的基础上，&lt;br>
我们还可以觉得所有自己写的Bug都是可以修复的，&lt;br>
所以一些暂时的Bug不用太重视，&lt;br>
所谓&lt;code>When there's a bug, there's a fix.&lt;/code>&lt;/p>
&lt;h2 id="与人交流">与人交流&lt;/h2>
&lt;h3 id="永远只实现90的方案">永远只实现90%的方案&lt;/h3>
&lt;p>老程序员之间会口口相传的一句道理叫：&lt;br>
“相比于覆盖100%的复杂设计，我更喜欢覆盖90%的简单设计。”&lt;/p>
&lt;p>虽然这样子写不出来100%的Bug了，&lt;br>
但其实根据这个原则，&lt;br>
我们可以把放弃掉的10%用户都看成是一个巨大Bug。&lt;/p>
&lt;p>这么看起来，&lt;br>
我们在更少的工作量情况下，&lt;br>
完成了更大的Bug，&lt;br>
其实效率更高了呢。&lt;/p>
&lt;h3 id="永远实现100的方案">永远实现100%的方案&lt;/h3>
&lt;p>中国的智慧长者们会讲一句东方谚语，叫：&lt;br>
“行百里者半九十。”&lt;/p>
&lt;p>当我们做一个系统设计/业务实现时，&lt;br>
假如不能做到最好，&lt;br>
不考虑完所有的情况，&lt;br>
那其实相当于整个功能没有实现。&lt;/p>
&lt;p>软件合理的流程应该是一开始设计好整个系统，&lt;br>
然后再开发，一次性全部上线，&lt;br>
之后再整理上一次的Bug，&lt;br>
伙同下一次的所有设计、功能再上线。&lt;br>
这样旧的Bug也可以活得更久，&lt;br>
新的Bug也可以持续上线。&lt;/p>
&lt;p>在100%的方案里面，&lt;br>
Bug虽然会减少一部分，&lt;br>
但是我们可以分散写Bug的权责，&lt;br>
最终设计、实现、测试、上线整个流程的所有人都是Bug的父母。&lt;/p>
&lt;h3 id="code-review时也不解释自己的代码">Code Review时也不解释自己的代码&lt;/h3>
&lt;p>随着现代软件开发流程的普及，&lt;br>
大部分程序员用上了Git等版本控制工具。&lt;br>
但是这些只不过是上传代码的工具，&lt;br>
即使是版本控制跟项目流程工具结合时，&lt;br>
我们也应当相信个人的力量。&lt;/p>
&lt;p>发Code Review时利用好自动发邮件功能，&lt;br>
少解释代码逻辑，多催别人“快approve我的代码”。&lt;br>
因为小的Code Review比较容易看，&lt;br>
写的Bug会被一眼看穿，&lt;br>
所以更棒的做法是发一次改动几百上千行的大的PR。&lt;br>
这样不仅能显示我们的工作量，&lt;br>
还能让别人对Review我们的代码望而生怯。&lt;/p>
&lt;p>久而久之，&lt;br>
别人只能Review我们的代码风格，&lt;br>
然后Bug们就能隐藏在代码逻辑里，&lt;br>
在开发环境、测试环境、生产环境之间遨游了。&lt;/p>
&lt;h3 id="适当指责别人写的不好">适当指责别人写的不好&lt;/h3>
&lt;p>假如以上的技巧你都掌握了的话，&lt;br>
那恭喜你，成为了一个写Bug中级工程师。&lt;br>
此时你不仅拥有了写Bug的权利，&lt;br>
你还拥有了指责别人的权利。&lt;/p>
&lt;p>当然，我们不能上升到人身攻击，&lt;br>
所以我们应该主要攻击别人的代码：&lt;br>
“你这么写不好”&lt;br>
“我觉得这样写不行”&lt;br>
“你这么写以后会有Bug”&lt;/p>
&lt;p>为了保持神秘，我们也要少跟别人解释为什么/什么是好代码什么是坏代码。&lt;br>
心态好的人被指责了，可能会去查谷歌，从而写更少的Bug；&lt;br>
心态不好的人被指责了，他可能会怀疑自己不适合干这一行。&lt;/p>
&lt;p>总的来说，跟我们写Bug竞争的人会变少。&lt;br>
这样我们下次敞开写Bug的时候，&lt;br>
还能反驳“你也写了一个Bug”。&lt;/p>
&lt;h3 id="为bug的合理性辩护">为Bug的合理性辩护&lt;/h3>
&lt;p>Bug也分很多种，&lt;br>
不同的场景会催生不同的Bug，&lt;br>
严重性、时效性、后果也各有不同。&lt;br>
写Bug的确是再正常不过的日常了。&lt;/p>
&lt;p>根据“存在即合理”的说法，&lt;br>
我们要勇于为自己的Bug辩护，&lt;br>
主要的话术可以聚集以上的技巧，&lt;br>
总结精华如下：&lt;/p>
&lt;ul>
&lt;li>怎么重现的？我电脑上是好的，你确定你操作没问题？&lt;/li>
&lt;li>这种是边缘情况，不要这么操作就行，可以忽略。&lt;/li>
&lt;li>以前就是这么实现的，这不是Bug，这是Feature。&lt;/li>
&lt;li>最开始是好的，是改需求改挂的，假如需求不改就不会挂了。&lt;/li>
&lt;li>跑脚本跑错了，改一下重跑就行。数据的问题，怎么能叫Bug呢？&lt;/li>
&lt;li>这个功能不是我写的。&lt;/li>
&lt;li>这个Code Review的时候，A君没有看出来。&lt;/li>
&lt;li>这个测试的时候，B君没有测出来。&lt;/li>
&lt;/ul>
&lt;p>牢记以上话术，&lt;br>
适当时候抛出，&lt;br>
写Bug时心里的底气就会更足了。&lt;/p>
&lt;h2 id="后期维护">后期维护&lt;/h2>
&lt;h3 id="当权责分明的人">当权责分明的人&lt;/h3>
&lt;p>一个五千多年历史的文明古国里流传着这么一句话：&lt;br>
“不在其位，不谋其政。”&lt;/p>
&lt;p>意思是“别人写的代码，我们不用管。别人写的Bug，我们不用修”。&lt;br>
现代工具提供了很便利的历史记录功能，&lt;br>
比如Git的话可以使用&lt;code>git blame&lt;/code>，&lt;br>
这样的功能可以让我们快速定位某个Bug是谁写的。&lt;/p>
&lt;p>平常跟别人讨论代码的时候，&lt;br>
多用“你的代码”、“我的代码”、“他的代码”等指代副词加强代码归属感，&lt;br>
这样出了Bug以后，别人是甩不了锅的。&lt;br>
虽然这样的操作弊端是我们自己写的Bug，&lt;br>
也得我们自己修复。&lt;br>
但是依照上文的操作，&lt;br>
我们肯定可以把锅给甩掉。&lt;/p>
&lt;p>总而言之就是一句话：&lt;br>
Bug都是人写的，&lt;br>
不是你写的，就是我写的。&lt;/p>
&lt;p>当权责分明的人，&lt;br>
这样别人就不会对我们的代码感兴趣，&lt;br>
我们自己的代码，&lt;br>
想写多少Bug就写多少Bug。&lt;/p>
&lt;h3 id="信奉无知即无罪">信奉无知即无罪&lt;/h3>
&lt;p>无知者究竟无罪还是有罪是吃瓜群众们很喜欢争论的话题，&lt;br>
但在我们写Bug的程序员业界，&lt;br>
很显然：无知者无罪。&lt;/p>
&lt;p>比如我们要用一个第三方库，怎么用呢？&lt;br>
百度一下，找到的第一段代码复制粘贴下来就行了。&lt;br>
我们不一定要去理解所有的代码原理是什么的，&lt;br>
因为要实现功能的需求更紧迫嘛。&lt;br>
就算出Bug了怎么办？&lt;br>
无知者无罪，&lt;br>
我又不知道这样会有Bug。&lt;/p>
&lt;p>不太清楚这里要怎么操作，&lt;br>
求A君写一段代码发我。&lt;br>
虽然我还是不太清楚具体操作，&lt;br>
但是这段代码是A君写的，&lt;br>
这样有Bug了有罪的也是他。&lt;br>
而且我之后调用出了问题，&lt;br>
也可以写出不少blame到他头上的Bug呢。&lt;/p>
&lt;p>无知即无罪，就是：&lt;br>
我们写程序的时候，&lt;br>
不需要懂得每一行程序的原理，&lt;br>
能用就行了，&lt;br>
这样程序出问题了，&lt;br>
也怪不到我头上。&lt;br>
毕竟谁没个菜鸟的时候呢？&lt;/p>
&lt;h3 id="分担权责到用户和运营上">分担权责到用户和运营上&lt;/h3>
&lt;p>技术肯定是不能解决一切问题的，&lt;br>
而且技术肯定不能解决人的问题。&lt;/p>
&lt;p>所以很多时候的Bug，&lt;br>
不是我们实现的不对，&lt;br>
而是用户的操作不对。&lt;/p>
&lt;p>这个工具是写给程序员用的，&lt;br>
他们都很聪明，&lt;br>
就不用写那么完善了，&lt;br>
适当报个&lt;code>NullPointerException&lt;/code>,&lt;br>
他们肯定能读懂trace，&lt;br>
报个&lt;code>segmentation fault&lt;/code>,&lt;br>
他们肯定会用&lt;code>gdb&lt;/code>逐步调试的吧。&lt;/p>
&lt;p>这个工具最终是运营用的，&lt;br>
&lt;code>end user&lt;/code>可以培训的，&lt;br>
所以就不用太好用了，&lt;br>
功能做出来就行。&lt;br>
适当报个400，&lt;br>
教一下用户用console看一下就行了。&lt;br>
不是所有情况的500都是用不了的bug，&lt;br>
有些情况只要那么操作就可以解决了。&lt;/p>
&lt;p>用户怎么不懂呢？&lt;br>
这，也是另一种意义上的Bug吧。&lt;/p>
&lt;h3 id="多写代码生产力破坏力">多写代码，生产力=破坏力&lt;/h3>
&lt;p>好了，孙子兵法三十五计都看完了，&lt;br>
最后一步，那当然是提升生产力了。&lt;/p>
&lt;p>只要你熟读本文，&lt;br>
掌握了Bug生产之术，&lt;br>
那你勤于加班，&lt;br>
多写代码&lt;br>
肯定能掌握Bug大生产之术。&lt;/p>
&lt;p>就像中国神话里一位叫“愚公”的人说的，&lt;br>
写Bug也一样：&lt;/p>
&lt;blockquote>
&lt;p>虽我之死，无子存焉；&lt;br>
但100行代码里有51个Bug，&lt;br>
修了1个，还有78个Bug；&lt;br>
虽码不加增，Bug无穷匮也。&lt;/p>
&lt;/blockquote>
&lt;p>还是要继续修炼也。&lt;/p>
&lt;p>&lt;a href="https://coolshell.cn/articles/4758.html">&lt;em>本文思想仿《如何写出无法维护的代码》&lt;/em>&lt;/a>&lt;/p></description></item><item><title>我眼中的大佬们</title><link>https://liriansu.com/posts/2017-09-16-interesting-humans/</link><pubDate>Sat, 16 Sep 2017 16:07:46 +0000</pubDate><guid>https://liriansu.com/posts/2017-09-16-interesting-humans/</guid><description>&lt;p>近期有一个表情“给大佬递茶”用的蛮多的，&lt;br>
我理解的“大佬”的含义，&lt;br>
就是“三人行，必有我师焉”里的“师”一样的含义。&lt;/p>
&lt;p>最近&lt;a href="https://www.zhihu.com/people/su-zi-yue-50/activities">因为在公众场合吹的牛逼多了&lt;/a>，&lt;br>
有些不明真相的群众可能觉得我也是大佬。&lt;br>
我心有点惶恐，&lt;br>
于是打算给诸位介绍一下我眼中的大佬们。&lt;/p>
&lt;blockquote>
&lt;p>DISCLAIMER:&lt;/p>
&lt;p>本文没有客观事实，都是主观观点。&lt;br>
假如有不恰当的地方，那都是我观点不恰当。&lt;/p>
&lt;p>这些大佬基本都是我认识他，但他不认识我，&lt;br>
没有利益相关。&lt;/p>
&lt;/blockquote>
&lt;h2 id="jeff-atwoodjeff-stack-overflowso-的创始人">&lt;a href="https://blog.codinghorror.com/about-me/">Jeff Atwood&lt;/a>, &lt;a href="https://stackoverflow.com/">Stack Overflow&lt;/a> 的创始人&lt;/h2>
&lt;p>在我&lt;a href="https://liriansu.com/read-blogs-to-write-blogs">刚开始补个人博客的有段时间&lt;/a>里，&lt;br>
我&lt;del>单方面&lt;/del>认识了很多大佬，&lt;br>
学习了非常多的博客文章，&lt;br>
&lt;a href="https://blog.codinghorror.com/about-me/">Jeff Atwood (下称 Jeff)&lt;/a> 的 &lt;a href="https://blog.codinghorror.com/">codinghorror.com&lt;/a> 就是其中之一。&lt;/p>
&lt;p>&lt;a href="https://blog.codinghorror.com/about-me/">他的 About Me 页面&lt;/a>写的特别认真，&lt;br>
至少我很喜欢这种风格：&lt;br>
在单个页面内，&lt;br>
首先介绍自己，&lt;br>
再讲一些微不足道的经历，&lt;br>
最后主要讲自己的三观（世界/人生/价值）。&lt;/p>
&lt;p>作为 &lt;a href="https://stackoverflow.com/">SO&lt;/a> founder,&lt;br>
&lt;a href="https://blog.codinghorror.com/about-me/">Jeff&lt;/a> 大概在业界也是知名的，&lt;br>
这方面我了解的不多。&lt;br>
不过他讲的几个事情我记得很牢：&lt;/p>
&lt;p>一个是&lt;a href="https://blog.codinghorror.com/on-the-meaning-of-coding-horror/">网站名称的由来&lt;/a>，&lt;br>
就是&lt;a href="https://book.douban.com/subject/1477390/">《代码大全》&lt;/a> &lt;a href="https://www.amazon.com/Code-Complete-Practical-Handbook-Construction/dp/0735619670">(Code Complete)&lt;/a> 这本书里的小标题：&lt;br>
Coding Horror, 翻译成中文大概是“屎代码”的意思。&lt;br>
于是我也去补完了&lt;a href="https://book.douban.com/subject/1477390/">《代码大全》的中文版&lt;/a>，&lt;br>
感觉虽然是有点年代的书，&lt;br>
但里面讲的一些程序员的劣习，&lt;br>
也是中枪无数。&lt;br>
于是看完了中文版以后，&lt;br>
我又很饥渴地把&lt;a href="https://www.amazon.com/Code-Complete-Practical-Handbook-Construction/dp/0735619670">英文原版&lt;/a>也学习了一遍。&lt;/p>
&lt;p>还有一个就是写博客。&lt;br>
Jeff 曾&lt;a href="https://blog.codinghorror.com/fear-of-writing/">多次&lt;/a>讲到在他心目中，&lt;br>
&lt;a href="https://blog.codinghorror.com/how-to-write-without-writing/">写作是自我学习的很好的方式&lt;/a>。&lt;br>
不过他自己写博客主要是想找个地方记一下好玩的事情。&lt;/p>
&lt;h2 id="陈皓haoelhaoel-weibo-酷壳的站长haoel">&lt;a href="https://weibo.com/haoel">陈皓，haoel&lt;/a>, &lt;a href="https://coolshell.cn/haoel">酷壳的站长&lt;/a>&lt;/h2>
&lt;p>&lt;a href="https://coolshell.cn/haoel">陈皓（下称耗子叔）对自己的描述&lt;/a>是：&lt;/p>
&lt;blockquote>
&lt;p>大家好，我是陈皓，&lt;br>
我不是高手，我也不是牛人，&lt;br>
我只是在跟随着我的兴趣和喜好去学习一些技术。&lt;/p>
&lt;/blockquote>
&lt;p>不过在我眼中，&lt;br>
他是我认识的寥寥几个&lt;a href="https://coolshell.cn/articles/17446.html">做编程技术十多年&lt;/a>的人，&lt;br>
即使现在可能充当了CTO的角色，&lt;br>
但依然&lt;del>在写代码&lt;/del>奋战在技术一线。&lt;/p>
&lt;p>他的很多文章传播的比他的名字要广，&lt;br>
（换种说法就是被各大编程营销号转载过）&lt;br>
比如&lt;a href="https://coolshell.cn/articles/4990.html">《程序员练级攻略》&lt;/a>，&lt;br>
比如&lt;a href="https://coolshell.cn/articles/9308.html">《“做环保的程序员，从不用百度开始”》&lt;/a>，&lt;br>
耗子叔也会用很地道的语言汉化一些有趣的文章，&lt;br>
比如&lt;a href="https://coolshell.cn/articles/4758.html">《如何写出无法维护的代码》&lt;/a>&lt;/p>
&lt;p>这些文章里总有一种很好闻的程序的味道，&lt;br>
我很喜欢。&lt;br>
能从这里那里学到一些&lt;a href="https://coolshell.cn/articles/17497.html">一线工程师的很酷的想法&lt;/a>，&lt;br>
也算是每天进步一点点了。&lt;/p>
&lt;h2 id="曹政caozcaoz">&lt;a href="https://www.zhihu.com/people/cao-zheng/activities">曹政，caoz&lt;/a>&lt;/h2>
&lt;p>前阵子跟&lt;a href="https://www.zhihu.com/people/jia-jia-15-81">张总&lt;/a>坐地铁聊天的时候，&lt;br>
我问他除了&lt;a href="https://blog.xiqiao.info/">西乔&lt;/a>&lt;a href="https://blog.devep.net/virushuo/">霍炬&lt;/a>，&lt;br>
还有啥很棒的公众号，求推荐一下。&lt;/p>
&lt;p>他先是翻出了&lt;a href="https://weixin.sogou.com/weixin?type=1&amp;amp;query=mactalkpro">MacTalk&lt;/a>, &lt;a href="https://weixin.sogou.com/weixin?type=1&amp;amp;query=tiny4voice">TinyFool&lt;/a>, &lt;a href="https://weixin.sogou.com/weixin?type=1&amp;amp;query=angelatalk">嘀嗒嘀嗒&lt;/a>等&lt;br>
商业互吹（此处褒义）的公众号小圈子推荐给我，&lt;br>
然后我们向往了一下这种大佬都是互相认识的氛围。&lt;br>
我又给他推荐了好像&lt;a href="https://weixin.sogou.com/weixin?type=1&amp;amp;query=kesoview">跟雷军、张小龙都很熟的keso&lt;/a>。&lt;br>
最后他把珍藏多年的&lt;a href="https://www.zhihu.com/people/cao-zheng/activities">曹政（下称caoz）&lt;/a>的公众号介绍了给我&lt;a href="https://weixin.sogou.com/weixin?type=1&amp;amp;query=caozsay">（公众号：caoz的梦呓）&lt;/a>，&lt;br>
张总介绍说&lt;a href="https://www.zhihu.com/question/19596615/answer/14322195">他是4399的技术大牛&lt;/a>，&lt;br>
大家都叫他曹总什么什么的。&lt;br>
当时我心里就简单地把&lt;a href="https://www.zhihu.com/people/cao-zheng/activities">caoz&lt;/a>跟&lt;a href="https://www.zhihu.com/people/fenng/activities">Fenng&lt;/a>打上了一样的标签。&lt;/p>
&lt;p>不过后来他发的好多篇公众号文章给我看改观了：&lt;br>
我发现caoz这个人，有意思。&lt;br>
比如他跟keso都会发文章搞事，&lt;br>
但他们不太一样。&lt;br>
keso喜欢怼大势，&lt;br>
就是xxx改变世界，&lt;br>
xxx不是好的方向，&lt;br>
格局很大，气势很足。&lt;br>
caoz喜欢怼具体的事情，&lt;br>
比如割韭菜 + 无数的举例，&lt;br>
而且也会表露出对具体的人的厌恶。&lt;/p>
&lt;p>caoz这样更容易招黑，&lt;br>
&lt;del>粉丝也不容易涨&lt;/del>&lt;br>
不过他也不care,&lt;br>
想说什么照样说，&lt;br>
而且还会故意说些“洗粉”的真话，&lt;br>
很是肆意。&lt;/p>
&lt;p>排除一些我并不赞同的道理，&lt;br>
caoz讲的很多道理都句句到点，&lt;br>
有实际事情支持，&lt;br>
的确能学到不少。&lt;/p>
&lt;p>&lt;em>//此处都是主观感受，缺少引用，因为找不到怎么生成微信文章的永久链接…&lt;/em>&lt;/p>
&lt;h2 id="王垠yin完全用linux工作work-with-linux的作者">&lt;a href="https://www.yinwang.org/">王垠&lt;/a>，&lt;a href="https://www.douban.com/group/topic/12121637/">《完全用Linux工作》&lt;/a>的作者&lt;/h2>
&lt;p>王垠（下称垠神），博客是 &lt;a href="https://www.yinwang.org/">当然我在扯淡 (https://www.yinwang.org/)&lt;/a>&lt;br>
早年间一篇&lt;a href="https://www.douban.com/group/topic/12121637/">《完全用Linux工作》&lt;/a>收获了很多迷弟，&lt;br>
后来的好几篇文章，比如&lt;a href="https://www.yinwang.org/blog-cn/2017/05/10/microsoft-separation">《微软的秘密离职协议》&lt;/a>也收获了很多黑子。&lt;br>
在我心目中，垠神是知乎三大话题性程序员之一&lt;br>
（还有一个是&lt;a href="https://zhuanlan.zhihu.com/p/25031872">曾博（现已永久退出知乎）&lt;/a>）&lt;/p>
&lt;p>撇去别的，&lt;a href="https://www.zhihu.com/question/20102511">垠神的本身经历使得他这个人充满了话题性&lt;/a>。&lt;br>
首先是敢于表达刺耳的个人想法（并且多年没变），&lt;br>
光这一点并不是垠神过人之处，&lt;br>
垠神还会辩证地思考问题，&lt;br>
敢于在公众前表达对事物两面性的思考。&lt;br>
比如他最开始被大众所知是因为&lt;a href="https://www.douban.com/group/topic/12121637/">《完全用Linux工作》&lt;/a>一文，&lt;br>
但是多年以后他又发了&lt;a href="https://www.douban.com/group/topic/44818003/">《谈Linux，Windows和Mac》&lt;/a>一文。&lt;br>
又比如他最开始&lt;a href="https://www.zhihu.com/question/50128385">加入了微软&lt;/a>，&lt;br>
然后又&lt;a href="https://www.yinwang.org/blog-cn/2017/04/11/strike">一个人地罢工&lt;/a>（这样的事情的确不少）&lt;/p>
&lt;p>大部分人眼中，垠神没有自己的作品，而且反复无常。&lt;br>
但其实垠神的文章，&lt;br>
把他对别人的意见那部分排除掉，&lt;br>
他对技术的理解、思考~~、运用~~其实是超越了大部分人的（比如我）。&lt;br>
比如他&lt;a href="https://www.yinwang.org/blog-cn/2017/05/23/kotlin">对 Kotlin - Checked Exception 的思考&lt;/a>，&lt;br>
讲到程序设计和程序员能力的关系那部分，&lt;br>
非常有启发性。&lt;/p>
&lt;p>而且很多时候，垠神的观点真的是振聋发聩，比如：&lt;/p>
&lt;blockquote>
&lt;p>&lt;a href="https://www.douban.com/group/topic/44818003/">每次仇恨一个东西，你就失去了向它学习的机会。&lt;/a>&lt;/p>
&lt;/blockquote>
&lt;p>以至于我司工作日的时候，&lt;br>
只要谁发现了垠神又发文章了，&lt;br>
他就会高呼：“垠神又发文章了！好特么勤快！链接我发群里了！”&lt;br>
然后大家纷纷一起学习。&lt;/p>
&lt;p>&lt;em>其实我还蛮想把垠神跟凤姐放在一起类比的，&lt;/em>&lt;br>
&lt;em>但是想想，知道凤姐但理解凤姐的人太少了。&lt;/em>&lt;br>
&lt;em>这样容易引起误会，这一段就剪掉吧。&lt;/em>&lt;/p>
&lt;h2 id="冰封ice1000ice1000github-ice1000-喜欢程序语言的高中生">&lt;a href="https://www.zhihu.com/people/ice1000/activities">冰封&lt;/a>，&lt;a href="https://github.com/ice1000">ice1000&lt;/a>, 喜欢程序语言的高中生&lt;/h2>
&lt;p>我最开始是在知乎的女装话题下刷到&lt;a href="https://www.zhihu.com/people/ice1000/activities">冰封&lt;/a>（下称ice1000）的动态的，&lt;br>
看了一圈发现这好像是个程序员友军，&lt;br>
又看了一下，发现是个&lt;a href="https://www.zhihu.com/question/64427785">高中生大佬&lt;/a>。&lt;/p>
&lt;p>跟上文讲到的几个大佬不一样，&lt;br>
ice1000 的影响力可能主要停留在知乎，&lt;br>
但 ice1000 的未来是无穷的。&lt;br>
虽说人人平等，但有的人更加平等，&lt;br>
&lt;a href="https://www.zhihu.com/question/63691021">很多道理早知道和晚知道是不一样的&lt;/a>。&lt;/p>
&lt;p>ice1000 能在高中的时候，&lt;br>
&lt;a href="https://www.zhihu.com/question/57850781">确定了自己的兴趣&lt;/a>，并且打算为止奋斗一生，&lt;br>
比起我这种大学读完四年，&lt;br>
才&lt;a href="https://liriansu.com/my-programmer-habits">确定我真的是喜欢代码的人&lt;/a>肯定要强许多。&lt;br>
（更别提他 GitHub 的 activity 也是吊打我了）&lt;/p>
&lt;p>祝 ice1000 能找到自己的道路，&lt;br>
认准它，顺利地走下去。&lt;/p>
&lt;h2 id="笛子ocarina你什么都没看见uc-nothing小绿与小蓝green-blue-life系列作者">&lt;a href="https://weibo.com/echohall?profile_ftype=1&amp;amp;is_all=1">笛子&lt;/a>，&lt;a href="https://www.u17.com/comic/16179.html">《你什么都没看见》&lt;/a>&lt;a href="https://ac.qq.com/Comic/comicInfo/id/536332">《小绿与小蓝》&lt;/a>系列作者&lt;/h2>
&lt;p>&lt;a href="https://weibo.com/echohall?profile_ftype=1&amp;amp;is_all=1">笛子Ocarina（下称笛子）&lt;/a>，&lt;br>
是跟&lt;a href="https://weibo.com/u/6365729214">孙渣&lt;/a>，&lt;a href="https://weibo.com/A4TYPHOON">鱼总&lt;/a>等画师一个圈内的画手。&lt;/p>
&lt;p>看她的&lt;a href="https://www.u17.com/comic/16179.html">《你什么都没看见》&lt;/a>，&lt;br>
我总感觉跟&lt;a href="https://en.wikipedia.org/wiki/Franken_Fran">《疯狂怪医芙兰》&lt;/a>有异曲同工之妙&lt;br>
（虽然画风非常不一样）&lt;br>
还有&lt;a href="https://ac.qq.com/Comic/comicInfo/id/536332">《小绿与小蓝》&lt;/a>系列，&lt;br>
很多地方跟&lt;a href="https://xkcd.com/"> xkcd 系列漫画&lt;/a>也有异曲同工之妙，&lt;br>
或者说跟&lt;a href="https://blog.xiqiao.info/">西乔的神秘的程序员系列漫画&lt;/a>有异曲同工之妙。&lt;/p>
&lt;p>虽然有&lt;a href="https://zh.moegirl.org/zh-hans/Ocarina">“笛子，强，不上色”的梗&lt;/a>，&lt;br>
但其实可以看出笛子就是一个很喜欢画漫画的人，&lt;br>
而且很幸运地，她的事业也是画漫画。&lt;br>
这个特性跟“奇思妙想”这个特性就产生了 1+1&amp;raquo;2 的特性了。&lt;/p>
&lt;p>最开始的&lt;a href="https://ac.qq.com/Comic/comicInfo/id/536332">《小绿和小蓝》&lt;/a>就是笛子表达一些小思考的所在，&lt;br>
&lt;del>明明是笛子缺刀片了&lt;/del>&lt;br>
里面的很多梗跟 &lt;a href="https://xkcd.com/">xkcd&lt;/a> 一样，&lt;br>
都是荒诞但有趣的：&lt;br>
比如&lt;a href="https://ac.qq.com/ComicView/index/id/536332/cid/95">“走钢丝时一边后空翻一边双手分别转5x5魔方同时倒背国家民法”的这种梗&lt;/a>，&lt;br>
就跟“三人行，必有我师焉”是一样的道理呀。&lt;/p>
&lt;p>最后，因为篇幅原因，很多大佬就不写上去了。&lt;br>
（我有一堆仰慕的大佬，但是这里的空间写不下了）&lt;/p>
&lt;p>还有一些大佬，自身的姿势水平非常高，&lt;br>
但是因为比较少时间输出观点/价值观/干货/技术内容，&lt;br>
所以很容易被人民群众（比如我）忽略掉，&lt;br>
在此道个歉。&lt;/p>
&lt;p>不论如何，&lt;br>
最后引用笛子的一篇感慨作为结束吧：&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/cest_tama_la_vie.jpg" alt="cest-tama-la-vie">&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/cest_tama_la_vie_translate.jpg" alt="cest-tama-la-vie-translate">&lt;/p></description></item><item><title>什么是连字 (ligature)</title><link>https://liriansu.com/posts/2017-09-13-what-is-ligature/</link><pubDate>Wed, 13 Sep 2017 22:45:39 +0000</pubDate><guid>https://liriansu.com/posts/2017-09-13-what-is-ligature/</guid><description>&lt;p>或者叫“为什么PDF里拷出来的有些字会消失”，&lt;br>
“为什么有些字体里fi可以连在一起”，&lt;br>
“Fira Code是怎么做到连体符号的”&lt;/p>
&lt;h2 id="ligature">ligature&lt;/h2>
&lt;p>ligature，维基百科中文页是叫“合字”，其实概念意义上更接近“连字”。&lt;br>
正如字面意义上，连字就是连在一起的字，比如中文的连字是这样的：&lt;/p>
&lt;blockquote>
&lt;p>俗话说，见字如见人。&lt;/p>
&lt;p>有的专家根据特总的签名，&lt;br>
分析说他的狂放就如同他那一横一样不羁……&lt;/p>
&lt;/blockquote>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/trump_chinese_ligature.jpg" alt="trump-chinese-ligature">&lt;/p>
&lt;p>在拉丁语系中，很多时候会用到连字这一特性。&lt;br>
&lt;a href="https://en.wikipedia.org/wiki/Typographic_ligature">比如说德语的字母 &lt;code>ß&lt;/code> 最开始其实是 &lt;code>ss&lt;/code>&lt;/a>，&lt;br>
&lt;a href="https://en.wikipedia.org/wiki/Typographic_ligature">拉丁字母中的 &lt;code>W&lt;/code> 最开始的时候是 &lt;code>VV&lt;/code>, 两个 &lt;code>V&lt;/code>&amp;hellip;&lt;/a>，&lt;br>
非常神奇。&lt;br>
而我们熟悉的音标里的 &lt;code>æ&lt;/code> 这个字母，&lt;br>
看起来很像连字，但其实不是连字，&lt;br>
&lt;code>æ&lt;/code> 是古英语等一系列语系里真实用到的字母。&lt;/p>
&lt;h2 id="fi与印刷体">fi与印刷体&lt;/h2>
&lt;p>在活字印刷盛行的时候，&lt;br>
人们都是用字模来印文章的。&lt;br>
一篇文章，&lt;br>
假如要用不同的字体，&lt;br>
那就要选用对应的不同的字模。&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/fi.png" alt="fi">&lt;/p>
&lt;p>有些字体里面当 字母&lt;code>f&lt;/code> 和 字母&lt;code>i&lt;/code> 连在一起的时候，&lt;br>
&lt;code>f&lt;/code> 的一横会跟 &lt;code>i&lt;/code> 的一点撞上，导致不好排版。&lt;br>
所以为了方便、美观，有些字体直接会有 &lt;code>fi&lt;/code> 连字的字模。&lt;br>
这里不论是印刷字体的连字，还是上面手写字体的连字，&lt;br>
都是一样的概念，都叫 &lt;code>ligature&lt;/code>。&lt;/p>
&lt;h2 id="电脑字体里的-ligature">电脑字体里的 ligature&lt;/h2>
&lt;p>虽然说电脑字体不会有印刷字体所有的物理限制，&lt;br>
但有些字体的 &lt;code>fi&lt;/code> 还依然保留了 &lt;code>ligature&lt;/code> 的这一特性。&lt;br>
假如你在你的电脑字体配置页面找一找，&lt;br>
是可以找到相关的属性的。&lt;/p>
&lt;p>基于电脑也能支持连字这个设定，&lt;br>
于是聪明的人就想到了可以用它来搞事！&lt;br>
比如有一款字体叫 &lt;a href="https://github.com/tonsky/FiraCode">Fira Code&lt;/a>。&lt;/p>
&lt;p>&lt;a href="https://github.com/tonsky/FiraCode">Fira Code&lt;/a> 宣称自己是最适合程序员的编程语言，&lt;br>
因为它对各种数学符号都极度友好（细节请点开下图）&lt;/p>
&lt;p>&lt;img src="https://raw.githubusercontent.com/tonsky/FiraCode/master/showcases/all_ligatures.png" alt="fira-code-demo">&lt;/p>
&lt;p>当然前提是编辑器也要能支持 ligature,&lt;br>
比如像 JetBrains系IDE:&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/jetbrains_ligature.png" alt="jetbrains-ligature">&lt;/p>
&lt;p>果然正如古代智慧说的一样：&lt;/p>
&lt;blockquote>
&lt;p>苟日新，日日新，又日新&lt;/p>
&lt;/blockquote>
&lt;p>还是要多学习一个呀。&lt;/p></description></item><item><title>数据仓库解决方案 RedShift 入坑指南</title><link>https://liriansu.com/posts/2017-09-08-redshift-as-data-warehouse/</link><pubDate>Fri, 08 Sep 2017 22:59:08 +0000</pubDate><guid>https://liriansu.com/posts/2017-09-08-redshift-as-data-warehouse/</guid><description>&lt;p>最近工程师小谢遇到了一个难题，&lt;br>
就是手头上有千万级别的数据，&lt;br>
但是没有一个快糙猛的解决方案。&lt;/p>
&lt;h2 id="提出问题">提出问题&lt;/h2>
&lt;blockquote>
&lt;p>想直接看 RedShift 相关的，&lt;br>
请跳过前两节瞎扯淡。&lt;br>
直接到第三节观看。&lt;/p>
&lt;/blockquote>
&lt;p>不像少部分优秀的可以活在彼岸的人，&lt;br>
可以醉心于写出完美的数据库，&lt;br>
在须臾间学会所有的程序语言；&lt;br>
世上大部分程序员都活在此岸，&lt;br>
他们要解决一个个特定的业务问题。&lt;/p>
&lt;p>工程师小谢就很烦恼，&lt;br>
&lt;a href="https://liriansu.com/what-is-cash-cow"> 上次产品经理小刘提了个老酷炫的IDEA： &lt;/a>&lt;br>
“现金牛”。&lt;br>
观众们很过瘾，&lt;br>
但作为要实现功能的人，&lt;br>
小谢有点郁闷。&lt;/p>
&lt;p>具体来说，难点在下面几个：&lt;/p>
&lt;ol>
&lt;li>
&lt;p>数据量很大。&lt;br>
公司是做菜品相关的，每天记录的菜品数据非常多。&lt;br>
而且随着公司业务发展，菜品增速增长率也很高。&lt;br>
（也就是“指数级上升”）&lt;/p>
&lt;/li>
&lt;li>
&lt;p>时间比较紧。&lt;br>
不像学校里的大作业，可以有一整个学期来实现到交付。&lt;br>
真正的需求是事情要尽可能早的完成，即使一开始不一定是完美的，&lt;br>
但是会更早得到外部反馈，正面/负面的评价有助于大家调整前进方向。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>质量有要求。&lt;br>
基于“现金牛”的这个需求交付完成以后，又会有新的需求降临到小谢的肩上。&lt;br>
所以这个此时的解决方案，也要解决彼时的问题。&lt;br>
随着业务/数据量的增大，短时间内（比如说一年），解决方案得稳定靠谱。&lt;br>
长时间内（比如说三年），解决方案要能拓展，至少是便于重构的。&lt;/p>
&lt;/li>
&lt;/ol>
&lt;h2 id="解决方案">解决方案&lt;/h2>
&lt;p>上面的几个现世问题，&lt;br>
其实跟万千现世问题一样，&lt;br>
都是一个问题：&lt;code>如何在有限的资源下，完成既定的目标？&lt;/code>&lt;br>
解决方案也都是通用的：&lt;code>转换资源、付出时间、更换目标&lt;/code>。&lt;/p>
&lt;p>当然，小谢明白，脱离实际例子的方法论都没有意义。&lt;br>
所以小谢打算整一个数据仓库 (Data Warehouse)&lt;/p>
&lt;p>数据仓库，跟数据库 (DataBase) 很像，&lt;br>
就像军械库是放军械的地方，&lt;br>
车库是放车的地方，&lt;br>
数据仓库/数据库就是放数据的地方。&lt;br>
&lt;del>多了个仓是因为还放仓鼠&lt;/del>&lt;/p>
&lt;p>二者不同之处详细来说，&lt;br>
就是因为要解决的问题不一样：&lt;br>
数据库是要给业务提供基础保证，&lt;br>
数据仓库则是给面向决策的数据分析提供便利；&lt;br>
所以二者的设计思想也不一样：&lt;br>
数据库遵守范式设计，强调数据约束、一致性，读写操作都有涉及，&lt;br>
数据仓库则是存储大量冗余数据、统计数据，对读的优化更多。&lt;/p>
&lt;p>&lt;strong>举个栗子&lt;/strong>就是今天中午小谢去吃了四斤烤鱼（真能吃），&lt;br>
“四斤烤鱼”的数据存在了数据库里，是用来买单算钱的。&lt;br>
但“今天中午，四斤，烤鱼”这样的统计数据就存在了数据仓库里，&lt;br>
以用来之后的统计分析。&lt;/p>
&lt;p>业界很多的数据仓库都是基于 &lt;code>Hadoop/Spark/Storm&lt;/code> 的一套 &lt;code>Java&lt;/code> 系技术栈的。&lt;br>
比如拼多多，用的就是 &lt;code>Hadoop/Hive/HBase/Kafka&lt;/code> 一套技术栈。&lt;br>
比如小红书，用的也是 &lt;code>Hadoop/Hive/Spark/Kafka&lt;/code> 一套技术栈。&lt;/p>
&lt;p>但是问题来了：&lt;br>
这些小谢都不懂啊，很尴尬。&lt;br>
不过还好，小谢有钱，&lt;br>
他可以去招几个懂的。&lt;br>
很可惜，招聘是个玄学问题，&lt;br>
他看上的看不上他，&lt;br>
看上他的他看不上。&lt;/p>
&lt;p>于是小谢想来想去，&lt;br>
也只能自己动手，&lt;br>
最终选择了：&lt;/p>
&lt;h2 id="redshift-亚马逊云服务全家桶-之-数据仓库-管理助手">RedShift, 亚马逊云服务全家桶 之 数据仓库 管理助手&lt;/h2>
&lt;h3 id="特点">特点&lt;/h3>
&lt;p>作为一种数据仓库的解决方案，&lt;br>
RedShift 有几个特点：&lt;/p>
&lt;ul>
&lt;li>
&lt;p>省事，假如你也用了 AWS 的其它服务。&lt;br>
自带监控，需要定制化的话还可以跟 AWS CloudWatch 结合；&lt;br>
往里面插入数据推荐用的 &lt;code>COPY&lt;/code> 命令是和 AWS S3 联动的；&lt;br>
高可用、拓展性、备份等都是 AWS 保证的。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>提供全套 &lt;code>PostgreSQL&lt;/code> 语法。&lt;br>
基本上兼容 &lt;code>PostgreSQL&lt;/code> 的地方，换一下 &lt;code>DBDriver&lt;/code> 就可以无痛使用了。&lt;br>
但是 RedShift 也只提供了一套 &lt;code>SQL&lt;/code> 的标准，&lt;br>
假如要做 &lt;code>SQL&lt;/code> 之外的（比如文件）数据存放，&lt;br>
就很吃力了。&lt;del>by design. wontfix&lt;/del>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>贵，相对而言。&lt;br>
定价大概最便宜的实例类型 (dc1.large, 15GB Mem, 0.16TB SSD) 是一年一万多人民币，&lt;br>
不算人力价格的话，比自建数据仓库肯定要贵。&lt;br>
不过算上人力价格的话……就另说了。&lt;/p>
&lt;/li>
&lt;/ul>
&lt;h3 id="部署">部署&lt;/h3>
&lt;p>部署使用 RedShift 的主要步骤如下：&lt;/p>
&lt;ol>
&lt;li>
&lt;p>先别急着创建实例，先按照 AWS 的教程走一遍，&lt;br>
会对 COPY/Encoding/Cluster 有初步了解。&lt;br>
&lt;del>不喜欢读英文文档的同学，可以右上角切换成中文&lt;/del>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>创建合适的 AWS RedShift 实例。&lt;br>
恭喜你完成了_从无到有搭建数据仓库_这个成就。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>对接业务，比如选择合适的 Driver。&lt;br>
我们用的是 django, 直接用 &lt;code>psycopg2&lt;/code> 就可以连接了。&lt;br>
然后就是ETL、缓存、图表等通用的业务操作了。&lt;/p>
&lt;/li>
&lt;/ol>
&lt;h3 id="心得">心得&lt;/h3>
&lt;p>用了 RedShift 一阵子，&lt;br>
有几点学到的地方：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>SQL 语句不是直接执行，而是编译后分发执行&lt;/strong>。&lt;/li>
&lt;/ul>
&lt;p>不论我们执行任何语句，即使是 &lt;code>INSERT INTO&lt;/code> 这种单条操作，&lt;br>
RedShift 都要编译后执行，耗时 500ms 起步_所以要用COPY来做数据导入_。&lt;br>
又比如我们部署了四个 RedShift 节点，那在&lt;br>
&lt;code>SELECT * FROM orders WHERE business_id = 100&lt;/code> 编译完成以后，&lt;br>
RedShift 会把操作根据建表时选定的分区键 &lt;code>DISTKEY&lt;/code> 把命令分发到各个节点操作。&lt;br>
所以合理的表结构也是查询速度的关键_通用的&lt;del>废话&lt;/del>真理_。&lt;/p>
&lt;ul>
&lt;li>&lt;strong>插入数据用 COPY 命令；更新数据 COPY 到临时表以后，用 DELETE USING + INSERT INTO 来更新数据&lt;/strong>&lt;/li>
&lt;/ul>
&lt;p>因为每条 SQL 都要编译，所以尽量做批量操作，单条操作是非常愚蠢的。&lt;br>
（就像我们最开始那么愚蠢一样=_=）&lt;br>
RedShift COPY 命令支持 GZIP, JSON, From S3 等多种操作，&lt;br>
大部分情况下，加载速度和存储效率都会比普通的 INSERT 要好。&lt;br>
同理，更新单条数据采用了先删再增的方式。&lt;/p>
&lt;ul>
&lt;li>&lt;strong>定时维护数据仓库&lt;/strong>&lt;/li>
&lt;/ul>
&lt;p>RedShift 不会自动回收 DELETE/UPDATE 所释放的空间，&lt;br>
需要用户手动运行 &lt;code>VACUUM&lt;/code> 命令来清理表。&lt;br>
&lt;code>VACUUM&lt;/code> 本身也是IO密集型操作，&lt;br>
所以最好是在空闲的时间（比如早上四点）定时跑。&lt;/p>
&lt;ul>
&lt;li>&lt;strong>注意表的限制&lt;/strong>&lt;/li>
&lt;/ul>
&lt;p>在 RedShift 里，&lt;br>
&lt;code>unique / primary key / foreign key&lt;/code>都是展示信息，&lt;br>
没有实质约束力。&lt;/p>
&lt;p>还有 RedShift.varchar 存储的是单字节字符，&lt;br>
像 MySQL 的 &lt;code>utf8&lt;/code> 默认是三字节字符，&lt;br>
假如用了 &lt;code>utf8mb4&lt;/code> 就是四字节字符。&lt;br>
所以 MySQL 里的 varchar(50) 换算到 RedShift 里就应该是 varchar(200)。&lt;br>
&lt;em>被Emoji坑了的人留&lt;/em>&lt;/p>
&lt;h2 id="总结">总结&lt;/h2>
&lt;p>总的来说，&lt;br>
RedShift 的最大的好处在于用钱换取生产力，&lt;br>
简单易用，是 AWS 全家桶用户对数据仓库的一种解决方案。&lt;br>
具体用法多加注意，也没有什么特别之处。&lt;/p>
&lt;p>不过最近好像是给亚马逊交了不少钱，&lt;br>
他们都派工程师上门免费 support 了。&lt;/p>
&lt;p>小谢心想。&lt;/p>
&lt;h2 id="课外阅读">课外阅读&lt;/h2>
&lt;ul>
&lt;li>
&lt;p>&lt;a href="https://docs.aws.amazon.com/zh_cn/redshift/latest/dg/tutorial-tuning-tables.html">AWS - RedShift 官方教程 - https://docs.aws.amazon.com/zh_cn/redshift/latest/dg/tutorial-tuning-tables.html&lt;/a>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;a href="https://coolshell.cn/articles/6470.html">酷壳 - 由12306.CN谈谈网站性能技术 - https://coolshell.cn/articles/6470.html&lt;/a>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;a href="https://en.wikipedia.org/wiki/Data_warehouse">维基百科 - 数据仓库 - https://en.wikipedia.org/wiki/Data_warehouse&lt;/a>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;a href="https://my.oschina.net/xsh1208/blog/1052781">全面了解mysql中utf8和utf8mb4的区别 - https://my.oschina.net/xsh1208/blog/1052781&lt;/a>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;a href="https://blog.xiqiao.info/2013/01/14/1366">西乔 - 历史悲剧 - https://blog.xiqiao.info/2013/01/14/1366&lt;/a>&lt;/p>
&lt;/li>
&lt;/ul></description></item><item><title>写代码怎么偷懒？多练练</title><link>https://liriansu.com/posts/2017-08-31-lazy-coding-practice/</link><pubDate>Thu, 31 Aug 2017 20:25:12 +0000</pubDate><guid>https://liriansu.com/posts/2017-08-31-lazy-coding-practice/</guid><description>&lt;p>相比于“一门语言”，&lt;br>
“一门程序语言”更多时候是“一门规范”。&lt;br>
（当然，“语言”本身就是“规范”。）&lt;/p>
&lt;p>&lt;img src="https://imgs.xkcd.com/comics/standards.png" alt="standards">&lt;/p>
&lt;p>&lt;a href="https://liriansu.com/lazy-coding-thinking">上次讲到了写代码想偷懒的话&lt;/a>，&lt;br>
&lt;strong>搞明白、想清楚再写&lt;/strong>是解决根源的一个办法。&lt;br>
但是凡人（没打错字）的需求始终不是重点，&lt;br>
写程序要偷懒，&lt;br>
最终还是在代码上偷懒的。&lt;/p>
&lt;h2 id="best-practice">Best Practice&lt;/h2>
&lt;p>外国程序员很喜欢念叨一个词，&lt;br>
叫&lt;code>Best Practice&lt;/code>。&lt;br>
比如说&lt;code>Java&lt;/code>里面&lt;code>JSON&lt;/code>要怎么处理，&lt;br>
就可以搜&lt;code>Java JSON Best Practice&lt;/code>；&lt;br>
比如我对数据库一窍不通，&lt;br>
但我就是要学，&lt;br>
可以搜&lt;code>Database Best Practice&lt;/code>；&lt;br>
比如我是甲方，&lt;br>
我不知道我自己想要什么，&lt;br>
我也可以搜&lt;code>Requirements Best Practice&lt;/code>。&lt;/p>
&lt;p>这种英文单词一般会有一个直译的中文，&lt;br>
叫&lt;code>最佳实践&lt;/code>，&lt;br>
听起来巨蠢。&lt;br>
但是用来举例子就很好用。&lt;/p>
&lt;p>我加入&lt;a href="https://liriansu.com/my-work">再惠&lt;/a>的时候，&lt;br>
只写过一点&lt;code>Python&lt;/code>，&lt;br>
代码习惯也是不加&lt;code>encoding&lt;/code>，&lt;br>
不知道&lt;code>from __future__&lt;/code>，&lt;br>
写&lt;code>print&lt;/code>不写括号的，&lt;br>
所有要用到的第三方库都装在全局的&lt;code>site-packages&lt;/code>下面。&lt;br>
来了以后&lt;a href="https://docs.python-guide.org/en/latest/dev/virtualenvs/">我知道了&lt;code>virtualenv&lt;/code>&lt;/a>。&lt;br>
后来张总玩&lt;code>Lucene&lt;/code>的时候我给他配了下&lt;code>Gradle&lt;/code>，&lt;br>
并解释了一下：“这个东西很简单的，跟&lt;code>virtualenv&lt;/code>是类似的概念。”&lt;br>
张总感慨道：&lt;br>
“其实学一门语言就是从这些工具开始啊，&lt;br>
这样才有一种我上手了的感觉啊！”&lt;/p>
&lt;p>还有就像&lt;a href="https://blog.golang.org/go-fmt-your-code">&lt;code>Go&lt;/code>语言的&lt;code>gofmt&lt;/code>命令&lt;/a>，&lt;br>
这个命令会强制执行统一的代码风格调整，&lt;br>
不能配置、不能定制化、缩进统一使用Tab。&lt;br>
我十分痛苦，&lt;br>
不过也十分认可这里的思想：&lt;br>
“语言风格就是&lt;del>林黛玉&lt;/del>哈姆雷特，千人千面。&lt;br>
相比于完美的风格，统一的风格更科学。”&lt;/p>
&lt;p>&lt;code>Best Practice&lt;/code>就是实际操作时的指南，&lt;br>
了解、掌握、实践&lt;code>Best Practice&lt;/code>可以&lt;del>少些很多代码&lt;/del>少走很多弯路，&lt;br>
用精妙的方法解决实际问题。&lt;/p>
&lt;h2 id="精妙的方法">精妙的方法&lt;/h2>
&lt;p>按照套路，接下来应该讲一段精妙的方法。&lt;br>
不过小弟我没啥精妙的方法，&lt;br>
就只能举自身当反例了。&lt;/p>
&lt;p>在写&lt;code>API&lt;/code>的时候，&lt;br>
经常要处理&lt;code>URL&lt;/code>，&lt;br>
处理&lt;code>URL&lt;/code>实际上是字符串拼接。&lt;br>
比如&lt;code>Python&lt;/code>里面把一个&lt;code>dict&lt;/code>转换成&lt;code>query string&lt;/code>格式，&lt;br>
我以前会这么写：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python3" data-lang="python3">&lt;span style="display:flex;">&lt;span>params &lt;span style="color:#f92672">=&lt;/span> {&lt;span style="color:#e6db74">&amp;#39;name&amp;#39;&lt;/span>: &lt;span style="color:#e6db74">&amp;#39;afu&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;action&amp;#39;&lt;/span>: &lt;span style="color:#e6db74">&amp;#39;take a plane&amp;#39;&lt;/span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>query_string &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#39;&amp;amp;&amp;#39;&lt;/span>&lt;span style="color:#f92672">.&lt;/span>join([&lt;span style="color:#e6db74">&amp;#39;&lt;/span>&lt;span style="color:#e6db74">{}&lt;/span>&lt;span style="color:#e6db74">=&lt;/span>&lt;span style="color:#e6db74">{}&lt;/span>&lt;span style="color:#e6db74">&amp;#39;&lt;/span>&lt;span style="color:#f92672">.&lt;/span>format(k, v) &lt;span style="color:#66d9ef">for&lt;/span> k, v &lt;span style="color:#f92672">in&lt;/span> params&lt;span style="color:#f92672">.&lt;/span>items()]) &lt;span style="color:#75715e"># &amp;#39;name=afu&amp;amp;action=take a plane&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>当时自我感觉良好，&lt;br>
觉得&lt;code>Python&lt;/code>不愧是&lt;code>Python&lt;/code>啊，&lt;br>
&lt;code>List Comprehension&lt;/code>真优雅，真好看。&lt;br>
然而这段代码不仅有Bug，&lt;br>
其实&lt;code>Python&lt;/code>有专门的库&lt;code>urllib&lt;/code>来处理这类问题，&lt;br>
&lt;code>urllib&lt;/code>也已经考虑了各种边界情况（比如带非法字符等）：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python3" data-lang="python3">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 举Python3为例&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">import&lt;/span> urllib
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>params &lt;span style="color:#f92672">=&lt;/span> {&lt;span style="color:#e6db74">&amp;#39;name&amp;#39;&lt;/span>: &lt;span style="color:#e6db74">&amp;#39;afu&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;action&amp;#39;&lt;/span>: &lt;span style="color:#e6db74">&amp;#39;take a plane&amp;#39;&lt;/span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>query_string &lt;span style="color:#f92672">=&lt;/span> urllib&lt;span style="color:#f92672">.&lt;/span>parse&lt;span style="color:#f92672">.&lt;/span>urlencode(params) &lt;span style="color:#75715e"># &amp;#39;name=afu&amp;amp;action=take+a+plane&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>后来又学到了&lt;code>urlencode&lt;/code>函数在&lt;code>Python2&lt;/code>和&lt;code>Python3&lt;/code>的位置都不一样，&lt;br>
一般是用&lt;a href="https://pythonhosted.org/six/">&lt;code>six&lt;/code>&lt;/a>这个库去处理兼容性的。&lt;br>
下面这段代码就不需要额外说明_举Python3为例_了：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">import&lt;/span> six
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>params &lt;span style="color:#f92672">=&lt;/span> {&lt;span style="color:#e6db74">&amp;#39;name&amp;#39;&lt;/span>: &lt;span style="color:#e6db74">&amp;#39;afu&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;action&amp;#39;&lt;/span>: &lt;span style="color:#e6db74">&amp;#39;take a plane&amp;#39;&lt;/span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>query_string &lt;span style="color:#f92672">=&lt;/span> six&lt;span style="color:#f92672">.&lt;/span>moves&lt;span style="color:#f92672">.&lt;/span>urllib&lt;span style="color:#f92672">.&lt;/span>parse&lt;span style="color:#f92672">.&lt;/span>urlencode(params) &lt;span style="color:#75715e"># &amp;#39;name=afu&amp;amp;action=take+a+plane&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>虽然有很多种方法都能达到同样的效果，&lt;br>
但软件工程中，&lt;br>
大家往往都定下一个&lt;code>Best Practice&lt;/code>然后遵守它。&lt;br>
这样不仅能省下写程序的功夫，&lt;br>
也能省下沟通争辩的功夫。&lt;br>
就像&lt;a href="https://www.python.org/dev/peps/pep-0020/">&lt;code>Zen of Python&lt;/code>&lt;/a>里说的一样：&lt;br>
&lt;code>There should be one-- and preferably only one --obvious way to do it.&lt;/code>&lt;/p>
&lt;p>之前我一直很好奇大部分人在用&lt;code>Python&lt;/code>写&lt;code>datetime&lt;/code>类型的时候，&lt;br>
都是用&lt;code>import datetime&lt;/code>+&lt;code>datetime.datetime(), datetime.date()&lt;/code>的写法，&lt;br>
我就一直不解，&lt;br>
&lt;code>from datetime import datetime, date&lt;/code>+&lt;code>datetime(), date()&lt;/code>这样感觉更好啊？&lt;br>
而且后续的代码更短。&lt;/p>
&lt;p>后来读到&lt;a href="docs.python-guide.org/en/latest/">&lt;code>Kenneth Reitz&lt;/code>的&lt;code>Hitchhiker's Guide to Python&lt;/code>&lt;/a>的时候我才明白，&lt;br>
&lt;code>Explicit is better than implicit&lt;/code>的体现就是显式指定包名，&lt;br>
这样代码表现力就会更强，也更易读。&lt;/p>
&lt;pre tabindex="0">&lt;code>## Very bad
[...]
from modu import *
[...]
x = sqrt(4) # Is sqrt part of modu? A builtin? Defined above?
## Better
from modu import sqrt
[...]
x = sqrt(4) # sqrt may be part of modu, if not redefined in between
## Best
import modu
[...]
x = modu.sqrt(4) # sqrt is visibly part of modu&amp;#39;s namespace
&lt;/code>&lt;/pre>&lt;p>从学到这一点以后，&lt;br>
我就下定决心再也不用&lt;code>from datetime import datetime&lt;/code>了。&lt;/p>
&lt;h2 id="总结">总结&lt;/h2>
&lt;p>&lt;code>Best Practice&lt;/code>这种东西，&lt;br>
看起来很美好，&lt;br>
用好了可以大大&lt;del>偷懒&lt;/del>减少工作量。&lt;br>
但它有一个重要特性：&lt;br>
&lt;code>Best Practice&lt;/code>从来不是试出来的，&lt;br>
而是&lt;strong>思索、学习、择优&lt;/strong>得到的。&lt;br>
多加一个&lt;code>if&lt;/code>，多加一个机器，多招一个人，多加一点班&lt;br>
可能只能解决当下的问题。&lt;br>
平时多学习一个，&lt;br>
才能到了要解决问题的时候，&lt;br>
面临技术、业务、上线时间的多重压力，&lt;br>
优雅地使用&lt;code>Best Practice&lt;/code>解决问题。&lt;/p>
&lt;p>总的来说，&lt;br>
为了&lt;del>偷懒&lt;/del> &lt;del>少干活&lt;/del>提高效率，&lt;br>
我们又定下了这么些小目标：&lt;/p>
&lt;ul>
&lt;li>多学习一个&lt;code>Best Practice&lt;/code>&lt;/li>
&lt;li>学到了就用，能用精妙的方法就不用愚蠢的方法&lt;/li>
&lt;li>通过思考来学习，而不是完全通过试错反馈机制来学习&lt;/li>
&lt;/ul>
&lt;p>毕竟编程风格可不能是&lt;a href="https://coolshell.cn/articles/2058.html">散弹枪编程&lt;/a>呀。&lt;/p></description></item><item><title>写代码怎么偷懒？我想想</title><link>https://liriansu.com/posts/2017-08-30-lazy-coding-thinking/</link><pubDate>Wed, 30 Aug 2017 23:10:52 +0000</pubDate><guid>https://liriansu.com/posts/2017-08-30-lazy-coding-thinking/</guid><description>&lt;p>我真的不是因为写了&lt;code>Python&lt;/code>，就在黑&lt;code>Perl&lt;/code>。&lt;/p>
&lt;h2 id="起">起&lt;/h2>
&lt;p>最近装了 &lt;a href="https://wakatime.com/dashboard">wakatime&lt;/a> 这个控件以后，&lt;br>
我一直忍不住好奇心去看看我平常到底有多少时间在写代码。&lt;br>
经过严谨的数据统计表明：&lt;br>
我只有25%的时间在写代码。&lt;br>
（按一周40小时算，&lt;br>
我一周只写10小时的代码=_,=）&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/wakatime_dashboard.jpg" alt="old-waka">&lt;/p>
&lt;p>这样不好。&lt;br>
于是我决定奋发图强，&lt;br>
在自以为沉浸地写了一周代码以后，&lt;br>
25%变成了33%。&lt;br>
于是严谨的数据统计依然表明：&lt;br>
我大部分的时间都在划水。&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/wakatime.png" alt="new-waka">&lt;/p>
&lt;p>于是我放弃了挣扎，&lt;br>
就像苏轼朋友佛印和尚讲过的一样：&lt;br>
&lt;code>既来之，则安之&lt;/code> &lt;em>不是他说的&lt;/em>&lt;/p>
&lt;p>我很开心地想道：&lt;br>
“哎呀。&lt;br>
我就花这么一点点时间干活，&lt;br>
是不是说明我效率高呀？”&lt;/p>
&lt;p>“不是的，只不过是因为你懒而已。”&lt;br>
心里的正义小人蹦了出来。&lt;/p>
&lt;p>我十分开心地嘴硬道：&lt;br>
“对呀对呀，我就是懒。&lt;br>
而且就像我以前说的，&lt;br>
懒有那种没有建设性的懒，&lt;br>
还有那种一劳永逸的懒。”&lt;/p>
&lt;p>嗯，今天我就要尝试说服我心里的正义小人，&lt;br>
&lt;strong>我不是在偷懒，我是在想问题！&lt;/strong>&lt;/p>
&lt;p>按老规矩，&lt;br>
用讲故事的方式讲道理。&lt;br>
献丑了！&lt;/p>
&lt;h2 id="承">承&lt;/h2>
&lt;p>我从大四到毕业，&lt;br>
一直在&lt;a href="https://www.qad.com/about">QAD&lt;/a>当研发（就是研发工程师）&lt;br>
一般来说，“研发工程师”这个说法是分工上这么叫的，&lt;br>
洋文里叫 &lt;code>SE, Software Engineer&lt;/code>,&lt;br>
对应测试工程师 &lt;code>QA, Quality Assurance&lt;/code>。&lt;br>
互联网公司里是Web编程的话，&lt;br>
会从另一个维度上分成前端工程师 &lt;code>FE, Front End&lt;/code>,&lt;br>
后端工程师 &lt;code>BE, Back End&lt;/code>。&lt;br>
有些也会从部门上拆分成架构、技术（业务）、算法、数据不同的组。&lt;/p>
&lt;p>&lt;a href="https://www.qad.com/about">QAD&lt;/a>主要是按业务拆分研发部门，&lt;br>
我们当时是Foundation组（基础架构组）。&lt;br>
公司做的是SaaS形式的ERP系统。（SAP, Oracle都是我们的竞争对手）&lt;br>
这里的SaaS可以简单理解为年费会员，&lt;br>
大众(Volkswagen)公司买QAD的ERP系统并不是一锤子买卖，&lt;br>
当合同签订以后，&lt;br>
我们还要负责整套系统的安装、培训、维护、升级工作。&lt;br>
（当然大众也要对应地交“物业费”就是了）&lt;br>
公司部门分工大概如下：&lt;/p>
&lt;ul>
&lt;li>R&amp;amp;D 负责开发软件。R&amp;amp;D也就是研发部门，Research and Development, 我在这…&lt;/li>
&lt;li>Sales 负责销售产品。（有的时候研发还没做完，产品就卖出去了，于是倒催研发…十分神奇…&lt;/li>
&lt;li>Service 负责产品的安装、上线、培训。有的时候客户有一些定制化的需求，Service也是要写代码的。比如中国的医药公司要开发一套药监局审查流程，这个明显不是标准流程，就需要&lt;strong>定制化开发&lt;/strong>。&lt;/li>
&lt;li>Support 负责日常的支持。比如产品平时出Bug了，晚上出Bug了，周末出Bug了，都要负责给客户解决…&lt;/li>
&lt;li>Finance, Law, HR, CEO 等其他队友提供内部支持，维系组织有序运转。&lt;/li>
&lt;/ul>
&lt;p>我当时参与的项目是叫&lt;code>CVC, Customer Version Control&lt;/code>。&lt;br>
要解决的问题，就是&lt;strong>定制化开发中的，代码版本控制难题。&lt;/strong>&lt;br>
比如还是大众公司，&lt;br>
他们2008年就安装了QAD2008版本，&lt;br>
然后基于2008版本做了大量关于车辆测试、车辆安全性能等方面的定制化开发。&lt;br>
于是在QAD要升级主程序版本的时候，&lt;br>
大众公司惊呼：&lt;a href="https://xkcd.com/1597/">“1079 Merge Conflicts Found!!!”&lt;/a>&lt;br>
这种定制化和主干的冲突，&lt;br>
只是当时我们要解决的其中一个问题，&lt;br>
其它还包括有超过10G的代码本地环境构建，&lt;br>
dev-test-sup-prod多环境代码管理，&lt;br>
soft/hard lock等。&lt;/p>
&lt;h2 id="转">转&lt;/h2>
&lt;p>正义小人：“ok，于是你讲了这么多，&lt;br>
跟具体写程序相关的一句话没讲……”&lt;/p>
&lt;p>的确，具体写程序的话是一句没讲。&lt;br>
那既然都扯这么多了，&lt;br>
我就再扯多点吧…&lt;/p>
&lt;p>技术选型上，最开始用了 &lt;code>Git&lt;/code> + &lt;code>Perl&lt;/code>。&lt;br>
因为要做代码版本控制，&lt;br>
所以核心的轮子就用了&lt;code>Git&lt;/code>，&lt;br>
当时团队的技术栈主要是&lt;code>Git vs SVN&lt;/code>，&lt;br>
又因为要做多环境管理，&lt;br>
所以&lt;code>git rebase&lt;/code>, &lt;code>git cherry-pick&lt;/code>, &lt;code>git filter-branch&lt;/code>等一串能修改历史的命令就优势明显。&lt;br>
又因为整个项目最终是一个命令行工具，&lt;br>
而且团队之前的主要技术栈是&lt;code>Perl&lt;/code>，&lt;br>
&lt;a href="https://www.tiobe.com/tiobe-index/">项目语言就采用了&lt;code>Perl&lt;/code>&lt;/a>。&lt;br>
&lt;code>Perl&lt;/code>这门语言最强大是它的命令行交互和文本处理，&lt;br>
很多&lt;code>shell&lt;/code>命令是天生共通的，&lt;br>
比如&lt;code>echo, test -f, $@&lt;/code>等；&lt;br>
文本处理上，正则和一些&lt;code>heredoc&lt;/code>也是非常美妙。&lt;br>
而&lt;code>Perl&lt;/code>最大的问题倒不在&lt;a href="https://coolshell.cn/articles/1903.html">语言本身被诟病的鬼画符&lt;/a>上，&lt;br>
最大的问题是：&lt;code>Perl&lt;/code>日渐衰弱。&lt;br>
比如假如我们说我们招&lt;code>Java&lt;/code>工程师，&lt;br>
那其实可以招到很多人才，&lt;br>
但同样招&lt;code>Perl&lt;/code>工程师，&lt;br>
招到同样人才的概率也不一定会高很多，&lt;br>
但是付出的成本要高更多。&lt;/p>
&lt;p>于是后来我干了一件事情，&lt;br>
下班时间用&lt;code>Java&lt;/code>把&lt;code>CVC&lt;/code>给重写了。&lt;br>
三四月份的上海特别凉快，&lt;br>
我住的离公司也近，&lt;br>
六点多吃完饭，走路回家洗个澡，&lt;br>
穿个拖鞋就蹦跶回公司。&lt;br>
白天写&lt;code>Perl&lt;/code>，晚上写&lt;code>Java&lt;/code>，特别开心。&lt;br>
当时老大也特别会顺势而为，&lt;br>
他看我自己在重构项目，&lt;br>
分给我的活也更少了，&lt;br>
于是后来上班的时间我也在“划水”写&lt;code>Java&lt;/code>了。&lt;br>
因为需求明确，功能点清晰，&lt;br>
就这样过了两个月，&lt;br>
两万行的&lt;code>Perl&lt;/code>代码再加同样量级的单元测试，&lt;br>
（一时间竟没找到比代码行数更恰当的数据……）&lt;br>
被我重构了一半到&lt;code>Java&lt;/code>&amp;hellip;&lt;br>
后来大家一起把各种Edge Case补上了，&lt;br>
整个产品正式切换成了&lt;code>Java&lt;/code>，&lt;br>
也算是一点微小的贡献吧。&lt;/p>
&lt;h2 id="合">合&lt;/h2>
&lt;p>我在QAD的时间(2014年7月到2016年10月)&lt;br>
基本上都贡献给了CVC这个项目。&lt;br>
同样的功能，&lt;br>
&lt;code>Perl&lt;/code>版本用了一年多实现，&lt;br>
&lt;code>Java&lt;/code>版本用了几个月就实现了。&lt;br>
决定性因素跟语言表现力毫无关系，&lt;br>
而在于&lt;code>业务需求&lt;/code>和&lt;code>业务理解&lt;/code>上。&lt;/p>
&lt;p>正如上文介绍项目流程里讲的，&lt;br>
项目要做的是&lt;strong>定制化开发&lt;/strong>，&lt;br>
需求就是来自于&lt;strong>Service&lt;/strong>部门同事。&lt;br>
他们一开始是不知道什么样的软件是好用的，&lt;br>
我们定义好的产品模式（比如自由checkout文件），&lt;br>
但是他们觉得另一种模式更好（开发人员更换频繁，需要对文件加soft lock），&lt;br>
或者是觉得产品可以更好（比如流程要和Jira高度结合）。&lt;br>
所以其实我们在&lt;code>Design - Refine&lt;/code>这个流程上不断进步&lt;br>
（中文的说法叫“走了不少弯路”）&lt;/p>
&lt;p>还有我们在重构过程中，&lt;br>
因为知道了整体的需求的样子，&lt;br>
就能更好地抽象逻辑。&lt;br>
就像是建筑师设计房子的时候，&lt;br>
因为知道了整体架构，&lt;br>
他才能确定房梁的承重，&lt;br>
部件的用材。&lt;/p>
&lt;p>正义小人想了想，说：&lt;br>
“噢，我明白了。你的意思是说，&lt;br>
偷懒不写程序，其实只是停笔，&lt;br>
想想要写什么样的程序？&lt;br>
需求更准确，理解更清晰，事情才会更好做？”&lt;/p>
&lt;p>“对呀对呀！满分理解！”&lt;/p>
&lt;p>正义小人又一脸嫌弃：&lt;br>
“但是现实生活中，是不会有这样的情况的。”&lt;/p>
&lt;p>是呀，所以我也只能一边说着“学到了学到了”，&lt;br>
一边想着“我是谁，我在哪，我要写什么程序？”&lt;/p></description></item><item><title>HR与程序员的日常（二）：OKR是啥</title><link>https://liriansu.com/posts/2017-08-13-okr/</link><pubDate>Sun, 13 Aug 2017 22:17:55 +0000</pubDate><guid>https://liriansu.com/posts/2017-08-13-okr/</guid><description>&lt;p>TI 输了，&lt;br>
熬夜看比赛的 Lirian 感觉心很痛。&lt;br>
于是他打算换个心情，&lt;br>
看看 Mia 最近的学习任务是啥。&lt;/p>
&lt;h2 id="okr-是什么">OKR 是什么&lt;/h2>
&lt;p>Mia 最近听的课程刚好讲到了 &lt;a href="https://en.wikipedia.org/wiki/OKR">OKR&lt;/a> 。&lt;br>
Lirian 其实只知道 &lt;a href="https://en.wikipedia.org/wiki/OKR">OKR&lt;/a> 是&lt;br>
Objectives and Key Results 的简称，&lt;br>
是一种绩效考核的方式，&lt;br>
&lt;a href="https://en.wikipedia.org/wiki/Performance_indicator">KPI&lt;/a> 是另一种绩效考核的方式。&lt;br>
感觉 &lt;a href="https://en.wikipedia.org/wiki/OKR">OKR&lt;/a> 跟 &lt;a href="https://en.wikipedia.org/wiki/Performance_indicator">KPI&lt;/a> 的关系，&lt;br>
可能像是素质教育与应试教育的关系一样，&lt;br>
各有优势，各有不同。&lt;/p>
&lt;p>于是 Lirian 用一招&lt;em>抛砖引玉&lt;/em>打开了话题：&lt;br>
“话说 &lt;a href="https://en.wikipedia.org/wiki/OKR">OKR&lt;/a> 和 &lt;a href="https://en.wikipedia.org/wiki/Performance_indicator">KPI&lt;/a> 究竟有啥区别啊？”&lt;/p>
&lt;p>Mia 回以一招&lt;em>斗转星移&lt;/em>：&lt;br>
“我觉得 &lt;a href="https://en.wikipedia.org/wiki/OKR">OKR&lt;/a> 和 &lt;a href="https://en.wikipedia.org/wiki/Performance_indicator">KPI&lt;/a> 是有本质区别的。”&lt;/p>
&lt;p>Lirian 顺势一招&lt;a href="https://zh.moegirl.org/zh-hans/%E4%B9%8C%E9%B8%A6%E5%9D%90%E9%A3%9E%E6%9C%BA">&lt;em>乌鸦坐飞机&lt;/em>&lt;/a>问了下去：&lt;br>
“噢，有什么区别~请讲~”&lt;/p>
&lt;p>没想到 Mia 不坐飞机，一招&lt;em>借力打力&lt;/em>回了过来：&lt;br>
“那我先问你，你知道 &lt;a href="https://en.wikipedia.org/wiki/Performance_indicator">KPI&lt;/a> 是什么吗？”&lt;/p>
&lt;p>Lirian 顿时懵逼了：&lt;br>
“啊…不知道……大概是绩效考核的一种方式？”&lt;/p>
&lt;p>“你这么讲也对。&lt;br>
&lt;a href="https://en.wikipedia.org/wiki/Performance_indicator">KPI&lt;/a> 的全称其实是 &lt;code>Key Performance Indicator&lt;/code>,&lt;br>
翻译成中文就是 &lt;code>关键绩效指标&lt;/code>。&lt;br>
工作上，每个人都可以有自己的 &lt;a href="https://en.wikipedia.org/wiki/Performance_indicator">KPI&lt;/a>,&lt;br>
一般是一年/半年结一次，&lt;br>
这个目标要符合 &lt;a href="https://en.wikipedia.org/wiki/SMART_criteria">&lt;code>SMART&lt;/code>&lt;/a> 原则。”&lt;/p>
&lt;p>“啥是 &lt;a href="https://en.wikipedia.org/wiki/SMART_criteria">&lt;code>SMART&lt;/code>&lt;/a> 原则啊？”&lt;/p>
&lt;p>“&lt;a href="https://en.wikipedia.org/wiki/SMART_criteria">&lt;code>SMART&lt;/code>&lt;/a> 原则就跟你知道的 &lt;code>SWOT&lt;/code> 分析方法一样，&lt;br>
是外国人很喜欢的缩写 (acronym).&lt;br>
具体来说，就是&lt;br>
&lt;code>Specific, 具体的&lt;/code>,&lt;br>
&lt;code>Measurable, 可量化的&lt;/code>,&lt;br>
&lt;code>Achievable, 能做到的&lt;/code>,&lt;br>
&lt;code>Realistic, 现实的&lt;/code>,&lt;br>
&lt;code>Timely, 有时限的&lt;/code>&lt;br>
这五个形容词的英文首字母缩写。&lt;br>
一个科学的 &lt;a href="https://en.wikipedia.org/wiki/Performance_indicator">&lt;code>KPI&lt;/code>&lt;/a> 就得 &lt;a href="https://en.wikipedia.org/wiki/SMART_criteria">&lt;code>SMART&lt;/code>&lt;/a>.”&lt;/p>
&lt;p>“噢噢噢，明白了。&lt;br>
比如诸葛亮的 &lt;a href="https://en.wikipedia.org/wiki/Performance_indicator">KPI&lt;/a>,&lt;br>
&lt;code>今年之内平复南蛮&lt;/code>，&lt;br>
就比&lt;code>有生之年光复汉室&lt;/code>要科学得多？”&lt;/p>
&lt;p>Mia 勉强赞同了这个类比：&lt;br>
“呃，可以这么说吧。”&lt;/p>
&lt;h2 id="为什么要用-okr">为什么要用 OKR&lt;/h2>
&lt;p>Lirian 想起了最开始的话题：&lt;br>
“那，&lt;a href="https://en.wikipedia.org/wiki/OKR">OKR&lt;/a> 和 &lt;a href="https://en.wikipedia.org/wiki/Performance_indicator">KPI&lt;/a> 究竟有啥本质区别呢？&lt;br>
我感觉 &lt;a href="https://en.wikipedia.org/wiki/OKR">OKR&lt;/a> 也得 &lt;a href="https://en.wikipedia.org/wiki/SMART_criteria">&lt;code>SMART&lt;/code>&lt;/a> 吧……”&lt;/p>
&lt;p>Mia 想了想，说：&lt;br>
“我觉得，&lt;a href="https://en.wikipedia.org/wiki/Performance_indicator">KPI&lt;/a> 和 &lt;a href="https://en.wikipedia.org/wiki/OKR">OKR&lt;/a> 的目的是不一样的。&lt;br>
&lt;a href="https://en.wikipedia.org/wiki/Performance_indicator">KPI&lt;/a> 是告诉你 &lt;code>要我做什么&lt;/code>，&lt;br>
&lt;a href="https://en.wikipedia.org/wiki/OKR">OKR&lt;/a> 是告诉你 &lt;code>我要做什么&lt;/code>。&lt;br>
还有，&lt;a href="https://en.wikipedia.org/wiki/Performance_indicator">KPI&lt;/a> 一般都和奖金挂钩，&lt;br>
&lt;a href="https://en.wikipedia.org/wiki/OKR">OKR&lt;/a> 就可能不会和奖金挂钩。&lt;br>
&lt;a href="https://en.wikipedia.org/wiki/Performance_indicator">KPI&lt;/a> 可能是一下子定一年的目标，&lt;br>
&lt;a href="https://en.wikipedia.org/wiki/OKR">OKR&lt;/a> 经常会变…”&lt;/p>
&lt;p>Lirian 感觉信息密度一下子变大了，&lt;br>
赶快打断了 Mia 的吟唱：&lt;br>
“且慢，小弟听不太懂……&lt;br>
什么是 &lt;code>要我做什么&lt;/code> ?”&lt;/p>
&lt;p>“&lt;a href="https://en.wikipedia.org/wiki/Performance_indicator">KPI&lt;/a> 的 &lt;code>要我做什么&lt;/code> 指的是它一般都是从上到下分解的任务。&lt;br>
比如我们公司今年要朝市值一亿元去努力，&lt;br>
每个部门要怎么怎么样，&lt;br>
具体到每个人要怎么怎么样，&lt;br>
这些都是要定性定量完成的任务。&lt;br>
而 &lt;a href="https://en.wikipedia.org/wiki/OKR">OKR&lt;/a> 的 &lt;code>我要做什么&lt;/code> 更多是把一亿元这个目标给摆出来，&lt;br>
然后部门去决定，短期、长期的部门目标。&lt;br>
每个人也会根据部门的目标，&lt;br>
去决定自己的目标。”&lt;/p>
&lt;p>“啊？这么听起来 &lt;a href="https://en.wikipedia.org/wiki/Performance_indicator">KPI&lt;/a> 考核压力很大啊！&lt;br>
听下来我还是喜欢 &lt;a href="https://en.wikipedia.org/wiki/OKR">OKR&lt;/a> &amp;hellip;”&lt;/p>
&lt;p>“是的呀，&lt;a href="https://en.wikipedia.org/wiki/OKR">OKR&lt;/a> 就是硅谷湾区那边弄出来的，&lt;br>
Google 就把 &lt;a href="https://en.wikipedia.org/wiki/OKR">OKR&lt;/a> 给发扬光大了。&lt;br>
不过其实这个会因人、岗位而异的。”&lt;/p>
&lt;p>“嗯，怎么讲？”&lt;/p>
&lt;p>“&lt;a href="https://en.wikipedia.org/wiki/Performance_indicator">KPI&lt;/a> 里面有一点很重要，就是可以量化。&lt;br>
比如像计件工作的车间工人，&lt;br>
可以直接用完成数量来考核。&lt;br>
这种时候他的个人意愿、创造力等不会是考核里的重要因素。&lt;br>
但像不能量化的工作，&lt;br>
就像你们程序员，&lt;br>
难道能用代码行数来考核吗？&lt;br>
明显不科学。&lt;br>
&lt;em>此处有想到了 &lt;a href="https://en.wikipedia.org/wiki/Indent_style#K.26R">K&amp;amp;R naming convention&lt;/a> 而死命点头的 Lirian&lt;/em>&lt;br>
像 HR,&lt;br>
假如是做招聘还好，&lt;br>
可以根据招聘岗位数量来量化。&lt;br>
但是假如是做培训什么的，&lt;br>
也无法量化，强行上 &lt;a href="https://en.wikipedia.org/wiki/Performance_indicator">KPI&lt;/a> 就会很痛苦。&lt;br>
所以说 &lt;a href="https://en.wikipedia.org/wiki/Performance_indicator">KPI&lt;/a> 和 &lt;a href="https://en.wikipedia.org/wiki/OKR">OKR&lt;/a> 这两种绩效考核的方式，&lt;br>
是因人、岗位、公司而异的。”&lt;/p>
&lt;blockquote>
&lt;p>此处 Lirian 又想到了《主角与配角》里的陈佩斯&lt;/p>
&lt;p>朱时茂对他说：“像你这种人，还真得下死命令。”&lt;/p>
&lt;p>明显就是 &lt;a href="https://en.wikipedia.org/wiki/OKR">OKR&lt;/a> 和 &lt;a href="https://en.wikipedia.org/wiki/Performance_indicator">KPI&lt;/a> 的戏剧冲突啊。&lt;/p>
&lt;/blockquote>
&lt;p>Lirian 思索 + 理解了一番，&lt;br>
又问：&lt;br>
“那像 &lt;a href="https://www.qad.com/about">QAD&lt;/a> 呢？&lt;br>
&lt;a href="https://www.qad.com/about">QAD&lt;/a> 是用 &lt;a href="https://en.wikipedia.org/wiki/Performance_indicator">KPI&lt;/a> 还是 &lt;a href="https://en.wikipedia.org/wiki/OKR">OKR&lt;/a> 的？”&lt;/p>
&lt;blockquote>
&lt;p>&lt;a href="https://www.qad.com/about">QAD&lt;/a> 是 Mia 和 Lirian 相识的地方。&lt;br>
一家专做 ERP 的跨国软件公司，&lt;br>
主要对手是 SAP.&lt;/p>
&lt;/blockquote>
&lt;p>Mia 邪魅一笑：&lt;br>
“&lt;a href="https://www.qad.com/about">QAD&lt;/a> 既不用 &lt;a href="https://en.wikipedia.org/wiki/Performance_indicator">KPI&lt;/a>,&lt;br>
也不用 &lt;a href="https://en.wikipedia.org/wiki/OKR">OKR&lt;/a>.&lt;br>
&lt;a href="https://www.qad.com/about">QAD&lt;/a> 用的是 &lt;a href="https://en.wikipedia.org/wiki/Management_by_objectives">MBO&lt;/a>.”&lt;/p>
&lt;p>Lirian 惊了个呆：&lt;br>
“还有这种操作啊？&lt;br>
听起来像是啥电视台的名字，&lt;br>
这个 &lt;a href="https://en.wikipedia.org/wiki/Management_by_objectives">MBO&lt;/a> 又是什么？”&lt;/p>
&lt;p>Mia 解释了一下：&lt;br>
“这个 &lt;a href="https://en.wikipedia.org/wiki/Management_by_objectives">MBO&lt;/a> 呢，&lt;br>
全称叫 &lt;code>Management by objectives&lt;/code>.&lt;br>
中文可能叫 &lt;code>目标管理&lt;/code>，其实跟 &lt;a href="https://en.wikipedia.org/wiki/Performance_indicator">KPI&lt;/a> 有相似之处。&lt;br>
它是上世纪六七十年代出现的绩效考核方法，&lt;br>
比 &lt;a href="https://en.wikipedia.org/wiki/Performance_indicator">KPI&lt;/a> 和 &lt;a href="https://en.wikipedia.org/wiki/OKR">OKR&lt;/a> 都早，&lt;br>
萧规曹随，&lt;a href="https://www.qad.com/about">QAD&lt;/a> 就一直用 &lt;a href="https://en.wikipedia.org/wiki/Management_by_objectives">MBO&lt;/a> 用了下来。&lt;br>
不过近两年转的 PDP,&lt;br>
其实就有 &lt;a href="https://en.wikipedia.org/wiki/OKR">OKR&lt;/a> 的影子。”&lt;/p>
&lt;h2 id="okr-要怎么操作">OKR 要怎么操作&lt;/h2>
&lt;p>Lirian 想了想，&lt;br>
又理了一下思路：&lt;br>
“既然 &lt;a href="https://en.wikipedia.org/wiki/OKR">OKR&lt;/a> 和 &lt;a href="https://en.wikipedia.org/wiki/Performance_indicator">KPI&lt;/a> 是因部门而异的，&lt;br>
是不是意味着公司里可以同时使用两套绩效考核的方式啊？”&lt;/p>
&lt;p>“是的呀。&lt;br>
就像邓爷爷说的，&lt;br>
&lt;code>不管黑猫白猫，抓到老鼠的就是好猫。&lt;/code>&lt;br>
所有管理理论在具体落地的时候，&lt;br>
只要合适就可以实施。”&lt;/p>
&lt;p>“那，有没有可能同一个部门里，&lt;br>
有些员工用 &lt;a href="https://en.wikipedia.org/wiki/OKR">OKR&lt;/a>,&lt;br>
有些员工用 &lt;a href="https://en.wikipedia.org/wiki/Performance_indicator">KPI&lt;/a> 管理呢？”&lt;/p>
&lt;p>“哦，这个不可能。”&lt;/p>
&lt;p>Lirian 表示疑惑：&lt;br>
“为啥呀，&lt;br>
假如我在一个 &lt;a href="https://en.wikipedia.org/wiki/OKR">OKR&lt;/a> 团队里，&lt;br>
但是我就是需要明确的量化的指标告诉我干啥，&lt;br>
那该咋办？”&lt;/p>
&lt;p>Mia 回答的很快：&lt;br>
“那其实说明你不适合这个团队，&lt;br>
因为团队有自己的统一风格也是很重要的。”&lt;/p>
&lt;p>Lirian 只能无奈地学到了这个事实：&lt;br>
“好吧……”&lt;/p>
&lt;p>讲到了团队，Mia 又补充了几点：&lt;br>
“目前的 &lt;a href="https://en.wikipedia.org/wiki/OKR">OKR&lt;/a> 应用状况是：&lt;br>
在中国，用的比较多的是创业公司、互联网公司、正在转型的公司。&lt;br>
美国的话就是硅谷的科技公司。&lt;br>
当然因为 &lt;a href="https://en.wikipedia.org/wiki/OKR">OKR&lt;/a> 其实只是一个指导方针，&lt;br>
所以每个公司执行的政策也会各有不同。”&lt;/p>
&lt;p>Lirian 心想：&lt;br>
嗯，正如每个人都会有一套 RestFul 的风格……&lt;/p>
&lt;p>Mia 又想起来 &lt;a href="https://en.wikipedia.org/wiki/Performance_indicator">KPI&lt;/a> 有一点很大的弊端：&lt;br>
“还有就是 &lt;a href="https://en.wikipedia.org/wiki/Performance_indicator">KPI&lt;/a> 有一个很大的问题，&lt;br>
大家很容易本末倒置。&lt;br>
为了完成 &lt;a href="https://en.wikipedia.org/wiki/Performance_indicator">KPI&lt;/a> 的定量指标，&lt;br>
就背离了公司本来的目标。”&lt;/p>
&lt;p>“是啊，不忘初心很重要。&lt;br>
希望 CN Dota 加油，&lt;br>
明年 TI 加油吧。”&lt;/p>
&lt;p>“啊？”&lt;/p>
&lt;p>“唔，我来跟你讲讲什么是 TI 吧。”&lt;/p>
&lt;p>（本章完）&lt;/p></description></item><item><title>GitHub上的小标签有什么好玩的</title><link>https://liriansu.com/posts/2017-08-08-github-badges/</link><pubDate>Tue, 08 Aug 2017 23:10:01 +0000</pubDate><guid>https://liriansu.com/posts/2017-08-08-github-badges/</guid><description>&lt;p>GitHub很多项目主页都会放上好玩的小标签（GitHub Badges），&lt;br>
这次我们也来玩点表面功夫。&lt;/p>
&lt;h2 id="首先我们要有一个项目">首先，我们要有一个项目&lt;/h2>
&lt;p>前阵子&lt;a href="https://www.jingkaizhao.com/">靖哥哥&lt;/a>口嫌体正直地吐槽了一下&lt;a href="https://github.com/typicode/lowdb">lowdb&lt;/a>：&lt;/p>
&lt;blockquote>
&lt;p>这个lowdb，&lt;br>
好用是好用，&lt;br>
但是也太low了吧&amp;hellip;&lt;/p>
&lt;/blockquote>
&lt;p>我十分好奇，&lt;br>
跑去看了看&lt;a href="https://github.com/typicode/lowdb">lowdb&lt;/a>的介绍：&lt;/p>
&lt;blockquote>
&lt;p>这是一个 JSON 格式的微型数据库。&lt;/p>
&lt;/blockquote>
&lt;p>诶，微型诶，感觉萌萌哒。&lt;br>
那 Python 有没有对标的库呢？&lt;br>
有，那就是&lt;a href="https://tinydb.readthedocs.io/en/latest/intro.html">tinydb&lt;/a>~&lt;/p>
&lt;blockquote>
&lt;p>tinydb 大概只有1200行源代码，以及1000行测试。&lt;/p>
&lt;/blockquote>
&lt;p>啥？！这还tiny呢？&lt;br>
怕是18级的tiny吧？&lt;/p>
&lt;p>于是我们决定，&lt;br>
&lt;strong>要有一个比tinydb还tiny的，比lowdb还要low的数据库。&lt;/strong>&lt;/p>
&lt;p>起名字顿时是个问题。&lt;br>
既然犹豫不定，&lt;br>
&lt;a href="https://liriansu.com/forgive-her-meme">那就选择原谅他吧&lt;/a>~&lt;br>
于是又一个轮子诞生了：&lt;/p>
&lt;p>&lt;a href="https://github.com/hui-z/ForgiveDB">原谅数据库(hui-z/ForgiveDB)&lt;/a>&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/github/forgive.jpg" alt="readme">&lt;/p>
&lt;h2 id="github-badges">GitHub Badges&lt;/h2>
&lt;p>忽略README里对项目本身的吹捧，&lt;br>
Logo下面那一长串绿绿的小标签，&lt;br>
就是Badges啦~&lt;br>
&lt;a href="https://liriansu.com/how-i-use-github">由于程序员一般都在GitHub上活动&lt;/a>，&lt;br>
所以大家也习惯把这些叫做是GitHub Badges&lt;br>
（即使在别的地方也可以用到它们）&lt;/p>
&lt;p>本质上这些小标签就是能点的图片，&lt;br>
比如用 &lt;a href="https://liriansu.com/hrbp-and-markdown">Markdown 语法&lt;/a>可以这么写：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-markdown" data-lang="markdown">&lt;span style="display:flex;">&lt;span>[&lt;span style="color:#f92672">![ForgiveDB&lt;/span>](&lt;span style="color:#a6e22e">https://img.shields.io/badge/ForgiveDB-HuiZ-brightgreen.svg&lt;/span>)](https://github.com/hui-z/ForgiveDB)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="font-style:italic">*这么一长串实际上是 Markdown 里图片的语法，加超链接的语法组合成的*&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>![&lt;span style="color:#f92672">图片的语法&lt;/span>](&lt;span style="color:#a6e22e">https://img.shields.io/badge/ForgiveDB-HuiZ-brightgreen.svg&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>[&lt;span style="color:#f92672">超链接的语法&lt;/span>](&lt;span style="color:#a6e22e">https://github.com/hui-z/ForgiveDB&lt;/span>)
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>上面一串就会变成这样子：&lt;/p>
&lt;p>&lt;a href="https://github.com/hui-z/ForgiveDB">&lt;img src="https://img.shields.io/badge/ForgiveDB-HuiZ-brightgreen.svg" alt="ForgiveDB">&lt;/a>&lt;/p>
&lt;p>&lt;em>这么一长串实际上是 Markdown 里图片的语法，加超链接的语法组合成的&lt;/em>&lt;/p>
&lt;p>&lt;img src="https://img.shields.io/badge/ForgiveDB-HuiZ-brightgreen.svg" alt="图片的语法">&lt;/p>
&lt;p>&lt;a href="https://github.com/hui-z/ForgiveDB">超链接的语法&lt;/a>&lt;/p>
&lt;h2 id="各种-badges">各种 Badges&lt;/h2>
&lt;p>具体来看，&lt;br>
我们在 &lt;a href="https://github.com/hui-z/ForgiveDB">ForgiveDB&lt;/a> 里用到的标签有这些：&lt;/p>
&lt;ul>
&lt;li>
&lt;p>&lt;a href="https://shields.io/">&lt;strong>shields.io&lt;/strong>&lt;/a>.&lt;br>
这个值得单独拎出来讲，&lt;br>
因为他们是个专门做 Badges 的网站，&lt;br>
上面图还是 SVG 矢量图，&lt;br>
在任何分辨率屏幕下都不会模糊。&lt;br>
假如我们想挑各种各样奇怪的 Badges,&lt;br>
（比如 star 项目的数量、&lt;br>
issue 关闭的数量、&lt;br>
npm, pypi, nuget的版本、&lt;br>
甚至是自定义任意字符）&lt;br>
都可以上&lt;a href="https://shields.io/">shields.io&lt;/a>找找看。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;a href="https://pypi.python.org/pypi/forgive">&lt;strong>PyPI&lt;/strong>&lt;/a>.&lt;br>
这个是 Python 官方的包仓库，&lt;br>
&lt;a href="https://shields.io/">shields.io&lt;/a>也支持版本自动嗅探。&lt;br>
低于 1.0.0 版本的好像还会变成屎黄色…&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;a href="https://pyup.io/repos/github/hui-z/ForgiveDB/">&lt;strong>pyup.io&lt;/strong>&lt;/a>.&lt;br>
这个服务很好玩，&lt;br>
授权以后它会自动检测你的 requirements 是不是最新的。&lt;br>
假如一有更新，&lt;br>
&lt;a href="https://github.com/hui-z/ForgiveDB/pull/7">pyup-bot 会直接给项目提一个 Pull Request&amp;hellip;&lt;/a>&lt;br>
简直酷炫。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;a href="https://travis-ci.org/hui-z/ForgiveDB">&lt;strong>travis-ci.org&lt;/strong>&lt;/a>.&lt;br>
这个就是大众熟知的 Travis 自动化集成工具了，&lt;br>
Travis 对开源项目免费，&lt;br>
十分友好。&lt;br>
而且功能强大，&lt;br>
&lt;a href="https://github.com/marketplace/travis-ci">和 GitHub 也有很多集成&lt;/a>，&lt;br>
用着十分舒服。&lt;br>
（前提是你得写点 UT 什么的）&lt;/p>
&lt;/li>
&lt;li>
&lt;p>其它：&lt;br>
还有一些 &lt;a href="https://codecov.io/github/hui-z/ForgiveDB?branch=master">CodeCov 测试覆盖率&lt;/a>,&lt;br>
&lt;a href="https://www.appveyor.com/">AppVeyor 又一个好用的 CI&lt;/a>,&lt;br>
&lt;a href="https://circleci.com/">CircleCI 双一个好用的 CI&lt;/a>&lt;br>
等等，等等……&lt;/p>
&lt;/li>
&lt;/ul>
&lt;p>大概这就是给 ForgiveDB 挑好看的标签的旅程了。&lt;br>
这份心情，&lt;br>
就像是给心爱的键盘选好看的键帽一样美好。&lt;/p>
&lt;p>&lt;a href="https://github.com/hui-z/ForgiveDB">最后欢迎大家给 ForgiveDB 提 Pull Request&lt;/a>~&lt;br>
就算是&lt;a href="https://github.com/hui-z/ForgiveDB/pull/8">像靖哥哥一样只改改文档&lt;/a>，&lt;br>
&lt;a href="https://github.com/hui-z/ForgiveDB/graphs/contributors">混个 contributor 也行&lt;/a>啊~&lt;/p></description></item><item><title>我们是怎么升级到Python3的</title><link>https://liriansu.com/posts/2017-08-06-py2-to-py3/</link><pubDate>Sun, 06 Aug 2017 12:07:32 +0000</pubDate><guid>https://liriansu.com/posts/2017-08-06-py2-to-py3/</guid><description>&lt;p>最近我们从Python2.7,&lt;br>
全线升级到了Python3.5。&lt;/p>
&lt;h2 id="python2-和-python3-有啥区别啊">Python2 和 Python3 有啥区别啊？&lt;/h2>
&lt;p>在程序员的理想乡里，&lt;br>
程序语言理应只是个好用的工具。&lt;br>
然而在现实生活里，&lt;br>
程序语言甚至是程序语言的版本，&lt;br>
关系到工程的很多方面。&lt;br>
Python2和Python3就像是小黄车和摩拜一样，&lt;br>
在某几个大的特性上有区别，&lt;br>
但本质上都一样，&lt;br>
不过一些细微之处又有不同。&lt;/p>
&lt;p>比如说 Python2 最坑的 Unicode.&lt;br>
写过 Python2 的人总会遇到 &lt;code>UnicodeDecodeError&lt;/code> 和 &lt;code>UnicodeEncodeError&lt;/code> 这样的错。&lt;br>
在电话面试的时候，&lt;br>
我们回答候选人我们为什么会用 Python2,&lt;br>
也是把锅丢给谢老板：&lt;/p>
&lt;blockquote>
&lt;p>嗯是这样的，&lt;br>
我们第一行代码到整个初期框架都是 CEO 选的。&lt;br>
他是美国回来的，&lt;br>
所以不知道中国要用中文，&lt;br>
也会遇到 Unicode 相关的问题。&lt;br>
于是他没想太多，&lt;br>
就选了 Python2.7.&lt;/p>
&lt;/blockquote>
&lt;p>&lt;em>真实原因还有很大一部分是因为当时一些库对 Python2 支持比较好&lt;/em>&lt;/p>
&lt;p>除了 Unicode 的区别，&lt;br>
Python2 到 Python3 还有一些系统自带函数有变化。&lt;br>
比如 &lt;code>urllib.urlencode -&amp;gt; urllib.parse.urlencode&lt;/code>,&lt;br>
&lt;code>StringIO.StringIO -&amp;gt; io.BytesIO&lt;/code>。&lt;br>
一般项目里面可以用&lt;a href="https://pypi.python.org/pypi/six">six&lt;/a>这个库来做兼容，&lt;br>
比如上面举的两个例子可以用&lt;code>six.moves.urllib.parse.urlencode&lt;/code>&lt;br>
和&lt;code>six.BytesIO&lt;/code>来替换，&lt;br>
Django也自带了一个&lt;a href="https://pypi.python.org/pypi/six">six&lt;/a>在&lt;code>django.utils.six&lt;/code>.&lt;br>
不过我们是自己搭建环境，&lt;br>
所以其实不用考虑兼容性，&lt;br>
迁移工作大概的 Milestone 如下：&lt;/p>
&lt;h2 id="一些微小的工作">一些微小的工作&lt;/h2>
&lt;ol>
&lt;li>确保自己代码的兼容性。&lt;/li>
&lt;li>确保第三方库的兼容性。&lt;/li>
&lt;li>确保单元测试能过。&lt;/li>
&lt;li>确保测试环境、集成测试能过。&lt;/li>
&lt;li>正式环境切换 Python3！&lt;/li>
&lt;li>宣布辉煌结果！&lt;/li>
&lt;/ol>
&lt;p>比如说讲些我们具体做的事情吧：&lt;/p>
&lt;p>&lt;a href="https://ldsink.com/">柳老板&lt;/a>很早就想把&lt;del>谢老板的&lt;/del>Python2换了。&lt;br>
所以大概在16年底的时候，&lt;br>
我们都有这个心理预期。&lt;br>
因为我们都是 &lt;a href="https://www.jetbrains.com/pycharm/">PyCharm&lt;/a> 用户，&lt;br>
(&lt;a href="https://www.jetbrains.com/pycharm/">JetBrains&lt;/a> 家巨好用的 &lt;a href="%5Bhttps://en.wikipedia.org/wiki/Integrated_development_environment%5D">IDE&lt;/a>)&lt;br>
所以都打开了 Python Compatibility Inspection。&lt;br>
然后写代码的时候注意不使用&lt;code>xrange()&lt;/code>, &lt;code>dict.iteritems()&lt;/code>, &lt;code>print &lt;/code>,&lt;br>
而用&lt;code>range()&lt;/code>, &lt;code>dict.items()&lt;/code>, &lt;code>print()&lt;/code>来代替。&lt;br>
对于Unicode一类的问题，&lt;br>
我们使用了&lt;code>__future__&lt;/code>这个功能，&lt;br>
确保每个文件的头都是：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># -*- coding: utf-8 -*-&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">from&lt;/span> __future__ &lt;span style="color:#f92672">import&lt;/span> absolute_import, unicode_literals
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 第一行指定 encoding&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 第二行 absolute_import 指定优先从绝对路径 import&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 参见 PEP-0328: https://www.python.org/dev/peps/pep-0328&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 第二行 unicode_literals 指定字符串默认使用 unicode 类型&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 参见 PEP-3112: https://www.python.org/dev/peps/pep-3112&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>比如有个很蠢的&lt;a href="https://docs.python.org/3/library/2to3.html">py2to3&lt;/a>的工具，&lt;br>
用它最好情况也只能把上面说到的“自己代码和系统依赖”给替换了。&lt;br>
具体的库替换、正确性验证还是得自己做。&lt;/p>
&lt;p>后来我们又大概过了一遍用到的第三方库（requirements.txt）。&lt;br>
最大的依赖 Django 本身是2/3都兼容的，&lt;br>
然后像 celery/redis/requests 这种兼容性也妥妥的。&lt;br>
之前我们用的 &lt;a href="https://boto.cloudhackers.com/en/latest/">AWS Python SDK - boto&lt;/a> 不支持 Python3，&lt;br>
这个好说，对应的功能可以用&lt;a href="https://boto3.readthedocs.io/en/latest/">boto3&lt;/a>来替换。&lt;/p>
&lt;p>比较麻烦的是当时用的微信库&lt;a href="https://github.com/doraemonext/wechat-python-sdk">python-wechat-sdk&lt;/a>。&lt;br>
这个主要是我们用到了微信的很多功能：&lt;br>
消息回复、用户管理、模板/图文、各种素材等。&lt;br>
本身代码量就不小，&lt;br>
而且之前的代码写的还比较屎，&lt;br>
亟需重构。&lt;br>
于是我们花了几个月来重构代码+换库，&lt;br>
最终换成了更科学更好用的&lt;a href="https://github.com/jxtech/wechatpy">wechatpy&lt;/a>。&lt;/p>
&lt;p>代码上的准备工作做完以后&lt;br>
（虽然这是轻巧的一句话，&lt;br>
但是因为实际开发中，&lt;br>
不可能空出一段时间专门用于架构升级。&lt;br>
所以我们都是在各种业务需求中找夹缝做的，&lt;br>
大概用了半年。）&lt;/p>
&lt;p>代码上的准备工作做完以后，&lt;br>
我们又用Python3跑了一下&lt;a href="https://en.wikipedia.org/wiki/Unit_testing">单元测试(UT)&lt;/a>。&lt;br>
&lt;strong>完善的自动测试，是平时的保障，是关键时刻的定心丸。&lt;/strong>&lt;br>
理论上 Python2 到 Python3,&lt;br>
不应当有任何外部表现差异，&lt;br>
UT也不应当有错。&lt;br>
所以在修复了UT的错误以后，&lt;br>
我们就有信心切换 Python3 跑跑了。&lt;/p>
&lt;p>这里还有个小差别，&lt;br>
就是我们之前的服务器用的是 &lt;code>Ubuntu 14 (Trusty)&lt;/code>，&lt;br>
Ubuntu14 上默认的 Python3 是 Python3.4。&lt;br>
最新的 Ubuntu 版本是 &lt;code>Ubuntu 16 (Xenial)&lt;/code>，&lt;br>
上面默认的 Python3 是 Python3.5。&lt;br>
&lt;a href="https://ldsink.com/">柳老板&lt;/a>也心水了 Ubuntu16 很久了，&lt;br>
于是这次切换 Python3,&lt;br>
我们也顺便把服务器版本升到了 Ubuntu16。&lt;br>
&lt;del>不能print中文的feature也下掉了&lt;/del>&lt;/p>
&lt;p>然后就是测试环境切换 Python3，&lt;br>
生产环境切换 Python3 了。&lt;br>
这里也有个小插曲，&lt;br>
生产环境切换 Python3 的时候，&lt;br>
我们原本想着先只&lt;a href="https://en.wikipedia.org/wiki/A/B_testing">升级一部分Server（灰度）&lt;/a>，&lt;br>
但是 Celery 的 Python2 Producer抛出的任务，&lt;br>
Python3 Consumer能接，&lt;br>
但是百分百完不成…&lt;/p>
&lt;p>于是我们决定这还灰个蛋，不灰了！&lt;br>
找一天晚上点份奶茶和小龙虾，&lt;br>
全线切换Python3！&lt;br>
因为做好了前期准备，&lt;br>
所以我们大概只花了十分钟切换成了Python3~&lt;br>
腰也不酸了，&lt;br>
颈椎也不疼了，&lt;br>
连美餐的饭也好像变得美味了起来。&lt;br>
现在的&lt;a href="https://www.kezaihui.com/#!/join">我司后台就是跑在Python3上的~&lt;/a>&lt;/p>
&lt;p>最后还有就是大家的开发环境也切换一下 Python3 啦，&lt;br>
以前写的 docstring 可以切换成 &lt;a href="https://docs.python.org/3/library/typing.html">type hintings&lt;/a> 啦之类的微小的工作了。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Python 2 的时候这么写&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">def&lt;/span> &lt;span style="color:#a6e22e">old_hint&lt;/span>(messages, data&lt;span style="color:#f92672">=&lt;/span>()):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> :type messages: list
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> :type data: list[dict]
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> :rtype: str
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> &amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">pass&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Python 3 就可以这么写&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">def&lt;/span> &lt;span style="color:#a6e22e">new_hint&lt;/span>(messages: list, data: list(dict) &lt;span style="color:#f92672">=&lt;/span> ()) &lt;span style="color:#f92672">-&amp;gt;&lt;/span> str:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">pass&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="总结">总结&lt;/h2>
&lt;p>从 Python 2 到 Python 3 的好处见仁见智，&lt;br>
对于不同的情况各有不同。&lt;br>
做成这么一件微小的事情，&lt;br>
感受比较深的就是：&lt;/p>
&lt;ul>
&lt;li>
&lt;p>&lt;strong>目标要清晰。&lt;/strong>&lt;br>
比如我们早早地就把 Python 3 提到了我们的 Scrum Board 上。&lt;br>
除了技术很清楚我们要做什么，&lt;br>
产品也会有意识地给我们升级架构留下排期。&lt;br>
目标清晰，大家步伐就会一致。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>要有推动者。&lt;/strong>&lt;br>
比如&lt;a href="https://ldsink.com/">柳老板&lt;/a>就充当了整件事情的推动者，&lt;br>
有序给大家分锅，具体哪个模块谁来重构，哪个库谁来换。&lt;br>
一些没人想干的麻烦/要背锅的事情他也都做了，&lt;br>
比如去修UT的兼容性之类的…&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>互相信任真好。&lt;/strong>&lt;br>
后端升级架构，&lt;br>
其实各方面都会受影响，&lt;br>
比如上文提到的 Celery 那个坑就让我们紧急回退了版本，&lt;br>
或者类比一下游戏厂商每周例行的停服务器操作。&lt;br>
这时候产生的一些锅，&lt;br>
就被一线的队友背了，&lt;br>
他们也没多埋怨就帮我们擦屁股去了…&lt;br>
ORZ 感恩！&lt;/p>
&lt;/li>
&lt;/ul>
&lt;p>不论如何，&lt;code>Python 3&lt;/code>毕竟是趋势，&lt;br>
&lt;a href="https://www.djangoproject.com/weblog/2015/jun/25/roadmap/">Django的新版本不会支持Python 2&lt;/a>,&lt;br>
&lt;a href="https://docs.celeryproject.org/en/latest/whatsnew-4.0.html#last-major-version-to-support-python-2">Celery的新版本也不会支持Python 2了&lt;/a>。&lt;br>
我们也不能落后呀。&lt;/p>
&lt;p>就像&lt;a href="https://coolshell.cn/articles/17583.html">陈皓老师&lt;/a>常说的一样：&lt;/p>
&lt;blockquote>
&lt;p>技术债是还不完的，但我们也要一直还！&lt;/p>
&lt;/blockquote>
&lt;p>&lt;del>陈皓老师：不，我没说过这句话，你自己编的。&lt;/del>&lt;/p></description></item><item><title>人类真愚蠢——《南方公园》</title><link>https://liriansu.com/posts/2017-08-05-south-park-intro/</link><pubDate>Sat, 05 Aug 2017 19:29:14 +0000</pubDate><guid>https://liriansu.com/posts/2017-08-05-south-park-intro/</guid><description>&lt;p>给你们介绍一个美漫。&lt;/p>
&lt;p>讲到美国动漫（美漫），&lt;br>
不同人的第一反应是不一样的。&lt;br>
有人会想到《狮子王》、《猫和老鼠》，&lt;br>
有人会想到《瑞克和莫蒂》、《Happy Tree Friends》，&lt;br>
也有人会想到《超人》、《守望者》。&lt;/p>
&lt;p>不过这些都不重要，&lt;br>
因为跟这些_辣鸡_动画/漫画相比，&lt;br>
我们今天要讲的是一个更_辣鸡_的动画：&lt;/p>
&lt;h2 id="南方公园-south-park">南方公园 South Park&lt;/h2>
&lt;p>在美国的南部，有个公园，叫南方公园。&lt;br>
我们有四个小学生主角：&lt;br>
&lt;code>Cartman&lt;/code>, &lt;code>Kyle&lt;/code>, &lt;code>Stan&lt;/code>, &lt;code>Kenny&lt;/code>.&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/sp/boys.jpg" alt="boys">&lt;/p>
&lt;p>众所周知，&lt;br>
小学生都是怪物。&lt;br>
南方四剑客（没错，这个称号就是这么&lt;a href="https://zh.moegirl.org/zh-hans/%E4%B8%AD%E4%BA%8C%E7%97%85">中二&lt;/a>）的日常，&lt;br>
也是波涛汹涌。&lt;/p>
&lt;p>比如说作为一家万众瞩目的创业公司，&lt;br>
要开新闻发布会啦（S18E01）：&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/sp/cartman_fw.jpg" alt="news">&lt;/p>
&lt;p>比如说作为一个变性人，&lt;br>
要享受自己选择厕所的权利啦（S18E03）：&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/sp/cartman_trans.jpg" alt="trans">&lt;/p>
&lt;p>比如还有 Elon Mask 的乱入啦（S18E04）：&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/sp/elon.jpg" alt="elon">&lt;/p>
&lt;p>比如里面的加拿大人都是这个画风（S18E06）：&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/sp/t_and_p.jpg" alt="t-p">&lt;/p>
&lt;h2 id="南方公园的特别之处">南方公园的特别之处&lt;/h2>
&lt;p>&lt;a href="https://www.adultswim.com/videos/rick-and-morty/">Rick And Morty&lt;/a>特别之处是它的背景、线索、剧情设定，&lt;br>
&lt;a href="https://mondomedia.com/channel/HappyTreeFriends">Happy Tree Friends&lt;/a>特别之处是它的直白、不留情面。&lt;br>
南方公园(South Park, 简称SP)的特别之处是在于他的世界观：&lt;br>
&lt;strong>每个人都是特别的，所有人都是愚蠢的。&lt;/strong>&lt;/p>
&lt;p>SP反政治正确（Political Correctness, 简称PC），&lt;br>
专门搞了个校长叫 P.C. Principal.&lt;br>
他做的事情全部都是政治正确的，&lt;br>
结果被讽刺地不行。&lt;/p>
&lt;p>SP也反政治不正确，&lt;br>
虽然PC校长一直被挂，&lt;br>
但最后他还是很帅地站出来拯救了南方公园，&lt;br>
以及发表了一番&lt;a href="https://wiki.southpark.cc.com/wiki/Kyle_Broflovski">gay little speech&lt;/a>。&lt;/p>
&lt;p>SP讽刺中国人。&lt;br>
在南方公园的中国人是开餐厅的，&lt;br>
眼睛小站不直，&lt;br>
满嘴蜜汁口音。&lt;/p>
&lt;p>SP讽刺加拿大人。&lt;br>
长的奇怪，&lt;br>
思想简单，&lt;br>
爱好奇葩，&lt;br>
连画风都跟别人不一样（字面意义上的画风不一样）…&lt;/p>
&lt;p>SP更加讽刺美国人。&lt;br>
比如美国电视不允许出现 F-word 这个脏话，&lt;br>
SP就在其中的某一集里面塞了两百多个 F-word…&lt;/p>
&lt;p>总而言之，&lt;br>
在南方公园，&lt;br>
所有人都会被黑。&lt;br>
但就是这一点让它变得特别：&lt;br>
&lt;strong>想要黑人，先要自黑。&lt;/strong>&lt;/p>
&lt;h2 id="从第几集看起呢">从第几集看起呢？&lt;/h2>
&lt;p>南方公园到现在已经有快20季，总共200集了。&lt;br>
但是剧情之间连贯性不是特别强，&lt;br>
所以想看的话可以从最新的18, 19季开始看起。&lt;br>
（直接到B站上搜 南方公园 就有资源了）&lt;/p>
&lt;p>或者也可以挑一些精彩的话题性单集看：&lt;/p>
&lt;ul>
&lt;li>
&lt;p>南方公园第8季第7集：迈克尔杰弗逊 (SP S08E07: The Jeffersons)&lt;/p>
&lt;/li>
&lt;li>
&lt;p>南方公园第10季第8集：魔兽世界 (SP S10E08: Make love, not Warcraft)&lt;/p>
&lt;/li>
&lt;li>
&lt;p>南方公园第17季第7/8集：冰与火之歌 (SP S17E07/08: A Song Of Ass and Fire)&lt;/p>
&lt;/li>
&lt;/ul>
&lt;p>不过不管从哪看起，&lt;br>
也改变不了你们是愚蠢的人类这个事实。&lt;br>
科科。&lt;/p></description></item><item><title>原来我喜欢的是打底裤</title><link>https://liriansu.com/posts/2017-07-30-girls-stockings/</link><pubDate>Sun, 30 Jul 2017 18:24:30 +0000</pubDate><guid>https://liriansu.com/posts/2017-07-30-girls-stockings/</guid><description>&lt;p>以前一直觉得穿黑色丝袜的小姐姐们好好看啊，&lt;br>
后来才知道，&lt;br>
我以为好看的那些都是打底裤。&lt;/p>
&lt;h2 id="背景">背景&lt;/h2>
&lt;p>以前的某个春天，&lt;br>
跟女朋友在街上闲逛的时候，&lt;br>
我感慨了一句：&lt;br>
“怪不得那么多男人喜欢黑丝，&lt;br>
PLMM穿黑丝是好看啊。“&lt;br>
女朋友鄙视了我一眼：&lt;br>
“你以为的黑丝，&lt;br>
其实都是打底裤。”&lt;br>
我：“啊？！？！？”&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/stockings/wtf.jpg" alt="wtf">&lt;/p>
&lt;p>年幼的我对黑丝的理解很简单：&lt;br>
“穿在腿上的，&lt;br>
黑的，&lt;br>
看起来有丝的感觉，&lt;br>
那应该就是黑丝了。”&lt;/p>
&lt;p>然后女朋友问我：&lt;br>
“你知道黑丝、裤袜、打底裤、紧身裤的区别吗？”&lt;/p>
&lt;p>“……啥啥啥？能再问一遍吗。。。”&lt;/p>
&lt;p>“你知道黑丝、裤袜、打底裤、紧身裤有什么区别不？”&lt;/p>
&lt;p>“……噢噢噢，紧身裤我知道！&lt;br>
紧身的裤子！&lt;br>
搞摇滚的特喜欢！&lt;br>
就是汪峰那种！”&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/cold.jpg" alt="cold">&lt;/p>
&lt;p>后来女朋友跟我稍微解释了一下，&lt;br>
再配合维基等解释，&lt;br>
我稍微总结一下这几个名词的区别：&lt;/p>
&lt;h2 id="丝袜">丝袜&lt;/h2>
&lt;p>丝袜就是丝质的袜子，&lt;br>
黑丝就是黑色的丝袜。&lt;/p>
&lt;p>这句话有没有很有韵律感，&lt;br>
感觉随时都要寻找光明了。&lt;/p>
&lt;p>一般来说丝袜都比较透，&lt;br>
像那种腿毛比较旺盛的妹子，&lt;br>
假如不刮腿毛的话，&lt;br>
穿浅色丝袜就容易不好看。&lt;br>
所以从这个角度上来说，&lt;br>
黑色丝袜也更受欢迎。&lt;br>
而且&lt;a href="https://www.zhihu.com/question/20320697">黑色显瘦&lt;/a>嘛。&lt;/p>
&lt;h2 id="裤袜">裤袜&lt;/h2>
&lt;p>裤袜其实可以算是丝袜的一种，&lt;br>
分不清也不是你的错。&lt;/p>
&lt;p>裤袜就是像裤子一样的丝袜，&lt;br>
普通的丝袜是袜子，&lt;br>
是两只一对的。&lt;br>
裤袜就只有一条，&lt;br>
它是连在一起的。&lt;/p>
&lt;h2 id="打底裤">打底裤&lt;/h2>
&lt;p>首先打底裤跟&lt;a href="https://zh.moegirl.org/zh-hans/%E5%AE%89%E5%85%A8%E8%A3%A4">安全裤&lt;/a>肯定是有区别的。&lt;br>
&lt;del>作为一个舞区观众，&lt;br>
我大概很了解安全裤&lt;/del>&lt;/p>
&lt;p>打底裤是长裤，&lt;br>
好像说最开始功能跟安全裤类似，&lt;br>
都是防走光打底用的。&lt;br>
但是因为一些打底裤穿着很舒服，&lt;br>
也很自然地变成了单穿的长裤。&lt;/p>
&lt;p>春秋之际路上小姐姐穿的黑色薄薄的裤子，&lt;br>
其实很多都是打底裤。&lt;/p>
&lt;h2 id="紧身裤">紧身裤&lt;/h2>
&lt;p>没错，就是汪峰的那种裤子。&lt;/p>
&lt;h2 id="总结">总结&lt;/h2>
&lt;p>女朋友看完了我上面的解释，&lt;br>
表示我总结的很好，&lt;br>
但是理解的不对：&lt;br>
现在丝袜大部分也是连在一起的了，&lt;br>
裤袜比丝袜要厚。&lt;/p>
&lt;p>我：&lt;br>
ToT 不听不懂不学不看，&lt;br>
太复杂啦。&lt;br>
我只知道，&lt;br>
原来我不喜欢黑丝，&lt;br>
我喜欢打底裤。&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/stockings/what.jpg" alt="what">&lt;/p></description></item><item><title>现金牛是什么梗？</title><link>https://liriansu.com/posts/2017-07-27-what-is-cash-cow/</link><pubDate>Thu, 27 Jul 2017 22:31:18 +0000</pubDate><guid>https://liriansu.com/posts/2017-07-27-what-is-cash-cow/</guid><description>&lt;p>最近产品经理小刘很苦恼，&lt;br>
因为别人一直问他，&lt;br>
PPT上面的&lt;em>现金流&lt;/em>是不是写错了？&lt;br>
写成了&lt;em>现金牛&lt;/em>?&lt;/p>
&lt;p>故事的背景大概是，&lt;br>
因为客户在我们的云平台上管理会员，&lt;br>
所以我们想免费给他们展示一波数据，&lt;br>
给他们做商业决策来点帮助。&lt;/p>
&lt;h2 id="swot">SWOT&lt;/h2>
&lt;p>说到商业决策的分析方法，&lt;br>
有个&lt;a href="https://en.wikipedia.org/wiki/SWOT_analysis">很著名的 SWOT 分析法&lt;/a>，&lt;br>
会从四个维度来分析当前形势：&lt;/p>
&lt;ul>
&lt;li>S, Strengths, 优势，&lt;/li>
&lt;li>W, Weaknesses, 劣势；&lt;/li>
&lt;li>O, Opportunities, 机遇，&lt;/li>
&lt;li>T, Threats, 威胁。&lt;/li>
&lt;/ul>
&lt;p>比如诸葛亮在三顾茅庐作的&lt;a href="https://baike.baidu.com/item/%E9%9A%86%E4%B8%AD%E5%AF%B9/188772">隆中对&lt;/a>，&lt;br>
就是典型的 SWOT 分析：&lt;br>
&lt;em>举个栗子，不要在意细节&lt;/em>&lt;/p>
&lt;ul>
&lt;li>优势：&lt;code>将军既帝室之胄，信义著于四海。&lt;/code>&lt;/li>
&lt;li>劣势：&lt;code>今操已拥百万之众，挟天子以令诸侯，此诚不可与争锋。&lt;/code>&lt;/li>
&lt;li>机遇：&lt;code>刘璋暗弱，张鲁在北，民殷国富而不知存恤，智能之士思得明君。&lt;/code>&lt;/li>
&lt;li>威胁：&lt;code>将军身率益州之众出于秦川，百姓孰敢不箪食壶浆，以迎将军者乎？&lt;/code>&lt;/li>
&lt;/ul>
&lt;p>把 SWOT 画成&lt;a href="https://zh.wikipedia.org/zh-hans/%E8%AF%B1%E5%AF%BC%E5%85%AC%E5%BC%8F">&lt;code>奇变偶不变符号看象限&lt;/code>&lt;/a>的图大概是这样子：&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/bcg/swot.jpg" alt="swot-matrix">&lt;/p>
&lt;p>很多鸡汤小故事里会描述一个这样的场景：&lt;/p>
&lt;blockquote>
&lt;p>A公司以前发展很快，&lt;br>
但是最近陷入瓶颈了，&lt;br>
老板很苦恼。&lt;/p>
&lt;p>后来他们花一百万美金请了专业商业公司B的人来分析，&lt;br>
这个B公司的人花了一个月的时间实地考察，&lt;br>
然后花了两天画了一个 PPT,&lt;br>
上面就两张图。&lt;br>
一张是家人合照，&lt;br>
因为美国人都很有家庭观念。&lt;br>
另外一张就是 SWOT 分析。&lt;/p>
&lt;p>A公司老板很气愤：&lt;br>
“我花一百万不是让你来做 PPT 的！”&lt;br>
这个B公司的人很平静地回复道：&lt;br>
“是的，你画十块钱也能让别人做 PPT,&lt;br>
但是只有一百万才能买得到我们的 SWOT 分析。”&lt;/p>
&lt;p>听了这个精彩回答，&lt;br>
会议场上顿时响起了经久不绝的热烈掌声。&lt;br>
最后A公司的人照着 SWOT 分析的建议严格地去做了，&lt;br>
果然药到病除，&lt;br>
公司又回到了飞速增长的道路上。&lt;/p>
&lt;/blockquote>
&lt;p>:)&lt;/p>
&lt;p>故事里可能扯皮的有点多，&lt;br>
但是我们可以大概了解到：&lt;br>
这种商业分析更多是用一定的姿势，&lt;br>
从多个角度去看问题，&lt;br>
最终提供了一个范用的方法论。&lt;br>
假如真的像故事里&lt;code>严格地去做&lt;/code>这么有行动力的话，&lt;br>
那肯定是有正面的效果的。&lt;/p>
&lt;h2 id="bcg-matrix">BCG-matrix&lt;/h2>
&lt;p>那么类似的，&lt;br>
&lt;em>现金牛&lt;/em>这个词其实是出自另外一套分析方法。&lt;/p>
&lt;p>产品经理小刘预设了大家都跟他有一样丰富的人生经验，&lt;br>
上来就丢了这么一张图：&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/bcg/base.jpg" alt="base">&lt;/p>
&lt;p>&lt;em>当然实际上他放的图更加专业，&lt;br>
这图是作者随便翻译和随便画的&lt;/em>&lt;/p>
&lt;p>大家有点懵逼，&lt;br>
然后快速地指出了图里有个错别字。&lt;/p>
&lt;p>小刘没有办法，&lt;br>
只能给大家说了些洋文，&lt;br>
举了个栗子：&lt;/p>
&lt;p>首先，你现在是一家跨国大型公司的老总。&lt;br>
你手下有二十万个员工，两百个厂房，五十多条产品线。&lt;br>
每月的十号都是发薪日，&lt;br>
作为一个不拖欠工资，&lt;br>
遵守劳动法，&lt;br>
有良心的资本家，&lt;br>
你发现每月九号账上还很多的现金，&lt;br>
十号就所剩无几了。&lt;br>
而且你的利润率还比隔壁黑心企业低很多。&lt;/p>
&lt;p>于是你看着上文提及的五十多条产品线，开始思考：&lt;br>
&lt;strong>哪些产品赚钱？哪些产品可以下线？哪些产品有增长空间？&lt;/strong>&lt;/p>
&lt;p>因为你在交大读过 MBA ,&lt;br>
SWOT 的故事你也听过，&lt;br>
觉得那个是针对公司策略，&lt;br>
或者单个产品的。&lt;br>
你不想画五千多万做 SWOT 分析，&lt;br>
于是你请来了&lt;del>圣地亚哥&lt;/del>波士顿咨询公司的人。&lt;/p>
&lt;p>这群人依据老祖宗的&lt;code>奇变偶不变符号看象限&lt;/code>的道理，&lt;br>
一边画图一边说：&lt;/p>
&lt;blockquote>
&lt;p>To analyze the business, we should plot&amp;hellip;&lt;/p>
&lt;/blockquote>
&lt;p>你打断了他们的施法：&lt;/p>
&lt;blockquote>
&lt;p>Chinese please, excuse my bad English&lt;/p>
&lt;/blockquote>
&lt;p>于是他们用中文介绍了起来：&lt;/p>
&lt;p>老总啊，贵司的问题很大一部分是现金流不明确啊。&lt;br>
这样子，我们画个图，&lt;br>
横轴呢，从左到右是 ** 挣钱多 &amp;gt; 挣钱少 **&lt;br>
纵轴呢，从下到上是 ** 花钱少 &amp;gt; 花钱多 **&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/bcg/en.jpg" alt="en">&lt;/p>
&lt;p>于是从现金这个角度，&lt;br>
根据这两个维度，&lt;br>
四个区域我们来看看贵司的产品们。&lt;/p>
&lt;ul>
&lt;li>
&lt;p>左上角的&lt;strong>Stars 明星产品&lt;/strong>。&lt;br>
这种产品挣的钱多，花的也多！&lt;br>
比如你们天天在电视上做广告的那个，&lt;br>
虽然卖得好，但是天价广告费。&lt;br>
别人认识贵司都是从这些产品开始，&lt;br>
可要保持。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>左下角的&lt;strong>Cash Cows 现金牛&lt;/strong>。&lt;br>
没错，这种就是花的少、挣的多的产品。&lt;br>
它们给贵司带来了长足的收入啊！&lt;br>
就跟牛一样，吃进去的是草，挤出来的是奶！&lt;br>
非常好！多关照！&lt;/p>
&lt;/li>
&lt;li>
&lt;p>右下角的&lt;strong>Dogs 老狗&lt;/strong>。&lt;br>
别看他们现在挣得少，花的少，没啥存在感，&lt;br>
但他们一般是贵司的现金牛转换过来的，&lt;br>
比如贵司的那个老牌数码相机，&lt;br>
以前很赚钱的，但是最近居然被智能手机给干下去了。&lt;br>
这些产品有情怀就维持一下吧。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>右上角的&lt;strong>Question Marks 问题少年&lt;/strong>。&lt;br>
这个，挣得少还花的多，&lt;br>
我们还真不好预测。&lt;br>
比如某巨头，&lt;br>
之前连续十年亏损也一样头变大了。&lt;br>
这些产品很有可能会变成你的明星产品，&lt;br>
乃至现金牛。&lt;/p>
&lt;/li>
&lt;/ul>
&lt;p>老总觉得这很科学。&lt;br>
后来波士顿咨询公司回去总结了一下，&lt;br>
这个套路就慢慢变成了一种范用的分析方式了，&lt;br>
大家叫它 &lt;a href="https://en.wikipedia.org/wiki/Growth%E2%80%93share_matrix">BCG-matrix (波士顿咨询公司矩阵)&lt;/a>&lt;/p>
&lt;h2 id="说明">说明&lt;/h2>
&lt;p>因为此文偏向讲梗，&lt;br>
所以很多地方夹杂魔改过的私货。&lt;br>
正统的横轴是 Relative market share,&lt;br>
纵轴是 Market growth rate，&lt;br>
Question Marks 和 Dogs 的翻译也是我随便翻的…&lt;br>
想了解更精确的内容请&lt;a href="https://en.wikipedia.org/wiki/Growth%E2%80%93share_matrix">自行查阅维基&lt;/a>。&lt;/p></description></item><item><title>程序员的二八定律</title><link>https://liriansu.com/posts/2017-07-25-pareto-rule-of-programmers/</link><pubDate>Tue, 25 Jul 2017 23:15:51 +0000</pubDate><guid>https://liriansu.com/posts/2017-07-25-pareto-rule-of-programmers/</guid><description>&lt;p>二八定律 (Pareto Principle),&lt;br>
泛指在各种事情中，&lt;br>
80%的结果是由20%的原因决定的，&lt;br>
这个定律一般用来定性而不是定量。&lt;/p>
&lt;p>很有趣的是，&lt;br>
程序员们就很吃这个定律。&lt;/p>
&lt;ul>
&lt;li>
&lt;p>20%的程序员写出了80%的代码。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>20%的程序员写出了80%的Bug。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>80%的代码出的Bug只占20%。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>也就是说有80%的Bug，是出在20%的代码里面。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>为了修复这20%的代码，程序员花掉了80%的时间。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>所以有80%的程序员，每天写代码的时间不到20%。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>80%的程序员都有自己偏好的编程语言，但只有20%的程序员会去辩论&lt;em>什么是世界上最好的编程语言&lt;/em>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>80%的纷争都是这20%的程序员搞起来的。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>80%的编程语言都是20%的程序员搞起来的。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>一门编程语言里，只有20%的功能会被经常用到。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>但是面试题目范围在另外80%里面。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>假如不点名地去黑一门语言，那不管你黑的是哪个点，有80%的用户都会觉得自己喜欢的语言被黑了。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>所以程序员们一般去黑剩下的那20%的编程语言。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>80%的程序员都在面向对象编程，但是只有20%的程序员有对象（此数据有偏差）&lt;/p>
&lt;/li>
&lt;li>
&lt;p>80%的程序员都知道小黄鸭编程法，但是只有20%的程序员有小黄鸭。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>80%的小黄鸭都被程序员抓起来了，此处应 @小黄鸭保护协会&lt;/p>
&lt;/li>
&lt;li>
&lt;p>80%的需求可以在20%的时间里面实现。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>剩下20%的需求要花80%的时间去研究，20%的时间去实现，80%的时间去测试。（没错总共是200%的时间）&lt;/p>
&lt;/li>
&lt;li>
&lt;p>不还技术债的话，80%的时间连20%的需求都做不完…&lt;/p>
&lt;/li>
&lt;li>
&lt;p>坚持还技术债、不断学习、提升自我的话，那就是&lt;/p>
&lt;/li>
&lt;/ul>
&lt;blockquote>
&lt;p>10 percent luck&lt;/p>
&lt;p>20 percent skill&lt;/p>
&lt;p>15 percent concentrated power of will.&lt;/p>
&lt;p>5 percent pleasure&lt;/p>
&lt;p>50 percent pain&lt;/p>
&lt;p>and 100 percent reason&lt;br>
to remember the name&lt;/p>
&lt;/blockquote></description></item><item><title>GitHub 要怎么玩</title><link>https://liriansu.com/posts/2017-07-18-how-i-use-github/</link><pubDate>Tue, 18 Jul 2017 23:15:49 +0000</pubDate><guid>https://liriansu.com/posts/2017-07-18-how-i-use-github/</guid><description>&lt;p>经常会听到其它程序员说：&lt;/p>
&lt;p>哎呀，又在 GitHub 上发现了个好玩的项目。&lt;/p>
&lt;p>那么问题来了，&lt;br>
他们怎么发现的呢？&lt;/p>
&lt;h2 id="github-是什么">GitHub 是什么&lt;/h2>
&lt;p>知乎上有个万赞答案写的很好，&lt;br>
叫 &lt;a href="https://www.zhihu.com/question/20070065/answer/79557687">怎样使用 GitHub ? - 珊姗的回答&lt;/a>&lt;/p>
&lt;p>不过里面的图有点过时，&lt;br>
新版的 GitHub 大概是这样的：&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/github/mine_panel.jpg" alt="user-page">&lt;/p>
&lt;p>学术地说：&lt;/p>
&lt;blockquote>
&lt;p>GitHub 是一个通过 Git 进行版本控制的软件源代码托管服务，&lt;br>
它是世界上最大的代码存放网站和开源社区。&lt;/p>
&lt;/blockquote>
&lt;p>简单的来说：&lt;/p>
&lt;p>&lt;strong>GitHub 是程序员放程序的地方。&lt;/strong>&lt;/p>
&lt;p>这里说的&lt;code>放&lt;/code>不仅指存放、放置，&lt;br>
还有放开、共享的意思。&lt;/p>
&lt;p>&lt;a href="https://github.com/NARKOZ/hacker-scripts">普通程序员会把自己业余写的一些工具放到 GitHub 上去&lt;/a>，&lt;br>
&lt;a href="https://github.com/fouber/blog/issues/1">文艺程序员会把 GitHub 当做写博客的地方&lt;/a>,&lt;br>
&lt;a href="https://shell909090.org/blog/archives/2792/">2B程序员会把公司的商业代码上传到 GitHub 上去&amp;hellip;&lt;/a>。。。&lt;/p>
&lt;h2 id="github-有什么好玩的">GitHub 有什么好玩的&lt;/h2>
&lt;p>那既然 GitHub 是程序员放程序的地方，&lt;br>
听起来这么严肃，&lt;br>
它怎么可能跟好玩沾上边？&lt;/p>
&lt;p>这个问题问得很好。&lt;br>
在我眼里，&lt;br>
所有程序员都是可爱的动物，&lt;br>
有一个词叫&lt;a href="https://www.reddit.com/r/ProgrammerHumor/">Programming Humor&lt;/a>，&lt;br>
翻译成中文大概是&lt;em>代码之趣&lt;/em>。&lt;br>
比如&lt;a href="https://xkcd.com">我很喜欢的XKCD系列漫画&lt;/a>，&lt;br>
就有很多关于代码的好玩的梗：&lt;/p>
&lt;p>&lt;img src="https://imgs.xkcd.com/comics/random_number.png" alt="xkcd221">&lt;/p>
&lt;p>（我凭本事丢骰子丢的4，&lt;br>
你为什么说这个数字不够随机？）&lt;/p>
&lt;p>&lt;img src="https://imgs.xkcd.com/comics/python.png" alt="xkcd353">&lt;/p>
&lt;p>（Python 大法好！）&lt;/p>
&lt;p>GitHub 上也有很多很好玩的东西。&lt;/p>
&lt;p>比如&lt;a href="https://github.com/mackyle/sqlite/blob/3cf493d4018042c70a4db733dd38f96896cd825f/src/os.h#L52-L62">etilqs的梗&lt;/a>:&lt;/p>
&lt;blockquote>
&lt;p>有个小型数据库软件叫 SQLite ，&lt;br>
它非常好用。&lt;/p>
&lt;p>于是知名杀毒软件 McAfee 就用了这个数据库，&lt;br>
McAfee 还以 sqlite_ 当文件名丢了很多文件在C盘放着。&lt;/p>
&lt;p>不懂计算机的用户们，装上 McAfee 以后发现，&lt;br>
C盘多了好多奇怪的文件。&lt;/p>
&lt;p>于是他们有些人 Google 到了 sqlite 的研发工程师的电话，&lt;br>
半夜打电话去吵醒工程师，&lt;br>
问C盘里多出来的这些文件是干啥的……&lt;/p>
&lt;p>后来 sqlite 就决定把临时文件的名字改成 etilqs。&lt;/p>
&lt;p>假如有人能分别得出这个词，&lt;br>
是 sqlite 反过来写。&lt;br>
那以他的智商，&lt;br>
也不至于半夜打电话叫醒 sqlite 的研发工程师了……&lt;/p>
&lt;/blockquote>
&lt;p>比如前阵子，&lt;br>
好几家公司有新闻的时候，&lt;br>
就有个&lt;a href="https://github.com/shengxinjing/programmer-job-blacklist">programming-job-blacklist&lt;/a>的项目，&lt;br>
列了一堆程序员找工作的黑名单公司&lt;br>
（列表皆整理，请谨慎食用）&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/gaoshi.jpg" alt="gaoshi">&lt;/p>
&lt;p>当然，&lt;br>
还有&lt;a href="https://github.com/avinassh/rockstar">酷炫的“是男人就一年不断 Contribution”的刷 Contribution 的项目&lt;/a>。&lt;br>
一分钟就可以让你变得绿油油的：&lt;/p>
&lt;p>&lt;img src="https://github.com/avinassh/rockstar/raw/master/images/greensgreensgreens.png" alt="contribution">&lt;/p>
&lt;h2 id="那-github-要怎么玩呢">那 GitHub 要怎么玩呢？&lt;/h2>
&lt;p>正如鲁迅说过：&lt;br>
有人的地方就会有江湖。&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/not_said.jpg" alt="no-i-didnt">&lt;/p>
&lt;p>作为一个以 &lt;a href="https://en.wikipedia.org/wiki/User-generated_content">UGC&lt;/a> 为主的网站，&lt;br>
我们当然是要关注更多的用户。&lt;/p>
&lt;p>我在 GitHub 上主要关注了三种用户（此分类不正交）：&lt;/p>
&lt;ol>
&lt;li>
&lt;p>一般意义上的大神，这些人粉着以示膜拜。&lt;br>
比如&lt;a href="https://zhuanlan.zhihu.com/p/20346580">从胖子变帅哥的Python程序员Kenneth Reitz&lt;/a>，&lt;br>
经常可以看看他又被哪个组织拉进去了，&lt;br>
又给哪个项目贡献代码了。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>项目作者、文章博主，这些人做的东西往往看着更好玩。&lt;br>
比如&lt;a href="https://github.com/Ovilia">羡辙学姐&lt;/a>，&lt;br>
占着一个巨好的 GitHub ID 不说，&lt;br>
我对前端的不少了解都是羡辙和&lt;a href="https://github.com/yyx990803">尤大&lt;/a>的feed刷出来的。&lt;br>
比如&lt;a href="https://github.com/haoel">皓哥&lt;/a>，&lt;br>
虽然他目前好像忙着搞事，&lt;br>
不过毕竟是一直奋斗在写代码一线的我辈楷模。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>我喜欢的身边的朋友，平时有更多可能性交流技术。&lt;br>
比如有&lt;a href="https://github.com/ldsink">基友ldsink&lt;/a>，&lt;br>
toolbox的一些脚本非常好用。&lt;br>
比如有&lt;a href="https://github.com/hczhcz">交大魔法师hcz&lt;/a>，&lt;br>
很多好玩的项目都是他给我的timeline刷出来的。&lt;/p>
&lt;/li>
&lt;/ol>
&lt;p>所以总结一下。&lt;/p>
&lt;p>GitHub 就是这么一个本来是放程序，&lt;br>
但是被玩成了同性交友的社交网站…&lt;/p>
&lt;p>（嗯，本文以一个讲梗的角度讲了下 GitHub ）&lt;/p></description></item><item><title>那当然是选择原谅她是什么梗</title><link>https://liriansu.com/posts/2017-07-02-forgive-her-meme/</link><pubDate>Sun, 02 Jul 2017 23:05:08 +0000</pubDate><guid>https://liriansu.com/posts/2017-07-02-forgive-her-meme/</guid><description>&lt;p>“她做了对不起我的事情，该怎么办？”&lt;br>
“那当然是选择原谅她啦！”&lt;/p>
&lt;h2 id="绿帽子">绿帽子&lt;/h2>
&lt;p>绿帽子这个词好像流传已久了。&lt;/p>
&lt;p>有说是春秋时期，&lt;br>
卖淫为生的人的家人要头裹绿巾，&lt;br>
以分贵贱。&lt;/p>
&lt;p>还有个比较逗的说法是，&lt;br>
古代有个已婚女士搞外遇，&lt;br>
每次早上丈夫出门，&lt;br>
她都给丈夫戴上一顶绿帽子，&lt;br>
以此作为明显的暗号。&lt;/p>
&lt;p>总而言之，&lt;br>
不论如何，&lt;br>
这个偏侮辱性的词语就流传了下来。&lt;/p>
&lt;p>不过最近的一个梗把这个侮辱性给弱化了…&lt;/p>
&lt;h2 id="那当然是选择原谅她">那当然是选择原谅她&lt;/h2>
&lt;p>这个&lt;a href="https://zh.moegirl.org/zh-hans/%E5%BD%93%E7%84%B6%E6%98%AF%E9%80%89%E6%8B%A9%E5%8E%9F%E8%B0%85%E5%A5%B9">短句的出处也是不一的&lt;/a>，&lt;br>
有说是&lt;a href="https://www.douyu.com/pis">卜同学&lt;/a>，&lt;br>
也有说是白同学…&lt;/p>
&lt;p>不过事实就是最近的表情包的确为它的热度推波助澜了：&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/forgive/of_course.jpg" alt="of-course">&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/forgive/be_strong.jpg" alt="be-strong">&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/forgive/enough.jpg" alt="enough">&lt;/p>
&lt;p>后来逐渐发展出了原谅帽系列表情：&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/forgive/hat.jpg" alt="hat">&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/forgive/take_my_hat.jpg" alt="take-my-hat">&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/forgive/hat_pa.jpg" alt="hat-pa">&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/forgive/hat_papapa.jpg" alt="hat-papapa">&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/forgive/hat_ulti_pa.jpg" alt="hat-ulti-pa">&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/forgive/hat_fight.jpg" alt="hat-fight">&lt;/p>
&lt;p>还有人做了原谅帽的游戏…&lt;br>
&lt;a href="https://green.ssyar.com/">green.ssyar.com&lt;/a>&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/forgive/hat_game.jpg" alt="hat-game">&lt;/p>
&lt;p>当然，&lt;br>
这个梗火了以后就会有对应的讨论：&lt;/p>
&lt;p>&lt;a href="https://www.zhihu.com/question/58602662">知乎：“当然是选择原谅她啊”系列表情图是不是歧视女性&lt;/a>&lt;/p>
&lt;p>&lt;a href="https://www.zhihu.com/question/58756792">知乎：“当然是选择原谅她啊”系列表情图是不是歧视男性&lt;/a>&lt;/p>
&lt;p>&amp;hellip;&lt;/p>
&lt;p>不过这个表情包真的很好玩啊，&lt;br>
每次我们谁写了个bug，&lt;br>
多了个需求，&lt;br>
就一下子想到了原谅帽了…&lt;/p>
&lt;h2 id="saint-patricks-day">Saint Patrick&amp;rsquo;s Day&lt;/h2>
&lt;p>爱尔兰有个节日叫&lt;a href="https://en.wikipedia.org/wiki/Saint_Patrick%27s_Day">Saint Patrick&amp;rsquo;s Day&lt;/a>，&lt;br>
大概讲的就是很久很久以前，&lt;br>
有个厉害的人到爱尔兰，&lt;br>
向大家传播了基督教感化了大家…&lt;/p>
&lt;p>于是在那一天，&lt;br>
大家都会穿上爱尔兰国旗颜色（绿色）的衣物、袜子、帽子，&lt;br>
聚在一起，&lt;br>
喝酒…&lt;/p>
&lt;p>就像中国人，&lt;br>
不论什么节都会过成情人节一样。&lt;br>
外国很多节，&lt;br>
最终都会变成喝酒的节…&lt;/p>
&lt;p>那这该怎么办呢？&lt;br>
当然是选择原谅她啦~&lt;/p></description></item><item><title>写程序的我的性格</title><link>https://liriansu.com/posts/2017-07-01-my-programmer-habits/</link><pubDate>Sun, 02 Jul 2017 00:20:23 +0000</pubDate><guid>https://liriansu.com/posts/2017-07-01-my-programmer-habits/</guid><description>&lt;p>写程序真开心啊。&lt;/p>
&lt;p>前阵子面试频繁的时候，&lt;br>
有一个工作了七八年的兄弟在简历上写，&lt;br>
自己大学学的是Java，&lt;br>
工作以后做的是全栈，&lt;br>
所以有十多年的Java开发经验，&lt;br>
七八年的前端开发经验，&lt;br>
还有若干年的Blabla&amp;hellip;&lt;/p>
&lt;p>当时周丞和我就很无奈，&lt;br>
假如工作经验真的是这么算的话。&lt;br>
那中学时期就开始参加OI的同学，&lt;br>
岂不是都是十年软件开发经验起步了？&lt;/p>
&lt;h2 id="经验">经验&lt;/h2>
&lt;p>我一直觉得软件开发的，&lt;br>
或者说程序员的，&lt;br>
“工作经验”是一件很扯的事情。&lt;br>
因为假如程序员停止了学习、思考与进步，&lt;br>
那么一个有十年工作经验的人，&lt;br>
只不过是工作的第一年学习了一年的工作经验，&lt;br>
然后又重复了九年。&lt;br>
真正的十年工作经验，&lt;br>
应该是那些“苟日新，日日新，又日新。”的人。&lt;/p>
&lt;blockquote>
&lt;p>有一句俗话叫&lt;br>
朝闻道，夕死可矣。&lt;/p>
&lt;p>这句话的意思就是一个人早上听到了一个很科学的道理，&lt;br>
想了一天，&lt;br>
到了傍晚终于发出了“死可矣”(すごい)的感慨之声。&lt;/p>
&lt;/blockquote>
&lt;p>当然，&lt;br>
人的一生不可能每天都在学习崭新的姿势，&lt;br>
就算某一天了解到了新的知识，&lt;br>
也不一定能够消化吸收，&lt;br>
说不定隔夜就忘了。&lt;/p>
&lt;p>不过我们人类这种生命，&lt;br>
正是所有过去的积淀。&lt;br>
我们读的书、&lt;br>
吃的饭、&lt;br>
做的事情都会消失，&lt;br>
但是我们的生命会越来越厚重。&lt;/p>
&lt;p>举个栗子，&lt;br>
我是记不得我写过的每一行代码的，&lt;br>
但是我能清晰地感觉到，&lt;br>
我身上有些特质，&lt;br>
和写程序有着一定的羁绊。&lt;/p>
&lt;ol>
&lt;li>懒&lt;/li>
&lt;li>科学&lt;/li>
&lt;li>试试看&lt;/li>
&lt;li>问个问题&lt;/li>
&lt;/ol>
&lt;h2 id="懒">懒&lt;/h2>
&lt;p>Quora上有个问题是&lt;br>
&lt;a href="https://www.quora.com/Do-intelligent-lazy-people-achieve-more-in-life-than-intelligent-active-people">聪明人里面，懒人是不是比勤奋的人贡献更大？&lt;/a>&lt;br>
有个回答我非常喜欢：&lt;/p>
&lt;blockquote>
&lt;p>“I divide my officers into four classes; the clever, the lazy, the industrious, and the stupid. Each officer possesses at least two of these qualities. Those who are clever and industrious are fitted for the highest staff appointments. Use can be made of those who are stupid and lazy. The man who is clever and lazy however is for the very highest command; he has the temperament and nerves to deal with all situations. But whoever is stupid and industrious is a menace and must be removed immediately!”&lt;br>
— General Kurt von Hammerstein-Equord&lt;/p>
&lt;p>在我眼里，我的下属们一共占了四种属性：&lt;br>
聪明的、懒的、勤奋的、蠢的。&lt;br>
他们每一个人都占了两种属性以上。&lt;/p>
&lt;p>那些既聪明又勤奋的人会做最重要的事情，&lt;br>
同样地，那些又蠢又懒的人也只会做最不重要的事情。&lt;br>
一个聪明的懒人也可以做很重要的事情，他有能力去处理各种事态。&lt;br>
假如一个人不仅蠢，生产力还巨高，那得马上开掉他！&lt;br>
by 一个可能有名的将军&lt;/p>
&lt;/blockquote>
&lt;p>我部分赞同这个答案，&lt;br>
因为我不仅自认为是一个聪明的懒人，&lt;br>
我还认为大部分好的程序员都是聪明的懒人。&lt;/p>
&lt;p>程序员很喜欢干的一件事情就是“自动化”。&lt;br>
GitHub之前有个&lt;a href="https://github.com/NARKOZ/hacker-scripts">很火的Repo (NARKOZ/hacker-scripts)&lt;/a>，&lt;br>
讲的是有个程序员离职以后，&lt;br>
其他同事在整理他写的程序。&lt;br>
发现他不仅写了一个自动泡咖啡的程序，&lt;br>
还写了一个“假如晚上九点电脑还开着，就随机编一个理由，给老婆发短信说会晚回家…”&lt;/p>
&lt;p>所以我想说的懒，&lt;br>
其实是“程序员式的懒”：&lt;br>
不是不想干活，&lt;br>
而是不想干重复性的工作；&lt;br>
相比于简单但重复的解决办法，&lt;br>
更愿意选择工作量大但一劳永逸的办法。&lt;/p>
&lt;p>毕竟聪明人支起世界，&lt;br>
懒人改变世界嘛。&lt;/p>
&lt;h2 id="科学">科学&lt;/h2>
&lt;p>我有两个口头禅，&lt;br>
一个是“这很科学”，&lt;br>
一个是“这不科学”。&lt;/p>
&lt;p>一方面，&lt;br>
我认为“万物都有自己的规律”，&lt;br>
“物理世界存在大一统定律”，&lt;br>
“事出反常必有妖”，&lt;br>
“程序不会自己出bug，都是人写的”，&lt;br>
“多用git blame我们就能找到那个人了”。&lt;/p>
&lt;p>另一方面，&lt;br>
我也认为“人类是愚蠢的，是短视的”，&lt;br>
“所以很多规律人类都没发现，比如关于人类自己的”，&lt;br>
“像老师、HR、销售等，跟人打交道的，都是厉害的”，&lt;br>
“更别提艺术那种，一千个人就有一千个freestyle的学科了”。&lt;/p>
&lt;p>比如程序员修bug，&lt;br>
首先第一步要做的就是问一句：&lt;br>
“能重现吗？怎么重现？”&lt;br>
假如一个bug不能重现，&lt;br>
我们就会说：&lt;br>
“我这咋是好的，重现不了，不修了。”&lt;br>
假如一个bug不能重现，&lt;br>
但是它很严重，&lt;br>
必须要修复，&lt;br>
我们就会感慨：&lt;br>
“卧槽，这不科学啊…”&lt;/p>
&lt;h2 id="试试看">试试看&lt;/h2>
&lt;p>直到目前为止，&lt;br>
程序都是为人服务的。&lt;br>
人是活在现实生活中的，&lt;br>
所以实践证明一切。&lt;/p>
&lt;p>假如两个程序员battle，&lt;br>
基本上一句话可以终结：&lt;br>
&lt;code>Talk is cheap, show me the code&lt;/code>。&lt;/p>
&lt;p>因为万事万物都是有规律的，&lt;br>
一定的条件下，&lt;br>
试一次就可以学到了。&lt;br>
比如压缩食物怎么样？试一试呗。&lt;br>
创业公司是什么样子？试一试呗。&lt;br>
Kotlin和Java有什么不同？试一试呗。&lt;/p>
&lt;p>就像诸葛亮用标记重捕法发现南蛮之地盛产孟获一样，&lt;br>
程序员也经常会用控制变量法来尝试。&lt;br>
比如之前说的重现一个bug，&lt;br>
试试ios，试试安卓，&lt;br>
试试win xp，试试有360的电脑。&lt;br>
世界这么大，&lt;br>
我们总会再见的。&lt;/p>
&lt;h2 id="问个问题">问个问题&lt;/h2>
&lt;p>小时候看过一个比喻，&lt;br>
说人的知识是一个圆，&lt;br>
知道的是面积，&lt;br>
不知道的是周长。&lt;br>
（翻译成鸡汤就是“你知道的越多，你不知道的也越多”）&lt;br>
果然鸡汤披上了科学的外衣，&lt;br>
就额外迷人呢…&lt;/p>
&lt;p>写程序做技术也是一样，&lt;br>
学到了更多的知识以后，&lt;br>
觉得未知的世界更大了。&lt;/p>
&lt;p>大四的时候第一次实习，&lt;br>
那之前只是把git理解为一个ftp一样的放文件的工具，&lt;br>
VIM更是从没用过，&lt;br>
所以我心中的问题那是多的一比。&lt;/p>
&lt;p>我实习的公司QAD给每个员工会安排一个Mentor，&lt;br>
可以类比于“老师傅带徒弟”的模式。&lt;br>
第一天入职的时候我找到自己座位坐了下来，&lt;br>
发现离我最近的同事叫Justin，&lt;br>
于是问他：“你是我的Mentor吗？”&lt;br>
(那时刻有种Saber问士郎的蜜汁即视感…)&lt;br>
他笑了笑说：“我也不知道啊”&lt;br>
最后发现其实他知道自己是我的Mentor -.-&lt;/p>
&lt;p>一开始我经常会问他git怎么操作，&lt;br>
比如说John往dev分支提交了最新代码，&lt;br>
我想用他的一个函数咋办。&lt;br>
他就会站到我身后，&lt;br>
一个字母一个字母把命令说出来，&lt;br>
然后让我敲一遍：&lt;br>
“打开Putty，git，G I T，空格，rebase，R E B A S E&amp;hellip;”&lt;br>
因为有种自己被当成智障的感觉，&lt;br>
所以我压力山大地操作完了以后，&lt;br>
又上网查了一遍我刚才做的操作是什么意思…&lt;br>
这样来回几遍以后，&lt;br>
我发现自己收获很大啊，&lt;br>
之后git相关问的就越来越少了。&lt;/p>
&lt;p>所以直到现在，&lt;br>
我还是很愿意当一个智障的好奇宝宝。&lt;br>
先看，再问，后想，&lt;br>
只要问到了，就是学到了。&lt;br>
每个人都有自己独到的厉害之处，&lt;br>
这个道理就跟老祖宗苏轼说的一样：&lt;/p>
&lt;blockquote>
&lt;p>吾上可陪玉皇大帝，&lt;br>
下可以陪卑田院乞儿，&lt;br>
眼前见天下无一不好人。&lt;/p>
&lt;/blockquote>
&lt;p>苏轼写文章的能发这样的豪迈感慨，&lt;br>
我写程序那也可以一样豪迈呀 :)&lt;/p></description></item><item><title>写程序与取名字</title><link>https://liriansu.com/posts/2017-06-24-naming-variable/</link><pubDate>Sat, 24 Jun 2017 19:36:17 +0000</pubDate><guid>https://liriansu.com/posts/2017-06-24-naming-variable/</guid><description>&lt;p>据说平均下来，&lt;br>
程序员会有10%的时间花在取名字上。&lt;/p>
&lt;p>今天和俊儒聊天的时候，&lt;br>
讲到了在知乎上看的，&lt;br>
《扩散性百万亚瑟王》为什么停运的原因：&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/ma_dead_reason.jpg" alt="ma">&lt;/p>
&lt;p>这种等级的中二程序员的确可以留名青史了…&lt;br>
大型程序一般都是团伙作案，&lt;br>
所以“写出逻辑清晰、见文知意”的程序，&lt;br>
也是一个程序员的必备技能。&lt;/p>
&lt;p>按照正常文章的套路走，&lt;br>
这里我们要介绍一下，&lt;br>
绝大多数的计算机词语是有唯一的中英对照的：&lt;/p>
&lt;pre tabindex="0">&lt;code>服务器 - Server
表 - Table
事务 - Transaction
等等
&lt;/code>&lt;/pre>&lt;p>像这类词语一般来说都没啥异议。&lt;br>
写程序的时候就直白地写就行了。&lt;br>
不过有的时候程序员要写富含需求的代码，&lt;br>
就可以玩一玩了。&lt;/p>
&lt;h1 id="代码片段">代码片段&lt;/h1>
&lt;p>之前有一段代码，&lt;br>
要实现软文、软广相关的功能。&lt;br>
于是取变量名时，&lt;br>
翔神一拍大腿：&lt;br>
那就是&lt;code>advertorial&lt;/code>这个词了！&lt;br>
这个词非常准确，&lt;br>
就是软文的意思。&lt;br>
吃瓜群众纷纷表示真牛逼！&lt;/p>
&lt;p>然后代码写好了，&lt;br>
到浏览器里跑一下：&lt;br>
结果后端接口调用挂了…&lt;br>
定睛一看，&lt;br>
原来是浏览器的防广告插件自动识别了advertorial这个词，&lt;br>
把我们的接口屏蔽了…&lt;br>
&amp;hellip;&lt;br>
于是后来数据库里，&lt;br>
软文还是&lt;code>advertorial&lt;/code>，&lt;br>
但是url里，&lt;br>
软文变成了&lt;code>soft_article&lt;/code>…&lt;br>
吃瓜群众纷纷表示更牛逼了…&lt;/p>
&lt;p>还有一段代码，&lt;br>
要实现一个大礼包相关的功能。&lt;br>
类似于星巴克88元的礼品卡，&lt;br>
送券送积分送储值等等…&lt;br>
于是问题来了，&lt;br>
这个“大礼包”的抽象类应该叫什么名字呢？&lt;/p>
&lt;p>当时系统里面已有的一些英文对照有：&lt;br>
&lt;code>积分奖 reward&lt;/code>, &lt;code>券 coupon&lt;/code>, &lt;code>礼品卡 gift_card&lt;/code>等等……&lt;br>
感觉好的名字都用完了，&lt;br>
我们都停下了手里的键盘，&lt;br>
开始了头脑风暴…&lt;/p>
&lt;p>gift_bag感觉很蠢，&lt;br>
尤其是有了gift_card。&lt;/p>
&lt;p>这种奖励是一系列产品的叠加，&lt;br>
也可以叫production，&lt;br>
但是这会跟production environment有歧义。&lt;/p>
&lt;p>最终我们给这个东西取名叫：&lt;br>
&lt;code>one_piece&lt;/code>。&lt;br>
没错，OnePiece就是《海贼王》里面的海贼宝藏。&lt;/p>
&lt;p>给抽象类取一个无意义的名字，&lt;br>
反而影响深刻，没有歧义。&lt;br>
简直是解释一次，终生难忘…&lt;/p>
&lt;h1 id="信达雅">信达雅&lt;/h1>
&lt;p>其实写程序起名字，&lt;br>
很多时候随便起一个也很容易，&lt;br>
但是想追求一个信达雅的表达，&lt;br>
就需要仔细想想了。&lt;/p>
&lt;p>最近业余时间写麻将相关代码，&lt;br>
就感觉翻译真难…&lt;br>
像花色和大小还能用纸牌的&lt;code>Suit&lt;/code>和&lt;code>Rank&lt;/code>来对应，&lt;br>
但是一些番名我就比较懵逼了：&lt;/p>
&lt;ul>
&lt;li>&lt;code>十三幺/国士无双&lt;/code>，根据&lt;a href="https://zh.wikipedia.org/wiki/%E5%8D%81%E4%B8%89%E5%B9%BA">维基百科的说法是&lt;code>ThirteenOrphans&lt;/code>&lt;/a>
&lt;ul>
&lt;li>那老头牌估计就是&lt;code>OrphanTile&lt;/code>了&amp;hellip;&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;code>九莲宝灯&lt;/code>，有翻译说是&lt;code>Nine Gates&lt;/code>，这个我先信了…&lt;/li>
&lt;li>&lt;code>海底捞月&lt;/code>，&lt;code>杠上开花&lt;/code>这些咋办…&lt;/li>
&lt;/ul>
&lt;p>:) 所以看来10%时间都花在取变量名上，&lt;br>
这个说法还是比较保守的呢。&lt;/p>
&lt;p>正如程序员经常说的&lt;br>
&lt;code>Talk is cheap, show me the code&lt;/code>，&lt;br>
有个有个很棒的翻译：&lt;br>
&lt;code>废话少说，放码过来&lt;/code>。&lt;/p>
&lt;p>还是要继续修炼啊。&lt;/p></description></item><item><title>我的工作</title><link>https://liriansu.com/posts/2017-06-11-my-work/</link><pubDate>Sun, 11 Jun 2017 13:49:36 +0000</pubDate><guid>https://liriansu.com/posts/2017-06-11-my-work/</guid><description>&lt;p>前两天和家里打电话，&lt;br>
聊到了工作上的事情，&lt;br>
我多讲了几句，&lt;br>
虽然爸妈听不懂，&lt;br>
但他们听的很开心。&lt;/p>
&lt;p>我一直是个粗糙的利己主义者，&lt;br>
有的时候会过量地我行我素。&lt;br>
难得有个机会思考一下，&lt;br>
就借此写点东西，&lt;br>
记录一下我现在的工作生活吧。&lt;/p>
&lt;h2 id="再惠">再惠&lt;/h2>
&lt;p>去年十月左右，&lt;br>
百姓网的HR PP找到了&lt;a href="https://github.com/LKI">我的GitHub&lt;/a>，&lt;br>
要了我的简历，&lt;br>
约我到百姓网面试。&lt;/p>
&lt;p>因为大学室友&lt;a href="https://ldsink.com/">周丞&lt;/a>之前就是在百姓干活的，&lt;br>
我就去问他百姓各方面怎么样。&lt;br>
他大概讲了一下他眼中的百姓，&lt;br>
然后问我是不是在找工作？&lt;br>
不如顺便发个简历来？&lt;br>
帮我内推一下？&lt;br>
我问他现在在哪工作，&lt;br>
他说在&lt;a href="https://www.kezaihui.com/#!/join">再惠&lt;/a>，是个创业公司。&lt;br>
我第一感觉再惠这个名字听起来不响亮，&lt;br>
于是上网搜了下，&lt;br>
结果除了融资的新闻和&lt;a href="https://www.kezaihui.com/#!/join">官网&lt;/a>，&lt;br>
没搜到任何有意义的信息，&lt;br>
连吐槽面试的贴子都没。&lt;br>
我又去知乎搜了一下再惠，&lt;br>
然后没搜到问题和回答，&lt;br>
只搜到两个人，&lt;br>
一个是&lt;a href="https://www.zhihu.com/people/zhao-yang-61-85/activities">创始人之一赵洋&lt;/a>，&lt;br>
另一个就是&lt;a href="https://www.zhihu.com/people/ldsink/activities">周丞&lt;/a>-_-&amp;hellip;&lt;br>
当时总有一种再惠不靠谱的感觉，&lt;br>
不过感觉周丞现在还是蛮开心的，&lt;br>
应该不像是在传销组织？&lt;br>
（毕竟看过很多被熟人带进传销组织的故事）&lt;/p>
&lt;p>结果没想到最后经过一番面试和抉择，&lt;br>
我还是加入了再惠这个传销组织 :)&lt;br>
（这句当然是玩笑话）&lt;/p>
&lt;p>我司①，也就是再惠，是做&lt;a href="https://en.wikipedia.org/wiki/Software_as_a_service">SaaS系统&lt;/a>的。&lt;br>
呃，其实我也搞不太懂这个词，所以按目前的情况来说，&lt;br>
我们主要在做餐饮行业的会员系统解决方案的。&lt;br>
举个栗子。&lt;/p>
&lt;p>周末我和女朋友打算出门吃顿好的，&lt;br>
在&lt;strong>大众点评&lt;/strong>上看到了魔都有家网红餐厅&lt;strong>暗恋桃花源&lt;/strong>，&lt;br>
于是决定去吃这家店。&lt;br>
吃完饭以后买单，&lt;br>
服务员提示说扫码成为桃花源的微信会员可以享受满100减5的&lt;strong>优惠&lt;/strong>，&lt;br>
于是我很开心地扫了桌子上贴的二维码，&lt;br>
然后关注了桃花源的&lt;strong>公众号&lt;/strong>，&lt;br>
之后在公众号里用&lt;strong>微信支付&lt;/strong>买了单。&lt;br>
之后过了一周，&lt;br>
某一天突然桃花源的公众号给我发了张“桃花源常伴你身旁，下次消费可以全单九折”的优惠&lt;strong>券&lt;/strong>。&lt;br>
然而有钱的我不想为九折优惠跑一趟，不为所动。&lt;br>
再惠的会员系统就&lt;strong>学习&lt;/strong>到了原来小额优惠打动不了这个顾客。&lt;br>
又过了两周我突然收到了一张优惠&lt;strong>力度更大&lt;/strong>的八折优惠券…&lt;br>
因为这家店味道和风情都不错，&lt;br>
我最终又回去吃了一顿 :)&lt;/p>
&lt;p>没错，上面这段话里的粗体字，&lt;br>
除了&lt;strong>大众点评&lt;/strong>都是我司的业务内容~&lt;br>
大众点评做的更多的是拉新，拉流量，&lt;br>
我司做的更多的是留存，维持会员关系。&lt;/p>
&lt;p>比如我司有个经典客户案例，&lt;br>
商户叫&lt;strong>玲珑宝宴&lt;/strong>，&lt;br>
店是开在饿了么公司附近的某个角落里…&lt;br>
之前一直是流量一般，没有盈利的状况，&lt;br>
老板还想过关掉门店。&lt;br>
但后来用了我司产品以后，&lt;br>
效果拔群！&lt;br>
也许是各种优惠吸引了饿了么程序员吧…&lt;br>
后来饿了么的人来面试，&lt;br>
他们还很开心地说过：&lt;br>
“诶我知道再惠，我用过你们的产品…”&lt;/p>
&lt;h2 id="过程和结果">过程和结果&lt;/h2>
&lt;p>正如黑恶势力老大训斥小弟说的那句：&lt;br>
“蠢材，我们的事业是正义的！”一样，&lt;br>
很多时候体验都是独一无二，因人而异的。&lt;br>
我很喜欢目前的工作，&lt;br>
一个原因是因为做事的过程十分&lt;strong>敏捷&lt;/strong>。&lt;br>
没错就是那个Agility，&lt;br>
每一点敏捷增加1的攻速②。 :)&lt;/p>
&lt;p>前几个月我写过一个bug，&lt;br>
是给微信的一个接口，&lt;br>
文档上规定接口一定要返回success这七个小写字母。&lt;br>
但有的时候微信会给我们发文档上没提的错误消息，&lt;br>
我就想当然地回复了fail…&lt;br>
于是，&lt;br>
第一天写的代码，&lt;br>
第一天晚上发了新版本，&lt;br>
第二天我们的公众号全部报错不能用了&amp;hellip;&amp;hellip;&lt;br>
这就是&lt;strong>敏捷&lt;/strong>&amp;hellip;&lt;br>
（当然后来研究了一会就修好了）&lt;/p>
&lt;p>我们还有家商户叫&lt;strong>雨树湾/胡姬兰&lt;/strong>③。&lt;br>
他们有个需求，&lt;br>
就是点套餐会免费赠送一杯滴滴咖啡，&lt;br>
但是为了对账，&lt;br>
这杯咖啡在点菜机上的价格是一分钱。&lt;br>
于是会出现客人在公众号里买单时，&lt;br>
因为送了两倍滴滴咖啡，&lt;br>
结果要付100.02块钱的恶心情况…&lt;br>
当天上午知道这个情况以后，&lt;br>
我们迅速讨论研究了一下，&lt;br>
抉择以后写了段代码特殊处理0.01元的情况，&lt;br>
然后又发了个版本，&lt;br>
于是下午买单的客人就不用多付那几分钱了。&lt;br>
这也是&lt;strong>敏捷&lt;/strong>&amp;hellip;&lt;/p>
&lt;p>除了&lt;strong>敏捷&lt;/strong>的做事过程，&lt;br>
还有一个很棒的是&lt;strong>透明&lt;/strong>的结果。&lt;br>
也就是说我们做的所有东西，&lt;br>
都会很快、很明显地反映出来。&lt;/p>
&lt;p>前阵子我们做&lt;a href="https://en.wikipedia.org/wiki/Growth_hacking">Growing Hack&lt;/a>的时候，&lt;br>
成立了一只诺曼底分队④。&lt;br>
他们的任务是到店 &lt;del>公费吃喝&lt;/del> 观察客人是怎么用我们产品的。&lt;br>
然后老板就会跟他们吐槽&lt;br>
POS机难用啊、&lt;br>
支付流程太麻烦啊、&lt;br>
客人不愿意加入会员啊、&lt;br>
POS机难用啊等问题。&lt;br>
这种时候小队队员们也只能苦笑着替大家背锅了&amp;hellip;&lt;/p>
&lt;p>还有一件很惊奇的事情，&lt;br>
就是我来面试的时候，&lt;br>
前端爸爸 同济大佬 靖哥哥⑤在面试过程中，&lt;br>
掏出了他的大电脑，&lt;br>
连上了数据库，&lt;br>
直接&lt;code>SELECT COUNT&lt;/code>了一下，&lt;br>
然后直接跟我展示数据库里我们多少条用户记录，多少条商户记录…&lt;br>
我就惊了，生产环境也能这么玩，感觉是好玩啊…&lt;/p>
&lt;p>既然过程到结果都是很愉快，&lt;br>
再加上写代码本来就很有趣这一点，&lt;br>
我的日常基本上就是：&lt;br>
开心地写代码、&lt;br>
开心地发版、&lt;br>
开心地吃饭、&lt;br>
紧张地修bug、&lt;br>
开心地发版……&lt;/p>
&lt;h2 id="后端工程师">后端工程师&lt;/h2>
&lt;blockquote>
&lt;p>现在的公司是再惠，技术团队不到20人，每个人都很强，我感觉自己是里面最菜的 :)&lt;/p>
&lt;/blockquote>
&lt;p>正如我在&lt;a href="https://liriansu.com/about/">个人介绍&lt;/a>里说的一样，我们技术团队不到20人 ;)&lt;/p>
&lt;p>目前分工如下：&lt;/p>
&lt;ul>
&lt;li>1个当CEO的（以前可以算1个技术，现在大概算是0.5个技术吧）&lt;/li>
&lt;li>2个Windows端工程师（我们要Hack别人的点菜机）&lt;/li>
&lt;li>2个Android端工程师（我们要写自己的商户端App）&lt;/li>
&lt;li>6个后端工程师&lt;/li>
&lt;li>其他都是前端工程师&amp;hellip;&lt;/li>
&lt;/ul>
&lt;p>我是六个后端之一。&lt;br>
后端的主要职责有：&lt;/p>
&lt;ul>
&lt;li>实现业务API。比如上面讲到的支付流程，公众号看到漂亮的支付页面这部分属于前端，输密码支付然后扣钱给商户这部分就是后端。&lt;/li>
&lt;li>打理数据库。比如之前传出的&lt;a href="https://www.acfun.cn/a/ac3416677">炉石数据丢失&lt;/a>、&lt;a href="https://www.zhihu.com/question/21793037">某酒店开房记录泄露&lt;/a>这些都是后端的锅…&lt;/li>
&lt;li>管理服务器。比如&lt;em>这破网页怎么这么慢&lt;/em>一般也是后端的锅…&lt;/li>
&lt;/ul>
&lt;p>平常用的语言是Python，&lt;br>
这是门很简单的语言，&lt;br>
&lt;a href="https://github.com/LKI/teach-girlfriend-python">当HR的女朋友也可以很快学会&lt;/a>&lt;br>
（不过相对于写Python，显然她对看奇葩说兴趣更大…）&lt;/p>
&lt;p>不过好像我大部分时间都花在了Chrome上&amp;hellip;&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/pics/wakatime_dashboard.jpg" alt="wakatime-dashboard">&lt;/p>
&lt;p>总的来说这些就是我的工作了，&lt;br>
希望个人的奋斗能赶上历史的进程吧。&lt;br>
一切安康。&lt;/p>
&lt;blockquote>
&lt;p>① 我司：就是我的公司的简称，好像是华为先用这个词，然后传播出去了，不是很正式的词。&lt;/p>
&lt;p>② 敏捷和攻速：是游戏里面的一个梗。很多游戏会分力量、敏捷、智力三种人物，游戏里的敏捷一般是名词。&lt;/p>
&lt;p>③ 雨树湾和胡姬兰：这家店做新加坡菜的，还蛮好吃。胡姬兰是新加坡的国花。他们店一开始叫雨树湾，后来改回胡姬兰了，更有辨识度。&lt;/p>
&lt;p>④ 诺曼底分队：取名自诺曼底登陆。我司取名一向富有风格，比如羊晨羊晓、神付、SoftArticle、OnePiece等&lt;del>内部黑话&lt;/del>…&lt;/p>
&lt;p>⑤ 前端爸爸：内部互膜文化盛行，类比于敬酒时两个人会争先放低杯位然后趴到地上，我们互相也会称呼XX爸爸、XX老板、XX老爷等…&lt;/p>
&lt;/blockquote></description></item><item><title>我也看完了《人人都是产品经理2.0》</title><link>https://liriansu.com/posts/2017-05-21-so-many-pm/</link><pubDate>Sun, 21 May 2017 00:18:14 +0000</pubDate><guid>https://liriansu.com/posts/2017-05-21-so-many-pm/</guid><description>&lt;p>最近把很有话题性的《人人都是产品经理》看完了，&lt;br>
看的是2.0版本，这大概是个读后感吧。&lt;/p>
&lt;p>这本书其实是入门级别的科普读物，&lt;br>
作者试图用简洁的语言、生动的例子和必要的术语来诠释产品经理（Product Manager）的日常。&lt;br>
因为书的定位不是教材，&lt;br>
所以指望看这本书能像看《算法导论》一样学到算法，&lt;br>
看《代码大全》一样学到代码之道是期待过高了。&lt;br>
不过这本书很多地方的视角还是很特别、很好玩的&lt;br>
:) 或者说有的时候从比较PM的角度来看问题的确会好玩一些。&lt;/p>
&lt;p>比如书里提到一句&lt;/p>
&lt;blockquote>
&lt;p>只做一次的事情求可行解，反复做的事情求最优解。&lt;/p>
&lt;/blockquote>
&lt;p>这句话就很科学。&lt;br>
因为写程序的时候也是这样的。&lt;br>
有些出现频次低的需求，&lt;br>
程序员就会写个脚本去做。&lt;br>
而假如这个需求老是出现，&lt;br>
那程序员就会重新审视问题，&lt;br>
完善地考虑一遍，&lt;br>
再优化/重做之前的脚本。&lt;/p>
&lt;p>书里还有一句话（稍微凝缩一下）&lt;/p>
&lt;blockquote>
&lt;p>对某个领域的激情是能通过做过什么而看出来的。“做过什么”是指“输出”而不是“输入”。比如看过什么书，逛什么网站都是输入。而写过一些言之有物的文章，做过一些哪怕很小的Demo，都算输出。&lt;/p>
&lt;/blockquote>
&lt;p>虽然这段话是说怎么面试PM的，&lt;br>
但其实任何事情都是这个道理。&lt;br>
举个栗子，&lt;br>
我最近已经不敢说“我很喜欢二次元文化了”。&lt;br>
因为我很长一段时间都没投过视频，&lt;br>
参与动漫相关的讨论，&lt;br>
甚至没发过弹幕（惭愧）&lt;br>
所以即便我没事会看一些动画、漫画，&lt;br>
这些也不过都是输入而已，&lt;br>
我并没有什么输出（滑稽）&lt;/p>
&lt;h2 id="我很喜欢的一个小节">我很喜欢的一个小节&lt;/h2>
&lt;p>书里有一个小章节，叫《如何通过提问把别人干翻》&lt;br>
大意是别人在讲PPT的时候，&lt;br>
你可以提这些问题来把他干翻：&lt;/p>
&lt;blockquote>
&lt;ol>
&lt;li>为什么要做这件事，不做的话会死人吗？&lt;/li>
&lt;li>这是用户的目标还是我们的目标？是不是老板的目标？老板换了怎么办？&lt;/li>
&lt;li>这个用户有普遍性吗？能代表多少人？这类用户对我们优先级是什么？&lt;/li>
&lt;li>数据来源是什么？什么时候获取的？是怎么采样的？&lt;/li>
&lt;li>为什么没有看到这个产品线的大图？5年后这个产品是什么样子？你实现整个图景的途径是什么？&lt;/li>
&lt;li>未来的确很美好，但怎么实现？现在如果只做一件事，最重要的是什么？你打算怎么做？&lt;/li>
&lt;li>……（还有很多）&lt;/li>
&lt;/ol>
&lt;/blockquote>
&lt;p>光是粗略的看了一遍问题，&lt;br>
我已经能想象会议室里的尴尬的沉默了……&lt;/p>
&lt;p>其实《把别人干翻》的这系列问题，&lt;br>
跟&lt;a href="https://coolshell.cn/articles/4758.html">《如何写出无法维护的代码》&lt;/a>的意思都是一样的，&lt;br>
通过反向的思考（假如我是刁民）来完善自我。&lt;/p>
&lt;h2 id="好奇心与行动力">好奇心与行动力&lt;/h2>
&lt;p>书里很多次地提到过一对词：【新手】和【专家】。&lt;br>
而且后面还说&lt;br>
“一个好的PM不仅有新手心态，热爱思考，拒绝存在即合理。&lt;br>
也会有专家能力，很快上手，做什么事情都很擅长。”&lt;br>
&lt;del>呸&amp;hellip;这又不是PM专属的&amp;hellip;作者真不要脸 :)&lt;/del>&lt;/p>
&lt;p>其实我眼中这就是两个词：&lt;br>
&lt;strong>好奇心&lt;/strong>和&lt;strong>行动力&lt;/strong>。&lt;/p>
&lt;p>好奇心会促使我们看到一个东西时，&lt;br>
想去玩一下体验一下，&lt;br>
然后试图搞清楚它的原理。&lt;br>
也会激发我们透过现象看本质，&lt;br>
比如&lt;a href="https://liriansu.com/x-y-z-question">XYZ问题&lt;/a>里的道理一样，&lt;br>
透过Z问题，越过Y问题，看到最初的X问题。&lt;/p>
&lt;p>行动力可以帮助我们满足好奇心。&lt;br>
陶菲格在自己的文章里质问自己：&lt;br>
“（为什么我要践行我的思想呢？）&lt;br>
难道只有我的头脑中才有思想？”&lt;br>
而他自己又回答道：&lt;br>
“其他人也有思想。&lt;br>
但是能让思想出世的却寥寥无几。”&lt;/p>
&lt;p>复用上文的的说法，&lt;br>
好奇心会增加输入，&lt;br>
行动力会把输入转化成有用的输出。&lt;/p>
&lt;p>总的来说作为一个外行人，&lt;br>
看《人人都是产品经理2.0》这本书的确增长了一点眼界。&lt;br>
不过假如人人都是程序员就更好了 XD&lt;/p></description></item><item><title>Vim, Tmux, Zsh怎么读</title><link>https://liriansu.com/posts/2017-05-12-pronunciations/</link><pubDate>Fri, 12 May 2017 22:41:02 +0000</pubDate><guid>https://liriansu.com/posts/2017-05-12-pronunciations/</guid><description>&lt;blockquote>
&lt;p>孔乙己显出极高兴的样子，将两个指头的长指甲敲着柜台，点头说，“对呀对呀！……回字有四样写法，你知道么？&lt;/p>
&lt;/blockquote>
&lt;p>前阵子 GitHub 上有一个很好玩的 Repo ：&lt;br>
&lt;a href="https://github.com/shimohq/chinese-programmer-wrong-pronunciation">shimohq/chinese-programmer-wrong-pronunciation&lt;/a>&lt;/p>
&lt;p>列了一些国内程序员容易读错的词，&lt;br>
过了一遍我发现我也中招了：&lt;br>
&lt;code>Django 读作 Jango 就行了，D不用读出来&lt;/code>&lt;/p>
&lt;h2 id="vim-怎么读">Vim 怎么读&lt;/h2>
&lt;p>这让我想起前阵子听&lt;a href="https://tianchunbinghe.blog.163.com">冰河学长&lt;/a>&lt;a href="https://music.163.com/#/song?id=28707021">和别人聊 Common Lisp 的时候&lt;/a>，&lt;br>
（一个多小时的纯聊天，听完收获很大）&lt;br>
把 Vim 单个字母地读出来读成了 &lt;code>V - I - M&lt;/code> &amp;hellip;&lt;br>
当时我就很好奇地去查了一下大部分人是怎么读 Vim 的。&lt;br>
结果在万能的 Vim Manual 里发现了 &lt;code>:help pronounce&lt;/code>，&lt;br>
里面是这么说的：&lt;/p>
&lt;blockquote>
&lt;p>Vim is pronounced as one word, like Jim, not vi-ai-em. It&amp;rsquo;s written with a&lt;br>
capital, since it&amp;rsquo;s a name, again like Jim.&lt;/p>
&lt;/blockquote>
&lt;p>也就是说 &lt;strong>Vim是一个词连读的，就好像读Tim一样&lt;/strong>，很科学&lt;/p>
&lt;h2 id="tmux-怎么读">Tmux 怎么读&lt;/h2>
&lt;p>不像 Vim 的读法，有一个比较官方的说法。&lt;br>
Tmux 的读法可以当做辩题…&lt;br>
&lt;a href="https://www.reddit.com/r/linux/comments/yz4r6/screen_vs_tmux/c6034gp/?utm_content=permalink&amp;amp;utm_medium=front&amp;amp;utm_source=reddit&amp;amp;utm_name=linux">比如 Reddit 上有小伙伴说，公司里因为没有统一的 Tmux 读法，所以很多人都装了 Screen&amp;hellip;&lt;/a>&lt;/p>
&lt;p>不过 &lt;strong>大部分人都觉得 Tmux 应该读作 Tee Mucks&lt;/strong>&lt;/p>
&lt;p>比如下面有个比较靠谱的回复说，&lt;/p>
&lt;blockquote>
&lt;p>Tmux 应该读作 Tee Mucks，因为 Tmux 其实是 Terminal Multiplexer 的缩写，所以应该读作 T-Mux (Tee Mucks)&lt;/p>
&lt;/blockquote>
&lt;p>又有人说：&lt;/p>
&lt;blockquote>
&lt;p>Tmux 的发音规则很简单，就跟 Gmail 一样&lt;/p>
&lt;/blockquote>
&lt;h2 id="zsh-怎么读">Zsh 怎么读&lt;/h2>
&lt;p>其实类似于 Tmux，大部分人觉得&lt;strong>Zsh 应该跟 Tmux, Gmail 一样发音&lt;/strong>&lt;br>
因为 Zsh 全称是 Z Shell：&lt;/p>
&lt;p>&lt;img src="https://imgs.xkcd.com/comics/admin_mourning.png" alt="xkcd686">&lt;/p>
&lt;p>&lt;del>其实也可以说纠结读音的人，都是PM需求提的不够多（滑稽）&lt;/del>&lt;/p>
&lt;p>总的来说，&lt;br>
我喜欢兼听则明。&lt;br>
能听懂不同发音指向的同一名词，&lt;br>
也能选择自己觉得最科学的发音来与人讨论问题 :)&lt;/p></description></item><item><title>我可能看了假的技术书</title><link>https://liriansu.com/posts/2017-04-22-how-google-works-note/</link><pubDate>Sat, 22 Apr 2017 01:48:05 +0000</pubDate><guid>https://liriansu.com/posts/2017-04-22-how-google-works-note/</guid><description>&lt;p>清明节的时候在火车上把 &lt;code>How Google Works&lt;/code> 给读完了，&lt;br>
我原以为读这本书会提升技术，&lt;br>
没想到提升了 HR 的知识（懵逼&lt;/p>
&lt;h2 id="这本书讲啥">这本书讲啥&lt;/h2>
&lt;p>写书的人叫 &lt;code>Eric Schmidt&lt;/code>，&lt;br>
是 Google 的 Executive Chairman。&lt;br>
然而我并不知道这个职位具体是做啥的，&lt;br>
大概翻译成中文会是“执行总裁”，&lt;br>
感觉做很多管理相关的工作。&lt;br>
不论如何，这个职位是不写代码的。&lt;/p>
&lt;p>这本书条理极其清晰，&lt;br>
整本书的内容用章节小标题即可概括：&lt;/p>
&lt;blockquote>
&lt;ol>
&lt;li>像创始人一样工作&lt;/li>
&lt;li>放权于员工&lt;/li>
&lt;li>只聘用比你优秀的人&lt;/li>
&lt;li>不要把职业发展和绩效管理混淆&lt;/li>
&lt;li>关注团队的两端：最好的和最差的员工&lt;/li>
&lt;li>既要节俭，又要慷慨&lt;/li>
&lt;li>不公平薪酬&lt;/li>
&lt;li>助推 &lt;em>这个翻译太屎了&lt;/em>&lt;/li>
&lt;li>能力越高，期望越高&lt;/li>
&lt;li>享受你的工作&lt;/li>
&lt;/ol>
&lt;/blockquote>
&lt;p>读完这本书基本上我的感想如下：&lt;/p>
&lt;ol>
&lt;li>卧槽，外国人的英语是溜啊&lt;/li>
&lt;li>不愧是谷歌，有些东西是只有他们才能这么搞，规模效应是厉害&lt;/li>
&lt;li>在吹牛逼之前，首先你得变得牛逼&lt;/li>
&lt;/ol>
&lt;h2 id="书里的招聘">书里的招聘&lt;/h2>
&lt;p>前几章的重心都在招聘上，&lt;br>
作者讲到一条大家都认同的道理，&lt;br>
就是&lt;strong>面试是无法精确衡量一个人的水平的&lt;/strong>。&lt;br>
所以对此，他们采取的解决方案就是&lt;br>
&lt;strong>招聘Top10%的人才，这样他们就算表现再差，也只会是中等水平&lt;/strong>。&lt;br>
看到这里，&lt;br>
我总有一种&lt;strong>我要买最贵的食材，这样做出来的菜就不会太难吃&lt;/strong>&lt;br>
的浪费的感觉&amp;hellip;&lt;br>
大厂毕竟是大厂啊&amp;hellip;（心酸地、嫉妒地&lt;/p>
&lt;p>作者还讲到了一个词，&lt;br>
叫 &lt;code>Exploding Offer&lt;/code>（会炸的录取通知书） &lt;em>依然是屎一样的翻译&lt;/em>&lt;br>
说是他们会给来面试候选人发有最后期限的offer，&lt;br>
比如 &lt;em>下周三之前，不接受我司offer就失效&lt;/em>。&lt;br>
这种发offer的方式，从公司、管理角度是非常棒的，&lt;br>
因为可控风险，防骑驴找马。&lt;br>
不过对于个人而言，&lt;br>
作者也觉得这种发offer的方式并不完美。&lt;br>
这里用“也”，&lt;br>
是因为我也觉得这种发offer的方式不完美。&lt;/p>
&lt;p>除了这些，&lt;br>
作者还讲到了一些好玩的点：&lt;/p>
&lt;ul>
&lt;li>面试一定要保持恒定的标准，最好采用结构化的测试问题&lt;/li>
&lt;li>没人喜欢现有的绩效考核制度，包括HR。&lt;/li>
&lt;li>更没人喜欢任何新的绩效考核制度。&lt;/li>
&lt;li>在一个组织里，更多时候是幂律分布，而不是高斯分布。&lt;/li>
&lt;/ul>
&lt;p>总的来说，&lt;br>
这本书可以休闲的读一下。&lt;br>
里面有不少故事，&lt;br>
但是里面的方法论不一定学得来，&lt;br>
毕竟所有的这些构成了 Google 独特的文化，&lt;br>
就好像 &lt;a href="https://www.valvesoftware.com/company/Valve_Handbook_LowRes.pdf">Valve员工手册&lt;/a> 里独特的 Valve 文化一样。&lt;/p></description></item><item><title>hunter2是什么梗</title><link>https://liriansu.com/posts/2017-03-26-hunter2-meme/</link><pubDate>Sun, 26 Mar 2017 23:58:26 +0000</pubDate><guid>https://liriansu.com/posts/2017-03-26-hunter2-meme/</guid><description>&lt;p>简单来说：&lt;br>
这是一个弱密码。&lt;/p>
&lt;h2 id="hunter2">hunter2&lt;/h2>
&lt;p>密码安全是个长盛不衰的话题，&lt;br>
前阵子又有人统计了&lt;a href="https://blog.keepersecurity.com/2017/01/13/most-common-passwords-of-2016-research-study/">2016年最弱的密码&lt;/a>。&lt;br>
每次明文存储密码的大网站数据库泄露，&lt;br>
也都&lt;a href="https://36kr.com/p/5038663.html">有人统计弱密码排名&lt;/a>。&lt;/p>
&lt;p>像&lt;code>123456&lt;/code>、&lt;code>letmein&lt;/code>、&lt;code>password&lt;/code>都是典型的弱密码。&lt;br>
&lt;code>hunter2&lt;/code>也是一个弱密码，&lt;br>
其中的梗&lt;a href="https://bash.org/?244321">起源于2004年左右IRC上面的一段对话&lt;/a>：&lt;/p>
&lt;pre tabindex="0">&lt;code>&amp;lt;Cthon98&amp;gt; 在聊天框里输入你的密码，系统会自动地把它变成星号
&amp;lt;Cthon98&amp;gt; ********* 你看！
&amp;lt;AzureDiamond&amp;gt; hunter2
&amp;lt;AzureDiamond&amp;gt; 我看不到星号
&amp;lt;Cthon98&amp;gt; &amp;lt;AzureDiamond&amp;gt; *******
&amp;lt;Cthon98&amp;gt; 我看到你发的是上面这行
&amp;lt;AzureDiamond&amp;gt; 哇哦，真的？
&amp;lt;Cthon98&amp;gt; 没错
&amp;lt;AzureDiamond&amp;gt; 你用hunter2把我的hunter2给hunter2了
&amp;lt;AzureDiamond&amp;gt; 哈哈，你看这串是不是很有意思
&amp;lt;Cthon98&amp;gt; lol 是啊。所以说每次你输入hunter2，我看到的都是*******
&amp;lt;AzureDiamond&amp;gt; 真是酷炫，我以前都不知道IRC会自动屏蔽密码
&amp;lt;Cthon98&amp;gt; 是的，不管你在哪输如hunter2，别人看到的都是*******
&amp;lt;AzureDiamond&amp;gt; 屌爆啦！
&amp;lt;AzureDiamond&amp;gt; 等等，你怎么知道我密码的？
&amp;lt;Cthon98&amp;gt; 呃，我只是把你的*******给复制了一下，你看到的可能是它的原样hunter2
&lt;/code>&lt;/pre>&lt;p>用表情图表示就是这样子：&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/hunter2.jpg" alt="hunter2">&lt;/p>
&lt;p>这样的套路在新时代就是这样子的：&lt;br>
&lt;del>（今天是马化腾的生日，转发你的密码到五个群，再看看你的头像）&lt;/del>&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/hunter2-god.jpg" alt="hunter2-god">&lt;/p>
&lt;p>[XKCD 936]也是讲密码安全的：&lt;/p>
&lt;p>&lt;img src="https://imgs.xkcd.com/comics/password_strength.png" alt="xkcd 936">&lt;/p>
&lt;p>于是某Redditor也发现了，&lt;br>
写教务处网站的那个同学，&lt;br>
&lt;a href="https://www.reddit.com/r/xkcd/comments/2f5xps/my_university_has_good_password_instructions/">也看XKCD&lt;/a>：&lt;/p>
&lt;p>&lt;img src="https://i.imgur.com/ElRxuGK.png" alt="password">&lt;/p>
&lt;p>所以总的来说，&lt;br>
&lt;code>hunter2&lt;/code>就是一个关于弱密码的梗。&lt;br>
希望大伙的密码都很安全，&lt;br>
相关的虚拟财产什么也都很安全 :)&lt;/p>
&lt;h2 id="其它">其它&lt;/h2>
&lt;p>在如今，用一个好的密码管理软件是很好的选择。&lt;br>
假如你嫌密码管理软件太麻烦，&lt;br>
那么选一个有数字、大写字母、小写字母、特殊字符的10位以上的密码也是不错的选择。&lt;/p>
&lt;p>然而有很多网站不支持特殊字符ORZ&lt;br>
还有网站限制了很短的密码长度…&lt;br>
╮(╯▽╰)╭ 假如网站登录框旁边，&lt;br>
能把他们当初注册的密码条件写上就好了。&lt;/p></description></item><item><title>搭建舒适的 Windows 开发环境</title><link>https://liriansu.com/posts/2017-03-24-windows-dev-env/</link><pubDate>Fri, 24 Mar 2017 02:00:55 +0000</pubDate><guid>https://liriansu.com/posts/2017-03-24-windows-dev-env/</guid><description>&lt;p>假如你也不介意身处&lt;a href="https://www.zhihu.com/question/24270600">鄙视链&lt;/a>的最底端，&lt;br>
那来交流一下&lt;code>怎么样搭建Windows的开发环境&lt;/code>吧&lt;/p>
&lt;h2 id="鄙视链we-are-the-same的最底端windows">&lt;a href="https://www.zhihu.com/question/24270600">鄙视链&lt;/a>的最底端：Windows&lt;/h2>
&lt;p>&lt;a href="https://www.zhihu.com/question/24270600">鄙视链&lt;/a>是程序员日常生活中确实的一部分，&lt;br>
比如拿经典的编程语言来说，&lt;br>
有种说法是：&lt;/p>
&lt;blockquote>
&lt;p>C 语言工程师鄙视 C++ 工程师，&lt;br>
C++ 工程师鄙视 Java 和 C# 工程师，&lt;br>
Java 工程师和 C# 工程师则互相鄙视。&lt;br>
写静态语言的工程师鄙视写动态语言的工程师。&lt;br>
用 Python 3 的工程师鄙视还在用 Python 2 的工程师，&lt;br>
用 Python 2 的工程师鄙视遇到 UnicodeEncodeError 的工程师。&lt;/p>
&lt;p>所有的工程师都鄙视 PHP 工程师。&lt;/p>
&lt;/blockquote>
&lt;p>而在用的操作系统方面，&lt;br>
&lt;a href="https://www.zhihu.com/question/24270600">鄙视链&lt;/a>的说法基本是这样的：&lt;/p>
&lt;blockquote>
&lt;p>用 Mac OS X 的工程师鄙视用 Linux 的工程师，&lt;br>
用 Linux 的工程师鄙视用 Windows 的工程师。&lt;/p>
&lt;/blockquote>
&lt;p>虽然是这么说，&lt;br>
但我还是很喜欢 Windows 的开发环境，&lt;br>
主要原因是：&lt;strong>可以玩游戏&lt;/strong>…&lt;br>
虽然目前我已经几乎不玩了，&lt;br>
但是这个&lt;strong>可以玩游戏&lt;/strong>的无限可能性深深地吸引着我&amp;hellip;&lt;/p>
&lt;p>o(〃&amp;lsquo;▽&amp;rsquo;〃)o&lt;br>
所以我们要通过一系列步骤，&lt;br>
搭建一个最舒服的 Windows 开发环境！&lt;del>和游戏环境&lt;/del>&lt;/p>
&lt;h2 id="必备软件">必备软件&lt;/h2>
&lt;p>有几个软件我认为是 Windows 开发环境中必不可少的。&lt;/p>
&lt;h3 id="chocolateychocolatey">&lt;a href="https://chocolatey.org/">Chocolatey&lt;/a>&lt;/h3>
&lt;p>&lt;a href="https://chocolatey.org/">Chocolatey&lt;/a> 是 Windows 上的命令行包管理软件，&lt;br>
不是官方的，&lt;br>
但是非常好用。&lt;/p>
&lt;p>以管理员身份打开 &lt;code>cmd.exe&lt;/code> 后运行一行命令即可装成功：&lt;/p>
&lt;pre tabindex="0">&lt;code>@powershell -NoProfile -ExecutionPolicy Bypass -Command &amp;#34;iex ((New-Object System.Net.WebClient).DownloadString(&amp;#39;https://chocolatey.org/install.ps1&amp;#39;))&amp;#34; &amp;amp;&amp;amp; SET &amp;#34;PATH=%PATH%;%ALLUSERSPROFILE%\chocolatey\bin&amp;#34;
&lt;/code>&lt;/pre>&lt;p>装好以后一行命令就可以装上常用软件，&lt;br>
以及把 Path 环境变量配好：&lt;/p>
&lt;pre tabindex="0">&lt;code>choco install -y 7zip everything git jdk8 nodejs npm python2 putty vagrant virtualbox vim wox
&lt;/code>&lt;/pre>&lt;p>唯一缺点是安装过程都是采用默认值静默安装的，&lt;br>
假如有些软件要取消掉右键菜单，&lt;br>
或者放在特定文件夹内则需要自己搞一下。&lt;/p>
&lt;h3 id="woxwox">&lt;a href="https://www.getwox.com/">Wox&lt;/a>&lt;/h3>
&lt;p>就是上一条 &lt;code>choco&lt;/code> 命令最后要装的那个 &lt;a href="https://www.getwox.com/">wox&lt;/a> ，&lt;br>
一个快速启动应用的工具。&lt;/p>
&lt;p>假如你知道 Mac OS 系统上的 &lt;code>Spotlight&lt;/code> 或者 &lt;code>Alfred&lt;/code> 的话，&lt;br>
&lt;a href="https://www.getwox.com/">wox&lt;/a> 就是它们在 Windows 上的版本。&lt;/p>
&lt;p>比如我在任何界面，&lt;br>
敲下 &lt;code>Alt + Space&lt;/code> 的快捷键以后，&lt;br>
就弹出了白色的输入框。&lt;br>
我输入程序名后按下回车，&lt;br>
就会自动打开该程序。&lt;br>
&lt;a href="https://www.getwox.com/">wox&lt;/a>支持通配符，&lt;br>
支持搜索，&lt;br>
支持系统操作（比如锁屏、重启），&lt;br>
加上 &lt;a href="https://www.voidtools.com/">everything&lt;/a> 以后支持搜索文件。&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/windows_wox.jpg" alt="wox-sample">&lt;/p>
&lt;h3 id="git-bashgit-scm">&lt;a href="https://git-scm.com/downloads">Git Bash&lt;/a>&lt;/h3>
&lt;p>此处讲的不是 Git ，而是特指 &lt;a href="https://git-scm.com/downloads">Git Bash&lt;/a>。&lt;br>
&lt;a href="https://git-scm.com/downloads">Git Bash&lt;/a> 是装 Git 附带装的基于 &lt;a href="https://www.mingw.org/">mingw (MINimal Gnu for Windows)&lt;/a> 的一个终端软件。&lt;br>
自带 bash / ls / find / grep / wc 等 Linux 命令行工具，&lt;br>
支持 .profile 自定义环境变量，&lt;br>
支持 git 文件状态显示。&lt;br>
有了这个以后我基本没用 cmd 或者 powershell 了。&lt;/p>
&lt;h2 id="我的偏好">我的偏好&lt;/h2>
&lt;p>前文的三个软件我是强烈推荐使用的。&lt;br>
下面还有一些带有一定的，&lt;br>
或者是强烈的个人品味的软件。&lt;/p>
&lt;ul>
&lt;li>&lt;code>VirtualBox + Vagrant + Putty&lt;/code>：平常开发的时候，我会用 &lt;code>vagrant init ubuntu/trusty64 &amp;amp;&amp;amp; vagrant up&lt;/code> 来起一个 Ubuntu 虚拟机，然后用 Putty 连上去，把这个虚拟机当一个完全体 Server 来用。&lt;a href="https://www.virtualbox.org/wiki/VirtualBox">VirtualBox&lt;/a> 是虚拟机载体，类似于 VMware ，但是版权协议更宽松。&lt;a href="https://www.vagrantup.com/">Vagrant&lt;/a> 是虚拟机管理软件，提供主机与虚拟机的数据通讯，还有一些自动化的活。&lt;a href="https://www.putty.org/">Putty&lt;/a> 是老牌远程终端软件。&lt;/li>
&lt;li>&lt;a href="https://www.jetbrains.com/">&lt;code>JetBrains全家桶，包括IntelliJ IDEA, PyCharm, Rider EAP, ReSharper&lt;/code>&lt;/a>：JetBrains 毕竟是做 IDE 的商业公司，还是比_一些_开源 IDE 要好的，比如他们家的 IDE 基本上不会出现&lt;a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=76936">10年都没解决的Issue&lt;/a>&amp;hellip;&lt;/li>
&lt;li>&lt;code>网易云音乐 + 有道词典 + 有道云笔记&lt;/code>：呃，这个不知道怎么介绍，就大概是字面意义上的需要这些东西吧。咖啡和音乐是程序员的好伙伴，我不怎么喝咖啡，我就只有音乐了。&lt;/li>
&lt;li>&lt;a href="https://www.voidtools.com/">&lt;code>everything&lt;/code>&lt;/a>：巨快巨好用的 Windows 全局搜索软件，效率可比 Linux 上的 &lt;code>locate&lt;/code> 命令。&lt;/li>
&lt;li>&lt;a href="https://en.wikipedia.org/wiki/Editor_war">&lt;code>Vim, Windows 上的是 GVim&lt;/code>：编辑器之神&lt;/a>。&lt;/li>
&lt;/ul>
&lt;h2 id="其它技巧">其它技巧&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://coolshell.cn/articles/9308.html">左耳朵耗子的建议： 作环保的程序员，从不用百度开始&lt;/a>&lt;/li>
&lt;li>除了 &lt;code>Alt + F4&lt;/code>，Windows上的 &lt;code>Win + E&lt;/code>, &lt;code>Win + R&lt;/code>, &lt;code>Win + D&lt;/code>, &lt;code>Win + L&lt;/code>, &lt;code>Win + Tab&lt;/code> 也很有用。&lt;/li>
&lt;li>而可以用 &lt;code>终端中左键选中&lt;/code> 来复制，&lt;code>Shift + Insert&lt;/code> 来粘贴。&lt;/li>
&lt;li>Windows 中与 &lt;code>ln&lt;/code> 类似的命令是 &lt;code>mklink &amp;lt;dest&amp;gt; &amp;lt;source&amp;gt;&lt;/code>。假如是目录则要加参数 &lt;code>mklink /d &amp;lt;dest&amp;gt; &amp;lt;source&amp;gt;&lt;/code>&lt;/li>
&lt;li>假如你用 Vim，把 &lt;code>&amp;lt;Caps Lock&amp;gt; 大写锁定&lt;/code> 键改成 &lt;code>&amp;lt;Ctrl&amp;gt;&lt;/code> 键吧。&lt;/li>
&lt;li>本文中用到的一些配置，也可以在&lt;a href="https://github.com/LKI/myconf">我 GitHub 的配置项目&lt;/a>中找到。&lt;/li>
&lt;/ul></description></item><item><title>HR与程序员的日常（一）： HRBP与Markdown</title><link>https://liriansu.com/posts/2017-03-20-hrbp-and-markdown/</link><pubDate>Mon, 20 Mar 2017 01:49:00 +0000</pubDate><guid>https://liriansu.com/posts/2017-03-20-hrbp-and-markdown/</guid><description>&lt;p>简单来说，&lt;br>
HRBP是一种角色，&lt;br>
Markdown是一种语法。&lt;/p>
&lt;blockquote>
&lt;p>Lirian是男程序员，&lt;br>
Mia是女HR。&lt;br>
他们经常会互相科普各种名词，&lt;br>
Lirian决定把谈话记下来。&lt;/p>
&lt;/blockquote>
&lt;h2 id="hrbp">HRBP&lt;/h2>
&lt;p>话说某一天Lirian问Mia：&lt;br>
“问个问题啊，HRBP究竟是什么？”&lt;/p>
&lt;p>Mia十分惊奇：&lt;br>
“怎么想起问这个了，贵司要招HRBP么？”&lt;/p>
&lt;p>“不是不是，我就是好奇一下。&lt;br>
比如先说HR吧，我在想，&lt;br>
HR的全称其实是Human Resources，&lt;br>
直译过来就是人力资源。&lt;br>
那假如说‘我是一个HR’，&lt;br>
直译过来岂不是‘我是一个人力资源’了么？&lt;br>
感觉怪怪的。”&lt;/p>
&lt;p>“哎呀，这个是习惯用法啦。”&lt;/p>
&lt;p>“那HRBP呢？HRBP全称是什么？”&lt;/p>
&lt;p>“HRBP的全称是&lt;strong>Human Resources Business Partner&lt;/strong>。&lt;br>
你首先得要有一个概念，&lt;br>
HRBP它广义上不是一个职位，&lt;br>
而是一种角色定义。”&lt;/p>
&lt;p>Lirian很困惑：“什么意思？”&lt;/p>
&lt;p>Mia并没有直接回答这个问题，&lt;br>
而是抛了另外一个问题：&lt;br>
“我从源头上跟你讲吧。&lt;br>
传统意义上人力资源的分类，&lt;br>
是分成了六大模块，&lt;br>
这个你知道吧？”&lt;/p>
&lt;p>Lirian表示知道：&lt;br>
“我想想啊，你别说啊，&lt;br>
六大模块应该有招聘，培训，薪资…呃…&lt;br>
呃…和其它三大模块！”&lt;/p>
&lt;p>“嗯，你前面的招聘、培训、薪资福利都说对了，&lt;br>
后面还有绩效、劳动关系，&lt;br>
和……人力资源规划~&lt;br>
但是呢，这种分类方式特别教条化，&lt;br>
怎么可能有人只做薪酬，&lt;br>
有人只做招聘呢？&lt;br>
比如你做招聘的，&lt;br>
肯定得了解候选人薪资呀，&lt;br>
也得了解绩效嘛。&lt;br>
所以后来就有人把六大模块这个理论完全抛开，&lt;br>
提出了全新的&lt;strong>三支柱&lt;/strong>理论。”&lt;/p>
&lt;p>“那是哪三个支柱呢？”&lt;/p>
&lt;p>“第一个就是HRBP。&lt;br>
第二个是SSC，Share Service Center，&lt;br>
SSC处理的都是一般性事务。&lt;br>
还有个叫做COE，Center Of Expert，&lt;br>
就人力资源专家，&lt;br>
你可以想像那些讲师，&lt;br>
专门做培训、招聘、绩效的。”&lt;/p>
&lt;p>Lirian好奇地问：&lt;br>
“那是不是说比如‘我去当个小HR’，&lt;br>
这里的小HR一般指的是SSC？”&lt;/p>
&lt;p>“嗯是的，世界上大部分HR都可以算是SSC。&lt;br>
在一个大的公司里面，&lt;br>
这部分HR就会专门来处理杂活，&lt;br>
这个类型的HR其实入门门槛很低。”&lt;/p>
&lt;p>“那假如我要当HRBP，&lt;br>
是不是我也得从SSC做起？”&lt;/p>
&lt;p>“这不一定。&lt;br>
假如你想当HRBP，&lt;br>
最有效的其实是你本来就是业务部门的人。&lt;br>
比如我以前是写代码的，&lt;br>
但我觉得哎呀写代码太吃力。&lt;br>
我会写，但是我写的不好，&lt;br>
于是我就去当HR。（Lirian笑）&lt;br>
然后我就去学了HR的课，&lt;br>
考了证书，&lt;br>
又做了几年招聘，&lt;br>
然后我再跑到一家公司去当研发部的HRBP了。&lt;br>
通常HRBP对资历要求比较高。&lt;br>
这种呢就是属于你从业务部门，&lt;br>
直接转去做HR，&lt;br>
那么你的优势会非常大，&lt;br>
但是事实上比较少的人会选择这么做。&lt;br>
我Manager Tina就是其中一个，&lt;br>
她以前是做销售卖ERP软件的，&lt;br>
所以她后来去当猎头做招聘就很有优势，&lt;br>
再后来她就当HR了。”&lt;/p>
&lt;p>Lirian对业务部门表示了疑惑：&lt;br>
“什么部门算业务部门啊？”&lt;/p>
&lt;p>Mia给出了定义：&lt;br>
“业务部门就是能给公司带来直接盈利的部门。”&lt;/p>
&lt;p>“喔！比如销售！”&lt;/p>
&lt;p>“对的，还有产品、售后支持部啊。&lt;br>
当然这种已经算有点偏的了。”&lt;/p>
&lt;p>“技术部呢？”&lt;/p>
&lt;p>“技术部也算啊~”&lt;/p>
&lt;p>Lirian想起他们经常采购手机什么的，&lt;br>
表示很惭愧：&lt;br>
“但我感觉我们净给公司花钱了……”&lt;/p>
&lt;p>“但是你们是生产出产品的人啊。&lt;br>
长远来看你们为公司生产了价值，&lt;br>
而盈利了。&lt;br>
像HR部门啊，行政啊，财务啊就不算业务部门。”&lt;/p>
&lt;p>Lirian感慨道：&lt;br>
“那感觉跨界的是有优势啊”&lt;/p>
&lt;p>“对，这种就是人力资源部门里不是科班出身的。&lt;br>
还有一种就是正正经经的，&lt;br>
大学也是学人力资源专业的，&lt;br>
然后从SSC，&lt;br>
做到了HR Specialist，&lt;br>
到HRBP，&lt;br>
一步一步往上做到Expert也是有的。”&lt;/p>
&lt;p>听完了这一段，&lt;br>
Lirian对HRBP是什么大概有了点了解，&lt;br>
他又问了：&lt;br>
“那HRBP究竟会做什么呢？”&lt;/p>
&lt;p>“这个呢，分很多种情况，&lt;br>
比如说十五年工作经验以上的HR吧。&lt;br>
就像我们老大，&lt;br>
他经常要开会，&lt;br>
那他都开些什么会呢？”&lt;/p>
&lt;p>“是啊，都开些什么呢？”&lt;/p>
&lt;p>“实际上这个层级的HR，&lt;br>
很多是和老板一起参与公司战略规划。&lt;br>
比如说Team Leader有一个目标，&lt;br>
然后HRBP就会说从人力资源的角度，&lt;br>
从人才配置的角度去帮助他实现这个目标。&lt;br>
特别是团队里出现了一些问题的情况，&lt;br>
就需要HRBP的建议，&lt;br>
像活特别多，干不完要招人；&lt;br>
或者是竞争对手一直在跟我们抢人这种。”&lt;/p>
&lt;p>“呃，等等。&lt;br>
这么听来我觉得HRBP也不是所有情况都适用的吧？&lt;br>
比如说万一有人不信这套理念，&lt;br>
万一Leader认为业务部门的事情，&lt;br>
就应该业务部门自己解决。&lt;br>
当然了从HR的角度来说，&lt;br>
肯定是他没认识到HR的重要性，&lt;br>
但感觉也会有很多公司都是这样没有HRBP的吧。”&lt;/p>
&lt;p>“会啊，初创型企业就是这样，&lt;br>
大公司里一般才有专门职位。&lt;br>
小规模的公司里这些活其实被经理啦，&lt;br>
主管啦，或者是部门的HR给分摊掉了。&lt;br>
但不要忘了，&lt;br>
这个时候业务部门的负责人，&lt;br>
他其实是自己在承担这一部分的角色。”&lt;/p>
&lt;p>“科学。&lt;br>
要这么定义的话，&lt;br>
的确是谁干这部分活，&lt;br>
谁就承担了HRBP的角色了。”&lt;/p>
&lt;p>“对的。”&lt;/p>
&lt;p>“那我来复述一下我对HRBP的理解吧？”&lt;/p>
&lt;p>Mia一摊手：&lt;br>
“请开始你的表演。”&lt;/p>
&lt;p>Lirian总结了三点：“&lt;/p>
&lt;ul>
&lt;li>首先HRBP广义上是一个角色，狭义上也可以是个职位。&lt;/li>
&lt;li>然后HRBP存在的作用就是帮业务部门处理战略上的事情。&lt;/li>
&lt;li>其次因为要帮业务部门的忙，所以假如他是懂业务出身，他是有一定优势的。&lt;/li>
&lt;/ul>
&lt;p>”&lt;/p>
&lt;p>Mia又补充了一下：&lt;br>
“HRBP就是帮业务部门解决痛点问题的，&lt;br>
假如他是业务部门出身会有非常大的优势。&lt;br>
因为部门的老板会很容易被他说服。&lt;br>
要不然假如说HRBP从来没写过代码，&lt;br>
技术部门的leader可能就会想：&lt;br>
‘你又不懂，凭什么指挥我啊’…”&lt;/p>
&lt;p>“嗯是啊。&lt;br>
那感觉HRBP做的厉害了以后，&lt;br>
下一步就直接当高层管理了？”&lt;/p>
&lt;p>“是有这个可能性，&lt;br>
但是其实很小。&lt;br>
基本上比起其他部门，&lt;br>
一个HRBP很难成为CEO，&lt;br>
顶多就当一个HR部门的头头算到顶了。”&lt;/p>
&lt;p>“喔，是这样啊。”&lt;/p>
&lt;p>Mia又想到了点什么，&lt;br>
补充道：&lt;br>
“我们刚才说的，&lt;br>
都是&lt;strong>真正的&lt;/strong>HRBP干的事情。&lt;br>
但事实是现在大多数公司HRBP都干的不是这个事情。&lt;br>
中国这套HR体系本来就是西方引入的嘛，&lt;br>
所以很多地方都变味了，&lt;br>
有些HRBP一开始又做招聘又做培训，&lt;br>
出了任何问题都要你解决。&lt;br>
这种HRBP就变成了每个团队的专用HR的感觉。”&lt;/p>
&lt;p>“噢，&lt;br>
所以正常来说就HRBP可以接活，&lt;br>
但是杂活呢，就分给SSC。&lt;br>
太专业的活，可以丢给Expert。”&lt;/p>
&lt;p>“没错，”&lt;br>
Mia通过了Lirian的答案，&lt;br>
突然又想考考他，&lt;br>
又问道：&lt;br>
“那你觉得HRM，就是HR经理和HRBP有什么区别呢？”&lt;/p>
&lt;p>Lirian想了想，说：&lt;br>
“我感觉这两个不是一个维度上的吧。&lt;br>
HRBP感觉是三支柱里的一个角色，&lt;br>
HRM感觉更多是职位高低的感觉，&lt;br>
比如小HR，普通HR和HR经理这种。”&lt;/p>
&lt;p>“差不多吧。&lt;br>
他们之间很大的差别是，&lt;br>
HRBP不会去制定公司的规章制度啊整套体系啊什么的，&lt;br>
因为他是针对特定的团队特定的业务。&lt;br>
但HRM就有这个责任，&lt;br>
去制定整套的规章制度。&lt;br>
比如假如公司要上市了，&lt;br>
老板需要有人来帮他制定完整的薪酬福利制度啊，&lt;br>
绩效考核制度啊，&lt;br>
这时候他需要的就是HRM，&lt;br>
而不是HRBP了。”&lt;/p>
&lt;p>Lirian学到了不少，&lt;br>
赶快表现出恍然大悟的样子：&lt;br>
“学到了！”&lt;/p>
&lt;p>Mia喝了口水，&lt;br>
总结了下陈词：&lt;br>
“反正我觉得最高级的HRBP，&lt;br>
就是站在老板的角度上想问题。&lt;br>
不过这样也满亏的，&lt;br>
拿着HR的钱，&lt;br>
做着老板的事情。”&lt;/p>
&lt;p>Lirian笑道：&lt;br>
“不过假如我是老板，&lt;br>
我肯定很喜欢你这样的员工。&lt;br>
假如我的每个员工都有ownership，&lt;br>
都像老板一样思考问题，&lt;br>
那我的公司一定是个伟大的公司。”&lt;/p>
&lt;h2 id="markdown">Markdown&lt;/h2>
&lt;p>喝了点水，&lt;br>
歇了歇以后，&lt;br>
Mia问Lirian：&lt;br>
“那你上次要跟我说的Markdown呢？&lt;br>
那是什么？”&lt;/p>
&lt;p>Lirian再次表示很惭愧：&lt;br>
“我感觉这个两三句话就说完了…”&lt;/p>
&lt;p>“说嘛说嘛~”&lt;/p>
&lt;p>“Markdown其实就是一种写文章的语法，&lt;br>
就像Word文件里指定了哪些字是标题，&lt;br>
哪些字是加粗的语法一样。&lt;br>
用Markdown来写文章可以让你更好地控制格式。”&lt;/p>
&lt;p>“啊？说完了？”&lt;/p>
&lt;p>“……说完了啊……”&lt;/p>
&lt;p>Mia感觉被两三句话就打发了，&lt;br>
很不服，于是继续问道：&lt;br>
“那上次看你用有道云笔记写东西，&lt;br>
为什么左右有一黑一白两个屏幕啊？”&lt;/p>
&lt;p>“喔，那个右边是预览页面。”&lt;br>
Lirian想了想，&lt;br>
详细地解释道：&lt;br>
“要讲Markdown，&lt;br>
我先来讲下Markup。&lt;br>
Markdown这个名字呢，&lt;br>
其实一开始是跟Markup针锋相对的。&lt;br>
Markup就是网页显示字体用的那种语法，&lt;br>
Microsoft Word用的也可以算是一种Markup。&lt;br>
Markup所宣扬的是WYSIWYG：&lt;br>
What You See Is What You Get，&lt;br>
中文翻译是所见即所得。&lt;br>
比如说我们要加粗一个字体，&lt;br>
我们就选中字体加粗一下。&lt;br>
但是这样有一个问题，&lt;br>
就是WYCSYCG：&lt;br>
What You Can&amp;rsquo;t See You Can&amp;rsquo;t Get，&lt;br>
格式的表现能力就一眼可见的那么多。&lt;br>
假如我想做到同样的文字，&lt;br>
在不同的环境下呈现不同的效果，&lt;br>
就不行了。&lt;br>
所以我们就有了Markdown。”&lt;/p>
&lt;p>Mia听得一脸懵逼，&lt;br>
Lirian就拿了台电脑开始展示起来了：&lt;br>
“比如说Markdown这种语法，&lt;br>
我们写文章可以这么写”&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-markdown" data-lang="markdown">&lt;span style="display:flex;">&lt;span># 这是大标题
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">## 这是二标题
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>想**加粗**字体要在字体两边各加两个星号，*斜体两边就只加一个星号*。
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>引用别人的话可以加反引号，`像这样子`。
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>引用鲁迅的话就可以在行首加大于号：
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">&amp;gt; &lt;/span>&lt;span style="font-style:italic">网上的人都瞎编我的名言 —— 鲁迅
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="font-style:italic">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">1.&lt;/span> 可以用数字来表示序号
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">2.&lt;/span> 就像这样
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">*&lt;/span> 也可以表示列表
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">*&lt;/span> 就像这样
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>上面这段Markdown呈现出来会长这个样子：&lt;/p>
&lt;h1 id="这是大标题">这是大标题&lt;/h1>
&lt;h2 id="这是二标题">这是二标题&lt;/h2>
&lt;p>想&lt;strong>加粗&lt;/strong>字体要在字体两边各加两个星号，&lt;em>斜体两边就只加一个星号&lt;/em>。&lt;/p>
&lt;p>引用别人的话可以加反引号，&lt;code>像这样子&lt;/code>。&lt;/p>
&lt;p>引用鲁迅的话就可以在行首加大于号：&lt;/p>
&lt;blockquote>
&lt;p>网上的人都瞎编我的名言 —— 鲁迅&lt;/p>
&lt;/blockquote>
&lt;ol>
&lt;li>可以用数字来表示序号&lt;/li>
&lt;li>就像这样&lt;/li>
&lt;/ol>
&lt;ul>
&lt;li>也可以表示列表&lt;/li>
&lt;li>就像这样&lt;/li>
&lt;/ul>
&lt;p>看完这段展示以后，&lt;br>
Mia表示：&lt;br>
“我感觉这跟你们写程序很像啊，&lt;br>
要记很多种东西，&lt;br>
而且写出来还要渲染，&lt;br>
感觉很麻烦啊。”&lt;/p>
&lt;p>Lirian解释道：&lt;br>
“Markdown里，&lt;br>
常用的语法也就大概10种左右吧。&lt;br>
这个很容易学的。&lt;br>
而且用Markdown可以把所有的富文本转换成纯文本，&lt;br>
纯文本就没有在不同的电脑上，&lt;br>
呈现的效果不一样的问题啦。”&lt;/p>
&lt;p>Mia想了想，&lt;br>
最后问道：&lt;br>
“那为什么云笔记要专门支持Markdown啊？&lt;br>
感觉这个功能就是给程序员设计的…”&lt;/p>
&lt;p>Lirian：&lt;br>
“我也不知道…”&lt;/p></description></item><item><title>一种轻量级的Http加密方式：Hawk</title><link>https://liriansu.com/posts/2017-03-18-hawk-authentication/</link><pubDate>Sat, 18 Mar 2017 23:55:18 +0000</pubDate><guid>https://liriansu.com/posts/2017-03-18-hawk-authentication/</guid><description>&lt;p>这是一篇关于&lt;a href="https://github.com/hueniverse/hawk1">Hawk&lt;/a>的简短介绍。&lt;/p>
&lt;h2 id="什么是hawk">什么是Hawk&lt;/h2>
&lt;p>&lt;a href="https://github.com/hueniverse/hawk1">Hawk&lt;/a>是一种轻量级的Http加密方式，&lt;br>
这里的轻量级是针对于OAuth / Digest这种加密方式而言。&lt;br>
&lt;a href="https://github.com/hueniverse/hawk1">Hawk&lt;/a>主要防范的是中间人攻击，&lt;br>
它基于服务器和客户端共有的秘钥，&lt;br>
在时间戳的基础上对请求加密，&lt;br>
生成互相匹配的特征码。&lt;/p>
&lt;p>&lt;a href="https://github.com/hueniverse/hawk1">Hawk&lt;/a>的好处是整个加密的过程对计算能力要求不高，&lt;br>
用到的也是简单的sha256算法。&lt;br>
而且它可以只针对单个请求加密，&lt;br>
所以应用场景十分灵活。&lt;/p>
&lt;p>在一个典型的&lt;a href="https://github.com/hueniverse/hawk1">Hawk&lt;/a>应用场景中，&lt;br>
客户端首先通过某种方式跟服务端通信，&lt;br>
获取秘钥。&lt;br>
在之后的Http请求中，&lt;br>
客户端对请求采用Hawk加密，&lt;br>
并且把基本信息放在Http Header里。&lt;br>
服务器收到请求以后，&lt;br>
采用同样的方式进行加密比对，&lt;br>
假如两边都对上了，&lt;br>
则是一个合法请求。&lt;br>
否则返回&lt;code>401 Unauthorized&lt;/code>&lt;/p>
&lt;h2 id="加密算法">加密算法&lt;/h2>
&lt;p>&lt;a href="https://github.com/hueniverse/hawk1">Hawk&lt;/a>协议规定的加密方式如下：&lt;/p>
&lt;p>这是一个样例的HTTP GET请求：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-http" data-lang="http">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#960050;background-color:#1e0010">GET https://example.com:8000/resource/1?b=1&amp;amp;a=2
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>要通过Hawk验证，&lt;br>
我们会把请求的特征用换行符拼接成如下格式，&lt;br>
最后再用&lt;code>HMAC sha256&lt;/code>进行加密：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-http" data-lang="http">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#960050;background-color:#1e0010">hawk.1.header
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#960050;background-color:#1e0010">1353832234
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#960050;background-color:#1e0010">j4h3g2
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#960050;background-color:#1e0010">GET
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#960050;background-color:#1e0010">/resource/1?b=1&amp;amp;a=2
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#960050;background-color:#1e0010">example.com
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#960050;background-color:#1e0010">8000
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#960050;background-color:#1e0010">some-app-ext-data
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>其中&lt;code>hawk.1.header&lt;/code>是表示用version为1的hawk来加密header，&lt;br>
&lt;code>1353832234&lt;/code>是unix timestamp，&lt;br>
&lt;code>j4h3g2&lt;/code>是客户端生成的随机字符串，&lt;br>
&lt;code>GET&lt;/code>是请求类型，&lt;br>
&lt;code>/resource/1?b=1&amp;amp;a=2&lt;/code>是请求的query，&lt;br>
&lt;code>example.com&lt;/code>和&lt;code>8000&lt;/code>分别是host和port，&lt;br>
而&lt;code>some-app-ext-data&lt;/code>是约定好要验证的额外内容（可为空）。&lt;br>
上面这段字符串是大小写敏感，空格敏感且换行敏感的。&lt;/p>
&lt;p>假如说我们的秘钥是&lt;code>werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn&lt;/code>，&lt;br>
则上面的样例请求经过&lt;code>HMAC sha256&lt;/code>加密后的特征码会是&lt;code>6R4rV5iE+NPoym+WwjeHzjAGXUtLNIxmo1vpMofpLAE=&lt;/code>&lt;/p>
&lt;p>最后我们把基本信息加入Http Header里，&lt;br>
请求就会变成这样子：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-http" data-lang="http">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#960050;background-color:#1e0010">GET https://example.com:8000/resource/1?b=1&amp;amp;a=2
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#960050;background-color:#1e0010">Authorization: Hawk id=&amp;#34;dh37fgj492je&amp;#34;, ts=&amp;#34;1353832234&amp;#34;, nonce=&amp;#34;j4h3g2&amp;#34;, ext=&amp;#34;some-app-ext-data&amp;#34;, mac=&amp;#34;6R4rV5iE+NPoym+WwjeHzjAGXUtLNIxmo1vpMofpLAE=&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>服务器端拿到&lt;code>HttpHeader.Authorization&lt;/code>以后进行加密比对即可。&lt;/p>
&lt;h2 id="其它事项">其它事项&lt;/h2>
&lt;ul>
&lt;li>Hawk提供Payload Validation，协议中指定的加密方式是&lt;code>sha256&lt;/code>，与header的加密方式&lt;code>HMAC sha256&lt;/code>不一样。&lt;/li>
&lt;li>假如客户端和服务器的Timestamp不一样，服务器应当返回Timestamp，由客户端计算时间差后再次请求。&lt;/li>
&lt;li>具体使用中可恰当魔改Hawk请求，比如增加对id的验证等。&lt;/li>
&lt;/ul></description></item><item><title>HR就讨厌我们这样的技术，今年一个offer都没发</title><link>https://liriansu.com/posts/2017-03-08-what-a-hard-backend-interview/</link><pubDate>Wed, 08 Mar 2017 20:44:40 +0000</pubDate><guid>https://liriansu.com/posts/2017-03-08-what-a-hard-backend-interview/</guid><description>&lt;p>还好我司HR人美心善，任劳任怨……&lt;/p>
&lt;h2 id="面试套路">面试套路&lt;/h2>
&lt;p>年后的求职市场逐渐活跃了起来，&lt;br>
直观感受就是收到的简历比年前要多不少，&lt;br>
于是最近基本上每天我们都有面试。&lt;/p>
&lt;p>我司目前一共有三个后端工程师：&lt;br>
津铭，周丞，我。&lt;/p>
&lt;p>我们面试的套路是&lt;code>电话面试 - 到场面试（三轮） - 发offer&lt;/code>。&lt;br>
这里的&lt;code>到场面试（三轮）&lt;/code>是指我们一共有三轮到面，&lt;br>
而不是提供三轮接送。&lt;/p>
&lt;p>不过前几天面了个广州的小兄弟，&lt;br>
觉得他还蛮不错的，&lt;br>
谢老板表示&lt;code>只要人厉害的话，来回路费都可以报了。&lt;/code>&lt;/p>
&lt;p>嗯，接下来就需要他证明自己是不是&lt;code>厉害的人&lt;/code>了。&lt;/p>
&lt;h2 id="面试标准">面试标准&lt;/h2>
&lt;p>其实我们的面试标准不高。&lt;br>
但因为上一句我用了&lt;code>其实&lt;/code>两个字，&lt;br>
说明我们的面试标准其实也不低。&lt;/p>
&lt;p>之前一次有一个前端工程师来面试，&lt;br>
算法题一题都没答出来，&lt;br>
实现题答得也不是特别好。&lt;br>
但是我们一致觉得这个候选人&lt;br>
&lt;code>大学四年学的是物理，毕业以后才写前端的&lt;/code>&lt;br>
能有这个水平很不错，&lt;br>
而且浑身散发着一种&lt;code>学习技术使我快乐&lt;/code>的光芒，&lt;br>
很让人喜欢。&lt;br>
于是我们发了offer，&lt;br>
候选人选择去了小红书&amp;hellip;/(ㄒoㄒ)/~~&lt;/p>
&lt;p>还有一次一个候选人来面试，&lt;br>
一路顺利地过到了我司CEO谢老板的当面面试。&lt;br>
谢老板是做技术的，&lt;br>
所以跟工程师很容易聊到一块去，&lt;br>
他跟候选人聊嗨了以后，&lt;br>
他问候选人：&lt;code>你为什么想到创业公司工作啊？&lt;/code>&lt;br>
候选人表示很激动，&lt;br>
回答道：&lt;code>因为我的梦想就是创业啊，我想看看外面的创业公司是怎么做的，然后学了成套技术以后，我就可以自己去创业了！&lt;/code>&lt;br>
当时谢老板就卧槽了。&lt;/p>
&lt;h2 id="我司技术">我司技术&lt;/h2>
&lt;p>我司技术邮箱组有两个，&lt;br>
一个是&lt;code>yanfa@kezaihui.com&lt;/code>，&lt;br>
研发部，很科学。&lt;br>
另外一个是&lt;code>llk@kezaihui.com&lt;/code>，&lt;br>
这个邮箱嘛，&lt;br>
御姐控表示很淡定。&lt;/p>
&lt;p>我司技术团队目前有10个人：&lt;br>
一个CEO，两个移动端，三个后端，四个前端。&lt;br>
类比于建筑行业就是：&lt;br>
一个包工头，两个推车工，三个水泥工，四个砌砖工。&lt;/p>
&lt;p>因为人少，所以虽然说是前后端分离，&lt;br>
但是干的活交叉性很强，&lt;br>
后端们也会热情地参与像&lt;a href="https://www.zhihu.com/question/53625757">&amp;lt;如何评价真阿当的文章：《2016年前端技术观察》？&amp;gt;&lt;/a>这样的热闹讨论中。&lt;br>
（主要是吃瓜）&lt;/p>
&lt;p>还有一次吃饭的时候，产品经理Allen来问问题，&lt;br>
说&lt;code>数据库里我们主动营销的有效时间是哪个字段啊？&lt;/code>&lt;br>
（没错我们产品经理也要知道数据库的表结构…）&lt;br>
津铭（后端）表示懵逼，有点忘了要看看代码，&lt;br>
然后靖哥哥（前端）说&lt;code>主动营销是ManualActivity&lt;/code>，&lt;br>
场面顿时有点尴尬…&lt;/p>
&lt;h2 id="后端面试">后端面试&lt;/h2>
&lt;p>年前谢老板表示我们今年工程师的quota是30个，&lt;br>
招满就不招了。&lt;br>
于是最近在&lt;code>金三银四&lt;/code>的招聘季里，&lt;br>
我们每天都在勤劳地面试…&lt;/p>
&lt;p>但是后端范围实在是太广了，&lt;br>
两个同为后端工程师的人，&lt;br>
工作内容不一定有很多交集。&lt;br>
前几天还面了个Oracle的兄弟，&lt;br>
我问他：&lt;code>你们前后端怎么通讯的？&lt;/code>&lt;br>
他说：&lt;code>Oracle自己做的WebService&lt;/code>&lt;br>
我：&lt;code>……那，你们用的什么框架？&lt;/code>&lt;br>
他说：&lt;code>Java，我们Oracle自己写的一套…&lt;/code>&lt;br>
我：&lt;code>……那，数据库呢？呃，Oracle？&lt;/code>&lt;br>
他：&lt;code>对…&lt;/code>&lt;br>
我不甘心：&lt;code>MySQL和Redis用么？&lt;/code>&lt;br>
他：&lt;code>不用……&lt;/code>&lt;/p>
&lt;p>我跟津铭前几天在地铁上还调侃道：&lt;br>
&lt;code>假如我们面试是面写SQL语句的话，估计Allen能过，谢老板就会挂了……&lt;/code>&lt;/p>
&lt;p>于是种种原因综合在一起，&lt;br>
我们今年后端一个offer都没能发出去…&lt;br>
&lt;em>叹气&lt;/em>&lt;/p>
&lt;p>面试是双向选择的事情，&lt;br>
双向选择都是看缘分的，&lt;br>
缘分需要等待，&lt;br>
我们就只好继续等待了。&lt;/p>
&lt;h2 id="其它">其它&lt;/h2>
&lt;p>我这篇文章是发在公众号和博客上的，&lt;br>
有可能你是在遥远的地方，&lt;br>
或者遥远的时间后看到的。&lt;br>
但是假如你对我司的岗位有兴趣，&lt;br>
非常欢迎直接投递简历，&lt;br>
或者跟我聊聊。&lt;/p>
&lt;p>作为一个工程师，&lt;br>
我十分喜欢现在的工作，&lt;br>
并且我想把这个机会介绍给你 :)&lt;br>
而且我司除了研发，&lt;br>
还有产品/运营/销售等很不错的岗位噢。&lt;/p></description></item><item><title>XYZ问题</title><link>https://liriansu.com/posts/2017-02-22-x-y-z-question/</link><pubDate>Wed, 22 Feb 2017 22:22:16 +0000</pubDate><guid>https://liriansu.com/posts/2017-02-22-x-y-z-question/</guid><description>&lt;p>有的时候我们想解决的是X问题，&lt;br>
但是我们却纠结于Y问题，&lt;br>
最后却陷入了Z问题的陷阱里。&lt;/p>
&lt;h2 id="简单的xyz问题">简单的XYZ问题&lt;/h2>
&lt;p>大部分时候，&lt;br>
我们的大脑会线性地思考问题，&lt;br>
有的时候我们想的越多，&lt;br>
反而容易陷入问题的陷阱里。&lt;/p>
&lt;ul>
&lt;li>比如我需要一把指甲刀。&lt;/li>
&lt;li>前天指甲刀还在房间桌子上，但我妈昨天刚整理过桌子。&lt;/li>
&lt;li>我记得我妈好像把东西都放书房抽屉里了。&lt;/li>
&lt;li>但是书房有好几个抽屉，我想弄清楚指甲刀在哪。&lt;/li>
&lt;li>于是我问我妈：&lt;strong>书房的抽屉里都有些什么啊?&lt;/strong>&lt;/li>
&lt;/ul>
&lt;p>在这个里，&lt;br>
用XYZ问题去归纳的话，&lt;br>
X问题就是&lt;strong>指甲刀在哪&lt;/strong>，&lt;br>
但我问出的Z问题却是&lt;strong>抽屉里都有什么&lt;/strong>。&lt;/p>
&lt;p>当然了，&lt;br>
这个例子本身也浅显极端，&lt;br>
我妈很容易看出只要脑袋好用一些，&lt;br>
直接问&lt;strong>指甲刀在哪&lt;/strong>就行了。&lt;/p>
&lt;p>但很多时候问题都没那么简单。&lt;/p>
&lt;h2 id="真实的xyz问题">真实的XYZ问题&lt;/h2>
&lt;p>我不擅长写网页，&lt;br>
但是每次我都想试试写网页。&lt;br>
大概就像那种不能吃辣，&lt;br>
但还是要吃辣的人一样。&lt;br>
这种情况下，我就很容易陷入XYZ问题中。&lt;/p>
&lt;p>比如我需要写一个&lt;strong>打字机效果&lt;/strong>出来，&lt;br>
根据命令行编程的经验，&lt;br>
我就觉得打字机效果大概可以等同于&lt;strong>每0.5秒更新一次内容&lt;/strong>，&lt;br>
我又觉得这个大概就等同于&lt;strong>更新内容，等0.5秒再更新&lt;/strong>，&lt;br>
于是我搜索&lt;strong>JavaScript sleep 0.5 second&lt;/strong>。&lt;/p>
&lt;p>/(ㄒoㄒ)/&lt;br>
很可惜，&lt;br>
这样得到的解决方案会跟我想要的相差很远。&lt;/p>
&lt;p>所以解决XYZ问题最好的办法就是：&lt;br>
&lt;strong>理清思路，找到X问题，直接解决它。&lt;/strong>&lt;/p>
&lt;p>在这个JavaScript的例子里，&lt;br>
我们的X问题其实是&lt;strong>JavaScript typewriter effect&lt;/strong>&lt;br>
（用这个去搜索就能找到很多现成方案了）&lt;/p>
&lt;h2 id="语文老师说要写作文总结">语文老师说要写作文总结&lt;/h2>
&lt;p>俗话说&lt;code>话粗理不粗，理粗情意重&lt;/code>。&lt;/p>
&lt;p>以后我们遇到问题的时候，&lt;br>
也可以想一想：&lt;/p>
&lt;ul>
&lt;li>我们的X问题是什么？&lt;/li>
&lt;li>我们有没有陷入Y问题的坑里？&lt;/li>
&lt;li>解决Z问题有助于解决X问题吗？&lt;/li>
&lt;/ul>
&lt;p>:)&lt;/p></description></item><item><title>用GitHub托管静态HTML页面</title><link>https://liriansu.com/posts/2017-02-03-hold-static-html-on-github/</link><pubDate>Fri, 03 Feb 2017 21:59:54 +0000</pubDate><guid>https://liriansu.com/posts/2017-02-03-hold-static-html-on-github/</guid><description>&lt;p>这是一篇入门级的技术文章，&lt;br>
教你怎么在GitHub上托管静态的HTML页面。&lt;/p>
&lt;h2 id="github项目主页">GitHub项目主页&lt;/h2>
&lt;p>GitHub有个设定，&lt;br>
就是&lt;strong>每个项目的gh-pages分支可以通过&lt;code>user-domain/项目名&lt;/code>来访问&lt;/strong>。&lt;/p>
&lt;p>比如以前我把一些常用的js/css库放到&lt;a href="https://github.com/LKI/static">我的static项目下(LKI/static)&lt;/a>，&lt;br>
该项目下&lt;code>gh-pages&lt;/code>分支的index.html就可以直接通过&lt;a href="https://liriansu.com/static/">lki.github.io/static&lt;/a>访问。&lt;/p>
&lt;p>GitHub的这个设定本意是&lt;a href="https://pages.github.com/">让每个项目都有自己的主页来展示&lt;/a>，&lt;br>
不过我们也可以借用这个设定来托管静态HTML页面。&lt;/p>
&lt;h2 id="托管静态页面">托管静态页面&lt;/h2>
&lt;p>托管页面的大概步骤如下：&lt;/p>
&lt;ol>
&lt;li>拥有自己的GitHub账号&lt;/li>
&lt;li>在GitHub上建立一个目录&lt;a href="https://github.com/new">(Create new repository)&lt;/a>&lt;/li>
&lt;li>用git创造该项目下建立&lt;code>gh-pages&lt;/code>分支，提交一个index.html文件&lt;/li>
&lt;/ol>
&lt;p>第3步的命令行版本大概如下：&lt;/p>
&lt;pre tabindex="0">&lt;code>$ cd /Users/liriansu/new-repo
$ git init # 初始化git目录
$ git checkout -b gh-pages # 新建gh-pages分支，并切换过去
# 跑完上一条命令后，把你的index.html文件放到new-repo文件夹里
$ git add index.html # 告诉git说index.html要提交了
$ git commit -m &amp;#34;add index.html&amp;#34; # 提交index.html
$ git remote add origin https://github.com/&amp;lt;username&amp;gt;/&amp;lt;repository&amp;gt;
$ git push -u origin gh-pages # 推到GitHub服务器上
&lt;/code>&lt;/pre>&lt;p>然后我们就可以在&lt;code>https://&amp;lt;username&amp;gt;.github.io/&amp;lt;repository&amp;gt;&lt;/code>上看到刚提交上去的index.html了。&lt;br>
最后假如你希望在GitHub上搭建个人博客，&lt;br>
可以参照&lt;a href="https://liriansu.com/how-this-blog-was-built">我的搭建方案&lt;/a>&lt;/p></description></item><item><title>最精简的程序语言：Iota</title><link>https://liriansu.com/posts/2017-01-24-iota-language/</link><pubDate>Tue, 24 Jan 2017 13:07:50 +0000</pubDate><guid>https://liriansu.com/posts/2017-01-24-iota-language/</guid><description>&lt;p>这门语言，只有两个保留字&lt;a href="https://en.wikipedia.org/wiki/Reserved_word">(reserved keyword)&lt;/a>&lt;/p>
&lt;h2 id="各种语言的reserved-keyword">各种语言的reserved keyword&lt;/h2>
&lt;p>今天逛SO的时候发现了这样一个问题：&lt;br>
&lt;a href="https://stackoverflow.com/questions/4980766/reserved-keywords-count-by-programming-language">Reserved keywords count by programming language?&lt;/a>&lt;/p>
&lt;p>各语言的保留字数目按从大到小的量大概如下：&lt;/p>
&lt;p>| ANSI COBOL 85 | 357 |&lt;br>
| JavaScript | 180 |&lt;br>
| C# | 102 |&lt;br>
| Java | 50 |&lt;br>
| Python 3.x | 33 |&lt;br>
| C | 32 |&lt;br>
| Go | 25 |&lt;br>
| Brainfuck | 8 |&lt;br>
| iota | &lt;strong>2&lt;/strong> |&lt;/p>
&lt;p>嗯，Python的保留字果然是少，&lt;br>
怪不得&lt;a href="https://news.ycombinator.com/item?id=8241308">有个笑话是说Python其实是“可执行的伪代码”&lt;/a>&lt;/p>
&lt;blockquote>
&lt;p>python is executable pseudocode, while perl is executable line noise.&lt;/p>
&lt;/blockquote>
&lt;p>不过等等，这个iota是什么语言？&lt;br>
居然只要两个保留字就可以实现图灵完备了？&lt;/p>
&lt;h2 id="iota-程序语言">Iota 程序语言&lt;/h2>
&lt;p>虽然这里我们说Iota是程序语言，&lt;br>
但其实真要用Iota写可执行的脚本程序还是没那么简单的。&lt;br>
这里的“程序语言”更大意义上是计算机科学里的图灵完备的解决可计算问题的概念，&lt;br>
那么首先我们来看Iota的设计概念：&lt;/p>
&lt;p>&lt;a href="https://en.wikipedia.org/wiki/Iota">Iota on wikipedia&lt;/a>&lt;/p>
&lt;p>呃，上面那个页面其实是希腊字母里的Iota &lt;code>ι&lt;/code>&lt;br>
下面这才是iota程序语言：&lt;/p>
&lt;p>&lt;a href="https://en.wikipedia.org/wiki/Iota_and_Jot">Iota and Jot&lt;/a>&lt;/p>
&lt;p>wiki上很好地介绍了iota，大概意思（也就是我消化过以后）：&lt;br>
相对于知名的&lt;a href="https://en.wikipedia.org/wiki/Lambda_calculus">lambda calculus&lt;/a>和&lt;a href="https://en.wikipedia.org/wiki/SKI_combinator_calculus">SKI combinator calculus&lt;/a>来说，&lt;br>
Iota和Jot是非常精简的&lt;a href="https://en.wikipedia.org/wiki/Formal_system">Formal System&lt;/a>，&lt;br>
它们的设计初衷就是用尽量少的算子来完成图灵完备的语言。&lt;br>
简单来说iota只有两个保留字，一个是 &lt;code>*&lt;/code>, 一个是&lt;code>i&lt;/code>，&lt;br>
&lt;code>*&lt;/code>会结合后面两个iota表达式，而&lt;code>i&lt;/code>会接受表达式&lt;code>x&lt;/code>，返回&lt;code>xSK&lt;/code>。&lt;/p>
&lt;p>看完上面一大段可能已经有点晕乎了，&lt;br>
那么换个角度，我们想象一下iota是怎么被创造出来的吧。&lt;/p>
&lt;p>一群人聚在一起，&lt;br>
当时已经有了图灵理论，&lt;br>
有了lambda算子，&lt;br>
有了functional programming，&lt;br>
于是有人提了个问题：&lt;br>
最精简的图灵完备的语言是什么？&lt;br>
于是&lt;a href="https://en.wikipedia.org/wiki/Chris_Barker_(linguist)">Chris Barker&lt;/a>站在一系列已有理论的基础上，&lt;br>
发明了&lt;a href="https://en.wikipedia.org/wiki/Iota_and_Jot">iota&lt;/a>这门语言。&lt;/p>
&lt;h2 id="ski-算子">SKI 算子&lt;/h2>
&lt;p>&lt;a href="https://en.wikipedia.org/wiki/SKI_combinator_calculus">SKI&lt;/a>就是iota发明路上一个很重要的巨人肩膀。&lt;br>
SKI一共定义了三个算子，分别是&lt;code>S&lt;/code>, &lt;code>K&lt;/code>, &lt;code>I&lt;/code>&lt;br>
:) 这名字听起来十分简单粗暴，我很喜欢。&lt;br>
规则如下：&lt;/p>
&lt;ul>
&lt;li>SKI以带括号表达式的形式呈现，可以把&lt;code>xy = z&lt;/code>简单理解为&lt;code>函数x接受参数y返回值z&lt;/code>&lt;/li>
&lt;li>&lt;code>I&lt;/code>接受一个参数，并返回它，即有&lt;code>Ix = x&lt;/code>&lt;/li>
&lt;li>&lt;code>K&lt;/code>接受两个参数，并返回第一个参数，即有&lt;code>Kxy = x&lt;/code>&lt;/li>
&lt;li>&lt;code>S&lt;/code>接受三个参数，返回一三参数对二三参数的操作结果，即有&lt;code>Sxyz = xz(yz)&lt;/code>&lt;/li>
&lt;/ul>
&lt;p>根据以上&lt;em>玄妙&lt;/em>的定义，神奇的事情发生了 :)&lt;br>
&lt;strong>&lt;code>SKI&lt;/code>实际上只需要&lt;code>S&lt;/code>和&lt;code>K&lt;/code>算子，&lt;code>I&lt;/code>算子可以用&lt;code>SKK&lt;/code>表示&lt;/strong> :&lt;/p>
&lt;pre tabindex="0">&lt;code> SKKx
= Kx(Kx) # 根据Sxyz = xz(yz)
= x # 根据Kxy = x
&lt;/code>&lt;/pre>&lt;p>而通过SKI，我们可以做很多的事情：&lt;/p>
&lt;ul>
&lt;li>递归&lt;/li>
&lt;li>取反&lt;/li>
&lt;li>布尔逻辑&lt;/li>
&lt;/ul>
&lt;p>以上例子可以&lt;a href="https://en.wikipedia.org/wiki/SKI_combinator_calculus">去维基看原文: SKI combinator calculus&lt;/a>&lt;/p>
&lt;h2 id="回到iota">回到iota&lt;/h2>
&lt;p>在SKI之后，&lt;a href="https://en.wikipedia.org/wiki/Chris_Barker_(linguist)">Chris Barker&lt;/a>提出了iota算子，&lt;br>
有 &lt;code>ix = xSK&lt;/code>&lt;/p>
&lt;p>所以可以推出：&lt;/p>
&lt;pre tabindex="0">&lt;code> ii
= iSK
= SSKK
= SK(KK)
= SKK &amp;lt;=&amp;gt; I
i(iI)
= i(ISK)
= i(SK)
= SKSK
= KK(SK)
= K
iK
= KSK
= S
&lt;/code>&lt;/pre>&lt;p>:) 瞧，这就是逻辑的魅力。&lt;br>
我们通过定义一系列很小的基石，&lt;br>
就能处理整个大厦。&lt;/p>
&lt;p>总而言之，iota在SKI的基础上定义了一个关键的算子，&lt;br>
再加上&lt;code>*&lt;/code>字符做到程序化地表示，&lt;br>
从而实现了最精简的程序语言这一目标。&lt;/p></description></item><item><title>如何在Mac OSX中用Finder打开特定Path</title><link>https://liriansu.com/posts/2016-12-26-go-to-path-in-osx/</link><pubDate>Mon, 26 Dec 2016 17:01:38 +0000</pubDate><guid>https://liriansu.com/posts/2016-12-26-go-to-path-in-osx/</guid><description>&lt;p>今天终于学到了这个很有用的知识，&lt;br>
感觉有必要记下来…&lt;/p>
&lt;p>两个方法：&lt;/p>
&lt;ol>
&lt;li>
&lt;p>在Terminal中输入&lt;code>open /Users&lt;/code>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>在Finder中敲&lt;code>Command + Shift + G&lt;/code>，然后输入&lt;code>/Users&lt;/code>&lt;/p>
&lt;/li>
&lt;/ol>
&lt;p>对Mac系统不熟悉的乡下人伤不起啊…&lt;/p></description></item><item><title>disqus不稳定，于是我开始用commentit了</title><link>https://liriansu.com/posts/2016-12-22-use-commentit/</link><pubDate>Thu, 22 Dec 2016 20:20:07 +0000</pubDate><guid>https://liriansu.com/posts/2016-12-22-use-commentit/</guid><description>&lt;p>挂在GitHub Pages上的静态博客的评论总是个蛋疼的问题，&lt;br>
我以前一直都是用&lt;a href="https://disqus.com/">disqus&lt;/a>的，&lt;br>
但是它总是处于墙于被墙的边缘…&lt;/p>
&lt;p>&lt;a href="https://liriansu.com/how-this-blog-was-built">因为&lt;del>自己感觉没那个必要从头搭建博客服务器&lt;/del>懒，于是我直接采用了GitHub Pages。&lt;/a>&lt;br>
但是由于GitHub Pages是静态页面，所以评论系统就成了问题。&lt;br>
于是研究了一番以后我用了&lt;a href="https://disqus.com/">disqus&lt;/a>的第三方评论。&lt;/p>
&lt;p>disqus的便利之处在于构建简单，&lt;br>
我只要去注册一下，加一个&lt;a href="https://github.com/LKI/lki.github.io/blob/b1c59b15a83fe0e0c9c2af55b15e1d3fa107c551/_includes/comments.html">comments.template&lt;/a>就可以自动展开成评论页面了。&lt;br>
但是出于种种原因&lt;a href="https://disqus.com/">disqus&lt;/a>对墙内用户支持的不好。&lt;/p>
&lt;p>而且我又不想用&lt;a href="https://duoshuo.com/">多说&lt;/a>，那个看起来无比蠢……&lt;/p>
&lt;p>直到我最近发现了一款黑科技：&lt;a href="https://commentit.io/getting-started">Comm(ent|it)&lt;/a>。&lt;br>
一句话概括它静态评论的原理是：&lt;code>所有的评论会变成Git Commit，push到你的Repository里面去&lt;/code>。&lt;/p>
&lt;p>雾草！&lt;br>
感觉很爽！&lt;/p>
&lt;p>而且其实&lt;a href="https://github.com/LKI/lki.github.io/blob/eb8e55e54fafc4effeeed8ed24ddae142829372b/_includes/comments.html">它的template配置和disqus的一样简单&lt;/a>。&lt;br>
补充：我们还要在&lt;a href="https://commentit.io/settings?master=true&amp;amp;group=true">commentit的配置页面&lt;/a>配一下允许直接提交到master :)&lt;/p>
&lt;p>:) 所以是时候在本页面下面评论，&lt;br>
以成为&lt;a href="https://github.com/LKI/lki.github.io/graphs/contributors">本博客GitHub项目的Contributor啦~&lt;/a>&lt;/p></description></item><item><title>用vundle来管理vim插件</title><link>https://liriansu.com/posts/2016-12-18-use-vundle-for-dotvim/</link><pubDate>Sun, 18 Dec 2016 02:22:16 +0000</pubDate><guid>https://liriansu.com/posts/2016-12-18-use-vundle-for-dotvim/</guid><description>&lt;p>今天把vim插件管理器换成了&lt;a href="https://github.com/VundleVim/Vundle.vim">Vundle&lt;/a>，&lt;br>
之前我一直用的是&lt;a href="https://github.com/tpope/vim-pathogen">pathogen&lt;/a>。&lt;/p>
&lt;h2 id="vim配置">Vim配置&lt;/h2>
&lt;p>其实我是在实习以后才开始用Vim的，&lt;br>
当时Justin直接把&lt;a href="https://github.com/LKI/dotvim">他的vim配置&lt;/a>给我clone了一份。&lt;br>
直接用现成的配置大大减缓了Vim的学习曲线，&lt;br>
而且很快就可以上手用起来了。&lt;br>
直到现在，我也觉得上手Vim的正确姿势就是找个大腿的配置。&lt;/p>
&lt;p>后来Vim稍微用的多了一些以后，&lt;br>
我开始尝试自己手动改vimrc来改设置。&lt;br>
改代码的基础就是看代码/学习代码，&lt;br>
于是我了解到了&lt;a href="https://github.com/tpope/vim-pathogen">pathogen&lt;/a>，&lt;br>
一个快速添加插件的Vim插件&amp;hellip;&lt;/p>
&lt;h2 id="pathogen">pathogen&lt;/h2>
&lt;p>pathogen的优点就是小巧和直白：&lt;/p>
&lt;p>你只需要添加autoload文件夹，&lt;br>
配置pathogen的载入，&lt;br>
就可以自己在预设好的插件目录下任意增删插件了。&lt;/p>
&lt;p>然而实际使用中有几个蛋疼之处：&lt;/p>
&lt;ul>
&lt;li>为了方便，我一般会用git submodule来添加插件。&lt;br>
git submodule不仅有着屎一样的用法，&lt;br>
它的commit还是固定的，&lt;br>
于是我经常要手动去更新插件版本。&lt;/li>
&lt;li>因为用了git submodule，删除插件也变得麻烦了。&lt;/li>
&lt;li>&lt;a href="https://github.com/tpope/vim-pathogen">pathogen&lt;/a>主要是&lt;a href="https://github.com/tpope">Tim Pope&lt;/a>写的，&lt;br>
而这个项目一年内只有三次更新…&lt;br>
一点也不活跃。&lt;/li>
&lt;/ul>
&lt;p>出于灵活度/便携度/活跃度的考虑，&lt;br>
我决定换个包管理器。&lt;/p>
&lt;h2 id="vundle">Vundle&lt;/h2>
&lt;p>于是我就想到了&lt;a href="https://github.com/VundleVim/Vundle.vim">Vundle&lt;/a>，&lt;br>
一个看起来很正式的Vim插件管理器。&lt;br>
它的配置其实也比较简单：&lt;/p>
&lt;p>本地克隆&lt;a href="https://github.com/VundleVim/Vundle.vim">Vundle&lt;/a>包（可用git submodule），&lt;br>
配置vimrc，然后在vimrc内写入插件名。&lt;/p>
&lt;p>不过第一次用命令&lt;code>vim +PluginInstall +qall&lt;/code>加载插件的过程可能比较慢。&lt;/p>
&lt;h2 id="现在的配置">现在的配置&lt;/h2>
&lt;p>于是鼓捣了一下，&lt;br>
成功从pathogen换成了vundle。&lt;br>
dotvim地址在&lt;a href="https://github.com/LKI/dotvim">github上&lt;/a>。&lt;/p>
&lt;p>题外话：&lt;br>
第一次了解到&lt;a href="https://github.com/VundleVim/Vundle.vim">Vundle&lt;/a>的时候，&lt;br>
我总感觉这有种浓浓的Emacs包管理山寨风，&lt;br>
于是当时我根本没考虑&lt;a href="https://github.com/VundleVim/Vundle.vim">Vundle&lt;/a>…&lt;br>
所以说&lt;strong>技术品味不能充当唯一技术评判标准呀~&lt;/strong>&lt;/p></description></item><item><title>后端工程师技能树</title><link>https://liriansu.com/posts/2016-12-16-backend-skill-tree/</link><pubDate>Fri, 16 Dec 2016 23:33:08 +0000</pubDate><guid>https://liriansu.com/posts/2016-12-16-backend-skill-tree/</guid><description>&lt;p>我最近打算点专精天赋&lt;code>后端工程师&lt;/code>，&lt;br>
于是先整理一份后端的技能树，&lt;br>
然后努力攒天赋点把它给点满。&lt;/p>
&lt;h2 id="全栈">全栈&lt;/h2>
&lt;p>前几天我和Joyce聊天讲到“我想写个后端技能树/练级攻略”，&lt;br>
她疑惑地问我：“你觉得各个端之间要分那么开么？”&lt;br>
我想了想，说：“呃。。。”（其实也不知道说什么）&lt;/p>
&lt;p>其实关于全栈的争论一直都有，每种意见都有科学之处：&lt;/p>
&lt;p>有人认为&lt;strong>全栈适合小团队，大团队更需要细化分工。&lt;/strong>&lt;br>
又或者&lt;strong>全栈是个伪命题，因为光一样技术学精学通就要花很大功夫了。&lt;/strong>&lt;br>
的确，在分工明确的情况下，各项全能的人才反倒是被浪费了，&lt;br>
更不用说这样的人本来就少。&lt;/p>
&lt;p>也有支持向全栈发展的人认为&lt;strong>新人适合专精一门，牛人始终是全能的。&lt;/strong>&lt;br>
以及&lt;strong>全栈指的不是语言，而是更基础的知识体系和综合能力。&lt;/strong>&lt;/p>
&lt;p>我其实是蛮羡慕全栈们的，而且我也希望以后某日化身为全栈。&lt;br>
但我总觉得目前的自己还是太菜了，连一门技艺也不精通，更别提全栈了。&lt;br>
而且武侠小说里面说得好：&lt;strong>大道相通&lt;/strong>。&lt;br>
也就是说我学好了一门技艺，想再去理解别的会更有经验，&lt;br>
即使达不到各项全能，说不定也能做到一精多专呢 :wink:&lt;/p>
&lt;p>嘿嘿，这么说来，写代码学技术和练武还是蛮像的。&lt;br>
就好像&lt;a href="https://coolshell.cn/articles/4990.html">程序员练级攻略&lt;/a>一样，打怪升级穿女装嘛~&lt;/p>
&lt;h2 id="后端技能树">后端技能树&lt;/h2>
&lt;ul>
&lt;li>程序基础
&lt;ul>
&lt;li>算法和数据结构&lt;/li>
&lt;li>语言基础&lt;/li>
&lt;li>框架和库&lt;/li>
&lt;li>抽象逻辑能力&lt;/li>
&lt;li>英语能力&lt;/li>
&lt;li>代码风格&lt;/li>
&lt;li>debug&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>计算机网络
&lt;ul>
&lt;li>网络协议&lt;/li>
&lt;li>服务器&lt;/li>
&lt;li>代理服务器&lt;/li>
&lt;li>网络安全&lt;/li>
&lt;li>权限&lt;/li>
&lt;li>RESTful&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>数据与数据库
&lt;ul>
&lt;li>关系型数据库&lt;/li>
&lt;li>非关系型数据库&lt;/li>
&lt;li>性能优化&lt;/li>
&lt;li>数据挖掘&lt;/li>
&lt;li>CAP&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>团队协作
&lt;ul>
&lt;li>沟通能力&lt;/li>
&lt;li>版本控制&lt;/li>
&lt;li>任务管理&lt;/li>
&lt;li>项目管理&lt;/li>
&lt;li>开源项目&lt;/li>
&lt;li>装逼与装菜逼&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>架构设计
&lt;ul>
&lt;li>高拓展&lt;/li>
&lt;li>高并发&lt;/li>
&lt;li>高可用&lt;/li>
&lt;li>高血压（并不）&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>价值观
&lt;ul>
&lt;li>学习意愿&lt;/li>
&lt;li>热爱技术&lt;/li>
&lt;li>心态开放&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;p>这是我心中的技能树，最后一节严格意义上不是技能树，&lt;br>
但我也觉得这些品质对一个后端工程师是有益的。&lt;br>
欢迎各种建议/评论 :)&lt;/p></description></item><item><title>git新手教程</title><link>https://liriansu.com/posts/2016-09-19-git-first-lesson/</link><pubDate>Mon, 19 Sep 2016 16:04:00 +0000</pubDate><guid>https://liriansu.com/posts/2016-09-19-git-first-lesson/</guid><description>&lt;p>这是一篇针对技术小白们的Git科普文章。&lt;br>
本文主要介绍版本控制工具Git的基本概念，&lt;br>
以及init,status,add,commit,reset,log几个基本命令。&lt;/p>
&lt;h2 id="什么是git">什么是Git&lt;/h2>
&lt;p>在十多年前，有好多程序员一起开发Linux系统。&lt;br>
这么多人一起写一个软件，他们就需要一个好的软件来&lt;br>
控制代码的版本/回滚代码/并行开发。&lt;br>
最开始他们是用的一个现成的软件叫&lt;em>BitKeeper&lt;/em>，&lt;br>
但是&lt;a href="https://git-scm.com/book/en/v2/Getting-Started-A-Short-History-of-Git">后来BitKeeper居然想收费！于是他们就开发出了Git…&lt;/a>&lt;/p>
&lt;p>没错，Git就是一个由程序员自己写的，&lt;br>
写给程序员自己用的，用来管理写程序的工具。&lt;br>
本文想做的就是把&lt;a href="https://en.wikipedia.org/wiki/Git">Git&lt;/a>这个&lt;em>程序员用的&lt;/em>工具&lt;br>
介绍给不懂写代码，但是要写文档，改文档的同学。&lt;/p>
&lt;p>（所以本文的具体栗子是在Windows系统下进行）&lt;/p>
&lt;h2 id="什么是版本控制">什么是版本控制&lt;/h2>
&lt;p>举个栗子：&lt;br>
今天要写毕业论文，我打开了Microsoft Word， 写完了第一章。&lt;br>
但我突然有一个更好的想法，我决定重写第一章。&lt;br>
于是我按下了&lt;strong>撤销&lt;/strong>按钮，Word文档&lt;strong>回滚&lt;/strong>到了最开始的地方。&lt;br>
我坐了三分钟，我发现其实还是我之前的第一章写的比较好。&lt;br>
于是我按下了&lt;strong>重复&lt;/strong>按钮，Word文档又&lt;strong>回滚&lt;/strong>到了我写完第一章的时候了。&lt;/p>
&lt;p>上面的栗子，其实就是一个典型的&lt;em>版本控制&lt;/em>场景。&lt;br>
而Git作为版本控制的工具，做的就是文件级别的&lt;em>版本控制&lt;/em>。&lt;/p>
&lt;p>接下来我们直接来试用Git。&lt;/p>
&lt;h2 id="安装git">安装Git&lt;/h2>
&lt;p>首先我们到&lt;a href="https://git-scm.com/download/win">Git的官方网站（英文）&lt;/a>&lt;br>
去下载最新的windows版本的git：&lt;br>
（当你用浏览器打开这个网站的时候，就应该有下载框弹出来了）&lt;/p>
&lt;p>下载地址：https://git-scm.com/download/win&lt;/p>
&lt;p>下载完毕以后打开，大部分设定用默认的就行了，&lt;br>
几个关键选项图示如下：&lt;/p>
&lt;p>安装选项：&lt;br>
&lt;img src="https://liriansu.com/assets/git_first_lesson/inst_opt.jpg" alt="options">&lt;/p>
&lt;p>安装命令：&lt;br>
&lt;img src="https://liriansu.com/assets/git_first_lesson/inst_cmd.jpg" alt="commands">&lt;/p>
&lt;p>换行符操作：&lt;br>
&lt;img src="https://liriansu.com/assets/git_first_lesson/inst_le.jpg" alt="line-endings">&lt;/p>
&lt;p>安装完毕后我们在任意菜单右键，&lt;br>
应该就可以看到“Git Bash Here”的选项。&lt;br>
并且打开以后我们输入&lt;code>git version&lt;/code>&lt;br>
可以查看到git版本号信息，&lt;br>
这就说明我们安装成功了。&lt;/p>
&lt;pre>&lt;code>$ git version
git version 2.9.0.windows.1
（具体版本可能会随时间变化，但这并不重要）
&lt;/code>&lt;/pre>
&lt;h2 id="新手上路">新手上路&lt;/h2>
&lt;h3 id="打开git-bash">打开Git Bash&lt;/h3>
&lt;p>git是一个命令行工具。&lt;br>
（虽然也有图形界面，但那个太蠢了，&lt;br>
我们还是学习更好用的敲命令吧）&lt;/p>
&lt;p>首先我们打开一个文件夹，&lt;br>
比如我打开的是D:\git-first-lesson\XML这个文件夹，&lt;br>
然后&lt;code>右键菜单 -&amp;gt; Git Bash Here&lt;/code>，&lt;br>
就打开了一个这样的Git Bash：&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/git_first_lesson/git_version.jpg" alt="hint">&lt;/p>
&lt;p>再顺便说一下几个基本的命令：&lt;/p>
&lt;ul>
&lt;li>&lt;code>ls&lt;/code>: list的简写，可以&lt;strong>查看当前文件夹下有哪些文件（夹）&lt;/strong>&lt;/li>
&lt;li>&lt;code>cd&lt;/code>: ChangeDirectory，可以&lt;strong>更换目录&lt;/strong>。&lt;code>cd ..&lt;/code>就是回到上一层目录&lt;/li>
&lt;/ul>
&lt;h3 id="git目录">Git目录&lt;/h3>
&lt;p>&lt;strong>想了解一个目录的状态，就使用&lt;code>git status&lt;/code>命令&lt;/strong>。&lt;br>
我们可以试着跑一下这个命令，但是Git会报这样的错误：&lt;/p>
&lt;pre>&lt;code>$ git status
fatal: Not a git repository (or any of the parent directories): .git
&lt;/code>&lt;/pre>
&lt;p>这个错误的字面意思是“错误：你并没有把当前目录（或者任何父目录纳入git版本控制）”。&lt;/p>
&lt;p>所以&lt;strong>为了将一个文件夹纳入版本控制，我们要使用&lt;code>git init&lt;/code>命令&lt;/strong>:&lt;/p>
&lt;pre>&lt;code>$ git init
Initialized empty Git repository in D:/git-first-lesson/XML/.git/
&lt;/code>&lt;/pre>
&lt;p>提示信息表示git已经初始化完成。&lt;br>
这个过程实际上是git在&lt;strong>当前目录&lt;/strong>新建了一个**.git**文件夹：&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/git_first_lesson/dot_git.jpg" alt="dotgit">&lt;/p>
&lt;p>然后我们再跑&lt;code>git status&lt;/code>就可以查看到当前目录状态了：&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/git_first_lesson/git_status.jpg" alt="git-st">&lt;/p>
&lt;h3 id="控制文件">控制文件&lt;/h3>
&lt;p>在我们初始化完git以后，git默认是把所有文件帮我们找出来的。&lt;br>
但是假如我们并不希望修改.wmv音频文件，.bak备份文件，Data数据文件夹怎么办？&lt;br>
或者假如我们只想版本控制.xml文件该怎么做呢？&lt;/p>
&lt;p>git在这里给我们留了一个控制文件，叫**.gitignore**文件。&lt;br>
我们可以&lt;code>右键 -&amp;gt; 新建文本文件 -&amp;gt; 重命名为.gitignore&lt;/code>或者直接在git-bash里面跑&lt;code>touch .gitignore&lt;/code>:&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/git_first_lesson/touch.jpg" alt="touch">&lt;/p>
&lt;p>假如我们想无视wmv文件，bak文件和Data文件夹，我们修改.gitignore内容为：&lt;/p>
&lt;pre>&lt;code>*.wmv
*.bak
Data\
&lt;/code>&lt;/pre>
&lt;p>假如我们只想控制xml文件，我们可以修改为：&lt;/p>
&lt;pre>&lt;code>*
!*/
!.gitignore
!*.xml
&lt;/code>&lt;/pre>
&lt;p>然后我们可以再跑一次&lt;code>git status&lt;/code>查看文件夹状态：&lt;br>
（在本例中我的.gitignore只控制了xml文件）&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/git_first_lesson/git_ignore.jpg" alt="ignore">&lt;/p>
&lt;h3 id="设置查看断点">设置/查看断点&lt;/h3>
&lt;p>Git最激动人心的地方到了：&lt;br>
有了前面的准备工作，&lt;br>
我们现在已经可以设置断点，&lt;br>
并且再未来随时回滚到任意断点了！&lt;/p>
&lt;p>我们直接看看怎么设置断点（Commit）：&lt;/p>
&lt;ul>
&lt;li>使用&lt;code>git add .&lt;/code>来记录当前目录的改动。&lt;/li>
&lt;li>使用&lt;code>git commit -m &amp;lt;commit_message&amp;gt;&lt;/code>来设置断点。&lt;/li>
&lt;/ul>
&lt;p>比如我们输入&lt;code>git add .&lt;/code>和&lt;code>git commit -m &amp;quot;My First Commit&amp;quot;&lt;/code>：&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/git_first_lesson/git_commit.jpg" alt="commit">&lt;/p>
&lt;p>好了！断点设置成功！接下来我们可以查看我们设置的断点：&lt;/p>
&lt;p>&lt;strong>我们可以使用&lt;code>git log&lt;/code>来查看断点，或者是&lt;code>git log --oneline&lt;/code>来查看断点的简略信息。&lt;/strong>&lt;/p>
&lt;p>比如这样子：&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/git_first_lesson/git_log.jpg" alt="log">&lt;/p>
&lt;h3 id="查看修改内容与回滚">查看修改内容与回滚&lt;/h3>
&lt;p>到目前为止，我们所做的操作都不会修改当前文件夹。&lt;br>
我们只是将&lt;em>整个文件夹当前的状态&lt;/em>纳入了版本控制。&lt;/p>
&lt;p>接下来我们要做的就是改动文件了。&lt;br>
比如我们稍微改动了&lt;code>Struture\recurse.xml&lt;/code>这个文件。&lt;/p>
&lt;p>&lt;strong>使用&lt;code>git diff&lt;/code>可以查看当前文本和上一版本的区别。&lt;/strong>&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/git_first_lesson/git_diff.jpg" alt="diff">&lt;/p>
&lt;p>&lt;strong>使用&lt;code>git reset --hard HEAD&lt;/code>可以回到上一个断点。&lt;/strong>&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/git_first_lesson/git_reset.jpg" alt="reset">&lt;/p>
&lt;h2 id="总结">总结&lt;/h2>
&lt;p>在本篇新手教程中，我们稍微介绍了版本控制和Git。&lt;br>
在安装完Git以后，我们接触到了以下命令：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>命令&lt;/th>
&lt;th>说明&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;code>git version&lt;/code>&lt;/td>
&lt;td>显示Git版本&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>ls&lt;/code>&lt;/td>
&lt;td>列出当前文件夹内文件&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>cd data&lt;/code>&lt;/td>
&lt;td>更改目录（进入data目录）&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>cd ..&lt;/code>&lt;/td>
&lt;td>回到上一层目录&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>git status&lt;/code>&lt;/td>
&lt;td>查看Git状态&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>git init&lt;/code>&lt;/td>
&lt;td>初始化（使当前文件夹纳入版本控制）&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>touch .gitignore&lt;/code>&lt;/td>
&lt;td>新建.gitignore文件&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>git add .&lt;/code>&lt;/td>
&lt;td>使所有未被ignore的文件加入版本控制&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>git commit -m &amp;quot;My first commit&amp;quot;&lt;/code>&lt;/td>
&lt;td>设置断点（准确的说是生成一个提交）(commit)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>git log&lt;/code>&lt;/td>
&lt;td>查看历史&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>git log --oneline&lt;/code>&lt;/td>
&lt;td>查看简单历史&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>git diff&lt;/code>&lt;/td>
&lt;td>查看当前文件夹状态与最近断点的区别&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>git reset --hard HEAD&lt;/code>&lt;/td>
&lt;td>回滚至上一断点&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>在之后的教程中，我们会更加深入地接触Git。&lt;/p>
&lt;p>（完）&lt;/p></description></item><item><title>You can live your dream</title><link>https://liriansu.com/posts/2016-06-27-you-can-live-your-dream/</link><pubDate>Mon, 27 Jun 2016 23:06:13 +0000</pubDate><guid>https://liriansu.com/posts/2016-06-27-you-can-live-your-dream/</guid><description>&lt;p>前阵子我偶然看到了一个非常棒的关于&lt;strong>梦想&lt;/strong>的视频&lt;/p>
&lt;p>视频地址在&lt;a href="https://www.youtube.com/watch?v=N5NF01Rpepo">Youtube&lt;/a>上 （需翻墙）&lt;/p>
&lt;p>总之各种意义上都是很正能量的一个视频，&lt;br>
台词如下：&lt;/p>
&lt;blockquote>
&lt;p>I don’t know what that dream is that you have. I don’t care how disappointing it might have been, as you’ve been working toward that dream. But that dream your holding in your mind that it’s possible that some of you already know that it’s hard. It’s not easy. It’s hard changing your life. That in the process working on your dreams you are going to incur a lot of disappointment, a lot of failure, a lot of pain. At moments when you‘re going to doubt yourself and say God why is this happening to me. I’m just trying to take care of my children, and my mother. I’m not trying to steal or rob from anybody. How does this have to happen to me?&lt;br>
For those of you all that have experienced some hardships don’t give up on your dream. The rough times are going to come, but they are not going to stay. They have come to pass.&lt;/p>
&lt;p>Greatness is not this wonderful, esoteric, illusive god-like feature that only the special among us will ever taste. It’s something that truly exists in all of us.&lt;/p>
&lt;p>It’s very important for you to believe that you are the one.&lt;br>
Most people they raise a family, they earn a living and then they die. They stop growing, they stop working on themselves, they stop stretching, and they stop pushing themselves. Then a lot of people like to complain but they don’t want to do anything about their situation. And most people don’t work on their dreams, why? One is because of fear, that they have fear of failure. What if things are worked out? And the fear of success, what if they do and i can’t handle it. These are not risk-takers.&lt;/p>
&lt;p>You spend so much time with other people, you spend so much time trying to get people to like you. You know other people more than you know yourself. You studied them you know about them, you want to hang out like them, you want to be just like them. And you know what you’ve invested so much time on them, you don’t know who you are. I challenge you to spend time by yourself.&lt;/p>
&lt;p>It’s necessary, that you get the losers out of your life, if you want to live your dream. But people who are running towards their dreams, life has a special kind of meaning.&lt;/p>
&lt;p>When you become the right person, what you do is start separating yourself from other people. You begin to have a sudden uniqueness. As long as you follow on other people, as long as your being a copycat you will never ever be the best copycat in the world. But you will be the best you could be. I challenge you to define your value.&lt;/p>
&lt;p>That everybody won’t see it, that everybody won’t join you, that everybody won’t have the vision. It is necessary to know that. That you are an uncommon breed.&lt;br>
It is necessary that you align yourself with people and attract people into your business, who are hungry. People who are unstoppable and unreasonable, people who are refusing to live life just as it is and who want more. The people that are living their dreams. are seeking winners to attach themselves to. The people that are living their dreams, are the people that know that if it’s gonna happen it’s up to them.&lt;/p>
&lt;p>If you want to be more successful. If you want to have and do stuff you’ve never done before, I’m asking you to invest in you. To invest in you!&lt;/p>
&lt;p>Someone’s opinion of you, does not have to become your reality. That you don’t have to go through life being a victim. And even though you face disappointments, you have to know within yourself, that I can do this, even if no one else sees it for me, I must see it for myself.&lt;/p>
&lt;p>This is what I believe and I am willing to die for it. Period.&lt;/p>
&lt;p>No matter how bad it is or how bad it gets, I’m going to make it.&lt;/p>
&lt;p>I want to represent an idea. I want to represent possibilities.&lt;/p>
&lt;p>Some of you right now, you want to go to the next level. I want a council, I want to be an Engineer, I want to be a Doctor. Listen to me. You can’t get to that level. You can’t get to that level economically where you want to be, until you start investing in your mind. You’re not reading books. I’m challenging you all to go to conference. I dare you to invest time. I dare you to be alone. I dare you to spend an hour to get to know yourself.&lt;/p>
&lt;p>When you become who you are, when you become the person you are created to be, designed to be who you were designed to be. When you become an individual. What you do is take yourself and start separating yourself from other people.&lt;/p>
&lt;p>I’m challenging you to get to a place where people do not like you or do not even bother you anymore. Why? Because you are not concerned about trying to make them happy. Because your trying to blow it, you’re trying to get to the next level. I need you to invest in your mind.&lt;/p>
&lt;p>If you’re still talking about your dreams. If you’re still talking about your goals. But you have not done anything yet, just take the first step.&lt;/p>
&lt;p>You can make your parents proud. You can make your school proud. You can touch millions of lives and the world will never be the same again because you came this way. Don’t let anybody steal your dream. Don’t let nobody steal your dream! After we face rejection and a “NO”, we have a meeting and no one shows up, or somebody said you can count on me, and they don’t come through. What if we had that type of attitude that cause repossess, nobody believes in you, you’ve lost again and again and again. The lights are cut off, but you still are looking at your dream, reviewing it everyday and saying to yourself, IT’S NOT OVER UNTIL I WIN!&lt;/p>
&lt;p>You can live your dream.&lt;/p>
&lt;/blockquote></description></item><item><title>URL中参数编码不正确的解决方案</title><link>https://liriansu.com/posts/2016-06-07-encoding-in-url/</link><pubDate>Tue, 07 Jun 2016 21:29:39 +0000</pubDate><guid>https://liriansu.com/posts/2016-06-07-encoding-in-url/</guid><description>&lt;p>说是说解决方案，其实并没有解决这个问题 :wink:&lt;/p>
&lt;h2 id="url中参数编码不正确">URL中参数编码不正确&lt;/h2>
&lt;p>最近在做Python-Scrapy的爬虫，用Tornado写了一个服务器程序，&lt;br>
但是遇到的问题是&lt;/p>
&lt;p>&lt;strong>Tornado无法解析URL的中文&lt;/strong>&lt;/p>
&lt;p>比如说样例小程序如下：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">from&lt;/span> tornado.ioloop &lt;span style="color:#f92672">import&lt;/span> IOLoop
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">import&lt;/span> tornado.web &lt;span style="color:#66d9ef">as&lt;/span> tw
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">SampleHandler&lt;/span>(tw&lt;span style="color:#f92672">.&lt;/span>RequestHandler):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">def&lt;/span> &lt;span style="color:#a6e22e">get&lt;/span>(self, path):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> self&lt;span style="color:#f92672">.&lt;/span>write(path)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>app &lt;span style="color:#f92672">=&lt;/span> tw&lt;span style="color:#f92672">.&lt;/span>Application([(ur&lt;span style="color:#e6db74">&amp;#39;/(.*)&amp;#39;&lt;/span>, SampleHandler)])
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>app&lt;span style="color:#f92672">.&lt;/span>listen(&lt;span style="color:#ae81ff">8080&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>IOLoop&lt;span style="color:#f92672">.&lt;/span>current()&lt;span style="color:#f92672">.&lt;/span>start()
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>但是访问&lt;code>https://localhost:8080/浮云计算&lt;/code>却只能得到&lt;code>æµ®äº�è®¡ç®�&lt;/code>这样一坨东西&amp;hellip;&lt;/p>
&lt;h2 id="解决方案">解决方案&lt;/h2>
&lt;p>长话短说，这是因为&lt;code>URL中文解码不正确&lt;/code>的原因导致的。&lt;br>
所以我们利用&lt;a href="https://tool.chinaz.com/tools/urlencode.aspx">站长工具url编码&lt;/a>手动替换中文访问即可：&lt;/p>
&lt;p>访问&lt;code>https://localhost:8080/%e6%b5%ae%e4%ba%91%e8%ae%a1%e7%ae%97&lt;/code>就可以得到&lt;code>浮云计算&lt;/code>啦。&lt;/p>
&lt;h2 id="详细原因">详细原因&lt;/h2>
&lt;p>一开始我怀疑是因为字符串没用utf8编码，&lt;br>
于是尝试了不同的转换方式：&lt;/p>
&lt;pre tabindex="0">&lt;code>self.write(str(path))
self.write(unicode(path))
self.write(path.encode(&amp;#39;utf8&amp;#39;))
&lt;/code>&lt;/pre>&lt;p>这些常识不是报错，就是根本没变化。&lt;/p>
&lt;p>最终我找到了&lt;a href="https://ju.outofmemory.cn/entry/62161">一个前人的经验&lt;/a>，里面是这么讲的：&lt;/p>
&lt;blockquote>
&lt;p>看来你是不知道在浏览器地址栏手动输入中文和在页面上一个的链接的编码处理方式是不同的。。。。&lt;br>
打个比方，在windows系统上，你在FF地址栏输入&amp;quot;https://localhost/中文.html?m=汉语&amp;quot;，这里的“中文”两字的编码是utf8（这一点应该是跟浏览器设置相关），而“汉语”则是gbk，跟操作系统相关（大部分中国人的windows应该都是cp936，也就是gbk）。&lt;br>
如果你是通过某个页面访问这个链接的，则所有字符的编码都是跟页面的编码相关。&lt;br>
在IE上也是一样。&lt;br>
所以，我觉得还是打消在浏览器地址栏输入中文这个想法吧，要不然你要解码两次，而且还要保证页面上的编码跟系统一样，不然无法保证手动输入和页面点击的兼容性。。。。&lt;/p>
&lt;/blockquote>
&lt;p>喔，原来是因为&lt;code>URL解码方式完全取决于浏览器和操作系统&lt;/code>，也就是说&lt;code>中文有可能以GBK来编码&lt;/code>&lt;/p>
&lt;p>怪不得Python/Tornado认不出来了！&lt;/p>
&lt;p>所以解决方案就是我们手动去解码一次啦~&lt;/p>
&lt;p>（或者Python3 XD）&lt;/p></description></item><item><title>在Windows上安装pip</title><link>https://liriansu.com/posts/2016-05-18-install-pip-on-windows/</link><pubDate>Wed, 18 May 2016 21:39:29 +0000</pubDate><guid>https://liriansu.com/posts/2016-05-18-install-pip-on-windows/</guid><description>&lt;p>pip是python的包管理工具，在Linux上安装比较简单，&lt;br>
但是在Windows上安装就稍微麻烦些。&lt;/p>
&lt;h2 id="安装python">安装Python&lt;/h2>
&lt;p>首先我们到Python的官网&lt;a href="https://www.python.org/downloads/">下载Python&lt;/a>。&lt;/p>
&lt;p>值得注意的是Python2和Python3非常不同，&lt;br>
里面的差别可能有半个Java和JavaScript的差别之大。&lt;br>
我习惯使用的版本是Python2.7。&lt;/p>
&lt;p>下载安装完以后，打开&lt;br>
&lt;code>我的电脑右键菜单&amp;gt;属性&amp;gt;高级系统设置&amp;gt;环境变量&lt;/code>&lt;br>
设置好Path：&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/python_path.jpg" alt="Python Path">&lt;/p>
&lt;p>然后我们打开命令提示符，就可以进python的shell啦：&lt;/p>
&lt;pre tabindex="0">&lt;code>&amp;gt; python
Python 2.7.11 on win32
Type &amp;#34;help&amp;#34;, &amp;#34;copyright&amp;#34;, &amp;#34;credits&amp;#34; or &amp;#34;license&amp;#34; for more information.
&amp;gt;&amp;gt;&amp;gt; exit()
&lt;/code>&lt;/pre>&lt;h2 id="安装pip">安装pip&lt;/h2>
&lt;p>我们使用&lt;a href="https://bootstrap.pypa.io/get-pip.py">get-pip.py&lt;/a>一键安装pip，&lt;br>
先把它右键另存为下载到某个地方。&lt;/p>
&lt;p>然后我们以管理员身份打开命令提示符，&lt;br>
直接用python运行该文件就可以安装pip了：&lt;/p>
&lt;pre tabindex="0">&lt;code>python get-pip.py
&lt;/code>&lt;/pre>&lt;p>Windows上运行pip的方式是：&lt;/p>
&lt;pre tabindex="0">&lt;code>python -m pip
Usage:
C:\CodeEn\Python27\python.exe -m pip &amp;lt;command&amp;gt; [options]
Commands:
install Install packages.
download Download packages.
uninstall Uninstall packages.
freeze Output installed packages in requirements format.
list List installed packages.
show Show information about installed packages.
search Search PyPI for packages.
wheel Build wheels from your requirements.
hash Compute hashes of package archives.
completion A helper command used for command completion
help Show help for commands.
&lt;/code>&lt;/pre>&lt;h2 id="安装c-for-python">安装C++ for Python&lt;/h2>
&lt;p>Windows上很多Python库都依赖于C++ 9.0，&lt;br>
点击下面链接下载并安装：&lt;/p>
&lt;p>&lt;a href="https://www.microsoft.com/en-us/download/details.aspx?id=44266">Microsoft Visual C++ Compiler for Python 2.7&lt;/a>&lt;/p>
&lt;p>最后我们就可以使用&lt;code>python -m pip install&lt;/code>来安装新的module啦&lt;/p>
&lt;h2 id="参考">参考&lt;/h2>
&lt;ol>
&lt;li>
&lt;p>&lt;a href="https://pip.pypa.io/en/stable/installing/">PyPA网站的Python安装指引&lt;/a>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;a href="https://stackoverflow.com/questions/4750806/how-do-i-install-pip-on-windows">StackOverflow - How do I install pip on windows&lt;/a>&lt;/p>
&lt;/li>
&lt;/ol></description></item><item><title>如何用Windows命令行统计文件行数</title><link>https://liriansu.com/posts/2016-04-15-how-to-calculate-file-lines-in-windows/</link><pubDate>Fri, 15 Apr 2016 22:13:15 +0000</pubDate><guid>https://liriansu.com/posts/2016-04-15-how-to-calculate-file-lines-in-windows/</guid><description>&lt;p>今天要统计文件行数，可是手边恰好没有Linux环境。&lt;/p>
&lt;h2 id="linux-统计代码行数">Linux 统计代码行数&lt;/h2>
&lt;p>在 Linux 下这是一件很简单的事情：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span> find . -name &lt;span style="color:#e6db74">&amp;#34;*.py&amp;#34;&lt;/span> | wc -l
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>这行语句就可以很简单地统计出当前目录下所有py后缀文件的行数了。&lt;/p>
&lt;h2 id="windows-统计代码行数">Windows 统计代码行数&lt;/h2>
&lt;p>这时我们就不能用cmd而是应当用PowerShell啦。&lt;/p>
&lt;p>&lt;a href="https://en.wikipedia.org/wiki/Windows_PowerShell">Powershell&lt;/a>是Windows基于.NET开发的一个自动化配置框架。&lt;br>
（其实就是新版命令行）&lt;/p>
&lt;p>然后我们可以输入：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-powershell" data-lang="powershell">&lt;span style="display:flex;">&lt;span> dir .\ -Recurse *.py | Get-Content | Measure-Object
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>我们就可以看到输出：&lt;/p>
&lt;pre tabindex="0">&lt;code>Count : 1253
&lt;/code>&lt;/pre>&lt;p>表示当前目录下py后缀文件一共有1253行。&lt;/p></description></item><item><title>为什么我讨厌吸烟</title><link>https://liriansu.com/posts/2016-03-31-why-i-hate-smoking/</link><pubDate>Thu, 31 Mar 2016 16:27:34 +0000</pubDate><guid>https://liriansu.com/posts/2016-03-31-why-i-hate-smoking/</guid><description>&lt;p>这两周读完了&lt;a href="https://www.pubu.com.tw/ebook/-%E4%B8%AD%E5%9C%8B%E7%85%99%E8%8D%89%E7%9A%84%E6%94%BF%E6%B2%BB%E7%89%88%E5%9C%96-23518">《中国烟草的政治版图》&lt;/a>&lt;/p>
&lt;h2 id="烟和毒品">烟和毒品&lt;/h2>
&lt;p>上周的某一天，跟往常一样，上班路上全是吸烟的年轻男性。&lt;br>
捂着鼻子走到了公司，我觉得非常不能理解：&lt;br>
为什么烟不算是毒品呢？&lt;/p>
&lt;p>大部分吸烟的人是做不到想戒烟就戒烟的，&lt;br>
而且就算是外力阻挠的情况下（家人反对，公共场合禁止），&lt;br>
这些烟民还是找机会吸烟。&lt;br>
既然这种精神上的依赖已经算得上是成瘾，&lt;br>
那么为什么我们不会认为香烟是毒品呢？&lt;/p>
&lt;p>于是我稍微地去搜了一下，主流的观点是这样子的：&lt;/p>
&lt;p>&lt;strong>知乎上的回答&lt;/strong>&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/smoking_zhihu.jpg" alt="zhihu">&lt;/p>
&lt;p>&lt;strong>reddit上的回答&lt;/strong>&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/smoking_reddit.jpg" alt="reddit">&lt;/p>
&lt;p>看来香烟的问题中外都有，总结下来有三点：&lt;/p>
&lt;ol>
&lt;li>
&lt;p>毒品这个词更大意义上是法律用词，在英文里drug也有药品的意思。&lt;br>
所以“香烟是毒品”这个说法本身不够严谨。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>从久远的时候，烟草就是一个行业了，到了现在烟草行业更是发展壮大。&lt;br>
作为国家的一大经济来源，而且为了照顾烟民的情绪，全面禁烟是不现实的。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>个人角度来看，烟瘾仅仅会伤害个人身体，不会危害社会。&lt;br>
酗酒会撞车，大麻会致幻，吸烟只会死得早。&lt;/p>
&lt;/li>
&lt;/ol>
&lt;h2 id="中国烟草的政治版图">中国烟草的政治版图&lt;/h2>
&lt;p>为了更严谨地看问题，以及努力完成&lt;a href="https://liriansu.com/my-reading-list-2016">今年的读书计划&lt;/a>，&lt;br>
我去读了李成写的&lt;a href="https://www.pubu.com.tw/ebook/-%E4%B8%AD%E5%9C%8B%E7%85%99%E8%8D%89%E7%9A%84%E6%94%BF%E6%B2%BB%E7%89%88%E5%9C%96-23518">《中國煙草的政治版圖》&lt;/a>。&lt;/p>
&lt;p>这本偏论文向的书里面主要讲述了中国烟草的现状，&lt;br>
国家角度上吸烟可能带来的健康影响，&lt;br>
对中国香烟从上到下的分析，&lt;br>
以及从政治角度治理这些问题的建议。&lt;/p>
&lt;p>整本书学术意味很浓厚，&lt;br>
基本没有小说性（也不应该有），&lt;br>
不过读起来还是津津有味，&lt;br>
比如里面有些数据非常引人深思：&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/smoke_to_death.jpg" alt="smoke to death">&lt;/p>
&lt;p>&lt;em>我们都要多运动&lt;/em>&lt;/p>
&lt;p>正如作者所说，&lt;br>
一方面情况在变得更好，&lt;br>
中国烟民的比例在下降，&lt;br>
而且民众也自下而上地觉醒了健康的意识。&lt;br>
但一方面情况也不是那么好……&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/smoking_bad.jpg" alt="bad">&lt;/p>
&lt;p>&lt;em>作者说&lt;/em>&lt;/p>
&lt;h2 id="我的愿景">我的愿景&lt;/h2>
&lt;p>我一开始讨厌烟，完全是觉得烟味太呛人。&lt;/p>
&lt;p>在庆幸家里没有人吸烟的同时，&lt;br>
我也逐渐觉得香烟更是一个社会问题：&lt;/p>
&lt;ol>
&lt;li>
&lt;p>对于国家，香烟产业是税收大户。&lt;br>
但是从公众健康来说，禁烟可以提高国民身体素质，&lt;br>
避免吸烟所带来的医疗支出。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>对于中国社会，吸上等烟是身份的体现，而且烟本身作为礼品是普适性的。&lt;br>
（假如我们在所有香烟包装上印很吓人的肺癌图片…）&lt;/p>
&lt;/li>
&lt;li>
&lt;p>对于低收入烟民，一包香烟就能在精神层面上让他们满足。&lt;br>
（所付出的仅仅是金钱和一点点寿命。）&lt;/p>
&lt;/li>
&lt;/ol>
&lt;p>所以理性地说，吸烟的确有害健康，但是总有人会不在意自己的或是他人的健康。&lt;br>
随着社会的发展，烟草带来的问题也会逐渐暴露，&lt;br>
但这也为解决烟草问题提供了一个契机。&lt;/p>
&lt;p>总的来说，我讨厌烟味，讨厌吸烟带来的健康问题，&lt;br>
我希望大家都可以活得更久。&lt;/p>
&lt;p>希望世界越来越好。&lt;/p></description></item><item><title>Ubuntu系统X packages can be updated的解决方案</title><link>https://liriansu.com/posts/2016-03-16-ubuntu-package-can-be-updated-solution/</link><pubDate>Wed, 16 Mar 2016 16:14:19 +0000</pubDate><guid>https://liriansu.com/posts/2016-03-16-ubuntu-package-can-be-updated-solution/</guid><description>&lt;p>一个关于Ubuntu系统的小技巧。&lt;/p>
&lt;h2 id="x-package-can-be-updated">x package can be updated&lt;/h2>
&lt;p>最近登录系统的时候，&lt;br>
系统老是提示&lt;/p>
&lt;pre tabindex="0">&lt;code> x packages can be updated.
y updates are security updates.
&lt;/code>&lt;/pre>&lt;p>噢，就像AppStore上面的小红点一样，&lt;br>
更新一下就好了，&lt;br>
于是敲下命令：&lt;/p>
&lt;pre tabindex="0">&lt;code> apt-get update
apt-get upgrade
&lt;/code>&lt;/pre>&lt;p>但是更新完以后，系统还是提示&lt;/p>
&lt;pre tabindex="0">&lt;code> x packages can be updated.
y updates are security updates.
&lt;/code>&lt;/pre>&lt;p>&lt;a href="https://ubuntuforums.org/showthread.php?t=1222909">在查阅了资料以后&lt;/a>才知道，&lt;br>
&lt;code>update&lt;/code> + &lt;code>upgrade&lt;/code>不能更新完所有的软件包，&lt;br>
还要跑一条命令：&lt;/p>
&lt;pre tabindex="0">&lt;code> apt-get dist-upgrade
&lt;/code>&lt;/pre>&lt;p>这个有一点点小烦人的提示就不见了。&lt;/p>
&lt;h2 id="motd">MOTD&lt;/h2>
&lt;p>ubuntu开机时显示的这个Message叫&lt;br>
&lt;a href="https://en.wikipedia.org/wiki/Motd_(Unix)">MOTD(Message of the day)&lt;/a>，&lt;br>
很多公司会让系统管理员定制自己服务器的MOTD。&lt;/p>
&lt;p>Ubuntu系统里，MOTD的脚本默认放在&lt;code>/etc/update-motd.d&lt;/code>下，&lt;br>
我们所看到的&lt;code>x packages can be updated&lt;/code>就是由&lt;br>
&lt;code>/etc/update-motd.d/90-updates-available&lt;/code>这个脚本提示的。&lt;/p>
&lt;p>所以我们想彻底去掉这个提示的话，&lt;br>
可以把&lt;code>/etc/update-motd.d/90-updates-available&lt;/code>这个文件删掉（不推荐）。&lt;/p>
&lt;p>同理，我们也可以定制一下自己的MOTD。&lt;/p>
&lt;h2 id="总结">总结&lt;/h2>
&lt;ol>
&lt;li>
&lt;p>Ubuntu下更新全部包命令为&lt;code>aptget update &amp;amp;&amp;amp; apt-get upgrade &amp;amp;&amp;amp; apt-get dist-upgrade&lt;/code>.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>系统一开始显示的Message叫&lt;a href="https://en.wikipedia.org/wiki/Motd_(Unix)">MOTD&lt;/a>，默认放在&lt;code>/etc/update-motd.d&lt;/code>下。&lt;/p>
&lt;/li>
&lt;/ol></description></item><item><title>创建GitHub项目主页</title><link>https://liriansu.com/posts/2016-03-15-create-github-repository-page/</link><pubDate>Tue, 15 Mar 2016 21:19:53 +0000</pubDate><guid>https://liriansu.com/posts/2016-03-15-create-github-repository-page/</guid><description>&lt;p>最近终于偶然了解了怎么给GitHub项目建主页。&lt;/p>
&lt;h2 id="github-pages">GitHub Pages&lt;/h2>
&lt;p>GitHub Pages是一个让用户很方便托管项目网页在GitHub的服务。&lt;br>
比如&lt;a href="https://liriansu.com/how-this-blog-was-built">我这个博客就是GitHub Pages建成的&lt;/a>。&lt;/p>
&lt;p>但是这样只能托管一个名为&lt;br>
&lt;a href="https://github.com/LKI/lki.github.io">GitHub用户名 + &amp;ldquo;.github.com&amp;quot;的项目(lki.github.io)&lt;/a>&lt;/p>
&lt;p>假如我还有一个项目也想用域名访问怎么办呢？&lt;/p>
&lt;p>于是我机智的我&lt;a href="https://github.com/LKI/lki.github.io/commit/86d73353e4b8f93ea7e759fb0d2f47b5d9ad8904">用&lt;code>git submodule&lt;/code>来解决了这个问题&lt;/a>。&lt;/p>
&lt;h2 id="git-submodule">Git Submodule&lt;/h2>
&lt;p>&lt;code>git submodule&lt;/code>其实是一个很蠢的解决方案：&lt;/p>
&lt;ol>
&lt;li>
&lt;p>为了保证最新的内容，父项目要随着子项目更新而更新。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>这个做法其实是hack了jekyll build，感觉不是特别靠谱。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;a href="https://stackoverflow.com/questions/1260748/how-do-i-remove-a-submodule">remove a git submodule&lt;/a>实在是太痛苦了！&lt;br>
所以没有必要就不要加git submodule啦。&lt;/p>
&lt;/li>
&lt;/ol>
&lt;h2 id="更好的解决方案">更好的解决方案&lt;/h2>
&lt;p>前几天在逛&lt;a href="https://zhangwenli.com/">羡辙学姐&lt;/a>的GitHub的时候发现了&lt;a href="https://github.com/Ovilia/cv/issues/3">这么一条Issue&lt;/a>&lt;/p>
&lt;p>里面这么说道：&lt;/p>
&lt;blockquote>
&lt;p>主页用 CNAME 指向 zhangwenli.com 后，ovilia.github.io 将跳转到 zhangwenli.com&lt;br>
其他项目 xxx 的 gh-pages 分支将会自动对应到 ovilia.github.io/xxx&lt;/p>
&lt;/blockquote>
&lt;p>喔！原来GitHub会默认地把some-repo项目的“gh-pages”分支映射到some-one.github.com/some-repo下面去。&lt;/p>
&lt;p>所以我们就可以用新建分支把&lt;a href="https://github.com/LKI/mymenu">菜谱&lt;/a>映射到&lt;a href="https://liriansu.com/mymenu">/mymenu&lt;/a>了。&lt;/p>
&lt;h2 id="总结">总结&lt;/h2>
&lt;ol>
&lt;li>
&lt;p>GitHub项目可以建一个&lt;code>gh-pages&lt;/code>分支来映射到github.com下面的github.com/repository-name.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>多看多学多试.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>假如不是绝妙的hack就要追求best practice.&lt;/p>
&lt;/li>
&lt;/ol></description></item><item><title>为什么我不招你当我的员工</title><link>https://liriansu.com/posts/2016-03-02-this-is-why-i-dont-give-you-a-job-zh-cn/</link><pubDate>Wed, 02 Mar 2016 13:41:04 +0000</pubDate><guid>https://liriansu.com/posts/2016-03-02-this-is-why-i-dont-give-you-a-job-zh-cn/</guid><description>&lt;p>匈牙利有一个叫Andor Jakab的人写了一篇很犀利的文章，&lt;br>
然后匈牙利网络评论就炸了。&lt;/p>
&lt;h2 id="译者说">译者说&lt;/h2>
&lt;p>在2011年，匈牙利有个叫Andor Jakab的人发了篇文章，&lt;br>
叫&lt;a href="https://jakabandor.blog.hu/2011/07/27/tolem_ezert_nem_kapsz_munkat">Tőlem ezért nem kapsz munkát&lt;/a>（现在链接已失效）。&lt;/p>
&lt;p>后来由于这篇文章影响太大，在Facebook上有上万个赞，&lt;br>
他就自己把文章翻译成英文，在这里：&lt;br>
&lt;a href="https://andorjakab.blog.hu/2012/01/06/this_is_why_i_don_t_give_you_a_job">This is why I don&amp;rsquo;t give you a job&lt;/a>&lt;/p>
&lt;p>虽然离Andor Jakab发这篇文章的时候已经有好几年了，&lt;br>
&lt;em>而且文章可能比较偏激…&lt;/em>&lt;br>
但是其中讲的道理还是令人深思的。&lt;br>
译文如下：&lt;/p>
&lt;h2 id="为什么我不招你当我的员工">为什么我不招你当我的员工&lt;/h2>
&lt;p>我能雇12个员工，给每个人税后760欧的工资，但是我偏不。&lt;br>
首先你能在我公司里的一间很棒的办公室里工作。&lt;br>
其次我们不做电话营销，也不是诈骗公司。&lt;br>
你的工作是正经活，也要求你有很高的职业素养。&lt;br>
你将会每天工作八小时，每周干五天。&lt;br>
我会合法地雇用你，帮你交足税和社保。&lt;br>
这样的工作我能雇12个人，但是我偏不。&lt;br>
我来解释为什么。&lt;/p>
&lt;h3 id="我不会雇女员工">我不会雇女员工&lt;/h3>
&lt;p>原因很简单：女人生小孩。&lt;br>
另外我也没有权利问她想不想生小孩。&lt;br>
假如我能问，而且她回答了，&lt;br>
理论上她也可以欺骗我，或是后来改主意了。&lt;/p>
&lt;p>别理解错了，我对&lt;em>女人生小孩&lt;/em>没有任何意见。&lt;br>
我也是这么出生的，我的小孩也是这么出生的。&lt;br>
我不会招女员工是因为：当她怀孕以后，&lt;br>
她就有三年产假，而且我不能解雇她。&lt;br>
假如她要生二胎，就一共有六年的假期了。&lt;/p>
&lt;p>当然，工作还是要做的，&lt;br>
所以在这长长的产假里，我得再招一个人替她干活。&lt;br>
但是我不能在她产假的时候解雇她，我也不能在她回来以后解雇她。&lt;br>
所以我只能把那个一直在替她干活的人给解雇掉。&lt;br>
而且当一个女员工度完产假以后，&lt;br>
法律要求我得把她的工资提升到她现在职位应有的数目上。&lt;br>
我还得把她产假那几年的的年假给她补上。&lt;br>
于是等她回来工作的时候，她还会有2到4个月的带薪年假。&lt;/p>
&lt;h3 id="我也不会雇50岁以上的员工">我也不会雇50岁以上的员工&lt;/h3>
&lt;p>并不是因为我对这些最有经验的员工有意见。&lt;br>
我不雇他们，是因为他们很快就到了&lt;a href="https://en.wikipedia.org/wiki/Protected_class">保护年龄&lt;/a>。&lt;br>
然后我就被他们套住了，就像我被女员工套住了一样。&lt;br>
在保护年龄里，你不能解雇他们。&lt;br>
所以我还是得给足薪水，即使他们干的不怎么样或者马马虎虎。&lt;br>
我不能解雇这些被法律保护的员工，但总得有个人来把事情做好，&lt;br>
所以我还是得再雇一个人。&lt;br>
我对法律保护他们没有任何意见，但是我不会雇佣他们。&lt;/p>
&lt;h3 id="我只会雇佣25到30岁的男员工">我只会雇佣25到30岁的男员工&lt;/h3>
&lt;p>雇佣他们其实也是很冒险的。&lt;br>
因为没有正当理由的话（比如我自己收入不足，或者我不喜欢他们的工作态度这些都不是正当理由），我是没有权利解雇他们的。&lt;br>
我直接解雇他们的话很有可能要上法庭，也很有可能是他们胜诉。&lt;br>
不过这个风险我能接受。&lt;/p>
&lt;h3 id="你拿到的是730欧我却要出1572欧">你拿到的是730欧，我却要出1572欧&lt;/h3>
&lt;p>| 你的税后收入 ||| 你的税前收入 ||| 我要出的钱 ||| 比值 |&lt;br>
|&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;ndash;|||&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;ndash;|||&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;|||&amp;mdash;&amp;mdash;|&lt;br>
| € 185 ||| € 238 ||| € 306 ||| 165% |&lt;br>
| € 227 ||| € 306 ||| € 393 ||| 173% |&lt;br>
| € 322 ||| € 458 ||| € 589 ||| 183% |&lt;br>
| € 408 ||| € 612 ||| € 786 ||| 193% |&lt;br>
| € 479 ||| € 765 ||| € 982 ||| 205% |&lt;br>
| € 570 ||| € 917 ||| € 1178 ||| 207% |&lt;br>
| &lt;strong>€ 760&lt;/strong> |||&lt;strong>€ 1223&lt;/strong> |||&lt;strong>€ 1572&lt;/strong> |||&lt;strong>207%&lt;/strong>|&lt;br>
| € 950 ||| € 1529 ||| € 1965 ||| 207% |&lt;/p>
&lt;p>这是根据www.nettober.com 薪水计算器得来的2011年最新的数据。&lt;br>
如你所见，我的公司要出1572欧才能付得起你760欧的收入。&lt;br>
要把这个接近两倍的比值给降下来的唯一方法是：&lt;br>
我付你更少的薪水。&lt;br>
不过我不会用更少的薪水来雇用你，&lt;br>
因为我觉得少于760欧的薪水很难让你活的体面。&lt;br>
你会感到压抑，不开心，然后影响你自己、我的公司、甚至我。&lt;br>
所以我不会以低于这个价格的薪水来雇佣任何人的。&lt;/p>
&lt;h3 id="只有匈牙利的法律这么蠢">只有匈牙利的法律这么蠢&lt;/h3>
&lt;p>&lt;img src="https://liriansu.com/assets/hungary_tax.jpg" alt="tax-chart">&lt;/p>
&lt;p>上面那张图出自Deloitte。&lt;br>
如你所见，国家拿走了你一半多的薪水。&lt;br>
我付了一千五百多欧，你却只能拿到不到一半，这也太蠢了吧。&lt;br>
更别提那些拿着基本工资的人却跟你享受着一样好的医保。&lt;/p>
&lt;p>我也认为一个35岁的员工每年应该有25天的年假。&lt;br>
这意味着这年假对应的一个月的工作还需要有个人来完成。&lt;br>
所以假如我需要12个员工的劳动的话，我得雇佣13个人来抵消假期。&lt;/p>
&lt;h3 id="尽管困难重重我还是愿意雇佣你的">尽管困难重重，我还是愿意雇佣你的&lt;/h3>
&lt;p>我是一个勇敢的企业家。企业家都要拥抱风险。&lt;br>
所以我会把我的房子卖了，住到一个租的房间里。&lt;br>
我希望我的房子能卖到90000欧的高价，&lt;br>
然后我就可以勇敢地创业。&lt;br>
假如最终我创业失败的话（创业好像基本上都会失败），&lt;br>
嗯，我会坚强地不哭的 :)&lt;/p>
&lt;p>我的公司会提供让客户满意的服务，一个好的办公场所是必需的。&lt;br>
我会雇13个人，因为我需要12个人的劳动力（有一个是来顶年假的）。&lt;br>
我们14个人（算上我）将会在158平米装修良好的办公室里工作。&lt;br>
因为租金大概是10欧每平米，再算上每平米3.5欧的设备支出，&lt;br>
在办公场地上的支出就是每个月2133欧。&lt;/p>
&lt;h3 id="根据计算我每个月的支出如下">根据计算，我每个月的支出如下&lt;/h3>
&lt;p>|办公场地|2133欧|&lt;br>
|薪水|13 x 1572欧 = 20436欧|&lt;br>
|其他支出（会计、营销之类的）| 3058欧|&lt;br>
|共计|25627欧|&lt;/p>
&lt;p>每个月支出这么大，听起来蛮吓人的对吧？&lt;br>
无论是淡季、旺季，夏天没什么生意的时候、圣诞节不用干什么活的时候，&lt;br>
无论我们盈利多少，我每个月的支出就是这么多。&lt;/p>
&lt;p>平均来看，我们公司每个月顶多提供1000小时的服务。&lt;br>
所以为了收支平衡，我需要把服务的价格定在：&lt;br>
25627欧 / 1000小时 = 25欧/小时。&lt;br>
但收支平衡是不够的，我也需要盈利。&lt;/p>
&lt;p>我不是个很贪心的人，毕竟挣钱很难。&lt;br>
为了保持20%左右的盈利率，我的定价将会是30欧/小时。&lt;br>
这意味着算上增值税就是37.5欧元每小时。&lt;br>
我不在乎那点零头，所以买我们服务的客户每小时要付37欧。&lt;/p>
&lt;p>这37欧里面，7欧直接给了国家，剩下的30才是我们的收入。&lt;br>
我是个乐观的人。&lt;br>
我们的营销将会引爆市场，我的计划天衣无缝。&lt;br>
我们每个月肯定能卖掉1000小时的服务。&lt;br>
生意兴隆，员工们全部都努力工作，我也很满意。&lt;/p>
&lt;p>这样我的公司每个月的收入就会有 1000 x 30欧 = 30000欧。&lt;/p>
&lt;p>除去支出，公司的利润会有4373欧。&lt;br>
我会给自己发2446欧的税前工资，算上其他部分公司就要支出3144欧。&lt;br>
税后我能拿到1521欧，基本上是我员工的两倍。&lt;br>
所以再除去我的工资，公司的利润（税前）就是1229欧。&lt;br>
此外，公司税还要122欧，本地经营税要600欧（按公司总收入的2%收）。&lt;br>
最后，公司账上每个月就只剩507欧了。&lt;/p>
&lt;p>这么看来我自己每个月能赚1521欧，但是别忘了，&lt;br>
为了开公司我把我90000欧的房子给卖了。&lt;br>
我还得租间房（每个月租金至少要300欧），&lt;br>
要不我就没地方住了…&lt;br>
我平时也会比较节约，不乱花钱，&lt;br>
我夫人也会工作赚钱。&lt;br>
我甚至没什么时间去花钱，&lt;br>
因为我会比我的员工更努力工作，&lt;br>
每天工作12小时，包括周末。&lt;/p>
&lt;p>这样子我每个月就能存900欧，&lt;br>
100个月以后我就能再买个90000欧的房子。&lt;br>
所以我大概需要9年来回本。&lt;br>
9年以后我就不需要勒紧裤腰带来过日子了，&lt;br>
不需要付租金，也不需要存很多钱。&lt;br>
我可以过欧洲人的生活了。&lt;/p>
&lt;p>处于这样的考虑——我希望你能理解——我并不是很想把我的房子卖了然后创业开公司。&lt;/p>
&lt;h3 id="但出于4个原因我绝对不会这么创业">但出于4个原因，我绝对不会这么创业&lt;/h3>
&lt;ol>
&lt;li>
&lt;p>有些在小房间里非法竞争的对手提供同样的服务，但他们每小时只收9欧。&lt;br>
他们只收钱不记账，更别提交什么增值税了。&lt;br>
他们也不用负责。没有担保人，名义上他们不做任何事情，名义上他们甚至还不是一间公司。&lt;br>
他们不需要租办公室，请会计。&lt;br>
他们只需要每天工作5小时，然后就可以赚1000欧。&lt;br>
他们还会嘲笑我这月薪760欧的工作，因为我这的员工还得准时上班，按时按质按量完成工作，&lt;br>
还不能欺骗顾客（假如我的员工欺骗了顾客，就会被炒鱿鱼）&lt;/p>
&lt;/li>
&lt;li>
&lt;p>竞争对手还会污蔑我的公司。&lt;br>
我将会背上贪得无厌、黑心商人的骂名，&lt;br>
毕竟看起来别人定价9欧的服务，我却要37欧。&lt;br>
我会成为善良的匈牙利人民的敌人，&lt;br>
而我“诚实”的竞争对手，要价只不过我要价的四分之一。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>很多员工来我的公司只是为了学习商业机密和抢走客户。&lt;br>
他们会信誓旦旦地保证“同样的服务，四分之一的价格”。&lt;br>
在抢走了足够多的客户资源以后，他们还会故意搞砸他们的工作，好让我提出解雇他们。&lt;br>
于是他们就把我告上法庭，说我非法解雇他们，然后他们就胜诉了。&lt;br>
同时，他们还在赚我以前辛苦谈好的客户的钱。&lt;br>
而且，他们还会在各大论坛注册小号，说自己以前在XX公司工作过，&lt;br>
那公司不仅服务很贵，而且质量也很差。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>上面这些所有诉苦都没任何实际作用，没人会关心我究竟怎么样。&lt;/p>
&lt;/li>
&lt;/ol>
&lt;p>基本上这就是我不招员工的原因了。&lt;br>
而且我认为那些创业经验丰富的企业家，&lt;br>
也会因为这样的原因不招员工。&lt;br>
所以这就是为什么越来越多的人找不到工作，&lt;br>
于是经济越来越低迷，税收也会变少。&lt;br>
好的工作越来越少，社会福利越来越差。&lt;br>
最终我们的社会救济就会变得跟集中营一样糟糕。&lt;/p>
&lt;h3 id="只有满足这些条件我才会招你当员工">只有满足这些条件，我才会招你当员工&lt;/h3>
&lt;ul>
&lt;li>
&lt;p>只要我想，我随时随刻都能解雇你&lt;/p>
&lt;/li>
&lt;li>
&lt;p>假如增值税低一些，只收20%，最好是只收15%&lt;/p>
&lt;/li>
&lt;li>
&lt;p>假如国家“只”收30%的个人所得税&lt;/p>
&lt;/li>
&lt;li>
&lt;p>假如高收入不再意味着高税收&lt;/p>
&lt;/li>
&lt;li>
&lt;p>假如国家反腐有力，而不是惩罚正经公司&lt;/p>
&lt;/li>
&lt;/ul>
&lt;p>除非满足了这些条件，否则我是不会招你当员工的。&lt;br>
除非国家在各方面都剔除了腐败，我是不会创业的，也就不会提供工作机会了。&lt;/p>
&lt;p>（完）&lt;/p></description></item><item><title>读博客和写博客</title><link>https://liriansu.com/posts/2016-02-29-read-blogs-to-write-blogs/</link><pubDate>Mon, 29 Feb 2016 13:27:52 +0000</pubDate><guid>https://liriansu.com/posts/2016-02-29-read-blogs-to-write-blogs/</guid><description>&lt;p>我最近把&lt;a href="https://www.raychase.net/category/recommended">四火的唠叨&lt;/a>里的推荐文章都看完了。&lt;/p>
&lt;h2 id="读博客">读博客&lt;/h2>
&lt;p>我很喜欢读别人的博客，&lt;br>
尤其是跟着timeline一篇一篇地往下读。&lt;/p>
&lt;p>读博客的时候不仅了解到&lt;a href="https://www.raychase.net/aboutme">四火&lt;/a>一开始是一个华为的软件工程师，&lt;br>
后来到了亚马逊。&lt;br>
更是看到了&lt;a href="https://www.raychase.net/3196">他在刚工作时的苦逼生活，还有办公室政治&lt;/a>。&lt;br>
不长的几篇博文，&lt;br>
可以学习到前辈们几年的经验浓缩。&lt;/p>
&lt;p>就像前阵子把&lt;a href="https://shell909090.org/blog/%E7%AE%80%E5%8E%86">shell909090&lt;/a>的博客给读完了。&lt;br>
&lt;em>吐槽一句：shell909090的“简历”页面倒更加像“关于”页面&lt;/em>&lt;/p>
&lt;p>看着比自己更早&lt;del>出道&lt;/del>工作也更厉害的前辈，&lt;br>
就会有种类似鸣人看着自来也的感觉：&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/cest_tama_la_vie.jpg" alt="some-thoughts">&lt;/p>
&lt;h2 id="写博客">写博客&lt;/h2>
&lt;p>以前我也写博客，不过更多是儿女情长的事情。&lt;br>
没有技术博客的积攒（当初自己也并不想积攒）。&lt;/p>
&lt;p>直到去年某一天看博客的时候，看到&lt;a href="https://en.wikipedia.org/wiki/Jeff_Atwood">Jeff Atwood&lt;/a>写的一句话：&lt;/p>
&lt;blockquote>
&lt;p>In 2004 I began this blog. I don&amp;rsquo;t mean to be overly dramatic, but it changed my life. Everything that comes after was made possible by this blog.&lt;/p>
&lt;/blockquote>
&lt;p>听起来很感慨的样子，于是顺着链接读完了&lt;a href="https://blog.codinghorror.com/how-to-achieve-ultimate-blog-success-in-one-easy-step/">他的感慨&lt;/a>。&lt;br>
Jeff觉得“虽然每篇博客都不长，但是持之以恒就改变了写博客的人”。&lt;/p>
&lt;p>&lt;img src="https://blog.codinghorror.com/content/images/uploads/2007/10/6a0120a85dcdae970b012877707709970c-pi.png" alt="me-on-web">&lt;/p>
&lt;h2 id="一些链接">一些链接&lt;/h2>
&lt;p>最后推荐几个我觉得很不错的博客：&lt;/p>
&lt;p>&lt;a href="https://blog.codinghorror.com/">StackOverFlow创始人Jeff Atwood的博客 codinghorror.com&lt;/a>&lt;/p>
&lt;p>&lt;a href="https://coolshell.cn/">陈皓的博客 coolshell.cn&lt;/a>&lt;/p>
&lt;p>&lt;a href="https://taosay.net">道哥的blog taosay.net&lt;/a>&lt;/p>
&lt;p>&lt;a href="https://shell909090.org/blog/">shell909090.org&lt;/a>&lt;/p>
&lt;p>&lt;a href="https://www.raychase.net/category/recommended">四火的唠叨 raychase.net&lt;/a>&lt;/p>
&lt;p>&lt;a href="https://lucida.me/">lucida.me&lt;/a>&lt;/p>
&lt;p>&lt;a href="https://www.qiukeke.com/">大舒&amp;rsquo;s wiki qiukeke.com&lt;/a>&lt;/p>
&lt;p>希望有一天我也能出现在别人的推荐链接里 :D&lt;/p></description></item><item><title>我的VR初体验</title><link>https://liriansu.com/posts/2016-02-27-my-first-vr-experience/</link><pubDate>Sat, 27 Feb 2016 21:08:19 +0000</pubDate><guid>https://liriansu.com/posts/2016-02-27-my-first-vr-experience/</guid><description>&lt;p>前阵子手机更新成了Android 6.0，&lt;br>
我照常到Gplay上看看有什么新App，&lt;br>
于是看到了一个Google Cardboard。&lt;/p>
&lt;h2 id="vr">VR&lt;/h2>
&lt;p>&lt;strong>VR&lt;/strong>，即&lt;strong>Virtual Reality&lt;/strong>，&lt;strong>虚拟现实&lt;/strong>。&lt;/p>
&lt;p>在一些科幻电影里面，我们会看到主角头戴头盔，&lt;br>
进入了虚拟的却栩栩如生的世界。&lt;br>
又或者是主角脑后插管，&lt;br>
通过电流刺激脑部，&lt;br>
进入了虚拟的却栩栩如生的世界。&lt;/p>
&lt;p>这就是&lt;strong>VR虚拟现实&lt;/strong>。&lt;/p>
&lt;p>因为本身概念上就带着一点娱乐性质，&lt;br>
&lt;strong>VR&lt;/strong>这个概念近几年都在游戏界很火。&lt;br>
就比如前几年的体感游戏这个概念，&lt;br>
其实就带有半VR的性质。&lt;/p>
&lt;h2 id="google-cardboard">Google Cardboard&lt;/h2>
&lt;p>[Google Cardboard][wiki-cardboard]是Google推出的VR平台。&lt;br>
它的神奇之处就是理论上只需要硬纸板、透镜，&lt;br>
就可以自行组装一个VR眼镜。&lt;/p>
&lt;p>当然这是理论上，&lt;br>
不过实际上一副Cardboard眼镜也只要几十RMB。&lt;/p>
&lt;p>这是我前几天在某宝上买的：&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/vr_glasses.jpg" alt="vr">&lt;/p>
&lt;p>在放入手机以后打开VR apps，&lt;br>
或者是3D电影就可以直接观看了：&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/vr_with_phone.jpg" alt="vr-phone">&lt;/p>
&lt;h2 id="vr感想">VR感想&lt;/h2>
&lt;ol>
&lt;li>
&lt;p>廉价。&lt;br>
廉价意味着普及，普及就可以改变生活方式。&lt;br>
可以想象以后的饭桌上家长就会斥责小孩：&lt;br>
“吃饭就别带头盔了…”&lt;/p>
&lt;/li>
&lt;li>
&lt;p>改变。&lt;br>
世界上每一项新的技术都会带来改变，&lt;br>
从铁器到蒸汽到互联网。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>VR技术还有很大的提升空间。&lt;/p>
&lt;/li>
&lt;/ol>
&lt;h2 id="相关推荐">相关推荐&lt;/h2>
&lt;p>&lt;a href="https://play.google.com/store/apps/details?id=com.google.samples.apps.cardboarddemo">Google Cardboard的App&lt;/a>&lt;/p>
&lt;p>&lt;a href="https://play.google.com/store/apps/details?id=com.nivalvr.inmind">App: InMind VR&lt;/a>&lt;/p>
&lt;p>&lt;a href="https://play.google.com/store/apps/details?id=com.hihill.link">App: Lost Kismet&lt;/a>&lt;/p></description></item><item><title>杂思丨《1984》读后感</title><link>https://liriansu.com/posts/2016-02-18-thoughts-on-1984/</link><pubDate>Thu, 18 Feb 2016 22:12:54 +0000</pubDate><guid>https://liriansu.com/posts/2016-02-18-thoughts-on-1984/</guid><description>&lt;p>看完了《1984》的第一感想就是：这本书比我想象中要短不少。&lt;/p>
&lt;h2 id="概要">概要&lt;/h2>
&lt;p>《1984》的故事发生在架空的20世纪，&lt;br>
一个普通的男主Winston在一个政治高压的国家里发生的故事。&lt;/p>
&lt;p>在一段动荡以后，世界分成了三个国家。&lt;br>
Winston所在的国家叫Oceania，Oceania是由the Party领导的。（原文）&lt;/p>
&lt;p>the Party的领导人叫Big Brother，&lt;br>
整个国家到处都贴着Big Brother的大幅照片，&lt;br>
照片下面是一行大字：&lt;br>
Big Brother is watching you.&lt;/p>
&lt;h2 id="关于书的感想">关于书的感想&lt;/h2>
&lt;p>看这本书实在是太有即视感了。&lt;/p>
&lt;ol>
&lt;li>
&lt;p>Big Brother.&lt;br>
书里面Big Brother是一个虚构的人物，他是the Party统治权力的化身。&lt;br>
我脑海中想象的Big Brother海报是类似于美国征兵的Sam大叔那样的，&lt;br>
虽然笑容和善，但是充满压迫感。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>政治高压。&lt;br>
跟Mia介绍完这本书的简介以后，Mia很敏锐地问我：&lt;br>
“很像在讽刺苏联诶，这书是冷战时候出版的么？”&lt;br>
的确，这本书是1949年出版，&lt;a href="https://en.wikipedia.org/wiki/Cold_War">冷战&lt;/a>是1947~1991年。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>合成词。&lt;br>
《1984》里面用了大量的合成词（至少我认为是合成的），&lt;br>
比如the Party对人民的三个要求：&lt;br>
crimestop, blackwhite, doublethink.&lt;/p>
&lt;/li>
&lt;/ol>
&lt;h2 id="三个词">三个词&lt;/h2>
&lt;p>书里解释了一下这三个词的意思：&lt;/p>
&lt;ul>
&lt;li>
&lt;p>crimestop: 国家公民所想的应该都是美好的事物，不能有任何不好的思想。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>blackwhite: 我们的敌人指鹿为马就是错的，但是我们的组织指鹿为马肯定是为了我们好。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>doublethink: 有的时候一件事情是对的，但是这件事情的反面也是对的。&lt;/p>
&lt;/li>
&lt;/ul>
&lt;p>在书里，the Party就主要依据着这三个原则统治人民。&lt;/p>
&lt;p>我觉得这是作者非常有意思的一个想法：&lt;br>
做到这三点，人民就不会存在不可控的想法了，&lt;br>
而the Party希望大家的想法都是可控的。&lt;/p>
&lt;p>就像书里主角问他一个朋友：&lt;br>
“把大家的想法都抹杀掉，对组织有什么好处呢？”&lt;/p>
&lt;p>他的朋友回答他：&lt;br>
“你是一个人，你会死，但是当你成为了组织的一部分时，你就永生了。&lt;br>
道理跟剪头发一样，虽然人失去了一部分，但是总体还是活着。&lt;br>
这就是权力，永生的权力。”&lt;/p>
&lt;p>看到这里，我不禁想到《辛德勒的名单》里面的一段对话：&lt;br>
“你可以轻而易举地处决一个集中营的人，但这不是权力。&lt;br>
真正的权力，是你把刀架在别人脖子上时，可以说：‘我宽恕你’。&lt;br>
这才是真正的权力。”&lt;/p>
&lt;h2 id="最后">最后&lt;/h2>
&lt;p>不知道这本书的中译是怎么翻译的呢，有机会得去看一看。ツ&lt;/p></description></item><item><title>我的2016书单</title><link>https://liriansu.com/posts/2016-02-15-my-reading-list-2016/</link><pubDate>Mon, 15 Feb 2016 11:07:57 +0000</pubDate><guid>https://liriansu.com/posts/2016-02-15-my-reading-list-2016/</guid><description>&lt;p>过年的时候有一个小契机，让我可以督促自己定下一个比往年要长的书单。&lt;/p>
&lt;h2 id="小契机">小契机&lt;/h2>
&lt;p>年后我在朋友圈里看到了这么一幅图：&lt;/p>
&lt;p>“一个赞一本书，一年读完。”&lt;/p>
&lt;p>这很棒嘛，于是我也发了这么一条状态：&lt;/p>
&lt;p>&lt;img src="https://liriansu.com/assets/book_per_like.jpg" alt="book per like">&lt;/p>
&lt;p>很好，今年要读73本书。&lt;/p>
&lt;p>这怎么可能嘛！&lt;/p>
&lt;h2 id="我的书单">我的书单&lt;/h2>
&lt;p>其实也不是不可能，&lt;br>
比如把天龙八部算成八部……&lt;/p>
&lt;p>毕竟不积跬步无以至千里，&lt;br>
我先整理了一个书单，&lt;br>
打算按顺序这么读下来：&lt;/p>
&lt;ul>
&lt;li>1984&lt;/li>
&lt;li>ANSI Common Lisp&lt;/li>
&lt;li>阿加莎克里斯蒂&lt;/li>
&lt;li>悲惨世界&lt;/li>
&lt;li>白板编程浅谈&lt;/li>
&lt;li>编程珠玑&lt;/li>
&lt;li>Code Complete 2 (Eng. Edition)&lt;/li>
&lt;li>Computer System Engineering&lt;/li>
&lt;li>创业时，我们在知乎聊什么&lt;/li>
&lt;li>触动人心 - 设计优秀的iphone应用&lt;/li>
&lt;li>重新定义团队：谷歌如何工作&lt;/li>
&lt;li>重构&lt;/li>
&lt;li>Docker - 从入门到实践&lt;/li>
&lt;li>Don&amp;rsquo;t Make me Think&lt;/li>
&lt;li>Dune&lt;/li>
&lt;li>代码整洁之道&lt;/li>
&lt;li>芙蓉镇&lt;/li>
&lt;li>鬼吹灯&lt;/li>
&lt;li>Head First设计模式&lt;/li>
&lt;li>红楼梦&lt;/li>
&lt;li>Java核心技术&lt;/li>
&lt;li>Java编程思想&lt;/li>
&lt;li>金瓶梅&lt;/li>
&lt;li>Learn Vimscript the Hard Way&lt;/li>
&lt;li>Linux Fundamentals - A Practical Guide to Learning Linux&lt;/li>
&lt;li>Lolita&lt;/li>
&lt;li>龙枪传奇&lt;/li>
&lt;li>龙枪编年史&lt;/li>
&lt;li>穆斯林的葬礼&lt;/li>
&lt;li>你一生的故事&lt;/li>
&lt;li>男人来自火星女人来自金星&lt;/li>
&lt;li>Programming Perl&lt;/li>
&lt;li>平江&lt;/li>
&lt;li>飘&lt;/li>
&lt;li>算法导论&lt;/li>
&lt;li>This is why i don&amp;rsquo;t give you a job&lt;/li>
&lt;li>天龙八部&lt;/li>
&lt;li>托马斯微积分&lt;/li>
&lt;li>UTF-8: The Secret of Character Encoding&lt;/li>
&lt;li>幽灵代笔&lt;/li>
&lt;li>隐杀&lt;/li>
&lt;/ul></description></item><item><title>Jekyll build fail的解决办法</title><link>https://liriansu.com/posts/2016-01-29-jekyll-build-fail-solution/</link><pubDate>Fri, 29 Jan 2016 23:24:45 +0000</pubDate><guid>https://liriansu.com/posts/2016-01-29-jekyll-build-fail-solution/</guid><description>&lt;p>我一直觉得笔记本和台式机&lt;code>jekyll build&lt;/code>出来的结果不一样，&lt;br>
我猜想是Jekyll的版本不一致。&lt;br>
结果后来&lt;code>gem update&lt;/code>以后，&lt;br>
反而&lt;code>jekyll build&lt;/code>还失败了…&lt;/p>
&lt;h2 id="jekyll-build">Jekyll build&lt;/h2>
&lt;p>&lt;code>jekyll build&lt;/code>的结果不稳定是很难受的，&lt;br>
尤其每次build完以后&lt;code>git status&lt;/code>看到的一大堆红色文件名。&lt;br>
而其实大部分都是各种HTML tag位置的差别。&lt;/p>
&lt;p>我怀疑这有可能是两台机器上Jekyll的版本不同导致的，&lt;br>
于是我就跑了&lt;code>gem update&lt;/code>以同步到最新版本。&lt;/p>
&lt;p>等这个命令跑完以后，我跑&lt;code>jekyll build&lt;/code>遇到的都是&lt;br>
&lt;code>jekyll build fail&lt;/code>这样的ruby错误了。&lt;/p>
&lt;h2 id="solution">Solution&lt;/h2>
&lt;p>搜了一下其实很简单，这是因为机子内同时装了多个版本的jekyll，&lt;br>
而他们又互相冲突所导致的错误。&lt;/p>
&lt;p>（我不禁想问&lt;code>gem update&lt;/code>为什么不会自动卸载旧版本？）&lt;/p>
&lt;p>没错，解决方案就是我们跑一条&lt;code>gem cleanup&lt;/code>卸载旧版本就可以了。&lt;br>
至少这个解决方案对我的问题是起效的。&lt;/p>
&lt;h2 id="gem-sources">Gem sources&lt;/h2>
&lt;p>另：有的时候gem官方源很慢，可以选择用&lt;code>gem sources&lt;/code>命令更换淘宝源。&lt;br>
（不过淘宝源未必更新那么频繁）&lt;/p>
&lt;pre tabindex="0">&lt;code>$ gem sources -l
*** CURRENT SOURCES ***
https://rubygems.org/
$ gem sources -r https://rubygems.org/
https://rubygems.org/ removed from sources
$ gem sources -a https://rubygems.org/
https://rubygems.org/ added to sources
&lt;/code>&lt;/pre></description></item><item><title>Jekyll-assume demo</title><link>https://liriansu.com/posts/2016-01-28-jekyll-assume-demo/</link><pubDate>Thu, 28 Jan 2016 11:06:56 +0000</pubDate><guid>https://liriansu.com/posts/2016-01-28-jekyll-assume-demo/</guid><description>&lt;p>For own interest, I extend a markdown rule using Jekyll.&lt;/p>
&lt;h2 id="grammar">Grammar&lt;/h2>
&lt;p>If a circle has a radius of {c-r} (20)cm, its circumference would be {c-c} (#c-r * 6.28)cm and its area would be {c-s} (#c-r * #c-r * 3.14)cm².&lt;/p>
&lt;p>Note: For demostrating the grammer I have to add a space between &amp;lsquo;}&amp;rsquo; and &amp;lsquo;(&amp;rsquo;.&lt;br>
There should be no space between &amp;lsquo;}&amp;rsquo; and &amp;lsquo;(&amp;rsquo;.&lt;/p>
&lt;h2 id="quick-show">Quick Show&lt;/h2>
&lt;p>If a circle has a radius of {c-r}(20)cm, its circumference would be {c-c}(#c-r * 6.28)cm and its area would be {c-s}(#c-r * #c-r * 3.14)cm².&lt;/p></description></item><item><title>Javascript之路</title><link>https://liriansu.com/posts/2015-12-21-learning-javascript/</link><pubDate>Mon, 21 Dec 2015 17:26:52 +0000</pubDate><guid>https://liriansu.com/posts/2015-12-21-learning-javascript/</guid><description>&lt;p>上大学的时候，有一门课是教各种Java的。&lt;br>
到了布置期末大作业的时候，老师大手一挥：“你们写个电商交易网站就可以了。”&lt;br>
我们满怀期待地问：“只要写后端？”&lt;br>
老师说道：“没有前端怎么叫网站？HTML, CSS, JS是每个程序员的基本素养。”&lt;/p>
&lt;h2 id="痛苦的自学之路">痛苦的自学之路&lt;/h2>
&lt;p>相对于美术，大部分程序员都更擅长数学。&lt;br>
我也一样。&lt;/p>
&lt;p>老师布下作业以后，班里大部分人（包括我）都是看W3School自学的。&lt;br>
于是我们在屏幕上数格子画&lt;code>&amp;lt;div&amp;gt;&lt;/code>。&lt;/p>
&lt;p>很快我们意识到，假如每个人都这么折腾的话，作业就完成不了了。&lt;br>
于是我们组成了小团队，一部分人专门研究前端，一部分人先把逻辑给实现了。&lt;/p>
&lt;p>最终在简陋的Ajax + jQuery下做完了&lt;a href="https://github.com/Water-Drop/iprs">那个项目&lt;/a>&lt;/p>
&lt;h2 id="bootstrap">Bootstrap&lt;/h2>
&lt;p>虽然一直是网页苦手，但是由于网页其实是最简单而且最方便的展示手段（比PPT要强）&lt;br>
于是我默默地&lt;a href="https://liriansu.com/teampicker">写些小东西练手&lt;/a>。&lt;/p>
&lt;p>对于库的利用使我_暂时_脱离了画&lt;code>&amp;lt;div&amp;gt;&lt;/code>的束缚，&lt;br>
可以专注于内容了。&lt;br>
（于是我又了解了&lt;a href="https://en.wikipedia.org/wiki/Lorem_ipsum">Lorem ipsum&lt;/a>）&lt;/p>
&lt;h2 id="free-code-camp">Free Code Camp&lt;/h2>
&lt;p>最近偶然发现了&lt;a href="https://www.freecodecamp.com/">这个JS入门网站&lt;/a>&lt;br>
不禁感慨当时为什么遇上合适的入门指南。&lt;/p>
&lt;p>不过男人四十尚少年嘛，&lt;br>
就好像关谷说的&lt;/p>
&lt;blockquote>
&lt;p>活到老 学到老&lt;/p>
&lt;/blockquote>
&lt;p>就是这么个道理。&lt;/p></description></item><item><title>石头剪刀布中的求输策略</title><link>https://liriansu.com/posts/2015-11-08-how-to-lose-in-rock-papar-scissors/</link><pubDate>Sun, 08 Nov 2015 21:01:28 +0000</pubDate><guid>https://liriansu.com/posts/2015-11-08-how-to-lose-in-rock-papar-scissors/</guid><description>&lt;p>小时候七八岁，那时候还在看《读者》。&lt;br>
里面有篇文章讲了一下石头剪刀布中的求胜策略。&lt;/p>
&lt;h2 id="石头剪刀布">石头剪刀布&lt;/h2>
&lt;p>先讲一段有用的废话吧。&lt;br>
一般的博弈情况下，问题都会简化成一个容易判断的模型。&lt;br>
也就是说虽然反应快的人可以把&lt;code>后手出招&lt;/code>当作必胜策略，&lt;br>
但是数学模型中一般都会摈弃掉这种可能性。&lt;/p>
&lt;p>（所以看起来数学家会不太喜欢社会学家？）&lt;/p>
&lt;p>在石头剪刀布这个模型里，规则基本上是三点：&lt;/p>
&lt;ul>
&lt;li>双方同时出招，在石头、剪刀、布三个里面选一个。&lt;/li>
&lt;li>石头赢剪刀，剪刀赢布，布赢石头。&lt;/li>
&lt;li>假如平手就再战一局。&lt;/li>
&lt;/ul>
&lt;p>这种三选一循环互克的游戏，国外也有，叫&lt;a href="https://en.wikipedia.org/wiki/Rock-paper-scissors">Rock-Paper-Scissors&lt;/a>&lt;/p>
&lt;h2 id="求胜策略">求胜策略&lt;/h2>
&lt;p>数学模型往往会假定对局双方都是聪明人，&lt;br>
显然地，在石头剪刀布中聪明人的策略就是乱出，&lt;br>
这样双方获胜的概率都是50%。&lt;/p>
&lt;p>不过在真实情况中，两边都是普通人。&lt;br>
&lt;em>(明明刚才说过要简化模型的=_=)&lt;/em>&lt;br>
所以我们需要做一个假设：&lt;/p>
&lt;p>&lt;strong>一般人不会连续两下都做出相同的选择&lt;/strong>&lt;/p>
&lt;p>也就是说当他这次出的是剪刀的话，下次较大可能不会出剪刀。&lt;br>
所以只要下局出布就可以不输。&lt;br>
同理，对方出石头，下局就出剪刀；对方出布，下局就出石头。&lt;/p>
&lt;p>概括地说，这样的假设条件下：&lt;br>
&lt;strong>对手出什么，下局就出被它克制的&lt;/strong>&lt;/p>
&lt;p>当然了，题设本身也是这个策略的弱点。&lt;br>
假如你的对手头很硬，一直不改变出招，&lt;br>
那么这个策略就会一败涂地。&lt;/p>
&lt;h2 id="实战案例">实战案例&lt;/h2>
&lt;p>和女朋友下楼梯的时候玩起了&lt;code>谁猜拳赢了就走一步&lt;/code>的游戏，&lt;br>
玩之前火速地想了一下：&lt;/p>
&lt;ol>
&lt;li>女朋友输了不开心，赢了才开心，而且她不开心我也不能开心。&lt;/li>
&lt;li>女朋友在逻辑上不会跟我计较，所以应该不会头很硬地和我勾心斗角。&lt;/li>
&lt;li>女朋友她第一下喜欢出布。&lt;/li>
&lt;/ol>
&lt;p>嗯，于是我采取了&lt;code>先出石头，再出被她克制的选项&lt;/code>&lt;br>
成功连败了五六局。&lt;/p>
&lt;p>嗯，毕竟求胜策略这种东西，也可以&lt;strong>反着来用&lt;/strong>嘛。&lt;/p></description></item><item><title>利用AUFS和Docker搭建多个私有开发环境</title><link>https://liriansu.com/posts/2015-10-21-build-seperate-env-using-aufs-and-docker/</link><pubDate>Wed, 21 Oct 2015 14:55:24 +0000</pubDate><guid>https://liriansu.com/posts/2015-10-21-build-seperate-env-using-aufs-and-docker/</guid><description>&lt;p>文章的开头先提个问题：&lt;br>
我们平常的工作中，一般都是怎样让每个人都拿到独立开发环境的呢？&lt;/p>
&lt;h2 id="八仙过海">八仙过海&lt;/h2>
&lt;p>比如最常见的做法：每人都有自己的电脑，爱怎么弄怎么弄，同步代码就用Git之类的。&lt;br>
但是这样初始化的过程很慢，要装各种软件各种配置。&lt;/p>
&lt;p>于是也有的是建一个中心服务器，大家用Putty这类软件SSH上去，每个人都有自己的账号。&lt;br>
但是这样环境不独立，而且权限控制很麻烦（毕竟每个人都想sudo）&lt;/p>
&lt;p>后来就直接分发虚拟机镜像了，每个人拿到一个10G的镜像文件，&lt;br>
直接Load一下，环境就起来了。&lt;br>
但是这样每次修改环境就要更新近10G…&lt;/p>
&lt;p>反正就是八仙过海，各有神通了。&lt;br>
利用&lt;a href="https://coolshell.cn/articles/17061.html">AUFS&lt;/a>和&lt;a href="https://liriansu.com/virtual-machine-vs-vagrant-vs-docker">Docker&lt;/a>也可以做到给每个人独立开发环境。&lt;/p>
&lt;h2 id="aufs">AUFS&lt;/h2>
&lt;p>根据Google:&lt;/p>
&lt;blockquote>
&lt;p>AuFS stands for Another Union File System. AuFS started as an implementation of UnionFS Union File System. An union filesystem takes an existing filesystem and transparently overlays it on a newer filesystem. It allows files and directories of separate filesystem to co-exist under a single roof.May 8, 2013&lt;/p>
&lt;/blockquote>
&lt;p>假设我们有一个目录如下：&lt;/p>
&lt;pre tabindex="0">&lt;code>$ tree
.
└── public
├── database
│   ├── dbfile1
│   └── dbfile2
└── src
├── helloworld.lisp
└── sudoku.lisp
&lt;/code>&lt;/pre>&lt;p>我们希望以public目录为基础，给每个人创建一个private环境&lt;br>
于是我们跑几条命令：&lt;/p>
&lt;pre tabindex="0">&lt;code>$ mkdir change private
$ mount -t aufs -o dirs=./change:./public none ./private
$ tree
.
├── change
├── private
│   ├── database
│   │   ├── dbfile1
│   │   └── dbfile2
│   └── src
│   ├── helloworld.lisp
│   └── sudoku.lisp
└── public
├── database
│   ├── dbfile1
│   └── dbfile2
└── src
├── helloworld.lisp
└── sudoku.lisp
&lt;/code>&lt;/pre>&lt;p>mount命令中，-t指定了type是aufs，-o是option&lt;br>
把change命令以读写权限，public目录以只读权限mount到了private里面&lt;/p>
&lt;p>假设我们在private命令中新增，修改了一个文件：&lt;/p>
&lt;pre tabindex="0">&lt;code>$ cd private/
$ touch newfile
$ echo &amp;#34;Changes&amp;#34; &amp;gt; src/sudoku.lisp
$ cd ..
$ tree
.
├── change
│   ├── newfile
│   └── src
│   └── sudoku.lisp
├── private
│   ├── database
│   │   ├── dbfile1
│   │   └── dbfile2
│   ├── newfile
│   └── src
│   ├── helloworld.lisp
│   └── sudoku.lisp
└── public
├── database
│   ├── dbfile1
│   └── dbfile2
└── src
├── helloworld.lisp
└── sudoku.lisp
&lt;/code>&lt;/pre>&lt;p>可以看到我们在private环境中所做的所有改动都在change中发生了！&lt;/p>
&lt;p>这就相当于图层（Layer）的叠加，我们往只读的public层上叠加了一层可写的change层。&lt;br>
&lt;em>不过对于删除文件的情况要进行额外的检测&lt;/em>&lt;/p>
&lt;h2 id="与docker的叠加">与Docker的叠加&lt;/h2>
&lt;p>有了上例中的mount，那和Docker就很好叠加了&lt;br>
利用&lt;a href="https://docs.docker.com/userguide/dockervolumes/">Docker的Volume&lt;/a>：&lt;/p>
&lt;pre tabindex="0">&lt;code>docker run -ti -v /tmp/docker/private:/work ubuntu /bin/bash
&lt;/code>&lt;/pre>&lt;p>这样就可以把private目录作为volume映射到docker container里面的/work目录了。&lt;br>
剩下的就是&lt;a href="https://docs.docker.com/userguide/dockerimages/">Get good use of docker images&lt;/a>了~&lt;/p></description></item><item><title>Virtual Machine, Vagrant, Docker的区别</title><link>https://liriansu.com/posts/2015-10-12-virtual-machine-vs-vagrant-vs-docker/</link><pubDate>Mon, 12 Oct 2015 12:49:55 +0000</pubDate><guid>https://liriansu.com/posts/2015-10-12-virtual-machine-vs-vagrant-vs-docker/</guid><description>&lt;p>Virtualization——虚拟化技术一直是计算机世界里面很重要的东西。&lt;br>
一般程序员听到这个词首先浮现出的就是Windows下面开着装着Linux系统的VMware。&lt;br>
而这个“装着Linux系统的VMware”就是我们口中的虚拟机（Virtual Machine）&lt;/p>
&lt;p>虚拟机的主要好处是可以创建一个与主机操作系统不同的开发环境&lt;br>
（比如说一般的办公室都是Windows系统电脑）&lt;/p>
&lt;p>但是开发的便利也会导致初始化一个这样的环境比较麻烦&lt;br>
而且当项目进行到一定程度，对环境本身一些变化有依赖的时候&lt;br>
从零开始创建虚拟机的开发环境会很繁琐&lt;br>
Vagrant就是一种用来解决这种繁琐的工具&lt;/p>
&lt;h2 id="vagrant">Vagrant&lt;/h2>
&lt;p>根据&lt;a href="https://docs.vagrantup.com/v2/why-vagrant/index.html">官方的说法&lt;/a>&lt;/p>
&lt;blockquote>
&lt;p>Vagrant provides easy to configure, reproducible, and portable work environments built on top of industry-standard technology and controlled by a single consistent workflow to help maximize the productivity and flexibility of you and your team&lt;/p>
&lt;/blockquote>
&lt;p>Vagrant本身不做虚拟机的工作，而是允许用户用VMware|VirtualBox|AWS来启动虚拟机镜像，他们管这叫Provider&lt;br>
当然了，镜像在Vagrant这里叫Box，而且很多公司已经做好了初始化的Box&lt;a href="https://atlas.hashicorp.com/boxes/search">在这里&lt;/a>可以直接用&lt;br>
Vagrant还提供了对Box的初始化脚本（Provisioning），这些初始化脚本可以用更多的脚本工具来完成对Box的配置&lt;/p>
&lt;p>所以其实相比于传统的虚拟机，Vagrant是站在巨人的肩膀上，完成了自动化。&lt;/p>
&lt;h2 id="docker">Docker&lt;/h2>
&lt;p>Docker项目的目标是实现轻量级的虚拟化方案，它和Virtual Machine最大的不同是Docker容器共享操作系统的内核&lt;br>
&lt;img src="https://dockerpool.com/static/books/docker_practice/_images/virtualization.png" alt="vm">&lt;br>
&lt;img src="https://dockerpool.com/static/books/docker_practice/_images/docker.png" alt="docker">&lt;/p>
&lt;p>所以Docker和传统虚拟机的对比是明显的：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>特性&lt;/th>
&lt;th>Docker&lt;/th>
&lt;th>Virtual Machine&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>启动&lt;/td>
&lt;td>秒级&lt;/td>
&lt;td>分钟级&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>大小&lt;/td>
&lt;td>一般为MB&lt;/td>
&lt;td>一般为GB&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>性能&lt;/td>
&lt;td>近原生&lt;/td>
&lt;td>弱于原生&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>单机支持量&lt;/td>
&lt;td>上千个&lt;/td>
&lt;td>一般几十个&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>内核&lt;/td>
&lt;td>共享&lt;/td>
&lt;td>独立&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h2 id="vagrant-vs-docker">Vagrant vs Docker&lt;/h2>
&lt;p>讲道理的话，这两个不应该放在一起比较， 这两者的虚拟化级别并不是一个量级上的&lt;br>
而且这两者并不矛盾，假如你需要在Windows系统上搭载数个特定发行版的Linux系统，完全可以先用Vagrant + Virtual Machine再嵌数个Docker&lt;/p>
&lt;p>硬要比较的话，假如你需要运行跨平台的虚拟，那就用Vagrant，&lt;em>否则&lt;/em>，用Docker&lt;/p>
&lt;p>最后再来张表对比一下吧：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>特性&lt;/th>
&lt;th>Virtual Machine&lt;/th>
&lt;th>Vagrant&lt;/th>
&lt;th>Docker&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>虚拟化&lt;/td>
&lt;td>完全虚拟化&lt;/td>
&lt;td>无&lt;/td>
&lt;td>系统虚拟化&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>镜像管理&lt;/td>
&lt;td>无&lt;/td>
&lt;td>有，一般为GB&lt;/td>
&lt;td>有，一般为MB&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>性能&lt;/td>
&lt;td>弱于原生系统&lt;/td>
&lt;td>弱于原生系统&lt;/td>
&lt;td>接近原生系统&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>内核&lt;/td>
&lt;td>独立&lt;/td>
&lt;td>独立&lt;/td>
&lt;td>共享&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h2 id="参考资料">参考资料&lt;/h2>
&lt;ol>
&lt;li>&lt;a href="https://dockerpool.com/static/books/docker_practice/index.html">《Docker —— 从入门到实践》&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://docs.vagrantup.com/v2/why-vagrant/index.html">Why Vagrant&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/shell909090/slides/blob/master/md/docker.md">Docker不是虚拟机&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://stackoverflow.com/questions/16647069/should-i-use-vagrant-or-docker-io-for-creating-an-isolated-environment">Shoud I use vagrant or docker&lt;/a>&lt;/li>
&lt;/ol></description></item><item><title>VIM中小键盘失灵的解决方案(Putty)</title><link>https://liriansu.com/posts/2015-10-09-use-keypad-with-vim-and-putty/</link><pubDate>Fri, 09 Oct 2015 15:34:16 +0000</pubDate><guid>https://liriansu.com/posts/2015-10-09-use-keypad-with-vim-and-putty/</guid><description>&lt;p>我目前的开发环境是用&lt;a href="https://www.vagrantup.com/">Vagrant&lt;/a>起一个虚拟机，然后用&lt;a href="https://www.putty.org/">Putty&lt;/a>连上去，用VIM做日常的开发工作。&lt;/p>
&lt;p>但某一天更新了一些配置以后，我在VIM里用小键盘输入1的时候，VIM就会在前一行加了一个q字符，让我很是困惑。&lt;/p>
&lt;p>后来&lt;a href="https://vim.wikia.com/wiki/PuTTY_numeric_keypad_mappings">谷歌了一下这个问题&lt;/a>，得知只要把Putty的Application keypad mode给关了就行了。&lt;/p>
&lt;h2 id="奇怪的错误">奇怪的错误&lt;/h2>
&lt;p>当刚开始小键盘的输入和预期有差别的时候，其实我是很困惑的。&lt;/p>
&lt;p>首先我在Bash里面小键盘一切正常，这说明我键盘没问题，应该是VIM哪里不对。&lt;/p>
&lt;p>其次我按的是1，结果出来的是前一行的q，我再按一下2，出来的是前一行的r。&lt;br>
假如键盘没有问题，要自己在VIM里面实现一个这种“功能”，那也要加一行配置：&lt;br>
&lt;code>inoremap &amp;lt;Num1&amp;gt; &amp;lt;Esc&amp;gt;Oq&lt;/code>&lt;/p>
&lt;p>但是这也太奇怪了吧，VIM里面怎么可能把&lt;code>&amp;lt;Num1&amp;gt;&lt;/code>给替换成&lt;code>&amp;lt;Esc&amp;gt;Oq&lt;/code>这么奇怪的东西？&lt;/p>
&lt;h2 id="寻求答案">寻求答案&lt;/h2>
&lt;p>于是我找到了&lt;a href="https://vim.wikia.com/wiki/PuTTY_numeric_keypad_mappings">VIM wiki上的一篇解答&lt;/a>&lt;/p>
&lt;p>根据这篇解答，问题是出在Putty上。&lt;br>
Putty会默认启用“Application Keypad Mode”，这个选项被启用以后&lt;br>
所有小键盘上的按键（包括&lt;!-- raw HTML omitted -->）都会输出一串按键序列：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>原按键&lt;/th>
&lt;th>生成序列&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;code>&amp;lt;Num1&amp;gt;&lt;/code>&lt;/td>
&lt;td>&lt;code>&amp;lt;Esc&amp;gt;Oq&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>&amp;lt;Num2&amp;gt;&lt;/code>&lt;/td>
&lt;td>&lt;code>&amp;lt;Esc&amp;gt;Or&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>&amp;lt;Num3&amp;gt;&lt;/code>&lt;/td>
&lt;td>&lt;code>&amp;lt;Esc&amp;gt;Os&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>&amp;lt;Num4&amp;gt;&lt;/code>&lt;/td>
&lt;td>&lt;code>&amp;lt;Esc&amp;gt;Ot&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>&amp;lt;Num5&amp;gt;&lt;/code>&lt;/td>
&lt;td>&lt;code>&amp;lt;Esc&amp;gt;Ou&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>&amp;lt;Num6&amp;gt;&lt;/code>&lt;/td>
&lt;td>&lt;code>&amp;lt;Esc&amp;gt;Ov&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>&amp;lt;Num7&amp;gt;&lt;/code>&lt;/td>
&lt;td>&lt;code>&amp;lt;Esc&amp;gt;Ow&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>&amp;lt;Num8&amp;gt;&lt;/code>&lt;/td>
&lt;td>&lt;code>&amp;lt;Esc&amp;gt;Ox&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>&amp;lt;Num9&amp;gt;&lt;/code>&lt;/td>
&lt;td>&lt;code>&amp;lt;Esc&amp;gt;Oy&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>&amp;lt;Num0&amp;gt;&lt;/code>&lt;/td>
&lt;td>&lt;code>&amp;lt;Esc&amp;gt;Op&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>.&lt;/code>&lt;/td>
&lt;td>&lt;code>&amp;lt;Esc&amp;gt;On&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>/&lt;/code>&lt;/td>
&lt;td>&lt;code>&amp;lt;Esc&amp;gt;OQ&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>*&lt;/code>&lt;/td>
&lt;td>&lt;code>&amp;lt;Esc&amp;gt;OR&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>+&lt;/code>&lt;/td>
&lt;td>&lt;code>&amp;lt;Esc&amp;gt;Ol&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>-&lt;/code>&lt;/td>
&lt;td>&lt;code>&amp;lt;Esc&amp;gt;OS&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>&amp;lt;Enter&amp;gt;&lt;/code>&lt;/td>
&lt;td>&lt;code>&amp;lt;Esc&amp;gt;OM&lt;/code>&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>居然&lt;code>&amp;lt;Num1&amp;gt;&lt;/code>真的变成了&lt;code>&amp;lt;Esc&amp;gt;Oq&lt;/code>！&lt;/p>
&lt;p>再去翻&lt;a href="https://the.earth.li/~sgtatham/putty/0.60/htmldoc/Chapter4.html#config-appkeypad">Putty关于Application keypad mode的说明&lt;/a>:&lt;/p>
&lt;blockquote>
&lt;p>Application Keypad mode is a way for the server to change the behaviour of the numeric keypad&lt;/p>
&lt;/blockquote>
&lt;p>唔，好吧，是服务器端决定的配置。&lt;/p>
&lt;p>所以在Putty下简单的解决方案就是关掉这个模式了：&lt;/p>
&lt;ul>
&lt;li>打开Putty配置&lt;/li>
&lt;li>选中左边的Terminal -&amp;gt; Features&lt;/li>
&lt;li>在&amp;quot;Disable application keypad mode&amp;quot;处打钩&lt;/li>
&lt;li>选中左边的Session&lt;/li>
&lt;li>保存Putty配置&lt;/li>
&lt;/ul>
&lt;p>&lt;img src="https://liriansu.com/assets/putty_application_keypad_mode.jpg" alt="关闭application keypad mode">&lt;/p>
&lt;h2 id="更多奇怪的答案">更多奇怪的答案&lt;/h2>
&lt;p>在&lt;a href="https://vim.wikia.com/wiki/PuTTY_numeric_keypad_mappings#Comments">VIM wiki页面的讨论板块&lt;/a>，有人给出了一个看起来很蠢的解决方案：&lt;/p>
&lt;pre tabindex="0">&lt;code>:inoremap &amp;lt;Esc&amp;gt;Oq 1
:inoremap &amp;lt;Esc&amp;gt;Or 2
:inoremap &amp;lt;Esc&amp;gt;Os 3
:inoremap &amp;lt;Esc&amp;gt;Ot 4
:inoremap &amp;lt;Esc&amp;gt;Ou 5
:inoremap &amp;lt;Esc&amp;gt;Ov 6
:inoremap &amp;lt;Esc&amp;gt;Ow 7
:inoremap &amp;lt;Esc&amp;gt;Ox 8
:inoremap &amp;lt;Esc&amp;gt;Oy 9
:inoremap &amp;lt;Esc&amp;gt;Op 0
:inoremap &amp;lt;Esc&amp;gt;On .
:inoremap &amp;lt;Esc&amp;gt;OQ /
:inoremap &amp;lt;Esc&amp;gt;OR *
:inoremap &amp;lt;Esc&amp;gt;Ol +
:inoremap &amp;lt;Esc&amp;gt;OS -
:inoremap &amp;lt;Esc&amp;gt;OM &amp;lt;Enter&amp;gt;
&lt;/code>&lt;/pre>&lt;p>刚开始看到这个答案我立刻想到了这张XKCD&lt;/p>
&lt;p>&lt;img src="https://imgs.xkcd.com/comics/workflow.png" alt="workflow">&lt;/p>
&lt;p>我认为mapping不应该是一个合适的解决方案，但是下面又有人讲了他自己苦逼的故事：&lt;/p>
&lt;blockquote>
&lt;p>After a while struggling with this very problem with vnc viewer 4.1.3 under XP with a Debian lenny vnc4server 4.1.1+X4.3.0-31, this vim remapping is the only solution which work.&lt;/p>
&lt;/blockquote>
&lt;p>好吧，至少他找到了解决方案。&lt;/p>
&lt;p>&lt;img src="https://imgs.xkcd.com/comics/wisdom_of_the_ancients.png" alt="solution">&lt;/p></description></item><item><title>这篇博客是怎么建成的</title><link>https://liriansu.com/posts/2015-09-24-how-this-blog-was-built/</link><pubDate>Thu, 24 Sep 2015 20:26:17 +0000</pubDate><guid>https://liriansu.com/posts/2015-09-24-how-this-blog-was-built/</guid><description>&lt;p>其实最开始的时候我是用&lt;a href="https://en.wikipedia.org/wiki/LAMP_(software_bundle)">LAMP&lt;/a>在学校的IP上搭了一个个人博客，当时这么搭博客有几个很蠢的问题：&lt;/p>
&lt;ul>
&lt;li>晚上11点断网，早上6点才恢复网络，所以这个“个人博客”会断网&lt;/li>
&lt;li>学校把对外的80端口给封了，而域名访问默认就是80，所以校外访问博客要变成 &lt;code>https://cloudisdream:8080&lt;/code>这种奇怪的模式&lt;/li>
&lt;li>由于是自己的电脑做服务器，还得保证一直开着，这样始终不太好&lt;/li>
&lt;/ul>
&lt;h2 id="java--servlet--structs--spring--hibernate">JAVA / Servlet / Structs + Spring + Hibernate&lt;/h2>
&lt;blockquote>
&lt;p>在收了可观的小费以后，旅店老板悄悄地告诉你： 每个大学的软件工程专业都会教JAVA+SSH&lt;/p>
&lt;/blockquote>
&lt;p>其实在LAMP之前，我曾经试过用课程里的Java+Servlet写过一个类微博的（个人？）网站&lt;/p>
&lt;p>大概长这样子:&lt;br>
&lt;img src="https://liriansu.com/assets/thatsMoonPage.jpg" alt="First site">&lt;/p>
&lt;p>一边写我就一边感慨网页设计真是艰难，而且其实这个主页也是模仿当时的网易微博的&lt;/p>
&lt;h2 id="lamp--wordpress">LAMP + WordPress&lt;/h2>
&lt;p>在前台HTML CSS JS到后台JAVA SQL都写过一遍以后，我开始意识到全栈工程师虽然听起来很美好，但是写起来实在是心太累了&lt;/p>
&lt;p>那个时候和ED聊天，刚好聊到&lt;a href="https://edward-mj.com/">他的博客&lt;/a>是用WordPress搭的，于是我就在自己的电脑上搭了一个服务器&lt;/p>
&lt;p>虽然文章开头说了这么搭建服务器的缺点，但是其实学校还是给我们提供了一个便利：&lt;strong>固定IP&lt;/strong>&lt;/p>
&lt;p>于是我就去万网买了个域名，CNAME一下到学校IP。&lt;/p>
&lt;p>但是因为实在遭不住一直开机，还要断网，后来还是抛弃掉了这个方式。&lt;/p>
&lt;h2 id="github-pages--jekyll">Github Pages + Jekyll&lt;/h2>
&lt;p>现在的博客就是最简单的&lt;a href="https://pages.github.com/">GitHub Pages&lt;/a> + &lt;a href="https://jekyllrb.com/">Jekyll&lt;/a>&lt;/p>
&lt;p>网页放在GitHub上可以享受版本控制这个得天独厚的优势，Jekyll用的是Ruby，简单易用好上手。&lt;/p>
&lt;p>从无到有搭建博客基本上就这么几步：&lt;/p>
&lt;ol>
&lt;li>注册Github账号，并创建 account.github.com 这个目录&lt;/li>
&lt;li>跑&lt;code>gem install jekyll&lt;/code>，然后&lt;code>gem new my-site&lt;/code>&lt;/li>
&lt;li>修改&lt;code>_config.yml&lt;/code>到自己的配置，然后在&lt;code>_post&lt;/code>文件夹里面新增博客即可&lt;/li>
&lt;/ol>
&lt;h2 id="comments">Comments&lt;/h2>
&lt;p>博客少了评论总感觉哪里不对，因为是GitHub上的静态页面，基本上解决方案有：用&lt;a href="https://duoshuo.com/">多说评论&lt;/a>，&lt;a href="https://disqus.com/">Disqus&lt;/a>，或者是用GitHub issue来定制化评论&lt;br>
（我一开始还以为disqus == disquz）&lt;/p>
&lt;p>综合各方面，我采用了Disqus，根据&lt;a href="https://help.disqus.com/customer/portal/articles/472138-jekyll-installation-instructions">官方的说明文档&lt;/a>&lt;/p>
&lt;p>直接在Page里面插入一段Comment Code就可以了。&lt;/p>
&lt;h2 id="enhancement">Enhancement&lt;/h2>
&lt;p>至此，基本主题的博客已全部搭建完毕&lt;/p>
&lt;p>但是还有几点不足的地方：&lt;/p>
&lt;ol>
&lt;li>页面最下方的Twitter图标最好要改成Weibo的（但是我还没搞懂怎么画）&lt;/li>
&lt;li>要补完About界面&lt;/li>
&lt;li>使用Kramdown的GFM render方式感觉还是不够好，尤其是界面上，还是&lt;a href="https://github.com/LKI/blogs/issues/3">GitHub Issue的Render方式&lt;/a>看起来比较舒服&lt;/li>
&lt;/ol>
&lt;p>看来以后在写博客的同时，也要对网站持续进行优化才可以呀！&lt;/p></description></item><item><title>为什么我要写博客</title><link>https://liriansu.com/posts/2015-09-23-why-im-blogging/</link><pubDate>Wed, 23 Sep 2015 00:00:00 +0000</pubDate><guid>https://liriansu.com/posts/2015-09-23-why-im-blogging/</guid><description>&lt;p>我其实很喜欢看别人写的东西，&lt;a href="https://coolshell.cn/articles/4758.html">技术类的&lt;/a>、&lt;a href="https://joshworth.com/dev/pixelspace/pixelspace_solarsystem.html">非技术类的&lt;/a>，&lt;a href="https://blog.csdn.net/redguardtoo/article/details/7222501">中文的&lt;/a>、&lt;a href="https://blog.codinghorror.com/show-dont-tell/">英文的&lt;/a>。&lt;/p>
&lt;p>很多人写文章的时候总喜欢说一句&lt;/p>
&lt;blockquote>
&lt;p>我先抛砖引玉&lt;/p>
&lt;/blockquote>
&lt;p>但是往往&lt;a href="https://coolshell.cn/articles/11312.html">他们写的都非常好&lt;/a>&lt;/p>
&lt;p>这样的文章看的我特手痒，想也写博客，但是问题就来了&lt;/p>
&lt;h2 id="博客的主题是什么">博客的主题是什么？&lt;/h2>
&lt;p>我一直有着写点什么的习惯，以前总是休闲散文写的比较多，更多是偏向于一种日记类的文章。&lt;br>
自从看了&lt;a href="https://coolshell.cn/haoel">陈皓&lt;/a>和&lt;a href="https://blog.codinghorror.com/about-me/">Jeff Atwood&lt;/a>的技术类博客以后，总有种写&lt;em>好的&lt;/em>技术博客的冲动。&lt;br>
因为我对逻辑、语言、思考都感兴趣，而我又不能准确描述我这些兴趣，那我就把它们都写出来好了。&lt;/p>
&lt;p>XKCD的自我描述是&lt;/p>
&lt;blockquote>
&lt;p>A webcomic of romance, sarcasm, math and language&lt;/p>
&lt;/blockquote>
&lt;p>&lt;img src="https://imgs.xkcd.com/comics/standards.png" alt="XKCD-927">&lt;/p>
&lt;p>希望我也能写出这种主题鲜明，又有趣又妙不可言的文章&lt;/p>
&lt;h2 id="我有什么能写出来的">我有什么能写出来的?&lt;/h2>
&lt;p>作为一个菜鸟，我最熟练的VIM水平其实放在网络上也只是一般&lt;br>
同时根据&lt;code>三人行必有我师焉&lt;/code>，也意味着来到这个博客的人中每三个里就有一个比我厉害&lt;/p>
&lt;p>（我是不是应该放一个博客访问计数器？然后每到三个倍数就alert(&amp;ldquo;Congratulations&amp;rdquo;)一下&amp;hellip;&lt;/p>
&lt;p>不过既然大家都比我懂的多，那我也就不怕献丑了。&lt;br>
好玩的，要费脑子的问题，或者对人生的杂念都会被我写下来。&lt;/p>
&lt;h2 id="中文博客还是英文博客">中文博客还是英文博客？&lt;/h2>
&lt;p>讲道理的话，这个问题我想了很久。&lt;br>
以至于我都快走火入魔了，同样的文章写了&lt;a href="https://liriansu.com/vagrant-up-but-mount-no-device-zh">一份中文的&lt;/a>和&lt;a href="https://liriansu.com/vagrant-up-but-mount-no-device-en">一份英文的&lt;/a>&lt;/p>
&lt;p>后来想了想，主要基于几个观点：&lt;/p>
&lt;ol>
&lt;li>母语是中文，所以中文写的会比英文写的更顺畅&lt;/li>
&lt;li>语言的选择决定了受众的范围，而外国受众大部分不了解中国的亚文化&lt;/li>
&lt;li>个人而言，以后认识的国内朋友可能会更多，这本身是一个不错的名片&lt;/li>
&lt;/ol>
&lt;p>于是，我便踏上了博客之路。&lt;/p>
&lt;p>现阶段目标是每周一篇吧，就像&lt;a href="https://discourse.codinghorror.com/t/how-to-achieve-ultimate-blog-success-in-one-easy-step/445/27">Jeff说的一样&lt;/a>：&lt;/p>
&lt;blockquote>
&lt;p>Pick whatever schedule works for you. And be realistic. I think starting with one post a month, like Catto, is a fine goal. Try to slowly ramp it up a bit over time as you get into the groove, and you&amp;rsquo;re on your way.&lt;/p>
&lt;/blockquote></description></item><item><title>我和女权的我打起来了</title><link>https://liriansu.com/posts/2015-08-27-fight-with-the-feminist-me/</link><pubDate>Thu, 27 Aug 2015 20:28:00 +0000</pubDate><guid>https://liriansu.com/posts/2015-08-27-fight-with-the-feminist-me/</guid><description>&lt;p>一直以来我都自以为是一个大男子主义的人，&lt;br>
但我和女权的我相处的都比较和谐。&lt;br>
但是今晚我和女权的我打起来了。&lt;/p>
&lt;p>（一）&lt;/p>
&lt;p>一直以来我都自以为是一个大男子主义的人，&lt;br>
但我和女权的我相处的都比较和谐。&lt;/p>
&lt;p>但是今晚我和女权的我打起来了。&lt;/p>
&lt;p>（二）&lt;/p>
&lt;p>做完饭以后，我把每个菜都尝了一遍。&lt;/p>
&lt;p>自我感觉还是挺不错的，只是菜的扮相不是特别好。&lt;/p>
&lt;p>我忧伤的想道：&lt;br>
“假如我是个女的就好了，以后就找个有钱的，天天研究怎么做菜。”&lt;/p>
&lt;p>这时，女权的我突然跳了出来：“你这样想是不对的！”&lt;/p>
&lt;p>我在吓了一跳的同时意识到了我话里隐含的逻辑漏洞，&lt;br>
赶快心虚地解释道：“不不不，假如我是个男的我也找个有钱的&amp;hellip;”&lt;/p>
&lt;p>女权的我看出了我的心虚，一针见血地说道：“你潜意识并不这么想。”&lt;/p>
&lt;p>男人嘴巴上的尊严让我让步不能，我于是反问：&lt;br>
“那就我找一个会做饭的，我去挣钱养家，可以伐？”&lt;/p>
&lt;p>女权的我立刻就回答道：&lt;br>
“你不能这么想。只有女性在自己选择了想做饭以后，你才可以这么想。”&lt;/p>
&lt;p>我眼神里充满了怀疑（别问我自己怎么知道的，真男人从来不照镜子）&lt;br>
“也就是说我是男的，依据女权的观点，我不能希望女的会做饭，但是假如我是女的，希望自己会做饭，这是可以的，而且是女权的？”&lt;/p>
&lt;p>女权的我盯着我，想了一下：“对的。”&lt;/p>
&lt;p>我退了一步，先使出一招&amp;lt;以退为进&amp;gt;：“所以其实女权是提倡平等？”&lt;/p>
&lt;p>女权的我紧跟着，使出了一招&amp;lt;海阔天空&amp;gt;：“是的，女权其实就是平权，你微博读的不错。”&lt;/p>
&lt;p>我立马使出连招&amp;lt;车五进一&amp;gt;&amp;lt;猴子捞月&amp;gt;：“那所以根据平权的观点，我也可以希望自己的配偶是醉心于为我做饭的？”&lt;/p>
&lt;p>没想到女权的我只用了一招&amp;lt;不动如山&amp;gt;就化解掉了我的所有言语：&lt;br>
“你个人可以这么想，但是有这个想法，你基本上就孤独终老了。”&lt;/p>
&lt;p>（三）&lt;/p>
&lt;p>可能是因为招数太华丽，有可能是因为无懈太可击，也可能是蚍蜉撼大树是两个好朋友，一走神我就发现自己出于了下风。&lt;/p>
&lt;p>于是我放下了筷子，重新开始了游戏：&lt;br>
“假如说我是女的，而且我是男权的，我就希望老公棒棒的，我差差的，何如？”&lt;/p>
&lt;p>“假如你是女的…”&lt;br>
女权的我一开口，我就松了一口气，还好女权的我没有反驳说“你不可能是个女的”。&lt;/p>
&lt;p>在这个问题上我可真争不过，&lt;br>
毕竟我前几周才知道我一直爱慕的丝袜其实囊括了打底裤。&lt;/p>
&lt;p>那一瞬间，我从“喜欢丝袜”的变态，变成了“喜欢打底裤”的傻逼。&lt;/p>
&lt;p>不过话说回来，打底裤看起来其实也不错，关键还是要看腿。&lt;/p>
&lt;p>“假如你是女的，你就不会这么想了。”女权的我简明扼要地告诉我。&lt;/p>
&lt;p>这个问题我也争不过。&lt;br>
因为这个问题讲下去，就会变成“你又不是庄子，你又不知道惠子眼中的鱼知不知道自己是怎么想的”了，&lt;/p>
&lt;p>而且最终还会变成“庄子//转发本条锦鲤”这样的东西。&lt;/p>
&lt;p>我看了看渐渐变凉的饭和渐渐消失的饿，意识到我要先去收剩菜了&lt;br>
“我先去下厨房”&lt;/p>
&lt;p>“哦”女权的我答应道。&lt;/p>
&lt;p>（五）&lt;/p>
&lt;p>“你咋去了这么久？”女权的我看我回来得比较迟&lt;/p>
&lt;p>“没办法，一个人老做两人份的饭，收起来累，刚说到哪了。”我挺着肚子坐了下来。&lt;/p>
&lt;p>“刚说到假如你这样的女生，肯定也是支持女权的。”&lt;/p>
&lt;p>我有点不服气：“难道所有女的都是女权的？比如我有个儿子，那我也希望将来的媳妇要对他好给他做饭好好照顾他，这也不行？”&lt;/p>
&lt;p>“的确，现实生活中有很多这样的婆婆，所以女权运动任重道远啊。”女权的我叹了口气，看起来很忧郁的样子。&lt;/p>
&lt;p>我还是不服气：“就算按女权的观点，也不是万事平等的吧。扛东西肯定是男的来吧？万一打仗征兵呢？肯定是男的吧，可是会死人的。”&lt;/p>
&lt;p>女权的我立刻指出了我题设的漏洞：“女权反对战争，不止女权，人权都反对战争。文明越发达，战争的可能性越少。”&lt;/p>
&lt;p>想了想，女权的我估计是没有玩过《文明》的，就没有整下去了。&lt;/p>
&lt;p>而且“可能性应该用小，而不是少”这句话也犹豫了一下，没有说出来。&lt;/p>
&lt;p>看我有点踌躇的感觉，女权的我使出了终极武器：&lt;br>
“你刚才讲的的确是男性弱势的地方，但是那些发生机会都少，而女性，还要生育呢。”&lt;/p>
&lt;p>听了这句话，虽然我心里有很多“不是说生小孩是自己选的吗？说好的选择了生育就选择了责任呢？”“说好的女性不是生育机器呢？”“男的也可以生小孩以后就不用女权了吗？”一系列问题，但最终还是没有说出口，点了点头表示了赞成。&lt;/p>
&lt;p>因为突然想到了我妈，假如她也比较女权的话那她肯定活的比较自由，不用这么在意我了。&lt;/p>
&lt;p>（六）&lt;/p>
&lt;p>安静了一阵子，我问女权的我：&lt;br>
“其实我们讲话还是挺科学的啊，为啥我一直觉得我要和你打起来了？”&lt;/p>
&lt;p>女权的我深了个呼吸，叹道：&lt;br>
“我也不想的。大概是整个社群比较激进，很多人的观点就是叫的越大声醒来的人才越多，我也不赞成这样的观点。但是没办法，毕竟辛德勒是在战乱结束以后才被拍成电影的，所以很多事情都要慢慢看的。”&lt;/p>
&lt;p>我不禁赞同：“嗯，基督山伯爵也说嘛，等待，和希望。”&lt;/p>
&lt;p>在气氛缓和了以后，男人残留在嘴巴上的尊严马上又让我跳了出来：&lt;br>
“不过我还是不赞同女权，我还是很大男子主义的。我觉得女性就应该柔弱一些，这样子不同性别的人都能发挥自己的特长到最好。其实女权和男权就应该像猪和驴在年货里的关系一样，反正我是不赞同男权的。说不定我还有处女情结呢！”&lt;/p>
&lt;p>女权的我看了看我，笑道：“ツ 没事，我也有处男情结。”&lt;/p></description></item><item><title>如何优雅地使用Perl的常量模块</title><link>https://liriansu.com/posts/2015-07-25-how-to-set-perl-constant-module/</link><pubDate>Sat, 25 Jul 2015 20:56:06 +0000</pubDate><guid>https://liriansu.com/posts/2015-07-25-how-to-set-perl-constant-module/</guid><description>&lt;p>最近的Perl Coding遇到了一个问题：需要对一系列常量进行合法性检测。&lt;/p>
&lt;p>在Research&amp;amp;Develop后，有一些心得。&lt;/p>
&lt;p>本文从Perl的常量定义上，给出一个_自认为_优雅的解决方案。&lt;/p>
&lt;h2 id="perl中一般的常量定义">Perl中一般的常量定义&lt;/h2>
&lt;p>在写项目的时候为了避免Magic Number的情况，我们经常需要定义常量。&lt;/p>
&lt;p>当然了，根据&lt;a href="https://coolshell.cn/articles/4758.html">如何写出无法维护的代码&lt;/a>的指导我们不应当定义常量，Number越Magic越好。&lt;/p>
&lt;p>一般来说，Perl中的常量如下：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-perl" data-lang="perl">&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">use&lt;/span> constant CONST_PI &lt;span style="color:#f92672">=&amp;gt;&lt;/span> &lt;span style="color:#ae81ff">3.1416&lt;/span>;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>在模块化的编码过程中，随着常量的增多，我们会需要把这些常量放到一个常量模块(Perl Module)里面：&lt;/p>
&lt;p>这样的做法也符合DRY(Don&amp;rsquo;t Repeat Yourself)的原则。#DRYBestPractice?&lt;/p>
&lt;p>比如说在哼哧哼哧地写了一阵子以后，我们有下面这个常量模块。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-perl" data-lang="perl">&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">package&lt;/span> Lirian::Constants;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">use&lt;/span> strict;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">use&lt;/span> warnings;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">#Math Const&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">use&lt;/span> constant CONST_PI &lt;span style="color:#f92672">=&amp;gt;&lt;/span> &lt;span style="color:#ae81ff">3.1416&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">use&lt;/span> constant CONST_E &lt;span style="color:#f92672">=&amp;gt;&lt;/span> &lt;span style="color:#ae81ff">2.718&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">#Default Config Parm Name&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">use&lt;/span> constant PARM_DB_NAME &lt;span style="color:#f92672">=&amp;gt;&lt;/span> &lt;span style="color:#e6db74">&amp;#39;dbName&amp;#39;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">use&lt;/span> constant PARM_DB_HOST &lt;span style="color:#f92672">=&amp;gt;&lt;/span> &lt;span style="color:#e6db74">&amp;#39;dbHost&amp;#39;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">use&lt;/span> constant PARM_GIT_USER &lt;span style="color:#f92672">=&amp;gt;&lt;/span> &lt;span style="color:#e6db74">&amp;#39;gitUser&amp;#39;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">require&lt;/span> Exporter;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">our&lt;/span> @ISA &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">qw(Exporter)&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">our&lt;/span> @EXPORT_OK &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">qw(
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> CONST_PI
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> CONST_E
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> PARM_DB_NAME
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> PARM_DB_HOST
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> PARM_GIT_USER
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> )&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">our&lt;/span> %EXPORT_TAGS &lt;span style="color:#f92672">=&lt;/span> (
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> all &lt;span style="color:#f92672">=&amp;gt;&lt;/span> &lt;span style="color:#f92672">\&lt;/span>@EXPORT_OK,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> math &lt;span style="color:#f92672">=&amp;gt;&lt;/span> [&lt;span style="color:#e6db74">qw(
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> CONST_PI
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> CONST_E
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> )&lt;/span>],
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> parm &lt;span style="color:#f92672">=&amp;gt;&lt;/span> [&lt;span style="color:#e6db74">qw(
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> PARM_DB_NAME
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> PARM_DB_HOST
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> PARM_GIT_USER
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> )&lt;/span>],
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> );
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>上面这段代码简单粗暴地展示了Perl中的常量模块。&lt;/p>
&lt;p>其中的&lt;code>our @ISA = qw(Exporter);&lt;/code>是表示本模块继承了&lt;a href="https://perldoc.perl.org/Exporter.html">Exporter&lt;/a>这个模块。&lt;/p>
&lt;p>通过这样的定义，我们便有了一个常量的“中心仓库”了。&lt;/p>
&lt;p>至于怎么使用，我们就来看下一节。&lt;/p>
&lt;h2 id="使用常量模块">使用常量模块&lt;/h2>
&lt;p>在上一节中，通过对Exporter的继承，我们有了一个Lirian::Constants模块。&lt;/p>
&lt;p>而一般地，我们会这么使用：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-perl" data-lang="perl">&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">package&lt;/span> Lirian::Math;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">use&lt;/span> Lirian::Constants &lt;span style="color:#e6db74">qw(:all)&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">use&lt;/span> strict;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">use&lt;/span> warnings;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">sub&lt;/span> &lt;span style="color:#a6e22e">get_circum&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">my&lt;/span> ($r) &lt;span style="color:#f92672">=&lt;/span> @_;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#ae81ff">2&lt;/span> &lt;span style="color:#f92672">*&lt;/span> CONST_PI &lt;span style="color:#f92672">*&lt;/span> $r;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ae81ff">1&lt;/span>;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>在正常的情况下，常量的使用方法比较简单，但假如需求有些绕：&lt;/p>
&lt;p>在程序的开始时，我们需要检验用户的配置文件，确保每个条目用户都是有效的。&lt;/p>
&lt;p>比如说需求文件如下：&lt;/p>
&lt;pre tabindex="0">&lt;code class="language-config" data-lang="config"> dbName=github
dbHost=localhost
gitUser=LKI
&lt;/code>&lt;/pre>&lt;p>显然地，一种简单但稍微蠢了点的方法是这么做：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-perl" data-lang="perl">&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">sub&lt;/span> &lt;span style="color:#a6e22e">validate_config_dumb&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">my&lt;/span> ($conf) &lt;span style="color:#f92672">=&lt;/span> @_;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> validate_parm($conf, PARM_DB_NAME);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> validate_parm($conf, PARM_DB_HOST);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> validate_parm($conf, PARM_GIT_USER);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>这样做有几个问题：&lt;/p>
&lt;p>1.config parameter一多，代码就很长，丑&lt;br>
2.增加config constant时，不仅要改常量模块，这里也要加，累&lt;br>
3.这样的代码提交上去感觉好丢脸，蠢&lt;br>
4.以上三点在&lt;a href="https://coolshell.cn/articles/2058.html">撞大运编程&lt;/a>里都不是问题&lt;/p>
&lt;p>那怎么样做才算是优雅的做法呢？&lt;/p>
&lt;h2 id="利用perl的export机制">利用Perl的Export机制&lt;/h2>
&lt;p>在Exporter中，定义在%EXPORT_TAGS中的文件可以直接引用：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-perl" data-lang="perl">&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">my&lt;/span> $tags &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">\&lt;/span>$Lirian::Constants::EXPORT_TAGS;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">my&lt;/span> $math_tags &lt;span style="color:#f92672">=&lt;/span> $tags&lt;span style="color:#f92672">-&amp;gt;&lt;/span>{math}; &lt;span style="color:#75715e"># [&amp;#39;CONST_PI&amp;#39;, &amp;#39;CONST_E&amp;#39;];&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">my&lt;/span> $parm_tags &lt;span style="color:#f92672">=&lt;/span> $tags&lt;span style="color:#f92672">-&amp;gt;&lt;/span>{parm}; &lt;span style="color:#75715e"># [&amp;#39;PARM_DB_NAME&amp;#39;, &amp;#39;PARM_DB_HOST&amp;#39;, &amp;#39;PARM_GIT_USER&amp;#39;];&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>这样就可以拿到常量的名字了，此时我们便需要&lt;a href="https://stackoverflow.com/questions/2187682/how-do-i-access-a-constant-in-perl-whose-name-is-contained-in-a-variable">在Perl中根据变量名获取变量值&lt;/a>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-perl" data-lang="perl">&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">my&lt;/span> $name &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#39;CONST_PI&amp;#39;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">my&lt;/span> $value &lt;span style="color:#f92672">=&lt;/span> Lirian::Constants&lt;span style="color:#f92672">-&amp;gt;&lt;/span>$name; &lt;span style="color:#75715e"># 3.1416&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>所以在上一小节的问题中，我们可以得出一个更优雅的解决方案啦~&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-perl" data-lang="perl">&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">sub&lt;/span> &lt;span style="color:#a6e22e">validate_config&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">my&lt;/span> ($conf) &lt;span style="color:#f92672">=&lt;/span> @_;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">my&lt;/span> $tags &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">\&lt;/span>$Lirian::Constants::EXPORT_TAGS;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">my&lt;/span> $parm_tags &lt;span style="color:#f92672">=&lt;/span> $tags&lt;span style="color:#f92672">-&amp;gt;&lt;/span>{parm};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">foreach&lt;/span> &lt;span style="color:#66d9ef">my&lt;/span> $parm_name (@$parm_tags) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">my&lt;/span> $parm_value &lt;span style="color:#f92672">=&lt;/span> Lirian::Constants&lt;span style="color:#f92672">-&amp;gt;&lt;/span>$parm_name;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> validate_parm($conf, $parm_value);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>大功告成！从此以后在加常量的同时，validate_config会自动地检验新增的配置选项啦~&lt;/p>
&lt;p>此时便可以使用&lt;a href="https://whatthecommit.com/">一个酷炫的Git Commit Message&lt;/a>来提交工作啦！&lt;/p></description></item><item><title>记一次有意义的吹B</title><link>https://liriansu.com/posts/2015-06-12-a-chat-with-roommates/</link><pubDate>Fri, 12 Jun 2015 22:06:00 +0000</pubDate><guid>https://liriansu.com/posts/2015-06-12-a-chat-with-roommates/</guid><description>&lt;p>（一）引言&lt;/p>
&lt;p>我经历了一场绝妙的装B&lt;br>
可是这个地方太小写不下&lt;br>
——&lt;a href="https://weibo.com/n/ooCast">@ooCast&lt;/a>&lt;/p>
&lt;p>（可能内含各种广告）&lt;/p>
&lt;p>（二）&lt;/p>
&lt;p>某天下午和室友们吹了一场有意义的B，&lt;br>
当时觉得不记下来的话，毕设也写不安稳，&lt;br>
但是最后权衡了一下，还是毕设特么重要，&lt;br>
所以直到毕设写完了才开始记录这次寝室谈话。&lt;/p>
&lt;p>记忆力和文笔都不好，请多担待。&lt;/p>
&lt;p>（三）租房&lt;/p>
&lt;p>话说最近在签三方的事情，和周丞一起去学生服务中心交表格。&lt;/p>
&lt;p>路上我问周丞租房子的事情，&lt;br>
然后相互吐槽了一下租房还真蛮贵的，&lt;br>
想住的离公司比较近的话一个月就要2k~3k。&lt;/p>
&lt;p>而且周丞懒，想租蘑菇公寓的房子，又要额外1k。&lt;/p>
&lt;p>不禁感慨了一番在魔都干个十年，&lt;br>
要被房子吃掉好多钱，&lt;br>
而且在这里买房子真不值。&lt;/p>
&lt;p>于是又探讨起了干十年就卷钱走人的可能性，&lt;br>
主要问题有2：&lt;/p>
&lt;ol start="0">
&lt;li>
&lt;p>很可能三十岁回老家的时候还是单身&lt;/p>
&lt;/li>
&lt;li>
&lt;p>回去以后是否有对口的工作&lt;/p>
&lt;/li>
&lt;/ol>
&lt;p>周丞觉得第一的话现在相亲市场这么发达，不慌，&lt;br>
他认为到时候他就是有房、有车、单身、没有不良嗜好的优质大叔了&lt;/p>
&lt;p>第二个问题倒挺忧伤的，&lt;br>
因为他查了一下，马兰坡Python程序员只有一个地方在招人：&lt;/p>
&lt;p>芒果TV。&lt;/p>
&lt;p>（四）毕业工作&lt;/p>
&lt;p>后来回到了寝室，问小赖打算怎么样。&lt;/p>
&lt;p>小赖说他出国没有理想的offer，想先gap一年，实习一下。&lt;/p>
&lt;p>我和周丞便怂恿他找我们内推，小赖便问一天多少钱，&lt;br>
我们表示实习钱差不多，基本上都是180/d，转正后工资才是重要的。&lt;/p>
&lt;p>小赖表示他不转正，这个不重要。&lt;/p>
&lt;p>过了一会他又忍不住问“像我们这种码农值多少钱？”&lt;/p>
&lt;p>于是我们展开了讨论，得出结论：&lt;/p>
&lt;ol start="0">
&lt;li>
&lt;p>根据现状来看，第一年的基本上是100k/y到240k/y之间&lt;/p>
&lt;/li>
&lt;li>
&lt;p>正常的码农干个三年，几十万年薪是有的&lt;/p>
&lt;/li>
&lt;li>
&lt;p>再不济，随便学点C艹，Java，每个月拿半狗（150k/y)是有的&lt;/p>
&lt;/li>
&lt;li>
&lt;p>但是很少有码农能拿到百万年薪（周丞：知乎上就三个）&lt;/p>
&lt;/li>
&lt;/ol>
&lt;p>“走走走，看工作去” 我们三人凑在显示器前，默默打开了草榴…&lt;/p>
&lt;p>唔…开错网了，于是我们关掉了草榴，&lt;/p>
&lt;p>默默打开了赶集、智联、拉勾网、JobDeer和各种互联网公司的hr主页&lt;/p>
&lt;p>（五）职业去向&lt;/p>
&lt;p>到网上一搜，果然大部分都是招什么Java开发工程师，10k/m，要求三年工作经验。&lt;/p>
&lt;p>然后我们又吐槽了一下，居然要求程序员工作经验，太扯了，&lt;br>
殊不知有些人是复制粘贴编译改Bug循环了三年。&lt;/p>
&lt;p>我们觉得这个薪资太低了，果断按了 高级搜索-&amp;gt;筛选-&amp;gt;月薪大于50k&lt;/p>
&lt;p>然后出来的职位包夸：产品经理、美X网中国区总经理、总架构师blablabla。&lt;/p>
&lt;p>面面相觑，&lt;br>
“难道我们干几年就几乎全部要转管理了？”&lt;/p>
&lt;p>小赖表示他不服，他想当羽毛球教练（小赖：每次我去南体都觉得那个教练菜）&lt;/p>
&lt;p>我和周丞极力赞扬他：“你看，羽毛球这运动很好的，很多白富美喜欢。说不定你就被看上了！”&lt;/p>
&lt;p>于是我们就去网上搜了一下羽毛球教练的工资：6k一个月。&lt;/p>
&lt;p>小赖表示他还是当程序员吧。&lt;/p>
&lt;p>（六）钱的去向&lt;/p>
&lt;p>乐观的我表示没事，虽然我们挣得不多，但是我们用的也少呀，&lt;br>
比如我们的社交费用会比别人少很多。&lt;/p>
&lt;p>周丞：那不一定啊，我们会买游戏&lt;/p>
&lt;p>小赖：游戏又没很多钱的&lt;/p>
&lt;p>周丞：不不不，一个游戏虽然才几十刀，但是很多的还是很贵的&lt;/p>
&lt;p>我：这个总比那些社交活动钱少吧&amp;hellip;&lt;/p>
&lt;p>周丞：而且我们那边的人天天去洗脚&lt;/p>
&lt;p>我和小赖：啊？！？！？&lt;/p>
&lt;p>周丞说他们那边的人去洗脚是一种娱乐活动，&lt;br>
要一两百一人次。。。&lt;/p>
&lt;p>小赖表示这尼玛性价比太低了，还不如去大宝剑。&lt;/p>
&lt;p>于是我们打开了大众点评，发现闵行的大宝剑才300一次。&lt;/p>
&lt;p>我表示这个又不舒服又不安全，&lt;br>
还不如投资在以后的婚姻上呢。&lt;/p>
&lt;p>（七）择偶观&lt;/p>
&lt;p>我问“你们那边彩礼一般要多少钱？”&lt;/p>
&lt;p>周丞“啊？还要彩礼，为啥？两个人平等的婚姻也要彩礼？”&lt;/p>
&lt;p>小赖“我们那边都有彩礼的，毕竟嫁女儿嘛。”&lt;/p>
&lt;p>周丞“那我妈还嫁儿子呢？凭啥我没彩礼…”&lt;/p>
&lt;p>我“那你入赘就好了，入赘就不要彩礼”&lt;/p>
&lt;p>周丞“啥是入赘。。。？”&lt;/p>
&lt;p>小赖“就是对外宣称是你嫁过去了，然后你要住妹子家”&lt;/p>
&lt;p>周丞“这么好？！？！好啊！没问题”&lt;/p>
&lt;p>小赖“对，小孩还要跟妈妈姓”&lt;/p>
&lt;p>我“啊，我就跟我妈姓的啊，入赘的评判标准就这些了吗？”&lt;/p>
&lt;p>小赖“唔，好像就这些了…”&lt;/p>
&lt;p>一阵沉默……（分析利弊中）&lt;/p>
&lt;p>周丞表示其实不结婚也没啥，也就纯生物学意义上没完成传宗接代的功能，&lt;br>
假如真老了，还是没有老婆，那他就去捐精！&lt;/p>
&lt;p>于是我们就到&lt;a href="https://www.fairfaxcryobank.com/index.shtml">美国著名精子库fairfaxcryobank&lt;/a>去围观了一发。&lt;/p>
&lt;p>（八）饮食&lt;/p>
&lt;p>正讲着，郁翔回来了。&lt;/p>
&lt;p>由于他是魔都土著，我们就吐槽他在魔都有根据地，理论上有优势。&lt;/p>
&lt;p>郁翔吐槽说其实他在左下角工作，家在右上角，一样也要租房。&lt;/p>
&lt;p>说到租房，周丞又表示了忧郁：&lt;br>
以后饭怎么解决啊？&lt;/p>
&lt;p>我们说现在饿了么这么发达，以后吃外卖就好了，&lt;br>
而且自己做饭未必比外卖便宜。&lt;/p>
&lt;p>实在不行就请个小保姆嘛，说不定就发展出美好姻缘了。&lt;/p>
&lt;p>但是请小保姆好贵啊！&lt;/p>
&lt;p>郁翔表示这种东西跟程序员鼓励师一样不靠谱：&lt;br>
“假如有人在我写代码的时候在旁边说话，我肯定想抡死她”&lt;/p>
&lt;p>的确，&lt;br>
面向对象编程的时候不需要其他对象了。&lt;/p>
&lt;blockquote>
&lt;p>——记一次有意义的吹B&lt;/p>
&lt;p>于 2015年06月12日晚10点&lt;/p>
&lt;/blockquote></description></item><item><title>Vagrant-up遇到mount no device的解决方案</title><link>https://liriansu.com/posts/2015-05-15-vagrant-up-but-mount-no-device-zh/</link><pubDate>Fri, 15 May 2015 10:29:05 +0000</pubDate><guid>https://liriansu.com/posts/2015-05-15-vagrant-up-but-mount-no-device-zh/</guid><description>&lt;p>今天跑&lt;code>vagrant up&lt;/code>的时候遇到了这个问题：&lt;/p>
&lt;pre tabindex="0">&lt;code>==&amp;gt; cvc-tools: Machine booted and ready!
==&amp;gt; cvc-tools: Checking for guest additions in VM...
==&amp;gt; cvc-tools: Configuring and enabling network interfaces...
==&amp;gt; cvc-tools: Mounting shared folders...
cvc-tools: /work =&amp;gt; D:/work/
Failed to mount folders in Linux guest. This is usually because
the &amp;#34;vboxsf&amp;#34; file system is not available. Please verify that
the guest additions are properly installed in the guest and
can work properly. The command attempted was:
mount -t vboxsf -o uid=`id -u devel`,gid=`getent group devel | cut -d:
-f3` work /work
mount -t vboxsf -o uid=`id -u devel`,gid=`id -g devel` work /work
The error output from the last command was:
/sbin/mount.vboxsf: mounting failed with the error: No such device
&lt;/code>&lt;/pre>&lt;p>查看了 &lt;a href="https://github.com/mitchellh/vagrant/issues/1657">https://github.com/mitchellh/vagrant/issues/1657&lt;/a>&lt;br>
以后，明白这是&lt;code>yum update&lt;/code>更新了内核，但是没有更新VirtualBox的连接的问题。&lt;/p>
&lt;p>于是重新添加一下VBox：&lt;/p>
&lt;pre tabindex="0">&lt;code>[lirian@localhost ~]$ sudo /etc/init.d/vboxadd setup
Removing existing VirtualBox non-DKMS kernel modules [ OK ]
Building the VirtualBox Guest Additions kernel modules
The headers for the current running kernel were not found. If the
following
module compilation fails then this could be the reason.
The missing package can be probably installed with
yum install kernel-devel-2.6.18-404.el5
Building the main Guest Additions module [FAILED]
(Look at /var/log/vboxadd-install.log to find out what went wrong)
Doing non-kernel setup of the Guest Additions [ OK ]
&lt;/code>&lt;/pre>&lt;p>根据以上信息，得知现在在跑的内核开发包缺失，于是再跑一下：&lt;/p>
&lt;p>&lt;code>yum install kernel-devel-2.6.18-404.el5&lt;/code>&lt;/p>
&lt;p>之后再vagrant up或者手动mount就可以解决问题了。&lt;/p>
&lt;p>总结：vagrant up遇到mount error: no such device可以通过以下脚本解决：&lt;/p>
&lt;pre tabindex="0">&lt;code>yum install kernel-devel-2.6.18-404.el5
/etc/init.d/vboxadd setup
mount -t vboxsf -o uid=`id -u devel`,gid=`id -g devel` work /work
&lt;/code>&lt;/pre></description></item><item><title>与LL患者的对话</title><link>https://liriansu.com/posts/2015-03-10-lovelive-story/</link><pubDate>Tue, 10 Mar 2015 19:43:00 +0000</pubDate><guid>https://liriansu.com/posts/2015-03-10-lovelive-story/</guid><description>&lt;h1 id="一">（一）&lt;/h1>
&lt;p>今天苍老师很开心地跑回了学校&lt;/p>
&lt;p>他说他要去当一个热情洋溢的游戏策划&lt;/p>
&lt;p>再也不用写代码了。&lt;/p>
&lt;h1 id="二">（二）&lt;/h1>
&lt;p>说到游戏，苍老师忧郁地说&lt;/p>
&lt;p>“我入了LL的坑”&lt;/p>
&lt;p>我立刻追问&lt;/p>
&lt;p>“你有没有想草船借舰啊poi”&lt;/p>
&lt;p>苍老师一脸荡笑&lt;/p>
&lt;p>“LL的坑已经足够大了nico”&lt;/p>
&lt;p>“哎，我已经肝了2K在国服了”&lt;/p>
&lt;h1 id="三">（三）&lt;/h1>
&lt;p>苍老师随即忧郁地说道&lt;/p>
&lt;p>我同情地说&lt;/p>
&lt;p>“没事，我玩秦时明月快一年也氪了1K”&lt;/p>
&lt;p>苍老师悲情地看着我&lt;/p>
&lt;p>“我1月入的坑”&lt;/p>
&lt;p>“没事我也是去年5月才入的坑”&lt;/p>
&lt;p>“我今年1月入的坑”&lt;/p>
&lt;h1 id="四">（四）&lt;/h1>
&lt;p>为了给我解释LL手游为什么魅力这么大&lt;/p>
&lt;p>苍老师拿出了Iphone4&lt;/p>
&lt;p>“日本人做游戏很精致的&lt;/p>
&lt;p>就算是N卡也有她自己的剧情…”&lt;/p>
&lt;p>苍老师盯着屏幕解说着&lt;/p>
&lt;p>我看着苍老师&lt;/p>
&lt;p>觉得有点理解为什么这么多人喜欢LL了&lt;/p>
&lt;h1 id="五">（五）&lt;/h1>
&lt;p>我又问苍老师&lt;/p>
&lt;p>“LL这游戏花时间吗？”&lt;/p>
&lt;p>苍老师想了下说道&lt;/p>
&lt;p>“我中午肝一次&lt;/p>
&lt;p>下午回家肝一次&lt;/p>
&lt;p>晚上十一点半再肝一次&lt;/p>
&lt;p>主要是我欲望比较强&lt;/p>
&lt;p>现在除了国服还肝日服”&lt;/p>
&lt;h1 id="六">（六）&lt;/h1>
&lt;p>我又问苍老师&lt;/p>
&lt;p>“那你还打算找妹子吗&amp;hellip;?”&lt;/p>
&lt;p>“找了妹子我就没时间陪老婆们了&amp;hellip;”&lt;/p>
&lt;p>苍老师回答道，我看着他&lt;/p>
&lt;p>他也自豪地看着我&lt;/p>
&lt;p>“我可是鸟厨！”&lt;/p>
&lt;blockquote>
&lt;p>（完）&lt;/p>
&lt;/blockquote></description></item><item><title>可能存在的婚姻恐惧</title><link>https://liriansu.com/posts/2015-02-28-marry-or-not/</link><pubDate>Sat, 28 Feb 2015 00:11:00 +0000</pubDate><guid>https://liriansu.com/posts/2015-02-28-marry-or-not/</guid><description>&lt;h1 id="一">（一）&lt;/h1>
&lt;p>每时每刻都有一百万个想法出生，但只有一个人能把它记下来 —— 福楼拜&lt;/p>
&lt;p>我不认识福楼拜 —— 高尔基&lt;/p>
&lt;p>搞你的基吧！ —— 加菲猫&lt;/p>
&lt;p>加菲好粗俗啊汪 —— 刚说完就被胖揍一顿的Odie&lt;/p>
&lt;p>写题记可以，但是不要偏题太远 —— 语文老师&lt;/p>
&lt;h1 id="二">（二）&lt;/h1>
&lt;p>说到婚姻问题，时间大概是一年前&lt;/p>
&lt;p>我爸和我进行了一场切磋&lt;/p>
&lt;p>他先让我一招：&lt;/p>
&lt;p>“儿子你有没有想过婚姻的问题啊?”&lt;/p>
&lt;p>我立刻用浑厚的内力打了一招亢龙无悔出去：&lt;/p>
&lt;p>“不以结婚为目标的恋爱都是耍流氓！”&lt;/p>
&lt;p>当高中级长的我爸见招拆招，一记庐山升龙霸：&lt;/p>
&lt;p>“那人在高中的时候能看得到这么远吗？”&lt;/p>
&lt;p>我赶忙绕开，刷了一招海底捞月：&lt;/p>
&lt;p>“我觉得只要两个人抱着真诚的心，那么结果是什么也是无所谓的”&lt;/p>
&lt;p>我爸老谋深算，使用了我段数不足用不出来的四十不惑…&lt;/p>
&lt;p>“我啊是见得多了，你这么小人生经验还不足……”&lt;/p>
&lt;p>正当我在思考要不要用“我玩过的电脑比你看过的电视多”来反击的时候&lt;/p>
&lt;p>我爸突然认真起来，使出了一招西方魔法里最厉害的除你武器：&lt;/p>
&lt;p>“其实啊，我觉得西方那一套挺科学的。两个人互相有好感就在一起了，天长地久某一天，突然因为观念不和，哇，和平分手了，也没什么。于是这样很多场恋爱下来，最终能在一起的夫妻，肯定就是命中真子/女…”&lt;/p>
&lt;p>我也是没想到一初恋就结婚甜蜜二十多年的我爸能说出这样的话&lt;/p>
&lt;p>当场只好甘拜下风&lt;/p>
&lt;h1 id="三">（三）&lt;/h1>
&lt;p>从小到大睡在床上都不太敢看着天花板&lt;/p>
&lt;p>假如一看就会觉得这个天花板为什么这么大啊&lt;/p>
&lt;p>我的人是这么的渺小&lt;/p>
&lt;p>因为实在是太弱小&lt;/p>
&lt;p>所以有些事情永远不会跟自己妥协&lt;/p>
&lt;p>我的人生也只有短短的一百多年&lt;/p>
&lt;p>我没有时间筛选与选择&lt;/p>
&lt;p>我只有时间等待与希望&lt;/p>
&lt;p>在小的时候（真的很小）也不知道谁规定的&lt;/p>
&lt;p>总是觉得以后说不定会单身一辈子呢&lt;/p>
&lt;p>于是认真地了解了在中国要怎么样才能领养小孩&lt;/p>
&lt;p>因为觉得不结婚是可行的，但是有两个问题还是很重要的&lt;/p>
&lt;p>一是性需求，二是养育小孩的问题&lt;/p>
&lt;p>毛主席说过自己动手丰衣足食，现在网络也发达&lt;/p>
&lt;p>第一个问题倒不是很关键&lt;/p>
&lt;p>想真正地养育小孩的愿望始终纠缠着我&lt;/p>
&lt;p>但是可惜未婚男子最早也只能四十岁以后领养小孩&lt;/p>
&lt;h1 id="四">（四）&lt;/h1>
&lt;p>最近的语文水平大概已经退步到跟蚂蝗在一个级别上了&lt;/p>
&lt;p>希望能准确表达自己的意思&lt;/p>
&lt;p>世界上的智慧都在这两个词里：等待与希望 —— 基督山伯爵&lt;/p>
&lt;p>一颗勇敢的心会自由地给予，自由地爱，直到受伤 —— 特雷莎修女&lt;/p>
&lt;blockquote>
&lt;p>（完）&lt;/p>
&lt;/blockquote></description></item><item><title>用Openpyxl做两个Excel文件的比对</title><link>https://liriansu.com/posts/2014-08-28-compare-excel-with-openpyxl/</link><pubDate>Thu, 28 Aug 2014 10:31:08 +0000</pubDate><guid>https://liriansu.com/posts/2014-08-28-compare-excel-with-openpyxl/</guid><description>&lt;h2 id="起因">起因&lt;/h2>
&lt;p>最近老是要做比对Excel报表的工作，于是想写一个Python的小脚本来做这个工作。&lt;br>
关于Python的Excel处理，以前只用过xlrd库，处理的是Office03的.xls文件。&lt;br>
这次写小工具的同时也是学习一下新的东西。&lt;/p>
&lt;h2 id="准备工作">准备工作&lt;/h2>
&lt;p>由于本次要比对的报表是Office07的.xlsx文件，上网查了一下Python怎么做比较合适。&lt;br>
看了几篇心得以后，敲定用Openpyxl（参考如下链接：）&lt;/p>
&lt;blockquote>
&lt;p>&lt;a href="https://www.gocalf.com/blog/python-read-write-excel.html">Python处理Excel的四个工具&lt;/a>&lt;/p>
&lt;/blockquote>
&lt;p>于是接下来是装Openpyxl，到官网上按照流程装了一发：&lt;/p>
&lt;blockquote>
&lt;p>&lt;a href="https://pythonhosted.org/openpyxl/">A Python Library: Openpyxl&lt;/a>&lt;/p>
&lt;/blockquote>
&lt;p>由于源码是到BitBucket上拖下来的，所以顺便还装了SourceTree。&lt;br>
据说SourceTree还有Git的相关功能，下次可以体验一下。&lt;/p>
&lt;h2 id="使用openpyxl">使用Openpyxl&lt;/h2>
&lt;p>Openpyxl装好以后直接import就能用啦：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">from&lt;/span> openpyxl &lt;span style="color:#f92672">import&lt;/span> &lt;span style="color:#f92672">*&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Openpyxl还提供了一个非常棒的教程~~（有点过于简单~~&lt;/p>
&lt;blockquote>
&lt;p>&lt;a href="https://pythonhosted.org/openpyxl/tutorial.html">Openpyxl Tutorial&lt;/a>&lt;/p>
&lt;/blockquote>
&lt;p>Openpyxl还有个弊端就是文档不怎么详细，只能去翻源码。&lt;/p>
&lt;h2 id="最终代码">最终代码&lt;/h2>
&lt;p>可以到我写的PythonScripts里找到我写的版本：&lt;/p>
&lt;p>&lt;a href="https://github.com/LKI/PythonScripts/tree/master/ExcelComparer">PythonScripts - ExcelComparer&lt;/a>&lt;/p></description></item><item><title>我的好友陈伟杰</title><link>https://liriansu.com/posts/2014-07-20-my-friend-edward/</link><pubDate>Sun, 20 Jul 2014 22:55:00 +0000</pubDate><guid>https://liriansu.com/posts/2014-07-20-my-friend-edward/</guid><description>&lt;h2 id="1">(1)&lt;/h2>
&lt;p>莫泊桑或者是福楼拜说过：&lt;br>
要写好描写性的文章，&lt;br>
你至少要写40个人。&lt;/p>
&lt;ul>
&lt;li>
&lt;p>综上所述，培根也说过：&lt;br>
知识就是力量，大家少吃培根。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>我并不想写好描述性的文章。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>我跟ED实在是太熟了，&lt;br>
不描写他一发简直心痒难耐。&lt;/p>
&lt;/li>
&lt;/ul>
&lt;h2 id="2">(2)&lt;/h2>
&lt;p>ED，中文的名字是陈伟杰，&lt;br>
英文名字是ED。&lt;/p>
&lt;p>跟别人介绍他的时候经常会是：&lt;/p>
&lt;ul>
&lt;li>
&lt;p>“这是ED。”&lt;/p>
&lt;/li>
&lt;li>
&lt;p>“诶！ED的意思难道是……？”&lt;/p>
&lt;/li>
&lt;li>
&lt;p>“不是的啦…只是名字简写…”&lt;/p>
&lt;/li>
&lt;/ul>
&lt;p>于是后来ED学会了一个新的词——蒟蒻。&lt;/p>
&lt;h2 id="3">(3)&lt;/h2>
&lt;p>我们口中的ED发音是&lt;code>'ed&lt;/code>。&lt;/p>
&lt;p>不过因为叫的多了，&lt;br>
所以“阿达”，“阿达娃”这种称呼也出来了。&lt;/p>
&lt;p>有一次一个学弟对着他的名字念了个&lt;code>,i:di:'wəd&lt;/code>&lt;/p>
&lt;p>于是ED就又多了一个“一滴喔的”这样奇怪的外号。&lt;/p>
&lt;h2 id="4">(4)&lt;/h2>
&lt;p>ED在大部分网站上的账号都是edward_mj。&lt;/p>
&lt;p>据他所说是因为edward这个名字实在是太常见了，&lt;br>
这样的账号都被抢注了。&lt;/p>
&lt;p>于是他只好加个mj的后缀，&lt;br>
意思是“马甲”。&lt;/p>
&lt;p>久而久之mj反而成了他的本体……&lt;/p>
&lt;p>现在浙大的同学都叫他“马甲”……&lt;/p>
&lt;h2 id="5">(5)&lt;/h2>
&lt;p>ED并不介意熟人怎么叫他。&lt;/p>
&lt;p>事实上对熟人在大部分事情上ED都相当随意。&lt;/p>
&lt;ul>
&lt;li>
&lt;p>某次我们annually跑到ED家附近去玩，&lt;br>
大家怂恿ED来BG一发，&lt;br>
ED就很鱼块地BG了一发。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>最近ED用自己的服务器搭了个能上Google的业务，&lt;br>
他也直接拿出来给大家用了。&lt;/p>
&lt;/li>
&lt;/ul>
&lt;h2 id="6">(6)&lt;/h2>
&lt;p>但是ED在生人面前看起来非常地羞涩&amp;amp;正经。&lt;/p>
&lt;p>由于混熟了以后大家对于ED感觉反差太大了，&lt;br>
于是ED获得了很多好友的一致评价：“（闷）骚”。&lt;/p>
&lt;p>至今还有很多人叫ED“骚杰”&lt;/p>
&lt;p>ED觉得非常蛋疼，&lt;br>
问我：“你说为什么会这样子捏”&lt;/p>
&lt;p>我想了想，&lt;br>
说：&lt;br>
“可能是因为你真的很（闷）骚吧。”&lt;/p>
&lt;p>其实骚也没什么，&lt;br>
屈原也骚。&lt;/p>
&lt;h2 id="7">(7)&lt;/h2>
&lt;p>初中的时候我在1班，&lt;br>
ED在2班，&lt;br>
本来理论上不会太熟，&lt;br>
但是我们在信息竞赛（OI）班里是同桌。&lt;/p>
&lt;p>初中的OI其实就是大浪淘沙，&lt;br>
由于很多假期都要留校，&lt;br>
实在是太寂寞了，&lt;br>
于是很多对此没多大兴趣的人都弃坑了。&lt;/p>
&lt;p>所以初一还有五、六十人参加的竞赛班，&lt;br>
到了初二就只剩我、ED、Li、LuLu、何升雨和孙艳梅了。&lt;/p>
&lt;p>人比较少，&lt;br>
我们每个人就有了自己固定的座位，&lt;br>
我就跟ED成了同桌。&lt;/p>
&lt;p>从初二到高三，&lt;br>
一直同桌了五年。&lt;/p>
&lt;h2 id="8">(8)&lt;/h2>
&lt;p>后来跟冯可聊天的时候，&lt;br>
她还很惊奇地跟我说：&lt;br>
“你也跟陈伟杰同桌呀。”&lt;/p>
&lt;p>冯可是ED小学时候的同桌，&lt;br>
她觉得“ED实在是太受了，&lt;br>
谁都能欺负他“&lt;/p>
&lt;p>这句话说的太对了。&lt;/p>
&lt;p>ED高一的时候坐在大灰和烨哥的中间，&lt;br>
那阵子他们两最大的爱好就是戳ED。&lt;/p>
&lt;p>ED又怕痒，&lt;br>
每次被戳都会像保卫萝卜里的萝卜一样抖动……&lt;/p>
&lt;p>于是大灰和烨哥就更喜欢戳ED了。&lt;/p>
&lt;h2 id="9">(9)&lt;/h2>
&lt;p>认识ED以后跟他聊天，&lt;br>
他说了一件初一的时候特别好玩的事情。&lt;/p>
&lt;p>当时我的一班和ED的二班，&lt;br>
语文老师是同一个人，&lt;br>
大学刚毕业的热血青年。&lt;/p>
&lt;p>有次晚上寝室卧谈，&lt;br>
ED他们寝室玩打电话的恶作剧游戏。&lt;/p>
&lt;p>有个同学就播了语文老师的电话：&lt;br>
“您好，&lt;br>
这里是红袖午夜情感电台。&lt;br>
情感故事请按1，&lt;br>
美眉聊天请按2……”&lt;/p>
&lt;p>然后（开着外放），&lt;br>
电话对面沉默了许久，&lt;br>
传来了一声“嘟”的按键声……&lt;/p>
&lt;p>他们一寝室强忍着笑，&lt;br>
问：&lt;/p>
&lt;p>“请问你按的是1还是2啊？……”&lt;/p>
&lt;p>……&lt;/p>
&lt;h2 id="10">(10)&lt;/h2>
&lt;p>假期的时候在寝室的只有学奥赛的几个同学，&lt;br>
于是我、ED还有Bill三个人就睡在同一个寝室。&lt;/p>
&lt;p>当时ED有个翻盖的手机，&lt;br>
这手机侧面有个非常酷炫的功能键，&lt;br>
按一下就能兹兹地自动翻盖。&lt;/p>
&lt;p>我和Bill都非常喜欢玩这个按钮，&lt;br>
于是没有两天这个键就被我们玩坏了……&lt;br>
不灵了……&lt;/p>
&lt;p>我们三个人都感到了蛋疼……&lt;/p>
&lt;h2 id="11">(11)&lt;/h2>
&lt;p>ED很多时候会灵光一闪地表现出无以匹敌的2B气质…&lt;/p>
&lt;p>有次假期留校，&lt;br>
早上起来我们在阳台刷牙。&lt;/p>
&lt;p>ED刷着刷着，&lt;br>
突然感慨了一句：&lt;br>
“其实，我觉得我大腿还是比较粗壮的！”&lt;/p>
&lt;p>我愣了一下，&lt;br>
然后笑疯了……&lt;/p>
&lt;p>哈哈哈哈哈哈哈至今想起来还是想笑…&lt;br>
太逗B了……&lt;/p>
&lt;h2 id="12">(12)&lt;/h2>
&lt;p>其实ED很瘦，看起来跟竹竿似的。&lt;/p>
&lt;p>而且ED比平均身高都高&lt;br>
（就是在班里坐最后一排的水平&lt;/p>
&lt;p>几年前有次坐在我爸车上，&lt;br>
在跟我爸随便聊天，&lt;br>
我爸突然说：&lt;br>
“最近不是流行一个词‘高富帅’么，&lt;br>
很多人都被称为‘高富帅’，&lt;br>
我看啊，&lt;br>
陈伟杰才算是‘高富帅’…”&lt;/p>
&lt;p>不得不说我顿时膜拜起了我爸的博学，&lt;br>
和我刚学会的侧面描写……&lt;/p>
&lt;h2 id="13">(13)&lt;/h2>
&lt;p>ED家住在市中心，&lt;br>
我们有一个玩的非常好的朋友圈，&lt;br>
所以基本上每个假期我都会跑到他家住几天，&lt;br>
跟他在市里疯玩一圈。&lt;/p>
&lt;p>ED爸妈在生活上对ED非常好，&lt;br>
就算是晚饭我们在外面吃完回来，&lt;br>
晚上在房间里聊天上网，&lt;br>
他麻麻也会端碗切好的水果给他。&lt;/p>
&lt;p>ED家还养了只狗，&lt;br>
ED说这只狗智商很高。&lt;/p>
&lt;p>不过我看到的都是一只2B doge：&lt;/p>
&lt;p>地板拖得太干净太滑，&lt;br>
这狗爪子也干净，&lt;br>
所以只要一见到人，&lt;br>
它就会很开心地滑倒在地板上……&lt;/p>
&lt;h2 id="14">(14)&lt;/h2>
&lt;p>到了大学ED参加了ACM&lt;br>
(Association for Computing Machinery-International Collegiate Programming Contest)&lt;br>
（简单的来说就是世界大学生信息竞赛）&lt;/p>
&lt;p>大二大三带领着浙大从中国打到俄罗斯总决赛，&lt;br>
打了两届Final。&lt;/p>
&lt;p>做个比喻，&lt;br>
就像是2018世界杯，&lt;br>
ED带领浙大足球队冲出中国走向俄罗斯……&lt;br>
（这个比喻太奇怪了啦&lt;/p>
&lt;p>问ED在俄罗斯比赛之外有什么感想，&lt;br>
ED说：&lt;/p>
&lt;ul>
&lt;li>
&lt;p>美眉太多了！&lt;/p>
&lt;/li>
&lt;li>
&lt;p>俄罗斯的人为什么不学英语！&lt;/p>
&lt;/li>
&lt;li>
&lt;p>国外的WIFI真难上！&lt;/p>
&lt;/li>
&lt;/ul>
&lt;h2 id="15">(15)&lt;/h2>
&lt;p>长时间的逻辑训练让ED思路异常清晰。&lt;/p>
&lt;p>所以ED可以在任何情况下清楚地知道自己想要什么，&lt;br>
不想要什么。&lt;/p>
&lt;p>所以ED了解自己以后应该怎么发展，&lt;br>
哪些人可以帮到自己，&lt;br>
怎么做可以解决问题。&lt;/p>
&lt;p>所以ED没有女朋友……&lt;/p>
&lt;h2 id="16">(16)&lt;/h2>
&lt;p>这点ED也非常忧伤：&lt;/p>
&lt;ul>
&lt;li>
&lt;p>ED：我这个人也不差，&lt;br>
为什么没有女朋友呢？&lt;/p>
&lt;/li>
&lt;li>
&lt;p>我：可能你太2B了…&lt;/p>
&lt;/li>
&lt;li>
&lt;p>ED：我也是很有威♂严的！…&lt;/p>
&lt;/li>
&lt;li>
&lt;p>我：那可能你太羞涩了…&lt;/p>
&lt;/li>
&lt;li>
&lt;p>ED：熟了以后我什么都敢做！…&lt;/p>
&lt;/li>
&lt;li>
&lt;p>我只能说：那你蛋疼…！&lt;/p>
&lt;/li>
&lt;li>
&lt;p>ED：……&lt;/p>
&lt;/li>
&lt;li>
&lt;p>ED：好吧…我蛋疼……&lt;/p>
&lt;/li>
&lt;/ul>
&lt;h2 id="17">(17)&lt;/h2>
&lt;p>俗话说物以类聚，&lt;br>
ED跟我在很多频率上非常一致。&lt;/p>
&lt;p>这次ED来上海，&lt;br>
他神秘兮兮地问我：&lt;br>
“B站上那个&lt;br>
《老夫从来没见过这么漂亮的妹子》视频你看过没？”&lt;/p>
&lt;p>我：“哈？那是啥视频啊…”&lt;/p>
&lt;p>于是ED翻出来给我看，&lt;br>
我听了两秒钟：&lt;br>
“这不是马来西亚的四叶草么！”&lt;br>
（https://www.acfun.cn/v/ac1195212）&lt;/p>
&lt;p>简直一拍即合。&lt;/p>
&lt;h2 id="18">(18)&lt;/h2>
&lt;p>ED最近把微信头像改成了钢炼里的EDWARD，&lt;br>
ED说他们不仅名字一样，&lt;br>
都有弟弟，&lt;br>
而且这个动画也挺好看的。&lt;/p>
&lt;p>ED以前的头像是阿狸，&lt;br>
他特别喜欢这只胖狐狸。&lt;/p>
&lt;p>于是那阵子他壁纸、表情、头像全是阿狸。&lt;/p>
&lt;p>后来ED喜欢散华礼弥。&lt;/p>
&lt;p>于是他把个人主页的封面图都改成了散华礼弥。&lt;br>
（https://edward-mj.com）&lt;/p>
&lt;p>理工男喜欢一个东西就是这么一根筋。&lt;/p>
&lt;h2 id="19">(19)&lt;/h2>
&lt;p>三年前，ED去浙大之前我跟他说：&lt;/p>
&lt;p>“你到时候找到女朋友了一定跟我说，&lt;br>
我假期一定让你带她回来，&lt;br>
我肯定不会跑到你房里去玩了 ;-)”&lt;/p>
&lt;p>三年以后，ED非常忧虑地跟我说：&lt;/p>
&lt;p>“我觉得某种意义上浙大和交大是一样的…”&lt;/p>
&lt;p>我安慰ED：&lt;/p>
&lt;p>“没事的。你看你们学长2009，&lt;br>
他不也没有女朋友么，&lt;br>
他比你更悲剧呢。”&lt;/p>
&lt;p>顺带科普了一发2009与九阴真经的梗给ED……&lt;/p>
&lt;h2 id="20">(20)&lt;/h2>
&lt;p>中学的时候我就想，&lt;br>
ED应该就是我最好的朋友了。&lt;/p>
&lt;p>于是我和ED从来没有说过“多联系”这样的话。&lt;/p>
&lt;p>任何时候，&lt;br>
只要有什么好玩的事情，&lt;br>
郁闷的事情，&lt;br>
我都直接一句：&lt;/p>
&lt;p>“ED”&lt;/p>
&lt;p>戳开了聊天窗口。&lt;/p>
&lt;p>这就是我的好友，&lt;br>
陈伟杰。&lt;/p></description></item><item><title>0x5f3759df 一个神奇的数字</title><link>https://liriansu.com/posts/2014-03-07-magic-number/</link><pubDate>Fri, 07 Mar 2014 14:11:31 +0000</pubDate><guid>https://liriansu.com/posts/2014-03-07-magic-number/</guid><description>&lt;p>今天在看各种算法介绍的时候看到了这么一句话“神奇数字0x5f3759df并不是约翰·卡马克发明的。之所以一开始被误解，主要是许多对卡神光环膜拜已久的游戏程序员在读Quake3源码时吓尿了……”一下子引起了我的好奇心，在查阅了一些资料以后整理整个故事如下。&lt;/p>
&lt;h2 id="雷神之锤3">雷神之锤3&lt;/h2>
&lt;p>雷神之锤3（Quake3）是90年代的经典FPS游戏，不仅画面精美，而且整个程序优化得很好，在配置一般的电脑上也能流畅地运行。这主要归功于其3D引擎id Tech3，而此引擎是由约翰·卡马克（John Carmack）领导开发的。&lt;/p>
&lt;p>卡马克是一个美国码农，id Software的创始人之一，他因在3D技术上的杰出成就而文明。卡马克还是一个开源软件的倡导者，1996年他放出了雷神之锤的源代码，而一个程序员将其改写成了Linux的版本并发给了卡马克。卡马克没有认为这是侵权，反而是要求他的员工们以这个补丁为基础开发雷神之锤的Linux版本。后来的日子id Software也一样公布了雷神之锤2的源代码，在2005年，雷神之锤3的源代码也被放出来了。&lt;/p>
&lt;p>（这是官方下载地址ftp://ftp.idsoftware.com/idstuff/source/quake3-1.32b-source.zip）&lt;/p>
&lt;p>我们知道，越底层的函数调用越频繁，假如把底层函数优化做好了，效率自然就上去了，3D引擎归根到底还是数学运算。在最底层的运算函数中（game/code/q_math.c中），有许多有趣的函数，有些更是令人惊叹这究竟是如何编写的。&lt;/p>
&lt;h2 id="神奇的0x5f3759df">神奇的0x5f3759df&lt;/h2>
&lt;p>在运算函数文件中可以找到这么一个函数，它的作用是将一个数开方并取倒数，功能上跟系统函数(float)(1.0/sqrt(x))一样，但是效率上快了四倍：&lt;/p>
&lt;pre tabindex="0">&lt;code>float Q_rsqrt( float number )
{
long i;
float x2, y;
const float threehalfs = 1.5F;
x2 = number * 0.5F;
y = number;
i = * ( long * ) &amp;amp;y; // evil floating point bit level hacking
i = 0x5f3759df - ( i &amp;gt;&amp;gt; 1 ); // WHAT THE FUCK?
y = * ( float * ) &amp;amp;i;
y = y * ( threehalfs - ( x2 * y * y ) ); // 1st iteration
// y = y * ( threehalfs - ( x2 * y * y ) ); // 2nd iteration, this can be removed
#ifndef Q3_VM
#ifdef __linux__
assert( !isnan(y) ); // bk010122 - FPE?
#endif
#endif
return y;
}
&lt;/code>&lt;/pre>&lt;p>这个函数最核心，最令人费解的就是标注了“WHAT THE FUCK”的那一句&lt;/p>
&lt;p>&lt;code>i = 0x5f3759df - ( i &amp;gt;&amp;gt; 1 );&lt;/code>&lt;/p>
&lt;p>再加上一句&lt;code>y = y * ( threehalfs - ( x2 * y * y ) );&lt;/code>就完成了求开方的运算。&lt;/p>
&lt;p>一般的求开方采用的都是牛顿迭代法，比如求sqrt(5)，那么先令A = 2然后B = 5 / A; A = (A + B) / 2;这样循环下去，A和B将会越来越接近，最终的结果就是根号五了。而卡马克给出的这个算法的牛逼之处在于它直接用了0x5f3759df一个数猜测了一个值，通过一次计算就很接近根号N的值了。这样省下了许多次迭代逼近的过程，那么函数效率则也就大大被优化了。&lt;/p>
&lt;p>普渡大学的数学家Chris Lomont了解到了这个数字以后很感兴趣，他打算研究一下这个数字的奥秘。这个Lomont也是一个牛人，精心研究以后他从理论上推导出了一个最佳猜测值：0x5f37642f，跟程序中的0x5f3759df十分接近。Lomont得出这个结果以后很满意，他拿自己这个数跟卡马克的神奇数字做速度比赛，结果卡马克赢了……谁也不知道卡马克是怎么求出这个数的……&lt;/p>
&lt;p>自己精心推导出的理论最佳值居然输给了卡马克，Lomont也是很不甘心，他用类似穷举的方法一个个地试过来，终于被他找到一个比卡马克的0x5f3759df要好一丁点的数字：0x5f375a86。于是Lomont很高兴地把这个结果写成了论文公之于世……（论文地址：https://www.matrix67.com/data/InvSqrt.pdf）&lt;/p>
&lt;p>这个算法也有了自己的名字：平方根倒数速算算法（Fast Inverse Square Root）&lt;/p>
&lt;h2 id="算法的发明者">算法的发明者&lt;/h2>
&lt;p>因为约翰·卡马克是整个雷神之锤项目的开发者，所以起初很多人也就简单的认为神奇数字0x5f3759df是卡马克的杰作。但是后来卡马克本人在回复问询邮件的时候否定了这个观点，卡马克回忆可能是雷神之锤项目的一个资深码农Terje Mathisen写下了这段代码。而Mathisen回复邮件则表示他以前的确写过类似的代码，但他并不是先行者。现在了解到最早的实现是Gary Tarilli在SGI Indigo中实现的，但他也表示他只是对常数进行了一些改进，实际上他也不是作者。&lt;/p>
&lt;p>虽然并没有定论表示整个算法究竟是谁发明的，但是大家还是津津乐道于卡马克、和他的神奇数字0x5f3759df。&lt;/p>
&lt;blockquote>
&lt;p>参考资料：&lt;br>
&lt;a href="https://www.guokr.com/post/90718/">https://www.guokr.com/post/90718/&lt;/a>&lt;br>
&lt;a href="https://www.matrix67.com/data/InvSqrt.pdf">https://www.matrix67.com/data/InvSqrt.pdf&lt;/a>&lt;br>
&lt;a href="https://www.matrix67.com/blog/archives/362">https://www.matrix67.com/blog/archives/362&lt;/a>&lt;br>
&lt;a href="https://en.wikipedia.org/wiki/Fast_inverse_square_root">https://en.wikipedia.org/wiki/Fast_inverse_square_root&lt;/a>&lt;br>
&lt;a href="https://en.wikipedia.org/wiki/John_Carmack">https://en.wikipedia.org/wiki/John_Carmack&lt;/a>&lt;br>
&lt;a href="https://zh.wikipedia.org/wiki/%E5%B9%B3%E6%96%B9%E6%A0%B9%E5%80%92%E6%95%B0%E9%80%9F%E7%AE%97%E6%B3%95">https://zh.wikipedia.org/wiki/%E5%B9%B3%E6%96%B9%E6%A0%B9%E5%80%92%E6%95%B0%E9%80%9F%E7%AE%97%E6%B3%95&lt;/a>&lt;/p>
&lt;/blockquote></description></item><item><title>妈的，交大</title><link>https://liriansu.com/posts/2013-1-11-i-love-sjtu/</link><pubDate>Fri, 11 Jan 2013 19:57:00 +0000</pubDate><guid>https://liriansu.com/posts/2013-1-11-i-love-sjtu/</guid><description>&lt;h1 id="一">（一）&lt;/h1>
&lt;p>前几天，浴室&lt;/p>
&lt;p>又听到旁边的基友众在讨论游戏&lt;/p>
&lt;p>大学男生嘛，自然就“他妈的关羽居然没杀”&lt;/p>
&lt;p>“宙斯出什么JBBKB啊”&lt;/p>
&lt;p>再前几天，旧行政楼户籍科&lt;/p>
&lt;p>安静的窗口前只有大四学长在咨询关于转户口的事情&lt;/p>
&lt;p>这让只是来询问身份证掉了怎么办的我有点恍惚&lt;/p>
&lt;p>终究有一天我们也会来户籍科的。&lt;/p>
&lt;h1 id="二">（二）&lt;/h1>
&lt;p>我爸说，来交大的人大部分都憋着一口气&lt;/p>
&lt;p>他们差那么一点就能去北京。&lt;/p>
&lt;p>我只知道很多人一开始并不喜欢交大&lt;/p>
&lt;p>甚至会讨厌交大晚上断网&lt;/p>
&lt;p>不过正如小王子所说的&lt;/p>
&lt;p>让沙漠变得美丽的，是他在不知道什么地方藏好的一片绿洲。&lt;/p>
&lt;p>交大的很多细节渐渐地让新生们迷恋上了&lt;/p>
&lt;p>二餐卖炒饭的阿姨最后总会送点什么东西给你&lt;/p>
&lt;p>你甚至可以直接从HL外卖哥那里买外卖&lt;/p>
&lt;p>交大的猫特别亲女生&lt;/p>
&lt;p>某月某日桂花就像计划好的一样突然都冒出来了。&lt;/p>
&lt;p>骂着“妈的浴室真TM远”然后哼哧哼哧地抱个盆子和室友去洗澡&lt;/p>
&lt;p>说着“妈的高数真TM烦”然后因为老师一句真性情的话大笑起来&lt;/p>
&lt;p>想着“妈的无论是谁都好请和我交往吧”然后觉得在交大单身其实也没什么&lt;/p>
&lt;p>反正以后都“要嫁就嫁交大男”的嘛，虚什么。&lt;/p>
&lt;h1 id="三">（三）&lt;/h1>
&lt;p>有两句话以前很流行，&lt;/p>
&lt;p>一句是“在网路上，没人知道你是一条狗”&lt;/p>
&lt;p>另外一句是“家乡就是那个你已经说了一千句不是但是你不允许别人说一句不是的地方”&lt;/p>
&lt;p>第一句话和本文没太大关系，只是用来说明以前是有多以前而已。&lt;/p>
&lt;p>交大的一天除了学术、生活、还有数千句的“妈的”“卧槽”。&lt;/p>
&lt;p>但是就是这个让你每天说妈的的学校，在你离开之后&lt;/p>
&lt;p>就会变成你的Mother School。&lt;/p>
&lt;p>数年后，说着“妈的想当初五月份的时候交大里都是石楠花的味道”&lt;/p>
&lt;p>但是说妈的的心情已经变成了想Mother的心情&lt;/p>
&lt;h1 id="四">（四）&lt;/h1>
&lt;p>只有呼吸困难的人才明白他在呼吸&lt;/p>
&lt;p>在我还没有沦落到一谈当年满腹回忆的时候&lt;/p>
&lt;p>我还是要说声，妈的，交大&lt;/p>
&lt;blockquote>
&lt;p>（完）&lt;/p>
&lt;/blockquote></description></item><item><title>想写一个小故事，姑且写之</title><link>https://liriansu.com/posts/2012-06-15-always-be-yourself/</link><pubDate>Fri, 15 Jun 2012 12:52:30 +0800</pubDate><guid>https://liriansu.com/posts/2012-06-15-always-be-yourself/</guid><description>&lt;p>很久很久以前，在一家糖果店里，有一个很美丽的米色糖果。&lt;/p>
&lt;p>她还小的时候不懂事，她爸妈都很爱她，她的糖衣最甜最美，她蹦蹦跳跳地独自走向橱窗。&lt;/p>
&lt;p>她遇见了红色糖果绿色糖果还有一颗黑色糖果。&lt;/p>
&lt;p>红色糖果说你不应该是米色你的糖衣应该是更好看的颜色。&lt;/p>
&lt;p>绿色糖果说你的米色很好看啊我喜欢然后靠近米色糖果偷偷地把自己的颜色蹭上去。&lt;/p>
&lt;p>黑色糖果说你的米色很好看你应该做你自己。&lt;/p>
&lt;p>红色糖果有很多绿色糖果有很多黑色糖果只有一个。&lt;/p>
&lt;p>米色糖果不知道听谁的，而且这种事情只能自己做决定。&lt;/p>
&lt;p>米色糖果决定遗忘自己的颜色和大家都当好朋友。&lt;/p>
&lt;p>这个故事没有结尾因为作者已经找不到米色糖果了。&lt;/p>
&lt;p>只有黑色糖果很悲伤。&lt;/p></description></item><item><title>昨天与朋友关于弹幕网站的聊天与感想</title><link>https://liriansu.com/posts/2012-05-16-a-chat-about-acfun/</link><pubDate>Wed, 16 May 2012 12:48:16 +0800</pubDate><guid>https://liriansu.com/posts/2012-05-16-a-chat-about-acfun/</guid><description>&lt;p>　　言语不清请各位谅解。正文从第八段开始。&lt;/p>
&lt;blockquote>
&lt;p>BGM请戳这里：&lt;a href="https://www.acfun.cn/v/ac294951">AC娘的重生&lt;/a>&lt;/p>
&lt;/blockquote>
&lt;p>昨天晚上九点多网管部的同学BG①，于是没吃晚饭提前洗了澡去吃烧烤。大概有二十多人到场，然后例行的吃东西聊天玩游戏②。&lt;/p>
&lt;p>聊天聊着聊着一个同事MM③就在起哄要我唱歌④，机油们也跟着起哄。&lt;/p>
&lt;p>众人起哄中HJ⑤问起为什么要叫我唱歌，她得到这样的回答：“浮云⑥唱歌很好听的呢！”“都发到网上去了！”“很多弹幕哦！”&lt;/p>
&lt;p>HJ显得很激动：“你发到哪个弹幕网站上呀？”&lt;/p>
&lt;p>我还没有回答，旁人已经帮我回答了：“ACFUN！”&lt;/p>
&lt;p>HJ便一脸“我懂了”的表情，看着我笑道：“AVFUN啊~”&lt;/p>
&lt;p>我也笑着问她：“你上AC么？”&lt;/p>
&lt;p>HJ（笑）⑦：“我是混B站的。”&lt;/p>
&lt;p>我：“恩，B站也是很好的弹幕网站哦。”&lt;/p>
&lt;p>此后又聊了一圈别的话题，然后穿插着我唱了几首歌⑧，玩了一阵子游戏，又聊到了弹幕网站的话题。&lt;/p>
&lt;p>HJ（跟之前提到的同事MM说）：“回去把视频地址发我。”&lt;/p>
&lt;p>同事MM：“他的视频弹幕可是有很多的！”&lt;/p>
&lt;p>我（弱）：“没有啦，这个有上限的…”&lt;/p>
&lt;p>HJ（高兴）：“浮云我跟你说，我很喜欢B站的原因是因为这个弹幕太好玩了！”&lt;/p>
&lt;p>我：“是呀！”&lt;/p>
&lt;p>HJ（认真且自豪）：“我最近在B站上看冰与火之歌，那个剧透看的好爽！什么‘前方高能反映’的。”&lt;/p>
&lt;p>我：“……⑨”&lt;/p>
&lt;p>我（嘀咕）：“又黑我大小学生！”&lt;br>
机油（暗暗窃笑）：“哈哈……”&lt;/p>
&lt;p>HJ（继续说）：“而且弹幕很多时候会有神吐槽的！”&lt;/p>
&lt;p>我（赞同）：“对对对，这个有。”&lt;/p>
&lt;p>HJ（举例状）：“比如‘这不科学’啦，‘打开的方式不对’啦……”&lt;/p>
&lt;p>我（囧）：“这些比较流于大众化啦，神吐槽其实指那些对很有特色的剧情而特别的吐槽……”&lt;/p>
&lt;p>HJ（听我说完以后）：“其实是‘打开的方式不对’还是‘打开的姿势不对’呢？”&lt;/p>
&lt;p>我（科学地）：“两个都可以。”&lt;/p>
&lt;p>HJ（说着说着捂嘴笑）：“当时我们为了这个争论很久，然后争着争着就把喵叔⑩打开了…”&lt;/p>
&lt;p>然后又是一阵没有边界欢乐的聊天。&lt;/p>
&lt;p>HJ：“诶，B站的叫‘up主’，A站的叫什么？”&lt;/p>
&lt;p>我①①：“A站的也叫up主啦。”&lt;/p>
&lt;p>HJ（好奇）：“其实A站和B站是什么关系呢？”&lt;/p>
&lt;p>我（想了下）：“这么说吧，弹幕网站最开始是日本的niconico。ACFUN可以说是大陆的首家有影响力的弹幕网站，后来鸟大了总会有林子的，于是ACFUN的环境有一段时间不是很好。于是有一个原来在ACFUN的动漫爱好者叫九碧时去创立了一家网站，就是现在的bilibili啦。”&lt;/p>
&lt;p>HJ（发问式的言语）：“我觉得A站很多喷子…”&lt;/p>
&lt;p>我：“怎么说呢，唔……宽泛的来讲，B站的动漫氛围要比A站好，A站的话，有很多ZZ，JS论坛的同学会来逛。B站对言论管制的比较厉害，发不太和谐的评论和弹幕很容易被封，A站相对比较宽松，所以整天可以看到喷子出没啦。其实我觉得喷子还是挺萌的，比如说弹幕网站上的这两种人：一种是我这样的，看到喜欢的内容会哈哈哈哈的笑，这时候我大部分时间都不会发弹幕‘我太喜欢这一段了’；而喷子们一般都把手放到键盘上，一看到自己不喜欢的内容就幽怨地发一句：‘这段好烂哦’‘我不喜欢这段’‘这种也发上来？’。其实理解了他们还是觉得他们好萌的！”①②&lt;/p>
&lt;p>这段后话题又转向了别的地方而且没有转回来了。&lt;/p>
&lt;blockquote>
&lt;p>以下为个人感想可以跳过，分割线后为注释。&lt;/p>
&lt;/blockquote>
&lt;p>我们不能认为自己就是正确，世界/时辰/AC就是错误的。我希望AC永远是小众网站，但是我也希望我的朋友能理解AC，爱AC娘。AC里，有人只去文章区，也有动漫宅，也有我这种鬼畜音MAD爱好者，还有音乐爱好者以及更多没被提到的人。AC娘每天都要接待各种各样的人哦！&lt;/p>
&lt;p>我内心是认为网络应该是向二次元世界一样美好的。个人而言，我从来不会把什么负面激动的情绪暴露在很多人眼中①③。我想说给别人的、影响别人的都是我觉得是很正面的情绪，比如“开心”，“笑话”，“愉快”，“温暖”。虽然我也很赞同那些阐述黑暗事实而宣扬自己心中的真理的人，但是我始终认为每个人的世界观要被言论改变是一定要有事实支撑的，我们如此红脸争执①④，为何不如一笑而欣赏生活中那些美？&lt;/p>
&lt;p>我喜欢AC娘，喜欢她越来越美，越来越好看！&lt;/p>
&lt;p>最后，祝你们身体健康，再见！&lt;/p>
&lt;hr>
&lt;p>①BG，论坛用语，主要意为“请客吃饭”。&lt;/p>
&lt;p>②从我少得可怜的经验来说，聚会玩的游戏以惩罚游戏为主，什么猜数字啦，接龙之类的，基本上都是输了然后羞耻play什么的…当然昨天也学到了一个名叫“几匹马”的游戏…&lt;/p>
&lt;p>③MM，论坛用语，释为“妹妹”or“美眉”，已经是脱离时代的叫法了。现代叫法应该叫“妹子”，不过个人不喜欢这个称呼。&lt;/p>
&lt;p>④杀破狼什么的，被机油发现然后发到了群里去了。于是三次元有一些人知道以后，称“哇原来还以为你是一个挺安静内敛的人……”&lt;/p>
&lt;p>⑤HJ，网管部的前辈学姐，人称虹姐，为了便于记事以下称HJ。&lt;/p>
&lt;p>⑥浮云即楼主，此处真名替换，以下不释。&lt;/p>
&lt;p>⑦本人不能完全再现当时场面，括号中为表情为今天的回忆，一群人吃饭气氛还是很欢乐的，所以大部分时候都是笑着，下文就不给特写了。&lt;/p>
&lt;p>⑧在别人面前还是不敢用狗耳模式唱歌，只能好好唱。&lt;/p>
&lt;p>⑨当时其实心里很认真的在思考HJ这是开玩笑的呢还是开玩笑的呢，不过HJ认真的表情以及后来的话语、行为都表示她说的其实是实话。&lt;/p>
&lt;p>⑩喵叔，网管部同事，属于有知识且温顺的那种人。&lt;/p>
&lt;p>①①其实HJ应该是那种天真可爱的弹幕网站受众，说不定他们就是弹幕网站流量的最大贡献者。&lt;/p>
&lt;p>①②当时这段话好几个地方好像HJ都有话说…但是我实在是忍不住于是一口气说完了，没给HJ插嘴的机会。现在回忆起来这么做应该不太对。&lt;/p>
&lt;p>①③当然也有和二次元好友聊天倾诉苦逼生活的情况……&lt;/p>
&lt;p>①④此处想到一个笑话：&lt;br>
有一天动物们在关公庙前面闻到很臭的味道。&lt;br>
蛇说：「我这么小不会放这么臭的屁，一定是牛。」&lt;br>
牛说：「我是吃草的不会放这么臭的屁。」&lt;br>
猪说：「放屁的人一定会脸红。」忽然关公冲了出来，把猪打飞说：「说了多少次了，我脸红是天生的。」&lt;/p>
&lt;blockquote>
&lt;p>（完）&lt;/p>
&lt;/blockquote></description></item><item><title>杰克之死</title><link>https://liriansu.com/posts/2010-05-27-death-of-jack/</link><pubDate>Thu, 27 May 2010 12:00:00 +0800</pubDate><guid>https://liriansu.com/posts/2010-05-27-death-of-jack/</guid><description>&lt;p>“杰克死了。”&lt;/p>
&lt;p>“真的？不可思议！”&lt;/p>
&lt;p>“太可惜了，我一向看好他的。”&lt;/p>
&lt;p>“活该。”&lt;/p>
&lt;p>“死了他一个，还有后来人。”&lt;/p>
&lt;p>“杰克是谁？”&lt;/p>
&lt;p>“一个人总是这样，死了比活着更出名。”&lt;/p>
&lt;p>“听说奥巴马表达了哀思。”&lt;/p>
&lt;p>“可以放假吗？”&lt;/p>
&lt;p>“别管他，反正迟早要死的。”&lt;/p>
&lt;p>“前几天我还见过他呢。”&lt;/p>
&lt;p>“这可以拍成电影…”&lt;/p>
&lt;p>“我终于可以放心地出去逛街了。”&lt;/p>
&lt;p>“怎么现在到处都在讨论他？”&lt;/p>
&lt;p>“杰克已然成为了一种现象。”&lt;/p>
&lt;p>“我是他高中老师，我有话说…”&lt;/p>
&lt;p>“请问他…他…”&lt;/p>
&lt;p>“他乐于助人，挺好的…”&lt;/p>
&lt;p>“浮躁的风气始终困扰着中国。”&lt;/p>
&lt;p>“杰克死的好。”&lt;/p>
&lt;p>“她死了就死了，值得讨论吗？”&lt;/p>
&lt;p>“我觉得他不应该死…”&lt;/p>
&lt;p>“我反对，他应该死。”&lt;/p>
&lt;p>“Jack?Who do you mean?”&lt;/p>
&lt;p>“《泰晤士报》报道…”&lt;/p>
&lt;p>“这是一场精心准备的操作。”&lt;/p>
&lt;p>“昨晚他给我托梦了。”&lt;/p>
&lt;p>“其实他脚踏两条船被发现了。”&lt;/p>
&lt;p>“他的死是个迷。”&lt;/p>
&lt;p>“对比悲哀的杰克，讨论的人们更悲哀。”&lt;/p>
&lt;p>“捷克是成千上万死人中平凡而又特殊的一个。”&lt;/p>
&lt;p>“我活着…”&lt;/p>
&lt;p>“最近有人打着杰克的旗号行骗…”&lt;/p>
&lt;p>“他曾经喜欢过我，我觉得，他不配。”&lt;/p>
&lt;p>“只有聪明人才能看到杰克现象的本质。”&lt;/p>
&lt;p>“杰克不是现象…”&lt;/p></description></item><item><title>关于我</title><link>https://liriansu.com/about/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://liriansu.com/about/</guid><description>&lt;p>朋友，你好呀。&lt;/p>
&lt;p>我叫苏子岳，出生在湖南岳阳。&lt;br>
这个名字的由来也跟我的出生地有关：&lt;br>
父母既希望我像诸&lt;strong>子&lt;/strong>百家一样才华横溢，&lt;br>
也希望我像山&lt;strong>岳&lt;/strong>一样坚实可靠。&lt;/p>
&lt;p>Lirian Su 是我的英文名。&lt;br>
Lirian 是我高中写的小说的主角之一，&lt;br>
他的人设就像我期望的那样：&lt;br>
文可静心作解，武能以一敌百。&lt;/p>
&lt;p>我出生在湖南，在广东求学长大。&lt;br>
初一开始参加信息学竞赛接触编程，&lt;br>
后来高中参加 NOIP 得的省一等奖，&lt;br>
让我可以免高考保送到上海交通大学，读软件工程。&lt;/p>
&lt;p>2014 年 7 月大四以后，&lt;br>
我在 &lt;a href="https://en.wikipedia.org/wiki/QAD_Inc">QAD China&lt;/a> 实习工作，&lt;br>
QAD 是一个跨国团队，&lt;br>
我也在这学到了教科书般的软件开发流程。&lt;br>
当时主语言是 &lt;a href="https://learnxinyminutes.com/docs/perl/">Perl&lt;/a>，&lt;br>
做的是基于 Git 的定制化代码版本控制工具。&lt;br>
后来在我逐渐成长为主程后，&lt;br>
&lt;a href="https://liriansu.com/lazy-coding-thinking">推进了整个项目的一次大重构，让项目的性能跟复杂度都得到了优化&lt;/a>。&lt;/p>
&lt;p>2016 年 10 月的时候，&lt;br>
我被百姓网HR邀请去面试，&lt;br>
因为&lt;a href="https://liriansu.com/my-friend-ldsink">好友周丞&lt;/a>以前实习工作也在百姓，于是就约了一顿饭。&lt;br>
结果被&lt;a href="https://www.zhihu.com/people/ldsink/activities">他&lt;/a>以一碗重庆小面拉到了现在的公司。&lt;br>
现在的公司简称叫&lt;a href="https://www.kezaihui.com/">再惠&lt;/a>，&lt;br>
刚来的时候整个公司的技术只有12个人，每个人都很强，&lt;br>
我感觉自己是里面最菜的 :)&lt;br>
&lt;a href="https://www.zhihu.com/question/19596230/answer/152193862">我把我的工作体验在知乎上面写了下来&lt;/a>，&lt;br>
当时我并不知道这篇文章会在后面几年安利了不少人加入再惠。&lt;/p>
&lt;p>工作上我一开始做的是 Web 后端的活，&lt;br>
主要工作包括了大后端会涉及的三个部分：&lt;br>
实现业务逻辑、设计管理数据库、搭建服务器部署环境。&lt;br>
这里每一块都有很多东西可以讲，&lt;br>
所以我就不讲了 :)&lt;/p>
&lt;p>2018 年 1 月开始，&lt;br>
我作为一条业务线的技术负责人开始带着团队向前冲，&lt;br>
不少人直接跟我说过：&lt;br>
“你是我最喜欢的 Leader.”&lt;br>
这样的话也勉励着我，&lt;br>
不仅要让努力的同事获得事业上的奖赏，&lt;br>
还会想尽办法让大家一起走在技术的最前线。&lt;/p>
&lt;p>&lt;a href="https://liriansu.com/ways-in-zaihui">在担任 Team Leader 的几年来&lt;/a>，&lt;br>
我每周都跟团队的伙伴们有着固定的周会，&lt;br>
大家一起分享技术、讨论职业成长。&lt;br>
我真心开心的一点，&lt;br>
是跟我一起工作的伙伴们离职率都比较低，&lt;br>
这也勉励着我继续向着更好的方向去努力。&lt;/p>
&lt;p>2022 年 2 月开始，&lt;br>
我加入了&lt;a href="https://datarc.cn/">北极数据&lt;/a>。&lt;br>
主要负责上海研发的我，&lt;br>
也兼顾了产品的职责。&lt;br>
在北极的一年多，&lt;br>
&lt;a href="https://liriansu.com/first-year-with-datarc">我在更深的水里体验到了数据、AI、技术行业创业的感受&lt;/a>。&lt;/p>
&lt;p>创业是一个被说烂了的词语，&lt;br>
本质其实就是人与商业。&lt;br>
对于人来说，思考、拼搏、信任都是关键的要素；&lt;br>
对于商业而言，现金流、模式、创新则至关重要。&lt;/p>
&lt;p>2023 年 9 月，&lt;br>
我受再惠创始人赵洋的撩拨，&lt;br>
又开启了在 OpusClip 的旅途。&lt;br>
这段旅途是我最近几年来最享受的过程，&lt;br>
有机会再好好给大家讲讲。&lt;/p>
&lt;p>从一线开发成长为技术负责人以后，&lt;br>
我也一直把自己当一个主程序员在用。&lt;/p>
&lt;p>工程上，我会推动项目去遵循社区的最佳实践，&lt;br>
因为这样才能最好地利用各种工具来&lt;del>偷懒&lt;/del>增加生产力。&lt;br>
语言上，我主要写 Python,&lt;br>
对 Go/JavaScript/Perl/Java/Lisp 有点了解（排名分先后）。&lt;br>
Life is short, I use Python.&lt;/p>
&lt;p>我还主要在知乎、GitHub 上保持活跃。&lt;br>
我在知乎主要当个看客，&lt;br>
但 GitHub 里我会参与不少项目。&lt;br>
我自己的项目主要分为两部分：&lt;br>
一部分是我自己的生活项目，比如&lt;a href="https://github.com/LKI/lki.github.io">我的个人主页&lt;/a>或者是&lt;a href="https://github.com/LKI/LKI">我的环境配置&lt;/a>；&lt;br>
另一部分是各种工具项目，比如&lt;a href="https://github.com/LKI/chinese-calendar">判定节假日的库&lt;/a>就挺受欢迎的。&lt;/p>
&lt;p>我习惯的&lt;a href="https://liriansu.com/windows-dev-env">开发环境是Windows&lt;/a>，&lt;br>
是一个重度的&lt;a href="https://liriansu.com/use-vundle-for-dotvim">Vim用户&lt;/a>和&lt;a href="https://liriansu.com/philosophy-of-git">Git用户&lt;/a>，&lt;br>
也是JetBrains大礼包的受害者。&lt;/p>
&lt;p>&lt;img src="https://imgs.xkcd.com/comics/labyrinth_puzzle.png" alt="xkcd 246">&lt;/p>
&lt;p>&lt;a href="https://liriansu.com/programmers-logic">喜欢语言和逻辑&lt;/a>，&lt;br>
&lt;a href="https://liriansu.com/play-gba-with-danmaku">喜欢好玩的事情&lt;/a>，&lt;br>
&lt;a href="https://liriansu.com/read-blogs-to-write-blogs">喜欢读博客&lt;/a>，&lt;br>
&lt;del>&lt;a href="https://liriansu.com/hunter2-meme">问题很多&lt;/a>&lt;/del>&lt;a href="https://liriansu.com/what-is-cash-cow">好奇心很旺盛&lt;/a>。&lt;/p>
&lt;p>很喜欢&lt;a href="https://www.python.org/dev/peps/pep-0020/">Python Zen&lt;/a>里的一句&lt;br>
&lt;code>Now is better than never&lt;/code>。&lt;br>
认为&lt;a href="https://liriansu.com/my-work">生命的意义在于现在，想做什么就不应该犹豫&lt;/a>。&lt;/p>
&lt;p>相比于覆盖100%情况的复杂设计，&lt;br>
更喜欢覆盖90%情况的简单设计。&lt;br>
我相信大道会是简单而纯粹的&lt;br>
（比如说我坚信存在&lt;a href="https://en.wikipedia.org/wiki/Grand_Unified_Theory">大一统理论&lt;/a>）&lt;/p>
&lt;p>相信人生而平等，&lt;br>
也相信一部分人会活得更加平等。&lt;br>
但不管怎么样，生活是由自己创造的。&lt;/p>
&lt;p>希望老了以后回顾自己的生命，&lt;br>
能坦然地念出这句诗：&lt;br>
苟利国家生死以，&lt;br>
岂因祸福避趋之。&lt;/p>
&lt;p>不喜欢贴标签，认为每个人最重要的是独立自由的身份。&lt;/p>
&lt;p>不喜欢后悔，不喜欢争执，认为事实说明一切。&lt;/p>
&lt;p>不喜欢政治，因为我觉得政治是不透明且不会公平地。&lt;/p>
&lt;p>不会主动参加社交活动，&lt;br>
&lt;a href="https://liriansu.com/how-to-lose-in-rock-paper-scissors">平常空余时间基本在陪女朋友&lt;/a>。&lt;br>
当然了，现在女朋友已经是我夫人了，&lt;br>
她在持续更新一档名为&lt;a href="https://www.xiaoyuzhoufm.com/podcast/6354b5052a992d56e91e6520">不可逃课 BookTalk&lt;/a>的博客节目。&lt;/p>
&lt;p>我的梦想是世界和平，好人都能幸福，&lt;br>
以及要成为一个很厉害的人。&lt;/p>
&lt;p>很高兴认识你。&lt;br>
（不过假如你读完了我的自我介绍，&lt;br>
不跟我介绍一下你的话，&lt;br>
我就没机会认识你了。）&lt;/p>
&lt;h2 id="关于本博客">关于本博客&lt;/h2>
&lt;p>&lt;a href="https://liriansu.com/how-this-blog-was-built">搭建博客很简单&lt;/a>，&lt;a href="https://liriansu.com/why-im-blogging">做个决定却不容易&lt;/a>&lt;br>
由&lt;a href="https://gohugo.io/">Hugo&lt;/a>生成, 挂在&lt;a href="https://github.com/LKI/lki.github.io">GitHub&lt;/a>上,&lt;br>
评论系统是用的&lt;a href="https://liriansu.com/use-commentit">commentit&lt;/a>，PV和UV是用的busuanzi&lt;/p>
&lt;h2 id="附录">附录&lt;/h2>
&lt;p>最近我花在写代码上的时间：&lt;br>
(没错，这个哥最近写代码的时间变少了)&lt;/p>
&lt;!-- raw HTML omitted -->
&lt;p>最近我用的编辑器：&lt;br>
(我查数据的 GUI 也是 PyCharm)&lt;/p>
&lt;!-- raw HTML omitted --></description></item></channel></rss>