给新人程序员的一些建议

作为一个从业快10年的程序员,我想给新入行的程序员们一些建议。这些建议是我希望自己可以在毕业的时候就读到的,也希望它们可以帮助你成为一个更好的程序员。 简单归纳一下,总共有7条: 保持健康 编程之外的爱好 持续学习 正确应对犯错 不要囿于角色 展示你的创意 刻意练习手速 下面我来详细说说每一点。 保持健康 三寸气在千般用,一旦无常万事休 –《金瓶梅》 首先要说的当然是健康,脱离的这个本钱,一切都无从谈起。久坐、不运动、睡眠不足、不注意及时补充水分、长期的伏案工作会对健康造成很大的影响,而不幸的是程序员这几样全都占了。很多程序员往往很年轻就已经有了各种各样的疾病:颈椎病、腰椎间盘突出、高血脂/高血压、胆结石、腱鞘炎等等,关于程序员过劳死的新闻更是隔一段时间就来刺激一下我们的神经。 研究表明,长期保持同一姿势(不论坐着还是站着)对身体都有不同程度的害处,而且这种害处是无法事后弥补的。也就是说,如果白天上班坐8个小时,那么就算你下班后去健身房练一个小时也于事无补。这几年很流行的站立式办公也是一样,如果你白天站立时间过久,会对膝关节造成较大的压力,同样会损害健康。比较推荐的方式是,写30-40分钟代码就起来走一走,喝杯水,远眺一会,跟同事聊聊天。 我知道,作为程序员我也常遇到那种写代码写High了连厕所也不想去的时候。不过为了长远的健康,还是要养成良好的习惯。 戒除不良习惯 除了长时间保持同一姿势之外,有很多程序员还有各种不良习惯。比如: 吸烟 喝酒 嗜糖(碳酸饮料,其他高糖饮料) 这些习惯一般都会美其名曰提神,大家都知道,程序员加班在业界算是比较常见的,萎靡不振是常态。然而这些号称提神的方法,其实没有一个是真正管用的。这些不良习惯说到底都是一种毒瘾,跟吸食大麻在本质上并无二致。不过好消息是你完全可以戒除这些不良习惯,只需要坚持一段时间,让毒瘾过去就好了(和真正的毒瘾一样,它们更多的是精神依赖,一旦你战胜了自己对它的精神依赖,就可以获得自由)。 我在大学和刚开始工作的前几年,也有烟瘾。写代码写累了就回去办公室外边冒一根,那种一氧化碳中毒带来的短暂的微醺感确实令人有放松的错觉,但是抽完烟回来写代码会感觉更累。而且口中老感觉有异味,咽喉不适,最主要的是精神萎靡,终于有一天我受不了了,决定戒烟(事实上和很多人一样,之前也有过无数次的戒烟)。当烟瘾发作的时候,我就去喝杯水,晚上则站站桩(站完之后口齿生津,神清气爽)。刚开始的3天是最难的,一周之后我就基本可以控制住去抽烟的欲望,然后就越来越轻松,完全感觉不到烟瘾对我的影响了。 碳酸饮料,高糖饮料也是一样。在饮食本来就不充裕的自然界,我们的祖先遇到了富含可以为身体提供能量的糖(比如蜂蜜)自然会大量摄入。这种嗜糖的基因在今天还在不断的产生作用,但是不同的是,我们现在可以很轻松的在食物、饮料中摄入比身体所需多得多的糖。这些糖会给健康带来很多问题,比如肥胖,高血糖,冠心病等等。 更多时候,我们想要喝饮料更多的是精神上的依赖,也就是上面说到的毒瘾。戒除对糖的依赖比烟和酒要困难一些,因为生活中有很多陷阱,比如酸奶,面包,饼干,水果等等。 零度可乐的陷阱 现在香烟的包装上印有焦油含量,有10mg的,有15mg的。焦油含量是影响一支烟口感的重要因素,通常说的“绵”其实是说焦油含量角度,这会让你感觉比较健康。然而陷阱是,一支烟抽完觉得不过瘾,神经感受到的刺激不够强烈,这会驱动你抽第二支,结果吸入的焦油反而更多。本来15mg焦油的一支烟就可以让你过瘾,现在两支10mg的才能达到同样的效果,相当于摄入了20mg。 零度可乐也是一样,那种无糖的有着甜味的添加剂会刺激你对糖的渴求,你需要摄入更多的糖来抵消这种虚幻的渴求 – 然后变得更不健康。 有人可能会说,没有这些嗜好,那活着有什么意思呢?相信我,当你戒除了这些毒瘾,有了一个健康的体魄,才真正能体会到活着的乐趣。当你为这些嗜好所控制,产生的那种病态的舒适感其实是虚无缥缈的。 一些建议 有规律的做一些运动,可以缓解颈椎,腰椎的不适,可以加快新陈代谢的速度,消耗多余的会沉积下来的能量。比如比较容易接触到,也容易上手的运动: 瑜伽/普拉提 乒乓球 跳绳 选择一个适合自己的运动方式,然后将其培养成一个习惯(比如坚持每周两次瑜伽,或者每天中午打30分钟的乒乓球)。如果这些和工作有冲突的话,比如公司要求长期晚上加班,那你可以考虑换一家公司。 培养一个编程之外的爱好 如果让不同的人对程序员打标签并排序,宅一定会排在前三。在任何的聚会上,程序员总是很容易被识别出来的:聪明,戴眼镜,话不多,略显闷骚,聊天容易冷场等等。也难怪,长期钻研技术,沉浸在非黑即白的二进制世界,爱刨根问底,这样很容易把天聊死。 我建议新手程序员可以找一个编程之外的爱好,一来可以拓展自己的社交圈,周末可以有个不一样的过法(而不是宅在家里写代码);二来可以帮助你成为更好的程序员。 你肯定有过这样的经历:一个编程问题一直困扰着你,试了很久都找不到解决方法,结果出去散了会步,或者和别人唠家常,突然脑海里灵光一闪,想到了问题的答案。事实上,我们大脑的工作方式就是如此奇妙,换一个完全不同的上下文就可以让大脑得到很好的休息,而且往往可以产生1+1>2的效果。写代码写累了去听听音乐,或者打一会乒乓球就可以很好的缓解疲劳,甚至可以打开思路,产生新的灵感。 一些建议 学习一项与编程无关的技能,比如: 乐器(比如吉他,架子鼓) 绘画(素描,水粉,水彩等)或者书法 制作美食 某一项武术(拳击,泰拳,空手道等) 这些看似毫不相干的爱好可以帮助大脑休息。另外需要注意的是,你无需真正成为某一项爱好的专家,不要有额外的压力:担心演奏不好、没有绘画天赋等等。没关系,它只是一个爱好而已。 我自己就尝试过很多不同的爱好,比如素描、书法等。 持续学习 软件开发是一个需要终身学习的行业(其实如果你不想做那种混吃等死的人的话,基本上每个行业都是这样)。我毕业的时候,SSH(Spring Struts Hibernate)是Web开发的主流,jQuery则是前端的新锐。有一些企业开始尝试Adobe的ActionScript,不过这个语言很快就消逝在了人们的视野。基于jQUery,但是融入了MVC理念的Backbone.js提供更高级的抽象能力,成为了开发“大型”前端应用的首选;紧随其后的,大而全的Angular.js则通过内置的双向绑定,依赖注入,完善的测试支持等让前端开发变得和后端开发一样健全;再后来虚拟DOM,Reactive范式的React栈则又一次颠覆了前端的开发方式。虽然现在还不知道下一次的颠覆会在哪里发生,但是可以肯定的是它一定会发生。 除了基础框架之外,各种构建工具也是层出不穷,从最早和后端放在一起的maven,rake,到基于NodeJS的grunt,再到gulp,到webpack,最后又回归到npm script。 程序员被裹挟在技术演进的洪流中,不能自已。作为程序员,你不但要非常扎实的掌握基础知识(操作系统原理,计算机网络,数据结构,算法等),还需要有非常强的快速学习能力,以及愿意不断去学习的态度,而后者可能更重要。 一些建议 读书 通过视频/文本教程等学习新技术 建议新手可以每天抽出一个小时来读书,周末可以多读一些。ThoughtWorks有个读书雷达,是一个很不错的书单,包括了很多的经典书籍。读书之外,还可以在线学习一些教程,比如Tutorialplus和Egghead等,都非常值得经常去看看,如果有比较新鲜有趣的技术,不妨自己亲自动手试一试。...

