穷人的持续交付 - 下

本文将使用一些免费的服务来为你的项目搭建`持续交付`平台,这些服务包括,持续集成环境,持续部署环境和服务端应用托管

January 10, 2016 2 min

穷人的持续交付 - 上

本文将使用一些免费的服务来为你的项目搭建`持续交付`平台,这些服务包括,持续集成环境,持续部署环境和服务端应用托管

January 9, 2016 1 min

如何总结你的上一个项目

下项目之后 通常来说,下项目总是一件比较高兴的事(大部分团队还会一起吃个饭庆祝一下)。这里面既有终于摆脱了厌烦了的技术栈的解脱感,也有对新项目/新技术的向往,可能还有些在旧项目中做的不太满意的事情,可以在新项目重头再来的期望。 可能有点老生常谈了,不过这里我想说说下项目后如何做总结的事儿。对上一个项目的总结,其重要程度可能要远远超过你的想象。我是在2014年初,在一个客户现场的一个会议室和一位同事谈我的Annual Review的时候,才意识到这个问题的。 Annual Review会回顾我们过去一年的项目经历,有哪些方面的进步,同时也会展望未来的计划。但是这其中有几个问题:第一个问题是以年为单位的Review粒度太粗,有些经历已经淡忘,也有人可能一年会换好几个项目;第二个问题是对于大多数人来说,展望未来是一件比较容易的事儿,每个人或多或少都会有一些计划(比如学会前端的某些技术,尝试一些DevOps方面的工作,或者了解一下大数据等等);但是对于回顾过去,我们其实并不擅长;最后一个问题是即使做了回顾,回顾的层次非常浅,作用并不大。 说到回顾过去,更多时候我们关注的是从项目中学到了什么样的新技术,这种浅层次的回忆和记流水帐是容易的,但是对于我们的成长并不会有太大的收益。真正会为帮助我们在将来的项目中做决策,甚至会影响我们学习效率,解决问题能力的是:深度回顾。 深度回顾练习 深度回顾可以帮助我们梳理知识,将实际的案例归纳总结为实际可用的知识。要获得这种能力,需要做一些针对性的练习。根据我自己的经验,这些练习大约可以归为3类,难度依次增加。 项目上的直接经验 这个练习比较简单,就是问问自己:“我在项目里学到了什么?” 要回答这个问题是很容易的,项目中用到的技术如模板引擎,前端框架,自动化测试套件,build工具等等,总结这些内容的过程,对于我们的PS来说都是“自动”发生的,几乎不需要付出额外的efforts。这些回顾、总结可以帮助我们成为一个“熟手”,即当下一次遇到相同或者类似的场景时,我们可以很容易直接应用这些经验。 更进一步,再问问自己在项目中的其他收获。比如客户关系处理的经历,团队建设的经验,甚至是写英文邮件的技巧等等方面,看看做的有没有问题,有没有提升的可能? 人类最牛逼的技能是:可以审视自己的行为。也就是站在旁观者的角度来看待自己的行为,随波逐流式的在各种琐事中沉浮事实上无法得到提升的。可以经常性的将自己置身事外,以一个旁观者的角度来审视自己做过的事情。并从中找出做得好的地方和不足的地方,然后自己给过去的自己一些建议,并记录下来。这些刻意的练习会帮助你养成回顾,从经验中学习的习惯,而这个习惯正是一个人区别于另一个人的绝对“捷径”。 练习讲故事 这个练习是,假想你遇到了一个同一个办公室的同事,他对你刚做完的这个项目很感兴趣,你来给他描述一下这个项目。描述的内容包括但不限于这些方面: 项目的背景介绍 该项目以何种方式,为那些用户,带来了什么样的价值?(business model是什么) 该项目的实际用户数量是什么级别? 项目的部署,运维是如何操作的? 项目的监控是怎样做的? 当遇到系统故障,项目组是如何反应的? 能把一件事情描述清楚是一件非常了不起的能力。我见过很多的程序员,写起代码来好不含糊,但是却很难将一件简单的事情讲清楚。我们当然要提防那些夸夸其谈,华而不实的“嘴子”,但是也至少得要求自己做到清晰,准确的将自己经历过的事情描述清楚。 描述项目背景需要至少需要交代这样一些内容:客户是谁,最终的消费者是谁,项目以何种方式运作(离岸交付,本地,onsite,咨询,培训等),我们帮助客户为消费者带来了什么样的价值。客户的商业模式是什么,在我们周围有哪些类似的项目。 即使在技术方面,也有很多被Dev忽略掉的信息,比如项目在产品环境中如何部署,数据中心建在何处,客户如何运维、监控等。实际的发布周期如何,发布流程如何,客户的内部论坛上都会有很多的这样的信息,但是很少有人关注。从一个项目roll off的时候,这些信息即使做不到了若指掌,至少也能描述清楚,否则难免有些“入宝山而空回”的遗憾。 回顾项目中的挑战 从简单的CRUD系统,到复杂的分布式计算,从企业内部的管理系统,到支持高并发、要求实时处理的交易平台,每个项目都会遇到一些挑战。除了技术上的挑战之外,还有陈旧而无文档的代码库,复杂的业务场景,不配和的客户接口人等等。挑战无处不在,那么作为项目中的一员,你是如何应对这些挑战的呢?最后又是如何解决的? 现实世界是一个充满了trade off的世界,我们需要做种种权衡,代码测试覆盖率和交付压力,性能和客户能负担的机器实例数量,框架A和框架B的优劣等等。我们在采取这个方案的时候,只能舍弃其他方案,由于谁也无法在事先准确预料采取某个方案一定是对的,那么在一个失败的方案背后,其实也是一个很好的教训,至少可以为未来的决策提供帮助。 遇到的最大的挑战是什么? 这个挑战是如何被解决的? 如果有机会重做,你会如何考虑? 其他练习 这里列出了一些我常用的,辅助性的练习。它们可以帮助你更好的梳理项目上学到的技能、知识,并且转换成你自己的知识。这些练习未必一定要等到项目结束之后才做,事实上它们都可以应用在日常的工作中。 记笔记 写博客 在办公室内演讲 去社区贡献话题 很多人都会记笔记,但只有一小部分的人在记录之后会持续翻阅。很多人会使用Evernote/印象笔记之类的工具将一些临时的想法,问题的思路,知识点的细节等记录下来,但是仅仅记录是不够的,笔记需要不断的检索、整理、提炼、修正、总结和归纳。在不断的加工之后,这些笔记可能会得到沉淀,并升华形成一些更有意义的内容(比如个人博客,或者可以发表到InfoQ/IBM DeveloperWorks平台上的文章等)。 除了记录笔记之外,写博客也是一种很好的总结形式。通过将素材不断充实、整理、完善,最终形成一个可供别人直接消费的文章,不但可以锻炼到总结能力,还可以很好的提升表达能力,而且可以帮助你将已有的知识体系化。如果你的博客写成了系列,也很容易通过Gitbook等将其发布为一本电子书,从而影响更多人(说不定还可以赚点咖啡钱)。 写博客/电子书,终究是书面形式的。事实上一个人可以很容易的通过文字将自己的实际情况隐藏起来。举个极端的例子:如果有足够的动机(比如公司的KPI要求),即使不熟悉某种语言/工具,仅仅通过Google,一个人也可以通过这种“作弊”的方式写出一篇“专家级”的文章。但是对于演讲这种面对面的形式,则基本上无法作弊,从而也更具有挑战性。另一方面,对于一个新的知识、技能,自己掌握是一回事儿,要讲出来让别人也能听懂,并从中收益,则完全是另外一回事儿。作为咨询师,语言表达(包括书面和演讲)能力的重要性勿庸赘言。整理知识,并归纳为演讲,会帮助你将体系化后的知识更好的表达出来。 在办公室里讲session有一定的挑战,但受众毕竟是“自己人”,压力相对会小一些(比如在ThoughtWorks,我们非常鼓励员工为其他人讲session,具体可以参看我的这篇文章)。要在社区中演讲则要面临更大的挑战,通过将话题不断锤炼,不断归纳,最终形成可以在社区分享的话题,则不但可以提高内容的质量,也可以更好的锻炼表达能力和临场应变能力。 不过归根结底,这些活动的重要输入还是对之前项目中的知识、经历的深度回顾。 总结 从项目上下来之后,需要深入思考并总结之前的经验,这种深入思考会帮助你建立比较完整的知识体系,也可以让你在下一项目中更加得心应手,举一反三。如果只是蜻蜓点水般的“经历”了若干个项目,而不进行深入的总结和思考,相当于把相同的项目用不同的技术栈做了很多遍一样,那和我们平时所痛恨的重复代码又有什么不同呢?

