你要专业

在我不算长的职业生涯中,有很多同事都给过我正面的评价(当然,可能有更多负面的评价,不过我都选择性的遗忘掉了)。有人欣赏我的命令行技巧,有人则称赞我代码写的比较快,有人说我的Vim的插件配置的很高效,还有人说坐在我旁边写PPT效率会变高。而我自己最喜欢一个评价是:有我在项目上的时候,团队就会觉得安心。

December 12, 2018 1 min

团队里的两类程序员

程序员的分类 最近几年,我在多个不同类型的项目上,以不同的角色工作过:有时候会为项目前期做一些预研、然后为后续的交付估算工作量;有时候则在项目中期加入团队,做本职的交付工作(就是写业务代码);而另外有些时候则会帮助客户的团队进行能力建设等等。 由于要在不同的场景和不同的上下文中频繁切换,我和很多不同水平、有着不同变成习惯和思维方式的程序员一起工作过。我觉得对于程序员这样一种角色,还可以再细化成两大类。虽然都是程序员,但是其职责,技能要求,甚至思维方式都可能有很大的不同。 这两大类程序员分别为: 原型类程序员(prototyper) 产品类程序员(engineer) 原型类程序员 如果通过敏捷的方式来运作一个项目,在项目开始的时候,开发往往需要客户/用户,BA(业务分析师)等角色一起协作。在有一个对需求的粗略梳理之后,通过技术手段快速实现应用程序的原型,用以快速验证业务场景。由于对需求的梳理是较为粗略的,其中有很多待验证的假设,如果按照传统的方式来运作,则会有很多不必要的浪费 设计师通过Photoshop作出页面 开发根据PS文件来开发 开发的同时,业务分析可能有了新的发现 设计师对Photoshop作出修改 开发根据新的PS来做修改 这种重量级的,瀑布方式的工作体验非常糟糕,不论是设计师,还是开发,总觉得很多事情都在变化,自己花费了很大力气做的像素级别的精准调整可能在第二天就要被推翻。不过现实世界就是这样:需求的变化是不可避免的,我们唯一能做的是积极拥抱变化,而不是在最开始就尝试设计、实现完美的效果。 与其在一开始就试图设计一个完美的、确定的系统,不如放弃幻想,每次只做简陋而可以示意的原型,然后不断去迭代,最后达到可用的系统。 比如,如果设计师完全不使用Photoshop,也不产出任何的PS文件,而是和开发坐在一起,开发一个简陋,但是易于修改(比如HTML+CSS)的页面,然后向业务分析师或者客户来确认,然后根据反馈来快速调整。在迭代过程中,每次确认之前,只做非常少量的工作,这样既可以避免返工,又可以让将来的调整更容易。 如果用这种方式来运作,我们队程序员的能力要求是这样的: 手速快(可以在很短时间内作出一个可以工作的原型) 技术广博(前后端) 可以与不同角色一起工作(最好是通过结对的方式) 比如通过python -m http.server 8080来运行一个Web服务器,而不是去考虑负载均衡或者HTTP缓存等,也无需考虑在为前端代码加入动态路由。 很有可能,一个在<head>里通过CDN引入外部依赖,然后将所有代码都写入main.js就可以让我们的想法变成触手可及的应用,在建立起快速反馈的机制之后,就可以和我们的BA,甚至客户一起来协作,并快速打磨原型,使之和客户的期望契合。 原型驱动 去年我参加了一个非常有意思的项目,在我加入的时候,客户只有一个非常粗糙的想法:在网络(不是计算机网络)中,如果某个实体被攻击了,那么对整个系统的影响是什么?比如某个变电站由于气温太高爆炸了(6·18西安变电站爆炸事故),那么哪些地铁站会受到影响?以及收到多大影响?又或者某个运营商的网络中断了,那么它对该城市的各大银行的转账业务有多大影响? 客户希望有一个比较直观的方式来展现网络中的节点,以及当故障发生时会有什么样的影响。我们从原型开始,没有设计师的参加,也没有专门的业务分析师,一开始只有有一个简单的文档来描述,然后我根据文档画了一个草图: 和客户确认了,我用bootstrap+leaflet做了一个简单的页面: 客户表示大致是这么个意思。这时候我的代码是这样的: 一个HTML文件 从CDN来获取jQuery,bootstrap,leaflet inline的script中写了一点微小的代码 inline的css 确定了这就是客户想要的效果之后,我做了一些简单的调整: 将第三方依赖下载下来,放到本地的一个目录中 将inline的JavaScript和CSS抽取到文件 写了一个简单的shell script用来启停本地的HttpServer 几周之后,客户对右侧的两个panel有一些新的需求,要求有一棵树,可以点击,然后要做各种同步: 这时候,我的代码还是几个微小的jQuery写的文件,通过简单的事件机制来完成交互。很快,客户有了一个新的需求:中间区域的图中的非叶子节点要可点击,点击之后右侧的一个panel显示该节点下的所有叶子,同样,右侧panel中的节点也需要可点击。 也就是说,中间的树需要两个不同的视图,而背后的数据只有一份(这样点击时的展开和收起才会是同步的),这时候用事件机制就很难做到了,而且代码的复杂度直线上升,而且可维护性基本没有。 基本满足客户的需求之后,团队里加入了两位同事,这时候我做了一个比较大胆的决定,用vue.js将整个应用重写,将大部分功能都抽象为组件,方便以后的扩展。完成的时候,界面看起来是这样子的: 如果整理一下思路,原型类开发的流程是这样的: 用CDN+胶水代码迅速实现 及时与客户沟通,并根据反馈修改 在需求相对稳定,方向确定之后,再做实际的技术选型 重构 — 甚至重写(使用靠谱的技术站进行) 比如上面这个项目,如果现在让我再来做一次技术选型,我可能会这样选择: 前端框架:React + Redux + React-router 界面原型:AntDesign 地图:Leaflet 可视化:D3 产品类程序员 另一方面,当idea已经经过验证,我们需要通过严谨的工程实践将其产品化,那么对开发的要求却又有不同:...