July 25, 2017 1 min

ThoughtWorks洞见在讲什么

ThoughtWorks洞见 ThoughtWorks洞见是ThoughtWorks的一个媒体渠道,汇集了来自ThoughtWorks最优秀的经验和思考,并分享给真正对软件有意愿思考和不断改进的人(修改自官方版本)。 截至目前为止,ThoughtWorks洞见已经汇集了50余位作者的300+篇文章(就在刚才,又有一篇更新)。那么这些文章中都在讨论什么样的话题呢?这篇文章将通过一些技术手段,提取出洞见中的关键字,然后采用可视化的方式呈现出来。 数据获取 本来我打算从RSS上读feed,解析出文章的link,再将所有文章爬一遍,最后保存到本地。不过写了几行代码后发现Wordpress(ThoughtWorks洞见目前托管在一个Wordpress上)默认地只输出最新的feed,这对于关键字提取来说数量远远不够。众所周知,语料库越大,效果越好。 既然是洞见本质上来说就是一个静态站点,那么最简单、最暴力的方式就是直接把站点克隆到本地。这一步通过使用wget可以很容易做到: wget --mirror -p --html-extension --convert-links -e robots=off -P . \ http://insights.thoughtworkers.org/ 默认地,wget会以站点的完整域名为目录名,然后保存整个站点到本地。我大概看了一下,其实不需要所有的目录,只需要一个层次即可,所以这里用find来做一个过滤,然后将文件名写到一个本地文件filepaths中。 find insights.thoughtworkers.org/ -name index.html -depth 2 > filepaths 这个文件的内容是这样的: insights.thoughtworkers.org/10-common-questions-of-ba/index.html insights.thoughtworkers.org/10-tips-for-good-offshore-ba/index.html insights.thoughtworkers.org/10-ways-improve-your-pairing-experience/index.html insights.thoughtworkers.org/100-years-computer-science/index.html insights.thoughtworkers.org/1000-cars-improve-beijing-transportation/index.html insights.thoughtworkers.org/3d-printing/index.html insights.thoughtworkers.org/4-advices-for-aid/index.html insights.thoughtworkers.org/5-appointments-with-agile-team/index.html insights.thoughtworkers.org/5-ways-exercise-visual-design/index.html insights.thoughtworkers.org/7-step-agenda-effective-retrospective/index.html insights.thoughtworkers.org/a-decade/index.html insights.thoughtworkers.org/about-team-culture/index.html insights.thoughtworkers.org/about-tw-insights/index.html insights.thoughtworkers.org/agile-coach/index.html insights.thoughtworkers.org/agile-communication/index.html insights.thoughtworkers.org/agile-craftman/index.html ... 数据处理 这样我就可以很容易在python脚本中读取各个文件并做处理了。有了文件之后,需要做这样一些事情: 抽取HTML中的文本信息 将文本分词成列表 计算列表中所有词的TFIDF值 计算每个词出现的频率 将结果持久化到本地 这里需要用到这样一些pyhton库: BeautifulSoap 解析HTML文档并抽取文本 jieba 分词 sk-learn 计算单词出现频率 pandas 其他数据处理 def extract_post_content(file): soup = BeautifulSoup(open(file).read(), "html.parser") return soup....