January 5, 2016 1 min

我的2015

2015年总结 2015年在不经意间就过去了。又是一年。按照惯例,我会在年末回顾一下这一年自己的进步,收获以及一些感慨(牢骚)。然后对来年做一点展望,看看什么地方可以做的更好。 项目经历 今年基本上经历了三个项目,性质也都不一样: 海外交付 国内交付 国内售前 3月前的项目以及没有什么印象了,依稀觉得项目上的所有实践都是“错”的,可能由于太过与荒诞,所以大脑自行将这段抹去了。 4月到6月在深圳的一个国内交付项目上,交付压力还挺大。不过也是在这个项目上,非常直接的体会到了其他角色的不容易。无论是客户的接口人,客户的项目经理,客户的领导,我们的开发,我们的UX,项目经理,还有交付的lead,所有人都不容易。 《项目经理是大傻逼吗》这篇文章就是为了纪念这个项目,或者说是被这个项目驱动出来的。 6月之后回到办公室,在一个海外交付项目上。说是一个项目,中间其实换了6,7个不同的工作内容(出钱的是同一个客户而已)。总之一片混乱,所幸我们在10月前就结束了和这个客户的合作。这个项目事实上除了锻炼项目上人的耐心外,基本毫无益处。甚至对于很多毕业生来说,是深刻的伤害。 10月之后,我难得的在beach上待了下来,而且一待就是3个月。中间在一个联合国的项目上工作了2周,然后就是为另外一个咨询项目准备了几周方案。当然,闲是不可能闲着的。在beach上,如果不出意外,肯定会比项目上更忙!比如打黑工啊,内部什么系统的改进啊,总是有好多事情。 由于有一些本地的项目机会,而我又不在具体项目上,就来做这个售前的角色。帮助客户梳理需求,分析问题,设计方案,计算工作量等等。但是这个过程往往循环往复,一轮接着一轮,在合同确认之前,需要很多次讨论和交流。这应该不会是我自己的一个方向,在项目上写代码,培养新人,分享自己的学习所得,和他人一起进步,是我自己比较有热情的方向。 技术方面 在海外交付项目上,乏善足陈,项目中用到的也是非常厚重,已经至少10年的技术。通常来看,这样的大组织,没有人对要做的事情真正关心。好不容易遇到一个特别靠谱的人,结果我们的项目又结束了。国内项目上倒是有很多有意思的东西: 如何在前端代码中很好的使用MVC 流畅的前端开发模式 如何做前端的测试 上面这三点,我希望可以找时间整理出一本电子书,可以让没有工程级做过项目的前端工程师能有一个参考。 另一方面,由于项目的压力,和项目人员的特殊性(开发就俩人,一个做前端,一个做后端,要集成就pair一下),所以很多实践都没有应用,比如结对,自动化测试等,做的都不够好。虽然我们很推崇,强调CI/CD的实践,但是当和客户的后端系统集成时,就各种悲剧。 联合国的项目上,技术栈比较新颖,上一家的技术人员使用了他们当时能找到的所有酷炫的新技术,并用在了项目中,然后他们公司被收购。留给我们的在今年来看,依然是比较新的: React Reflux ES6 mocha/chai 而在国内售前,基本上没有写过一行代码,更多是更高层次(高不一定是好哦)的工作。确认需求,估算工作量,确定方案(前后端测试,开发方式,部署策略,自动化测试等等)。 2016年,我希望可以多学习一些具体的编程知识,比如: mongodb 数据分析,数据挖掘 容器技术如docker 书籍 今年读了一些技术方面的书,更多的则是一些非技术类的。《自私的基因》是在2012年11月去墨尔本时,在广州白云机场买的,路上10个小时,读了几页。直到2015年才又拿起来,读了两章左右,基本上颠覆了我之前建立的对“进化论”的认识。 另外读了一些科普类的,比如《哲学家在干了些什么》,《上帝掷骰子吗》等,又扫了一次盲。再就是一些佛教相关的书籍,《西藏生死书》,《能断:金刚经》,《正见》等,人生观和价值观得到了刷新。 技术类的,主要是一些与具体技术关系不太大的,比如《恰如其分的软件架构》,《企业级应用架构模式》,《发布!》,《实例化需求》,《持续发布》之类。 虽然竣工于2014年,但是我的一本著作和一本译作都是2015年才发布出来,那就算作2015年的吧: 《轻量级Web应用开发》 《7周7Web框架》 社区 今年在深圳的时候,有幸和ThoughtWorks的首席科学家马丁.福勒在同一次活动中作为讲师。 回到西安之后,在本地社区中还讲过一个前端工程师需要掌握的技能列表的session 2016年希望可以做一些更加深入的topic,以及一些更有意思,可以帮助到更多已经在路上的工程师们。 People Development 这个不知道如何翻译了,但是确实做了一些具体的事情: 给我的sponsee们安排了读书会 组织了一次《编写可维护的JavaScript》的workshop 组织sponsee来做一个side project 组织《Web开发实战》的workshop 我自己总结出来了一套组织workshop的方式,其实很简单: 做好计划,做好课表,做好课件 找学员,同时从学员里找出有基础,而且有意愿接着run workshop的人 讲课,收集feedback,并改进课表,课件 将run workshop的任务传递给那些有基础,而且有意愿接着run workshop的人 2016年希望可以找到更多的候选人,并帮助他们成为更好的讲师,教练。...