January 14, 2018 1 min

反馈拯救世界

心流 你可能有过这样的体验:在玩一个很有趣的游戏时,时间会飞快的流逝,等你终于通关之后才发现已经是凌晨,而你的午饭和晚饭还都没吃。虽然可能饿着肚子,但是你内心却有一种很兴奋,很神清气爽的感觉。而当你在做一些不得不完成的工作/作业时(比如写年终总结报告),时间又会过得很慢,你的心情也常常变得焦虑或者暴躁。 通常来说,人的心情总是会在各种情绪中起伏不定,不过毋庸置疑,我们都希望永远或者至少是尽可能多的保持第一个场景中的状态。 这种精神高度集中,通过自己的努力不断完成挑战,并常常会有忘记时间流逝,甚至忘记自身存在,只剩下“做事情”本身的状态,在心理学上被称之为心流(Flow)。人们虽然很早就发现了这种现象,但是直到1975年,心理学家米哈里·齐克森米哈里(Mihaly Csikszentmihalyi)才将其概念化并通过科学的方式来研究。 心流(英语:Flow),也有别名以化境(Zone)表示,亦有人翻译为神驰状态,定义是一种将个人精神力完全投注在某种活动上的感觉;心流产生时同时会有高度的兴奋及充实感。 进入心流之后会有很多特征: 愉悦 全身心投入 忘我,与做的事情融为一体 主观的时间感改变 心流被普遍认为是一种绝佳的精神体验。根据齐克森米哈里的理论,与心流对应的,还有一些其他的心理状态: 当自身能力很高,但是做的事情很简单的话,你做起来会比较无聊;而当能力不足,要做的事情很困难的话,你又会陷入焦虑。有意思的是,如果你技能不足,而做的事情又比较简单的话,并不会产生“心流”体验。恰恰相反,这种状态(apathy)是很消极的,做事情的过程中,你既没有运用任何技能,也并没有接受到任何的挑战。 如何进入心流状态 齐克森米哈里要进入心流状态,需要满足至少三点: 有清晰的目标 有明确且事实的反馈 能力和挑战的平衡(都处于比较高的状态) 比如,玩游戏的时候,目标是明确的,不论是简单的通过策略消灭对方,还是将三个同一颜色的宝石移动到同一行);反馈也是实时的,同色宝石连在一起是发出的声音以及屏幕上闪过的炫目的光芒,敌人在被你手中武器杀死时的惨叫,你自己的血槽等等;最后,游戏不能过于简单,如果太简单,你很快会觉得无聊,又不能太难,这样你会觉得挑战太大。 不过要在工作上进入心流状态,远远比玩游戏要复杂。比如不明确的目标,冗长的反馈周期,能力与挑战的不均衡等等。 基于反馈的开发 2014年底,我在ThoughtWorks组织3周3页面工作坊的时候,发现了一个很有意思的现象:通常公司内部的培训/工作坊都会出现这种现象:报名的人很多,前几次课会来很多人,慢慢的人数会减少,能坚持到最后的人很少,能完成作业的就更少了。而在3周3页面中,参加的人数越来越多,而且作业的完成率非常高(接近100%)。 回想起来,我在培训的最开始就设置了一些机制,保证学员可以有一个非常容易沉浸其中的环境: 通过watch、livereload等机制,保证每次修改的CSS/HTML都可以在1秒钟内在浏览器上自动刷新 通过对比mockup和自己实现的样式的差异,来调整自己的目标 将这些工具做成开箱即用的,这样经验不足者不至于被技术细节阻塞 做完之后,学员们的作品直接发布到github的pages上 事实上,这些实践恰好满足了上述的几个条件: 目标明确 快速且准确的反馈 技能与挑战的平衡 由于工作坊是在周内下班后(8点结束),我见到很多学员在课后(很晚的时候)还在写代码、调样式,完全沉浸其中,忘记时间。到最后,参加培训的学员们被要求通过设计原则自己实际一个Web Site,很多没有前段开发背景的同事也做出了非常有“设计感”的作品。 编程语言的壁垒 使用JavaScript或者Ruby这种解释型语言的开发人员,在第一次接触之后就会深深的爱上它,并再也无法回到编译型语言中去了。想一想要用Java打印一行Hello World你得费多大劲? 解释型语言中,你很容易可以采用REPL环境,写代码会变成一个做实验的过程:函数名写错了,参数传错了,某个函数没有定义等等错误/手误,都可以在1秒钟内得到反馈,然后你再根据反馈来修正方向。 举个小例子,写一个字符串处理函数:将字符串”qiu,juntao”转换成“Qiu Juntao”,你会怎么做?你大概知道有这样一些原生的API: String.indexOf String.replace 大小写转换 正则表达式(可选) 如果用JavaScript来实现的话,你可以在Chrome的DevTools中完成大部分的工作: 注意这里的每次操作的反馈(特别是出错的情况),你可以在1秒钟内就知道明确的反馈,而不是等等待漫长的编译过程。DevTools里的console提供的REPL(read-eval-print-loop)可以帮助你建立流畅的编码体验。 如果用Java来做,你需要一大堆的准备工作,抛开JDK的安装,JAVA_HOME的设置等,你还需要编译代码,需要定义一个类,然后在类中定义main方法,然后可能要查一些API来完成函数的编写。而每一个额外的步骤都会延长反馈的时间。 测试驱动开发 那么在编译型语言中如何获得这种体验呢?又如何缩短反馈周期呢?答案是使用测试驱动开发(Test Driven Development)! 通常TDD会包含这样几个步骤: 根据用户故事做任务分解 根据分解后的Task设计测试 编写测试 编写可以通过测试的实现 重构 步骤3-5可能会不断重复,直到所有的Task都完成,用户故事也就完成了。如果仔细分析,这些步骤也恰好符合产生心流的条件:...

January 13, 2018 1 min

给新人程序员的一些建议

作为一个从业快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