March 12, 2017 2 min

可视化之根

可视化之根 多年前读过一篇非常震撼的文章,叫《Lisp之根》(英文版:The roots of Lisp),大意是Lisp仅仅通过一种数据结构(列表)和有限的几个函数,就构建出了一门极为简洁,且极具扩展性的编程语言。当时就深深的被这种设计哲学所震撼:一方面它足够简单,每个单独的函数都足够简单,另一方面它有非常复杂,像宏,高阶函数,递归等机制可以构建出任意复杂的程序,而复杂的机制又是由简单的组件组成的。 数据的可视化也是一样,组成一幅内容清晰、表达力强、美观的可视化信息图的也仅仅是一些基本的元素,这些元素的不同组合却可以产生出令人着迷的力量。 要列出“可视化元素之根”很容易:位置、长度、角度、形状、纹理、面积(体积)、色相、饱和度等几种有限的元素,邱南森在他的《数据之美》中提供了一张视觉元素的图,其中包含了大部分常用的元素。 令人振奋的是,这些元素可以自由组合,而且组合旺旺会产生1+1>2的效果。 心理学与认知系统 数据可视化其实是基于人类的视觉认知系统的,因此对人类视觉系统的工作方式有一些了解可以帮助我们设计出更为高效(更快的传递我们想要表达的信息给读者)的可视化作品。 心理物理学 在生活中,我们会遇到这样的场景:一件原价10元的商品,如果降价为5元,则消费者很容易购买;而一件原价100元的商品,降价为95元,则难以刺激消费者产生购买的冲动。这两个打折的绝对数字都是5元,但是效果是不一样的。 韦伯-费希纳定理描述的正是这种非理性的场景。这个定理的一个比较装逼的描述是: 感觉量与物理量的对数值成正比,也就是说,感觉量的增加落后于物理量的增加,物理量成几何级数增长,而心理量成算术级数增长,这个经验公式被称为费希纳定律或韦伯-费希纳定律。 – 摘自百度百科 这个现象由人类的大脑构造而固有,因此在设计可视化作品时也应该充分考虑,比如: 避免使用面积图作为对比 在做对比类图形时,当差异不明显时需要考虑采用非线性的视觉元素 选用多种颜色作为视觉编码时,差异应该足够大 比如: 如上图中,当面积增大之后,肉眼越来越难从形状的大小中解码出实际的数据差异,上边的三组矩形(每行的两个为一组),背后对应的数据如下,可以看到每组中的两个矩形的绝对差都是5: var data = [ {width: 5, height: 5}, {width: 10, height: 10}, {width: 50, height: 50}, {width: 55, height: 55}, {width: 100, height: 100}, {width: 105, height: 105} ]; 格式塔学派 格式塔学派是心理学中的一个重要流派,她强调整体认识,而不是结构主义的组成说。格式塔认为,人类在看到画面时,会优先将其简化为一个整体,然后再细化到每个部分;而不是先识别出各个部分,再拼接为整体。 比如那条著名的斑点狗: 我们的眼睛-大脑可以很容易的看出阴影中的斑点狗,而不是先识别出狗的四条腿或者尾巴(事实上在这张图中,人眼无法识别出各个独立的部分)。 格式塔理论有几个很重要的原理: 接近性原理 相似性原理 封闭性原理 连续性原理 主体/背景原理 当然,格式塔学派后续还有一些发展,总结出了更多的原理。工程上,这些原理还在大量使用,指导设计师设计各式各样的用户界面。鉴于网上已经有众多的格式塔理论及其应用的文章,这里就不在赘述。有兴趣的同学可以参考这几篇文章: 优设上的一篇格式塔文章 优设上的一篇关于格式塔与Web设计的文章 腾讯CDC的一篇格式塔介绍 视觉设计的基本原则 《写给大家看的设计书》一书中,作者用通俗易懂的方式给出了几条设计的基本原则,这些原则完全可以直接用在数据可视化中的设计中:...