January 2, 2016 1 min

使用graphviz绘图

2015年11月10日更新 在实践中,我又发现了一些graphviz的有趣的特性,比如时序图,rank以及图片节点等。在这里一并更新。 ##前言 日常的开发工作中,为代码添加注释是代码可维护性的一个重要方面,但是仅仅提供注释是不够的,特别是当系统功能越来越复杂,涉及到的模块越来越多的时候,仅仅靠代码就很难从宏观的层次去理解。因此我们需要图例的支持,图例不仅仅包含功能之间的交互,也可以包含复杂的数据结构的示意图,数据流向等。 但是,常用的UML建模工具,如Visio等都略显复杂,且体积庞大。对于开发人员,特别是后台开发人员来说,命令行,脚本才是最友好的,而图形界面会很大程度的限制开发效率。相对于鼠标,键盘才是开发人员最好的朋友。 ###graphviz简介 本文介绍一个高效而简洁的绘图工具graphviz。graphviz是贝尔实验室开发的一个开源的工具包,它使用一个特定的DSL(领域特定语言): dot作为脚本语言,然后使用布局引擎来解析此脚本,并完成自动布局。graphviz提供丰富的导出格式,如常用的图片格式,SVG,PDF格式等。 graphviz中包含了众多的布局器: dot 默认布局方式,主要用于有向图 neato 基于spring-model(又称force-based)算法 twopi 径向布局 circo 圆环布局 fdp 用于无向图 graphviz的设计初衷是对有向图/无向图等进行自动布局,开发人员使用dot脚本定义图形元素,然后选择算法进行布局,最终导出结果。 首先,在dot脚本中定义图的顶点和边,顶点和边都具有各自的属性,比如形状,颜色,填充模式,字体,样式等。然后使用合适的布局算法进行布局。布局算法除了绘制各个顶点和边之外,需要尽可能的将顶点均匀的分布在画布上,并且尽可能的减少边的交叉(如果交叉过多,就很难看清楚顶点之间的关系了)。所以使用graphviz的一般流程为: 定义一个图,并向图中添加需要的顶点和边 为顶点和边添加样式 使用布局引擎进行绘制 一旦熟悉这种开发模式,就可以快速的将你的想法绘制出来。配合一个良好的编辑器(vim/emacs)等,可以极大的提高开发效率,与常见的GUI应用的所见即所得模式对应,此模式称为所思即所得。比如在我的机器上,使用Sublime Text 编辑dot脚本,然后将F7/Cmd-B映射为调用dot引擎去绘制当前脚本,并打开一个新的窗口来显示运行结果: 对于开发人员而言,经常会用到的图形绘制可能包括:函数调用关系,一个复杂的数据结构,系统的模块组成,抽象语法树等。 ###基础知识 graphviz包含3中元素,图,顶点和边。每个元素都可以具有各自的属性,用来定义字体,样式,颜色,形状等。下面是一些简单的示例,可以帮助我们快速的了解graphviz的基本用法。 ####第一个graphviz图 比如,要绘制一个有向图,包含4个节点a,b,c,d。其中a指向b,b和c指向d。可以定义下列脚本: digraph abc{ a; b; c; d; a -> b; b -> d; c -> d; } 使用dot布局方式,绘制出来的效果如下: 默认的顶点中的文字为定义顶点变量的名称,形状为椭圆。边的默认样式为黑色实线箭头,我们可以在脚本中做一下修改,将顶点改为方形,边改为虚线。 ####定义顶点和边的样式 在digraph的花括号内,添加顶点和边的新定义: node [shape="record"]; edge [style="dashed"]; 则绘制的效果如下: ####进一步修改顶点和边样式 进一步,我们将顶点a的颜色改为淡绿色,并将c到d的边改为红色,脚本如下: digraph abc{ node [shape="record"]; edge [style="dashed"]; a [style="filled", color="black", fillcolor="chartreuse"]; b; c; d; a -> b; b -> d; c -> d [color="red"]; } 绘制的结果如下:...

November 10, 2015 6 min