March 1, 2017 3 min

新生儿日常记录的可视化 - 星空图

数据来源 从女儿心心出生开始,我们就通过各种方式记录她的各种信息:睡眠记录,吃药记录,体温记录,换尿布记录,哺乳记录等等。毕竟,处于忙乱状态的人们是很难精确地回忆各种数字的,特别是在体检时面对医生的询问时。大部分父母无法准确回答小孩上周平均的睡眠时间,或者平均的小便次数,这在很多时候会影响医生的判断。 我和我老婆的手机上都安装了宝宝生活记录(Baby Tracker)(这里强烈推荐一下,免费版就很好用,不过界面下方有个讨厌的广告,我自己买了无广告的Pro版本),这样心心的每次活动我们都会记录下来,很有意思的是这个APP的数据可以以CSV格式导出(这个太棒了!),而且它自身就可以生成各种的报告,报告还可以以PDF格式导出并发送给其他应用。 有了现实世界中的一组数据 – 我们记录的差不多100天的数据,而且正好我最近在复习D3相关的知识,正好可以用来做一些有趣的练习。 数据准备 从Baby Tracker导出的数据是一些CSV文件组成是压缩包,解压之后大致结果是这样的: 哺乳记录 睡眠记录 换尿布记录 喂药/体温记录 里程碑记录 我就从最简单换尿布数据记录开始吧。我们首先需要将数据做一些清洗和归一化,这样方便前端页面的计算和渲染。数据处理我一般会选择Python+Pandas的组合,只需要写很少的代码就可以完成任务。 python + pandas 原始数据看起来是这样的: name,date,status,note 心心,2016/11/13 17:00,嘘嘘 心心,2016/11/13 19:48,嘘嘘+便便 心心,2016/11/13 22:23,便便 心心,2016/11/14 00:19,便便,一点点,感觉很稀,穿厚点 心心,2016/11/14 04:33,嘘嘘 心心,2016/11/14 09:20,便便 心心,2016/11/14 11:33,便便 心心,2016/11/14 16:14,便便 心心,2016/11/14 21:12,嘘嘘+便便 心心,2016/11/14 23:12,嘘嘘+便便 心心,2016/11/15 00:32,嘘嘘+便便,有点稀 心心,2016/11/15 03:45,干爽 心心,2016/11/15 07:06,嘘嘘 心心,2016/11/15 10:30,嘘嘘+便便 为了方便展示,我需要将数据统计成这样: date,urinate,stool 2016-11-13,2,2 2016-11-14,3,6 2016-11-15,6,8 我不关心每一天不同时刻换尿布的事件本身,只关心每天中,大小便的次数分布,也就是说,我需要这三项数据:日期,当天的小便次数,当天的大便次数。这个用pandas很容易就可以整理出来了,status字段的做一个微小的函数转换(当然可以写的更漂亮,不过在这里不是重点,暂时跳过): import numpy as np import pandas as pd diaper = pd.read_csv('data/diaper_data.csv', usecols=['date', 'status']) diaper['date'] = pd....

February 22, 2017 2 min

前端页面性能调优

Web页面的性能 我们每天都会浏览很多的Web页面,使用很多基于Web的应用。这些站点看起来既不一样,用途也都各有不同,有在线视频,Social Media,新闻,邮件客户端,在线存储,甚至图形编辑,地理信息系统等等。虽然有着各种各样的不同,但是相同的是,他们背后的工作原理都是一样的: 用户输入网址 浏览器加载HTML/CSS/JS,图片资源等 浏览器将结果绘制成图形 用户通过鼠标,键盘等与页面交互 这些种类繁多的页面,在用户体验方面也有很大差异:有的响应很快,用户很容易就可以完成自己想要做的事情;有的则慢慢吞吞,让焦躁的用户在受挫之后拂袖而去。毫无疑问,性能是影响用户体验的一个非常重要的因素,而影响性能的因素非常非常多,从用户输入网址,到用户最终看到结果,需要有很多的参与方共同努力。这些参与方中任何一个环节的性能都会影响到用户体验。 宽带网速 DNS服务器的响应速度 服务器的处理能力 数据库性能 路由转发 浏览器处理能力 早在2006年,雅虎就发布了提升站点性能的指南,Google也发布了类似的指南。而且有很多工具可以和浏览器一起工作,对你的Web页面的加载速度进行评估:分析页面中资源的数量,传输是否采用了压缩,JS、CSS是否进行了精简,有没有合理的使用缓存等等。 如果你需要将这个过程与CI集成在一起,来对应用的性能进行监控,我去年写过一篇相关的博客。 本文打算从另一个角度来尝试加速页面的渲染:浏览器是如何工作的,要将一个页面渲染成用户可以看到的图形,浏览器都需要做什么,哪些过程比较耗时,以及如何避免这些过程(或者至少以更高效的方式)。 页面是如何被渲染的 说到性能优化,规则一就是: If you can’t measure it, you can’t improve it. - Peter Drucker 根据浏览器的工作原理,我们可以分别对各个阶段进行度量。 图片来源:http://dietjs.com/tutorials/host#backend 像素渲染流水线 下载HTML文档 解析HTML文档,生成DOM 下载文档中引用的CSS、JS 解析CSS样式表,生成CSSOM 将JS代码交给JS引擎执行 合并DOM和CSSOM,生成Render Tree 根据Render Tree进行布局layout(为每个元素计算尺寸和位置信息) 绘制(Paint)每个层中的元素(绘制每个瓦片,瓦片这个词与GIS中的瓦片含义相同) 执行图层合并(Composite Layers) 使用Chrome的DevTools - Timing,可以很容易的获取一个页面的渲染情况,比如在Event Log页签上,我们可以看到每个阶段的耗时细节(清晰起见,我没有显示Loading和Scripting的耗时): 上图中的Activity中,Recalculate Style就是上面的构建CSSOM的过程,其余Activity都分别于上述的过程匹配。 应该注意的是,浏览器可能会将Render Tree分成好几个层来分别绘制,最后再合并起来形成最终的结果,这个过程一般发生在GPU中。 Devtools中有一个选项:Rendering - Layers Borders,打开这个选项之后,你可以看到每个层,每个瓦片的边界。浏览器可能会启动多个线程来绘制不同的层/瓦片。 Chrome还提供一个Paint Profiler的高级功能,在Event Log中选择一个Paint,然后点击右侧的Paint Profiler就可以看到其中绘制的全过程:...

February 8, 2017 2 min