• 27 Mar 2017

    hero-image

    1
    引子

    大约在半年前,笔者去澳洲启动了一个新的项目,在项目初期只有笔者一人,到后来,随着需求的增加,团队也在慢慢的在增加,六月份是3个人, 7月10人, 到12月底已经28个人了。也就就是说一个全新的团队从启动之初到半年之后增加了将近30人,这还是笔者努力控制加人节奏的情况下。其中新人有19个人(完全没有公司经验),这些新人中还包括5个小鲜肉毕业生。有人会觉得说这是一件大大的好事,有人会觉得这是一件应该避免的事。

    觉得是好事的同学,会这么想,团队规模大了,能够大展拳脚了,leverage的人多了,资源也向自己倾斜。
    觉得应该避免这么完的同学,会这么想,短期,快速且绝大多数都是新人的团队启动方式显然太过激进,尤其是最为团队我们还承担着体现公司技术实力的重担。

    笔者认为不到万不得已,还是不要这么玩火,这是一件风险极高的有挑战的好事!

    2
    组团之前

    但是,万一幸运女神降临到你的头上,先深吸一口气,然后,你需要问自己三个问题:

    • 利益相关者期望是什么?
    • 这么快的加人,有什么坑需要我来填?
    • 我要在这个过程中扮演什么角色?
    1. 利益相关者期望是什么?
      一切没有原因的加人,都是耍流氓。就团队而言,利益相关人有三类:客户,公司,个人。

      客户对团队的期望。在上人之前,你需要弄明白的是,为什么要加这么多人,这个团队组件之后,客户对该团队有什么样的期待呢。有些客户是因为这个财年的钱有可能花不完,不把这些经费烧完不甘心,当然这种土豪客户还是稀有动物;有些客户是因为突然增加的商业计划;有些客户是因为有更换供应商的需要,基于技术,行业经验,解决方案上的优势,在其他供应商和你之间TA选择了后者;了解了客户的期望之后,不要给客户设定太高的期望,尤其是不要给他这种错觉——想要多少人都行,这都是小事一件。那句话怎么说来着,“少承诺,多交付!”

      公司对团队的期望。公司处于各种考虑,会对团队有不同的期望。比如,希望团队能够把该客户发展成战略客户,因为客户所在行业能够提高公司竞争力;或者,希望能够体现公司的技术影响力;或者,借此培养公司某一领域(大数据,数据分析,移动应用等)的技术能力和实践。不同的期望也就意味着不同的人员组成,你不会期待一个由毕业生组成的团队在客户那里体现公司的技术深度,同样你也不会期望由一堆技术牛人组成的团队,仅仅为客户提供产品维护工作。理清这个期望,也有助于团队争取合适的资源。

      个人对团队的期望。每个人都有自己的诉求,有的人是为了学习先进的生产关系,有的人是为了向牛人致敬,有的人想带带团队学习学习管理技能,有的人想增强自己和客户沟通的能力。你不会想要把一个只想做前端的开发放到devOps的团队里,你也肯定不想把一个iOS开发放进一个Java后台的坑里,因为这样做只能是互相伤害罢了。所以,你不仅需要找到技能比配的人,更为关键的是目标。

    2. 这么快的加人,有什么坑需要我来填?

      理清楚不同的期望,对于你如何挑选合适的团队成员是非常关键的,当然这是理想情况啦!因为,给你的人永远要缩水于你想要的人,比如能力和经验。 “我需要1个资深开发,2个高级开发再加上3个初级开发”, “好的,知道了,你需要6个开发”, 第二天,你收到了1个高级开发,2个初级开发外加3个毕业生。 回到这个问题本身,是多种多样的,如果要给出一个定义的话,那可以是这样子, “期望和现实之间的差距”。如果在加上限定词的话,可以是“由于过快的加人导致的团队无法达到期望的阴影面积”。好了,定义已经有了,那么我们来看看有什么坑呢?如果团队在任何方面和期望有差距的话,就会形成各式各样的坑,比如:技术坑,沟通坑,项目管理坑,交付坑,业务目标坑,团队建设坑...。那么问题来了,谁来填呢?还用问吗!

    3. 我要在这个过程中扮演什么角色?

      你要做的是搭建一个平台,一个框架体系,供团队成员在里面愉快的和客户玩耍。当然不是说你就是上帝,你说要有风就有风,你说要有树就有树,你更多的是一个协调者,参与者,谈判者,组织者,然后和很多人一起,比如说,客户,团队核心成员等,你起动手搭建这个框架。

      游戏规则非常重要,千万不要成为黑哨,没人知道你的规则是什么,也别说什么没有规则就是最好的规则,或者我们是自组织团队,不需要规则,自组织团队已经是很高境界了,没有多少团队能够达到,所以也就不要指望新组建的团队能够在短时间内成为那样一种理想的存在。

      当然,我们的目标不是限制,不是约束,而这个规则/框架的目标是为了能够支持该团队成为一个高效的交付团队。

    3
    团队建设

    好了,认清形式,弄明白自己的目标,接下来就是具体怎么搞了。

    技术面

    核心目标:构建的是团队的能力

    没有任何一个团队能在组建初期就达到技术能力的最大化,抛开团队协作的成分来看,团队至少需要了解目标客户的商业模式,业务需求,目标用户等,如果涉及遗留系统,还需要对它们进行深度学习,以便为维护,新特性开发或者和新系统集成时做些铺垫。因此团队的能力是需要培养的。不过,同样是能力建设,它确要被分开来看,目的是:给客户信心(能力提升还能给客户提供信心,是的,没错!),为团队设定能力提升目标。怎么分能达到这个两个目的呢?一般会这个分:技术能力应用能力。 来,先看下图 img-large-size-height

    图中有两个蛛网图,分别体现了团队的这两种能力。第一种能力,Technical Skill,主要是指的普遍使用的技术能力,比如.Net技术栈的能力,前端能力,devOps能力,构建的能力,版本管理的能力,自动化测试的能力等,这些能力的特点就是和客户没有任何关系,不管是和客户A合作还是客户B合作,这些都是不已客户为转移的;第二种能力,Application Skill,主要是指与客户强相关的应用能力,比如客户不同系统,代码库,基础设施,架构,甚至包括编码规范。当然,既然和客户强相关,那么不同客户的该类能力的差别就极大了,可以说是客户定制化能力。

    继续回答上面的问题,第一种能力给客户信心,第二种能力为团队提供能力提升目标。较为理想的状态是前者能力足够强,后者能够明确识别被给出团队需要提升的量化目标。我们来进一步解释一下,怎么就算足够强?和如何量化?目标怎么确定?

    先说如何量化,要做到量化就需要标准,它可以是客户定义或者团队定义,其实都没有关系,重点是双方能够达成一致。当然由团队定义的标准且有客户赞同是最好的,因为这样能够量化标准可以从团队的实际情况出发,让能力体现最大化。

    再说怎么算够强,这是相对概念,首先可以定义出满足客户需求的技术能力要达到何种量化水平,再给出当前团队的评估,最差情况也需要刚刚满足开发要求,比如客户想要做一个类淘宝的电商平台,而你的团队能力只能做静态门户网站,这显然是不够的。客户对团队的信心和两者之间的正向差距是成正比的。

    最后说目标怎么定,和客户一起制定,只需要保证步子不要迈的太大即可,且目标应该是阶段性的而非一次性。有了目标和现状,之间的差距就显而易见,于是自然而言的就驱动出各种能力提升计划,它可以是双方出差做知识分享,可以是结对编程,可以是一系列的workshop,以及持续的代码审核等等。

    管理面

    核心目标:构建的是团队的协作体系

    团队管理的核心是如何最大化团队的生产效率,并且随着团队的发展,团队管理的重点也在迁移。以刚刚成立团队为例,管理的目的如何让组员快速进入状态,清楚自己的和别人的职责,以及对事物的一致看法(使命,愿景,价值观,笔者会在之后的文化面提到)。在该项目上,笔者主要从以下三个方面出发:

    1. 标准的新人上手流程。在该项目中快速启动是核心目标,因此如果和让新人能够快速上手,了解客户的业务模式,组织架构,现有系统以及架构,代码库,如何构建部署,已经日常的事物,如请假等,我们把它称之为《新手上路指南》。不论何种形态的指南,有一个很重要的原则就是——宏观到微观。切记新人刚刚进入团队就开始熟悉代码,这样做损失的不仅是长期利益,甚至也牺牲了短期利益,因为不知道为什么而做出的决定,写出的代码不会好的!下图是该项目启动初期,团队快速增加时制定的上路指南,它是一个5天的活动,帮助新人了解客户,了解项目情况,而80%的活动都是在了解宏观的项目上下文,只留给新的开发人员20%的时间真正看看,了解一下代码库。 img-large-size

    2. 标准化工作流程。 一提到流程,很多人可能都会想到臃肿,复杂,冗长,无用,显然这不是实情。千万不要相信『没有流程是最好的流程』之类的理论,否则就这个团队要么像大雁那样自组织,要么就只能布朗运动了,当然成为后者的概率是不言而喻的。标准化工作流程的目的是让这个团队有组织有纪律的运行起来。

    需要制定哪些流程呢?这个问题的答案是随着团队的不同,同一团队的不同阶段而不一样。笔者的原则是,取决于当前团队面临的问题,以为未来的发展目标。在团队刚刚组件的时候,我们标准化了这么几个流程:基础开发流程,请假流程。随着人员不断增加,新的问题出现了,比如,提交代码后构建失败的概率大大增加,团队成员能力参差不齐,被标准化的流程又增加了:构建提交流程,请假流程,分享机制。在后来的时候,笔者开始未团队的未来发展考虑了,我们需要提现团队的技术领导力,于是流程又有新成员:每2周一次的小组长会议,以及同频率的核心成员例会,分别用于项目进度和风险的更新,追踪,以及对未来发展的思考和行动。

    1. 定义组织结构。 看到这个话题,可能读者会想,不就是一个团队嘛,有必要搞什么组织架构吗?会不会太重了?还有我们是扁平化的组织,不要搞那么多层级好不?先回答第一个问题,有没有必要不是说出来的,而是根据实际情况来,团队组建初期,10人以下的时候,Team Lead(以下简称TL)怎么搞都行,就那几个人,双手是能数得过来的,每个人在做什么、需要什么样的帮助、进度怎么样了、能力如何都一清二楚(具体如何从个人转型团队leader可以参见<<从自我驱动到带领10人团队>>)。当团队人数增加到15,20人时,TL就吃不消了。第二个问题,太重吗?那就不一定了,这个完全取决于TL,如果要把组织结构归类的话,不妨把它暴力的不负责任的归为:提升组织效率的和降低组织效率的,前者肯定不重,后者不言而喻,至于组织效率如何定义,则不在本文的讨论范畴。至于第三个问题,层级不意味着不扁平,扁平也不意味着没有层级,两者是没有因果关系的。下图是笔者团队在4个月时候的样子img-large-size-height

    由于团队成员的增加,笔者已经不能照顾到每个人,同时也到了想想未来这么大的团队如何发展的时间点,因为核心成员和STL这两种角色被提出。前者和笔者一起,规划,制定下一步发展计划,后者和笔者一起保证项目的正常交付。

    文化面

    核心:构建的是团队的行为模式

    什么是文化? 本文并不研究它的严格定义,笔者认为它就 > 没有明文规定的团队的行为模式

    比如TA收到指责时的反应,当TA听到不同声音时的行为,当TA发现上级的决定有可能是错误的时的反应,当TA发现别人的开发进度很慢且很有可能会让团队延迟发布时的反应,各种各样不同的行为和反应最终在团队内形成一种模式,没有具体规定和流程,但是人人遵循。在刚刚笔者团队刚刚成立的时候,团队文化建设并没有提上日程,因为人数还很少,但是四个月之后,人数增长到20+,有毕业生,有社招,有自己公司的。那时候出现了一个显著问题,就是大家不愿意表达自己真是的感受。边现在哪里呢?毕业生在团队中感到迷茫,但是他们仅原因私下在自己的小圈子里面分享这些,Senior开发感到迷茫,觉得自己没有表现出应有的价值,但他们也仅仅在团建时和一小撮人私下里吐个槽。显然,团队体量扩张的速度超出了团队的安全感的增长速度,这个混合团队已经没法给大家提供心里上的安全感了。笔者做了这几件事儿:

    • 人员能力培养计划,该计划主要是通过知识分享来提高大家对项目中使用到的关键技术的理解
    • Senior人员胜任力模型,主要描述了作为一个高级开发工程师,TA需要在团队中表现出的行为准则
    • 反馈导入,明确大家对于反馈的正确态度,如何给别人提供反馈以及如何收集反馈,详情请参见《你会给别人提反馈吗?

    前两件事情是在解决个人能力以及团队对自身期望的问题,希望能够通过这种方式,鼓励他们做出与与自己定位想匹配的事情,换句话是说,降低了关键行为的心理门槛。

    当你做完这些,你就能稍稍喘口气了,至少你有很大概率活下来了。

  • 05 Feb 2016

    本文发表在InfoQ<<只需三步,迁移遗留系统到云端>> hero-image

    背景

    在互联网大行其道唯快不破的今天,毫不夸张的说,对市场的响应速度甚至会决定一家企业的命运。我们的客户(房地产垂直搜索平台)就是这么一家互联网公司,为了缩短开发周期,减少 系统投放市场的时间,我们将现有的基于传统数据中心的基础设施迁移到云端,以便获取这种的能力。本文讲从大的方向上,讲述了我们在合作的过程中,一起将老的系统向云上迁移的经验,以及其中的一些实践。在此之前,我们先来看看他们的现有系统。

    现有系统

    img-large-size 图一

    图一是对现有核心系统的一个简单抽象,我们维护了三条业务线(在这里是指以业务为基础的,有独立的产品经理,销售团队,独立结算的团队,下文简称LoB),每个业务线对应的是不同类别的房产的搜索网站,比如商业和住宅。User是用户管理模块,该模块能提供用户管理,书签和搜索管理;Location是位置模块,根据用户的搜索条件给出实际地址和相邻地址;Search Engine用于存储所有信息,并提供搜索功能。可以看出三条LoB虽然是不同的网站,但是它们提供的服务是类似的。不仅如此,它们外观相似度也非常之高,除了主题之外几乎没有差别,同样的用户体验,相同的页面布局,还有非常显眼的标识用来说明他们来自于同一家公司。 从上述原因来看,它们应该集成在一个系统内,但其实不然,尽管这些业务线有如此高的相似度,但是从以下方面它们有着非常大的差别:

    • 部署和配置不同
      由于不同的房产有不同的搜索条件,因此在部署的时候,需要对不同的网站进行不同的配置。

    • 特性和发布时间不同
      不同的房产有不同的目标市场,需求决定了要开发那些特性,做什么样的市场推广活动,因此每个业务线都有自己的销售和开发团队,并且根据市场变化制定相应的特性开发和发布计划。

    • 不同的流量
      图一中不同颜色表示不同的流量等级,红色表示流量最大,黄色表示流量中等,而绿色则表示流量较小。对于不同类型的房产,市场的需求是不同的。

    • 目标客户不同,市场定位不同
      商业地产的目标客户是那些需要开展商业活动的商家们,而住宅房产的目标客户则是那些想要生活或者为子女提供更好教育机会的普通老百姓。

    业务愿景

    在了解了现有系统之后,我们再来了解一下他们的业务愿景,因为没有一家公司的IT改革是脱离业务驱动的,理解业务愿景有助于更加清晰地理解向云迁移背后的原因。同时云策略的适用场景有一个更加直观的认识。

    • 3年后的年营收翻一番

    • 基于LoB的运营模式
      这意味着每个团队将是完全独立的全功能团队,他们拥有独立的系统,具备独立开发,部署,运维,市场,销售的能力。这就为每个团队提供了非常大的自主权利,对业务的扩张和收缩提供非常好的自适应能力。

    • 效率
      这里所说的效率主要是指IT生产活动中的效率问题,本质上讲他们是一个互联网公司,如何能够提高IT系统的效率来支撑业务的发展这是他们所看重的。比如,提高人的效率,开发,上线,测试,运维,线上反馈等等,各个方面的效率问题。

    • 全球扩张计划
      中国恐怕是全球最活跃的房地产市场之一了,同时对海外房产的投资在中国持续升温,他们没有理由放过这个机会的,不仅如此包括在德国,意大利,中国香港都有他们的身影。

    基于以上的种种不同,图一所示的系统架构显然无法满足客户对商业愿景的实现,主要的问题有一下几点:

    • 无法独立运营
      由于这是一个所有LoB都整合在一起的系统,因此业务线之间存在着耦合。试想一下这种场景,LoB1根据市场的反馈已经完成了对房产中介品牌的增强,并且希望在涨价之前上线,因为这将是一个涨价的合理理由。与此同时LoB2正在开发新的页面来满足房产拥有者品牌的需求,但是这个特性只是开发了一半。按照当前的模式我们必须等待LoB2完成特性的开发之后才能一起上线,这样对于LoB1就错失了一次涨价的机会,而下一次涨价窗口将是几个月之后。

    • 资源利用效率低
      通过流量监控我们发现网站的访问量并不是一成不变的,以年为单位,网站流量在圣诞节之前会降低到平时的50%左右,圣诞节之后大概又会回升到平均水平200%左右,而这样的大流量会持续约1周左右的时间。其实这样的情况不难理解,因为在圣诞节期间大家休假,收假之后会迎来一波工作潮。从图一中我们也可以清晰地看到不同组件的不同流量,为了保证整体的响应速度,这个系统始终是以比较高流量的情况部署的,但是由于每个LoB无法独立部署,导致资源浪费的情况非常明显。

    • 扩张成本高
      前文我们提到了全球扩张计划,他们想进入中国市场,于是需要为中国的用户设计一个独立的网站用于提供房源,同时也要将这一扩张作为模式,为将来的向其他国家的房地产市场扩展做准备,为了实现这一目标,我们需要IT基础设施的支撑,能够快速灵活的横向扩张。但是基于现有的数据中心的模式,这将是一个痛苦的过程。

    架构愿景

    通过对原有IT架构的分析,我们发现它是很难支持业务愿景的实现的,因此针对这样的业务愿景,我们勾勒出了能够很好支撑业务愿景的IT架构愿景。

    • 独立业务线
      必须能够按照业务线来独立运营

    • 扩展性
      容易扩展或伸缩

    • 关注
      解决从开发到部署的所有问题,开发人员更加集中的关注如何更快的交付特性,而非各种环境问题,部署问题,发布问题

    • 效率
      提高资源利用率,根据不同的流量情况自适应分配资源。 基于这样的愿景,我们发现云平台能够很好帮助我们实现这样的一种IT愿景,如图二描述了系统迁移到云端之后的架构。 img-large-size 图二 首先,所有的业务线都是独立运营,他们能够自主选择自己何时发布上线,自主选择合适的SLA以及资源来适应流量的变化;其次,对于所有业务线共同分享的组件,独立于业务线之外,分开部署和运营,并且它们也能够根据流量的变化调整不同的资源进行适应。

    迁移三部曲

    当我们知道了现有系统的目标状态之后,下一步就是如何实现这个目标了。

    img-large-size 图三 如图三所示,在向云端迁移的时,从现有系统到目标系统的迁移,这个过程不是一蹴而就的,不是一次迁移就能完成的,而是周期性地持续进行,每一次的前进都是相关系统集成的结果。如果我们将目光聚焦在其中某一个迁移的周期内,这个过程大概分为三个阶段

    第一阶段:识别

    识别就是要弄清楚迁移什么。 对于原有的集成在一起的系统来说,这一过程与聚合更好相反,是把所有聚合在一起的功能特性分析并拆解,这个活动的目的就是深入理解当前系统承担的职责。在弄清楚职责之后,我们就可以更好的识别哪些职责是可以被剥离,拆分,并独立出去的。比如对这个房产搜索网站来说,识别之后发现我们的它的职责主要有:前段展示(桌面,移动),房产搜索,搜索的管理,用户管理,地理位置查询,同时还提供了部分API。在完成了识别之后,就是我们要选择从哪些职责开始入手迁移。这个过程并不是随机的,而是要根据现有的团队能力,业务目标,综合所决定的。 我的建议是从简单的,相对独立的职责入手,如果同时还能对业务发展有所支撑,那就是再好不过了,因为难度低,所以能够在迁移初期给团队带来自信和经验,随着迁移经验和自信的积累,那些耦合度高,依赖多的职责也能够轻松的迁移。以该房产搜索平台为例,在迁移初期,我们选择用户管理职责来迁移,一方面是因为它相对简单,相对独立,另一方面则是因为它对我们进行iOS开发提供了API支撑。

    第二阶段:提取

    在识别出系统职责并确定要迁移的职责之后,则是提取该职责为独立云服务的阶段了。 img-large-size 图四 如上图所示,这一阶段的核心就是将识别出来的职责独立于原系统之外,成为独立的云服务。这个过程有几点需要注意的是:快速创建,它需要快,多快呢?理想状态是创建成功(空服务)后就直接上线(灰度发布),或许这个目标在刚开始迁移的时候比较不容易实现,但是随着迁移自信和经验的积累,它是完全可行的,当然这也是为什么我们要从简单并相对独立的职责做起的另一个原因了;快速部署,我们创建新的服务是从空服务开始的,也就是说除了能在产品环境运行之外,它什么都没有。在这个阶段,我们的目标是将服务提取的两大痛苦阶段:创建和部署,变得简单高效。

    第三阶段:集成

    集成就是将新的云服务与原系统进行对接。 如果说前面两个阶段都是在做准备的话,那么这个阶段就是实施迁移的过程了,可以说这是最为重要的阶段,因为它是新老系统交割的一个时期。在这个阶段会有这样一些活动,首先,识别新服务需要哪些对外的接口,这需要对现存系统有比较深入的了解(当然如果接口比较简单,这一步也可以放在提取阶段来实现);其次,将现有系统中对要迁移职责的依赖切换到新服务上,这个过程有可能是一次完成,也有可能需要持续完成,主要取决于职责的独立程度以及现有系统依赖管理的复杂程度。最后,将该职责在原系统中移除。以用户管理职责为例,这一阶段就是将现有系统与用户服务集成,并将其该职责从系统中移除。

    迁移技巧

    理解完这三个阶段之后,不难看出,每两个阶段之间的转换是否高效,流畅,无障碍,对整个的系统向云端迁移都起着至关重要的作用。在长时间的迁移经验的积累下,我们发现以下的一些技巧能够帮助我们在整个迁移阶段中,平滑过渡。如图五所示,当识别出迁移职责后,Stencil+DevOps能够帮助我们快速创建和部署云服务,在原系统与云服务对接时,可以由测试来驱动,对接之后,监控能为我们本次迁移周期提供很好的反馈,以便开启一下个迁移周期。下面我们同样以该网站为例,来介绍一下不同阶段之间转换的技巧: img-large-size

    图五

    技巧一:Stencil + devOps

    前文提到,这一过程一定要高效,也就是要迅速地创建并部署新的服务,只有这样做我们才能讲这一过程常态化,如何才能做到呢?我们采用了Stencil+devOps。 Stencil就是一个服务模版,它能帮助我们快速生成一个空的服务,包括遵循组织规范的目录结构,标准的监控配置和接口,初始化的构建脚本等,使用Stencil的好处就是能够快速创建符合组织标准化的服务;devOps则用于服务的部署上线,维护,持续集成和发布环境的搭建,当然它同样遵循着组织的标准规范。如下所示,该模版主要包括3个部分:应用本身,部署脚本(AWS Cloudformation),docker配置(用于构建)。 img-small-size

    技巧二:测试

    当我们快速上线一个空服务之后,下一步就是如何快速做两个系统之间的集成,在进行系统间集成时,基本可以分为两个小步骤:定义新服务的接口+与现有系统的对接。定义服务接口可以是很简单的过程,也可以是很复杂,主要取决于原有系统中该职责的复杂程度。但不管复杂与否,定义服务接口的过程都是一致的——消费驱动。不同于将新服务的所有接口预定义出来,它是按照消费者的需求,驱动新服务提供应有接口的,当然这里的消费者指的是现有系统。 img-large-size 图六 从图六中我们可以看出来,现有系统(即消费者)和新服务(即服务)集成过程是由两组失败+成功的测试组成,或者说是由两组BDD组成。首先是消费者侧的BDD,中间人扮演了服务的角色,并且我们假定新服务的接口已经按照消费者的要求实现完成,此时由于消费者并没有完成相应代码的编写,所以我们会得到一个失败的测试,接着便是真正的编码,到我们得到一个成功的测试时,意味着消费者端的集成工作就完成了;接着就是服务侧的BDD,此时的中间人扮演的是消费者的角色,由于服务并没有定义期望的接口,所以我们会得到一个失败的测试,经过编码,我们得到了成功的测试,此时就意味着两个系统之间完成了互联互通,并且有了测试来保证。

    技巧三:监控

    在我们拆分原有系统之前,所有的模块都被整合在同一个系统之中,对系统的监控是统一的。但是当我们将现有系统拆分之后,就转变为多个独立系统,如何保证新服务良好运行,或者说如何实时监控新服务的运行状态对整个系统的稳定至关重要。在实施监控的时候,我们应该考虑这些方面:

    • 健康检查
      以服务为整体做的粗粒度的监控
      img-large-size 主要的目的是为了检查当前服务是否处于运行状态。如果检测出服务属于不可用状态的话,云端的负载均衡会根据预先的配置,删除该服务,并新增加一个全新的服务用于填补空缺。也就是说,基于当前的架构我们更倾向于重建服务而非修复不可用的服务。

    • 资源利用度
      以某个虚拟机节点为整体做的关于系统资源的监控 img-large-size 比如说CPU利用率,硬盘读写,内存利用率等,主要的目的是检查当前的节点是否出现过载或空闲的状态,得到这些状态信息之后,就能做出相应的处理。过载就说明资源无法满足当前的流量,应该增加节点,部署更多的服务来适应大流量情况;空闲就意味着资源是有富余的,应该减少节点,以便降低成本。

    • 日志
      所有服务内部状态的监控
      img-large-size 上面两种监控都无法得到服务内部运行状态,因此日志监控在这里就显示出了极大的重要性,尤其是两个系统间集成的日志,通过对系统日志的监控,使我们具有了监控系统内部逻辑的能力,有了这种能力我们就能够追事故的发生并得到关键信息,进而优化服务。

    总结

    从传统数据中心的基础设施向云端迁移是一个长期的过程,有可能还有很多未知的问题等着我们,但是我们发现在这同时又是一个对现有系统重新认识的过程,在这期间,我们有发现了其中的一些规律,每个功能的迁移都有各自的特点,同时又是相似的,这种相似性提取出来就是,识别,提取和集成。

  • 12 Oct 2015

    hero-image

    1
    同病相连

    最近跟一位同事谈心,他非常热爱技术,是一个不折不扣的极客,不仅如此他有很强的执行力,并能持之以恒,从他的身上我看到了未来几年将会成长起来的一个技术牛人。但是,他有比较严重的焦虑症,比如:几天没有看书就会非常纠结,通常情况是他需要花时间来陪孩子和家人,他会感觉自己浪费了宝贵时间,精力无法集中在当前所做的事情上。我接触的同事中,越是对技术有追求,好像越是有这样的感觉,算起来这种不安的感觉应该属于特定程序员群组中一种典型现象,其实做为导师的我也是常年被这种感觉所困扰。 他是这么描述自己的:

    我已经工作4年了,但是我在数据库底层HTTP协议并发分布式系统都没有深入地理解,我觉得特别害怕。

    不用讨论工作4年的程序员应该有什么样的表现,掌握多上技术,深度如何,视野是否开阔,我们来看看别人眼中的他吧:

    • 对技术极度有热情
    • 学东西非常快,几周时间就搞定了Ansible, Chef, Puppet
    • 阅读非常广,除了技术之外,涉足项目管理,金融,心里,社会等

    看看他的书单(我截取了其中1/4的一年要读完的书单,实际上他读完的书比计划要多),也会对他有更深刻的认识:

    • 像外行一样思考,像专家一样实践:科研成功之道(修订版)
    • 古今数学思想(新版·典藏本)(套装全3册)(第1~3册)
    • 思考,快与慢
    • 数据化管理:洞悉零售及电子商务运营
    • 探索复杂性
    • 日志管理与分析权威指南
    • ...

    2
    心理学上的安全感

    安全感是心理学研究中的重要概念之一,最早见于弗洛伊德精神分析的理论研究。虽然国内外对此做过诸多研究,然而对于“安全感”至今尚未达成共识,以下列举了一些关于安全感的定义:

    • 弗洛伊德认为当个体所受到的刺激超过了本身控制和释放能量的界限时,个体就会产生不安全感。换句话说,在弗洛伊德的精神分析理论中,冲突、焦虑、防御机制等是由个人幼年、成年阶段某种欲望的控制与满足方面缺乏安全感造成的。
    • 人本主义心理学家马斯洛最早对安全感作出了明确界定,指出“安全感”是一种从恐惧、焦虑中脱离出来的信心、安全和自由的感觉,特别是满足一个人现在和未来各种需要的感觉。
    • 安莉娟等对精神分析理论、人本主义心理学理论中的安全感理论进行总结,提出安全感的定义为:安全感是对可能出现的对身体或心理的危险或风险的预感,以及个体在应对处置时的有力无力感,主要表现为确定感和可控制感。

    从以上的定义我们大致能够看出安全感大致有两大要素:负面的外部刺激正面的内在能量。简单来说当内部能量能够抵消负面的外部刺激,人是有安全感,因为我的“能量结界”没有消散,反之则没有安全感,没有人会在“能量结界”被打穿之后还怡然自得。那么这个“能量结界”的大小就是所谓的舒适区域了,如果用绿色表示很安全的话,那么舒适区域应该是中心是深绿色周边是浅绿色的圆。理所当然,随着它的范围的增大,个人的舒适区域也就不断的增大。

    为什么会焦虑

    人为什么会焦虑,当某一件能够刺激内心产生负面影响的事情发生时,人们就有可能会产生焦虑的情绪。这是一种缺乏安全感的情绪和典型表现。在学生时代,我们会因为惧怕考试失败而焦虑;在职场上,我们会因为无法完成某项工作而焦虑;在孩子的教育过程中,我们会因为担心无法找到合适的学校而焦虑;在人到中年时,我们为因为身体的退步而焦虑。因为我们无法确定能否处理这种情形。因此对于一些场景,我们到会显得十分从容,“开卷考试,有书在手心中无忧”,“跟自己的下属沟通绩效问题,轻车熟路”,“住在一个教育资源较为发达的地区,孩子的教育问题就显得不那么明显”,“每天花半小时来做慢跑,非常显著的改善身体状况”。

    奇普•康利(Chip Conley)在他的《如何控制自己的情绪》很好的阐释了为什么会焦虑:

    焦虑 = 不确定性 * 无力感

    在讲述如何控制焦虑者众情绪时,他分享了一段TED上的经历:

    TED曾要求我谈谈幸福的无形资产,以及商界和政界领导人应如何开始学习衡量和重视人生最有意义的东西。这似乎是一个无情的讽刺,我的任务是登上讲坛,以一个专家的身份,探讨一个那时连我自己都觉得难以捉摸的主题。尽管我在《巅峰》一书中宣称要以自我实践的方法来经商,但我已经失去了那种神奇的感染力。“我陷入了觉得自己无用的思维定式,而能够克服这一挑战的唯一办法就是写下有关我人生经历的演讲词并练习无数遍。我以为追求完美是缓解焦虑的良药。你也许有过类似的遭遇,认为设定目标会让自己舒服。但事实是,追求完美只会放大焦虑。在接下来的几个月里,我一直痛苦地写着一份以幸福为主题的演讲词,这一次和我正常准备演讲的经历完全不同。我的风格是倾向于即兴发挥和贴近听众,而非机械式和反复演练。于是越临近TED大会,我就变得越焦虑。我的演讲被安排在会议的最后一天(就在电影导演詹姆斯·卡梅隆之前)。所以当我抵达会场时,我还有5天痛苦难熬的日子,要在聆听其他演讲者发言中度过,这使我越发焦虑。”

    因此,越是不确定或者超出自己能力的事情,焦虑的情绪就越容易产生,而越是这样,从这种焦虑情绪正挣脱的信心就越低,不安全的感觉就越强。

    3
    哪样的程序员更有安全感

    每个人都有一个自己的舒适区域,结合内部舒适区域和外部期待,下图能说明一些问题: img-mediu-size 根据上图所示,具有安全感的程序员一般长这样:

    跃跃欲试,接受挑战, 扩展自己的舒适区。我们的身边总是不乏这样的人,他们跃跃欲试,脸上总是挂着自信的笑容,总是各种场合中的焦点,从来不满足现状,每每有新挑战时,总会看到他们的身影。 如果用动态的眼光来看待他们的话,我们会发现他们的舒适区域始终处于一个动态的过程——始终在扩张之中,或者说他们在不断GET新技能。随着舒适区域的扩张,个人追求不断实现,而个人追求的实现,又带动其自身的扩张,还有什么比实现自己目标多带来的自信和成就感更足呢。等待的,将是社会期待的增加,也就是你的同事,领导对你有了认可,并提升了他们对你的期待,随之而来的将是更有挑战的工作,又一个扩展自己舒适区域或者GET新技能的机会便发生了。

    快速学习, 迅速减小社会期望和舒适区的差别。程序员的一个非常厉(ku)害(bi)的技能就是学习能力。除去被逼迫的成分外,这是一个非常实用,堪称看家本领之一。因为IT行业技术迭代速度之快令人发指,当某一项技术还没有熟悉的时候,关于该技术的缺陷以及改进方案已经吵的很热了;当你刚刚为掌握某个软件开发实践而洋洋得意时,突如其来的xxx已死之说,真是让你死的心都有了。其中的例子数不胜数,我们不妨看看(一个例子说明)。ThoughtWorks对员工有这么一个要求,每年至少学习一门编程语言,其实真是不多,实际上每年学习的都要远远多于要求。因此,强悍的快速学习能力,能够快速武装自己,胜任新的工作,提神核心竞争力,迅速扩大舒适区同时减小社会期望与其的差别。当然,并非所有新技术都值得学习,但是有两点值得提出:1. 新技术的思想能够扩展自己的视野,拓宽自己的思路;2.新技术的获取,能够大大提升自己的学习能力,你会越学越快,这个加速度会一直保持到你的大脑达到生理水平的巅峰。

    很强的执行力, 减小不确定性. 它的反义词大概是“拖延症”,俗称懒病。某百科上给出了这样的解释:

    严重的拖延症会对个体的身心健康带来消极影响,如出现强烈的自责情绪、负罪感,不断的自我否定、贬低,并伴有焦虑症、抑郁症等心理疾病,一旦出现这种状态,需要引起重视。

    看到这里,相信很多人都中招了吧。无限的拖延,无法正面改变即将发生的事情,但是它却能极大的增加事情的不确定性,并且随着事情的临近,这种不确定性在内心中的焦虑反应呈指数级增长,反过来,这种情绪又反哺拖延,除非有强大的外部力量介入,强行打破这种负能量闭环。说的这么高端,有没有实际的例子呢。不仅有,而且非常多,很多人大概都有这样的经历吧,在年终总结的截止日期的前一天晚上,奋笔疾书加班加点的写总结,又或者在做演讲的前一天晚上,开始写PPT。

    4
    获取安全感

    Rule #1: 学习那些自信满满地程序员们

    当然也需要甄别一下啦,有的人可能只是看起来很自信。不过上面提到的三个特征应该是妥妥的能够提升你的安全感的办法。其实我在写这条建议是,很是纠结。纠结在哪呢?我觉得内心没有安全感的程序员极度“肤浅”的分成两类:懒和其他。据非常不负责任统计(看看周围的人),其实很多时候还是因为懒,如果是真的懒,那就没救了。

    Rule #2: 通过焦虑情绪公式来提升安全感

    发动数学天赋,当某人或事情让人感到焦虑时,这两件事情能够帮忙:

    • 制作一张平衡表列出你知道的和你能影响的,它可以帮助你消除不确定性,去掉你对不知道的事情的神秘感,明确你所面临的是什么。因为焦虑只会潜藏在黑暗中,人们对不了解的事物有一种天然的恐惧,就好比美味的螃蟹在一开始的时候并不是每个人都敢吃的。然而黑暗中的不明事物也有可能真的是你所恐惧的事物也说不定,但这又有什么关系呢!当你知道原来在黑暗之中潜藏了一个恐怖猎人——霸王龙,你的对手已经清晰了,接下来要考虑的是你是否有能力对付的了它。你的焦虑情绪现在全部由无力感组成了。 img-mediu-size 当你把所有的相关因素归类到这四个象限后,也就意味着能够帮助你消除的计划产生了:你不需要对不能影响的事情做出任何反应,因为只是徒劳而已;你需要做两件事情,弄清楚那些不知道的因素,做一些能够对解决当前问题产生正面影响的行动。

    • 想想最极端的结果,降低无力感,如果最快的结果也是能够承受的,那还有什么是输不起的呢,更何况通常最坏的结果都不是最坏的,最坏的是由最坏的结果所引发的内心恐惧,焦虑和不安的负面情绪。当然每个人的无力感是不同的,因为每个人的舒适区域是不同的,舒适区域越大,无力感想对会越小。这很好理解,因为从概率的角度来讲,你能处理的问题范围,把握度会随着舒适区域的增大而增强。但直面极端结果是一个普适的方法。一方面,往往当最坏的事情发生时,你却释然了,反而一身轻松,能够坦然面对。这正是该公式所表达的核心思想之一,当结果发生时,不确定性为0,焦虑的情绪得到了释放,你当然会前所未有的轻松,这也是为什么人们到了让TA抓狂的事情发生时,却能坦然处之,临危不乱。另一方面,想想最极端的结果,有助于你评估失败的代价,很多时候人都是被自己或者他人吓怕了,一旦评估的结果并没有那么不可接受,自然也就没有必要战战兢兢的过着了。

    Rule #3: 匹配外部期待和个人能力

    float-left

    左图是一张耶基斯-多德森定律图,其中包含三个要素:效率,动机和任务难易程度。在一般情况下,动机愈强烈,工作积极性愈高,潜能发挥的愈好,取得的效率也愈大;与此相反,动机的强度愈低,效率也愈差。因此,工作效率是随着动机的增强而提高的。然而,心理学家耶基斯和多德森的研究证实,动机强度与工作效率之间并不是线性关系,而是倒U形的曲线关系。具体体现在:动机处于适宜强度时,工作效率最佳;动机强度过低时,缺乏参与活动的积极性,工作效率不可能提高;动机强度超过顶峰时,工作效率会随强度增加而不断下降,因为过强的动机使个体处于过度焦虑和紧张的心理状态,干扰记忆、思维等心理过程的正常活动。

    因此,你需要做的是让别人更好的了解自己,如果你觉得自己很厉害但是确没能让别人知晓,那么别人对你的期待就会低于你的预期,你将要做的工作的难度也不太可能匹配你所掌握的技能,当然面对这样的工作,估计大部分人也没有新鲜,激动,亢奋,大鸡血的感觉吧。另外一方面,如果你给别人的感觉是很牛X,结果有可能让你面临超出自己技能很多的任务,这会增加你的焦虑,降低你的效率,影响个人的名声。

    Rule #4: 焦虑,焦虑着也就没那么焦虑了

    说了这么多,感觉焦虑是一种要完全消灭,即便不能消灭也叫尽量避免的情绪,但凡事没有绝对,完全没有焦虑这种情绪也是不可取的,程序员需要适时地扩大自己的舒适区,而且焦虑也有它正能量的一面。

    走出舒适区会增加人的焦虑程度,从而产生应激反应,其结果是提升对工作的专注程度。在这个区域中被称作最佳表现区——在这个区域之中,人的工作表现将会得到改善,并且他们的技巧也会被优化。但是罗伯特 耶基斯(1907)的报告中提到“焦虑可以改善工作表现,但是当超过某一最佳激励状态之后,工作表现就开始恶化”,如果一个人离开最佳表现区,他将进入一个危险区,在危险区中焦虑程度的上升或者舒适程度下降会带来工作表现的快速恶化。

    所以在绩效管理之中管理者,或者是教练应该让人进入最佳表现区,并且维持一段足够的时间,从而达到更好的工作表现,提升他们的技巧,并且将这些表现和技巧固定下来。同样的道理,在目标设定之中改变焦虑的程度就会改变工作表现。

  • 10 Sep 2015

    hero-image

    新的机会

    有一天,你的老板找到你,他说你这段时间的表现都非常不错,我很欣赏你,正好呢,另外一个团队需要一个头,于是他决定把你提拔为那个团队的项目经理。这时的你可能会这么想,我将屌丝逆袭迎娶白富美。

    如果你,正在经历这种转变,从自我驱动到带领团队这么一个过渡阶段,那么恭喜你已经成功的,走过了《领导梯队》的第一个层次,并且迈向了更高的层次,这也是职业生涯的第一次晋级。 不过咱们也别高兴的太早,因为,也有不少人没有成功转型,没有屌丝逆袭,也没有迎娶白富美。

    想想以下几个问题:

    1. 为什么老板看上我?而不是其他人?
    2. 新的职位需要什么技能?工作内容是什么?
    3. 我要胜任新角色需要做出那些努力?那些我能搞定,那些需要别人帮助?

    这些问题不是打击你的信心,而是帮助你更好,更快的适应新角色。不过转头一想这些问题的答案好像也简单。

    1. 我的技术过硬,踏实,肯干,能解决别人搞不定的事情
    2. 没吃过猪肉,还没见过猪跑。我看我们的项目经理,比我清闲,也就是,催催我们的进度,跟客户开会,管理项目进度,控制风险,制定应对措施,向上汇报。至于技能嘛,差不多就是,协调沟通,资源整合,计划能力,识别风险。
    3. 看样子大部分我都是知道的,如果再找找其他项目经理学习学习经验,应该是错不了了。

    以上的答案还是不错的,已经说明你有很不错的观察能力和总结能力,不过团队负责人的职责可不仅仅是这些。我们先来看一下这个阶段的团队负责人,是什么样子了。一般来说,他将负责以下四个部分。

    img-mediu-size

    • 交付管理。 说白了就是要保证项目的按时交付,为了达到这样的目的,作为项目负责人需要关注交付范围,预算,人员计划,发布计划,并且需要实时监控项目进展,评估是否有潜在风险以及应对措施。
    • 客户管理。 有些团队可能没有我们平常意义上的客户,但是每一个客户都有一个广义上的客户。你可以认为你是boss,就是你的客户,或者是说甲方就是一个客户。作为团队的管理者,客户的所有沟通,合作,都是你的职责。
    • 人员管理。 重点是人员成长,如何帮助组员快速成长,并且在项目中承担更重要的角色。这是一个双向活动,就团队本身而言,需要组员成长一边提升交付能力;另一方面,作为组员提升自己的能力当仁不让。
    • 过程管理。 主要是日常项目活动的章程,比如说新人如何更快的上项目,软件开发过程中的各种实践:站会,迭代计划会议,结对编程,代码检视,持续集成,当然也包括一些开发之外的活动,比如请假,Team Building等。

    看到这儿是不是突然觉得,其实白富美,还真不容易取,屌丝的逆袭,也不是说说而已的。其实事实也是如此,这是一个非常关键的过渡时期,之所以重要,因为工作内容的转变是一方面,但更重要的是你的思维方式工作方式都发生了巨大的变化,同时,你也需要为此对领导力的成长付出巨大的努力。

    思维方式的转变

    事必躬亲到委派任务。 你不可能完成所有的工作,帮助团队成员成长,并使其承担职责更加重要。比如,你手头上有两件事情。一件事是为下一个90天计划做准备。另外一件事情是,和客户的,技术带头人,讨论某一个系统的未来架构。作为从技术出身的人,并且现在还在做着技术相关类工作的你,对于后者,是,更有把握的。以当前的团队领导阶梯储备情况,你必须亲力亲为这两件事情。渐渐的你会发现这样的事情越来越多,你从开始的逐渐适应变成了陀螺,忙得不可开交。其中一个非常明显的信号时,你的会变的很多,一些会在刚开始的时候对你来说是有价值的,有挑战的,但到了后面,就是失去的原来的价值。因此你要做的是讲自己的工作或者职责一一列举,进而考虑那些事情必须自己来完成,哪些事情可以委派给别人完成。这样做的好处显而易见,集中精力做应该做的事情,给别人以成长的机会。

    我有一个同事,他是某一个项目的负责人。有一次我们在聊天的过程中,他向我吐了一肚子苦水,主要是他多么多么的忙,甚至很多时候都不敢请假,即便生病也得扛着去上班。我请他列举了一下他所忙的一部分事情:

    • 所有跟客户的沟通都由他进行
    • 每周跟客户开一次项目状态更新会,他需要找多人收集信息
    • 主持没填的各种实践:站会,代码检视
    • 每人每月的谈心
    • 考虑如何做人员培养
    • 组织Team Building
    • 督促大家按时填写Time Sheet(简化版的工作日志)

    看到这样的工作列表,的确是没法请假。但是稍加分析一下,我们很快就能得出“不必事必躬亲”的结论,假如把其中划线的部分去掉,他的工作量将大大减少。《专业服务公司的管理》一书中专门就提供专业服务的公司的共性问题——授权不足展开了论述,它的危害主要有:降低项目的利润,影响职业发展,降低士气,缺乏对未来的投入等,如果有兴趣也可以看看这本书。

    培养自己的领导梯队。 说白了就是培养自己的得意助手。在某一方面可以成为的你备份,可以让你委以重任的人。如果我们拿交付管理举例子的话,你的成长轨迹应该是这样的:积累知识,从实践中学习;总结,形成理论观点;培养,构建自己的接班人。之后你的接班人再做同样的事情,生生不息。如果这样的事情持续进行的话,我们将会看到一个领导梯队不断的团队,就像是一个梯子一样,而你再梯子的中间,既为整个梯队培养人才,有成为别人的培养对象,这是一个健康的团队的表现。在ThoughtWorks我们有一条不成名的规定,如果你想从某一个项目roll off,请找到你的接班人。大多数的情况是,这样的接班人需要你自己来培养,这也是作为高级咨询师的职责和技能的一部分。

    工作方式的转变

    从关注局部的关注整体。这个阶段对可能出现的问题就是只见树木不见森林。你必须从只关注一些开发细节转变为能够关注项目的宏观层面,比如项目的交付进度,日期,潜在的风险以及相应的处理。举个例子,原来的你有可能只关注特性的开发,但是现在的你需要关注开发的整个生命周期=需求分析+开发+测试+部署+上线,每一个阶段无需深入细节,但必须在你的视野之内。从另外一个角度出发,也只有当你成功的培养了组员,并适当分配任务,才能在不陷入所有细节的情况下,对全局有所把握。反之,则需要你自己来发现所有细节,以便对整体有所把握。

    我和客户会定期的开会,来更新项目的整体情况,由于同时管理了多个小项目,但我仅仅工作在其中一个,所以无法得到所有详细信息,当然我也无需了解所有。每次开会之前我的准备工作就是,找到其他小项目负责人,了解一下信息:

    • 项目的整体进度
    • 是不是按计划进行,如果不是,是由那些因素导致的?
    • 有没有风险,如果有是什么?相应的对策是什么?
    • 有没有人员变动?
    • 。。。

    从追随者到领导者。所谓屁股决定脑袋,作为一个普通组员,我所关心的事情无非是写好代码,配合项目负责人,其他一概不管。很多情况下,我的工作内容是别人指定,更多的是扮演追随者的角色,但是作为团队负责人,则大大不同,你需要完成一个被决定者到做决定者的转变。这种角色的转变是不容易的,因为它所涉及决定的方方面面,不仅如此你还需要为结果负责。所谓事不关己高高挂起,当事关己时,则纠结不已。

    小气鬼。在对外时,如资源的协调,一定要有鲜明的立场——团队的利益是首要的。如果你的观察够仔细,你身边的项目负责人也够优秀,你就不难看到这样的场景——一个为了找到最佳人员的项目负责人和另外一个项目负责人争的面红耳赤,争执结束后他们又继续是好朋友。

    总结

    虽然仅仅是10人团队的管理,但是其中所蕴含的基本道理却是与管理100人1000人有共通之处。而从自我管理到管理他人的转变却是质的飞越,这个过渡中的思维和工作方式转换对该阶段的人来说,至关重要,希望各位能够好好把握个中关键成功转型。

  • 05 Jun 2015

    几个例子

    你会提反馈吗?不急回答,我们先来看几个例子。

    Feedback

    例子一:
    项目经理:“xxx,我本来对你的期望特别高,但是你让我有些失望啊。”
    xxx:“啊,不知道哪些地方做的不好呢?”
    项目经理:“本来我想让你承担更多的项目管理的工作,你就是我的备份,但你并没有做太多类似的事情” xxx:“哎,最近项目实在是太忙了,只顾着写代码了。” 项目经理:“只关注自己的工作是不够的,你需要更高的视野,需要从整个团队的角度出发思考问题。”
    xxx:“是的,是的,这阵子忙完了肯定会多关注的。”
    项目经理:“另外,有人给我提过你的一些反馈,说你的沟通不是很好。”
    xxx:“没问题,我一定改善跟别人的沟通”

    例子二:
    某次代码检视会议上,
    同事A:“这段代码不够简洁,逻辑表达也不是很清楚,而且还出现了重复”
    同事B:“是有点,我还没有来得及重构”
    同事A:“我觉得你的重构技巧需要提升,我看了上一次的重构代码,发现还是不理想,这些都是非常基本的面相对象常识”
    同事B:“。。。”
    同事A:“我觉得你可以看看《重构》和《Clean Code》,这对你代码能力的提升是很有帮助的,否则这样的代码还是会出现的。”

    例子三:
    不记得这是第几次了,团队其他成员吃中饭所花费的时间又一次超出了他心中的预期, 如果是原来那也无所谓,但是现在的特殊情况在于客户也在办公室和他们这个团队工作, 终于在一次午饭时间已过去半个小时是团队中只剩下自己和客户的情况下,他给全组发了一封邮件,

    标题:现在是1点50,但是除了xxx,客户A(中国人)和我,其他人都不在office
    内容:我们要把客户A当成真正的客户,假如另外一个客户也在这边,我们会这样吗?客户A会怎么想呢?

    问题出在哪里?

    其实以上的例子还有没有结束。

    例子一:
    当他们完成聊完以后,xxx摸了摸头上的微汗,心想终于结束了呢,心中不禁窃喜,看来项目经理 还是我的,不过他说的这些问题我怎么改进了,项目管理工作,沟通,感觉好宽泛。最终xxx还是没有达到 项目经理的期望,因为他根本不知道这期望是什么。

    反馈不具体,不直接。 项目经理的反馈太过模糊,“太多类似”,“思考问题”,这些模糊的形容词和目标不明确的动宾短语,组成了反馈的主要内容。它们本身是没有承载多少信息量的,偏偏在接受者听来感觉好像信息量很大的样子,但是又捉不住对方想要说明的关键点。

    例子二:
    同事B下班以后非常沮丧,作为一个毕业生他已经很尽力,其实这些书他都在看, 不过对他来说有些难,还需要一些时间。

    反馈的时机不对,没有争取对方的同意,最好的私下交流。

    例子三:
    当看到这封邮件时,传达到团队成员的信息是“你们不专业,态度不正确。” 邮件发完不久,他就收到了来自多个团队成员从手机端发来的回复,有的在分析本次吃饭话费时间的合理性, 有的认为是“大题小做”,有的则在说是不是“积怨已久”(其实他是对的)。

    反馈没有根据事实本身而是混杂了个人情绪因素,不仅如此反馈中的内容还增加了对对方态度的负面评价。

    如何做的更好?

    • 具体,直接
      具体直接的反馈有一大好处——使对方非常容易领会提供反馈人的意图,而这是反馈最核心的目的。 通常我们遇到的问题是,提供方经常会在不经意之间将具体的问题抽象化,或者是经过加工的, 所有的这些都是对简单朴素目的的干扰,以至于接受者会这样的疑问“请举个例子”,“比如说。。。”, “能具体一些吗?”。一个简单的技巧就是以某一件事情开始。

    • 针对行为本身
      对事物的认知可以为三个阶段:

      • 描述:客观存在的事实,不包含任何个人猜测
      • 解读:根据场景进行的猜测,个人的解读是不同的(背景,经历,教育等)
      • 判断:带有个人感情色彩的解读

      我们必须承认人对事物的认知是不同的,它跟每个人的经历,教育背景,工作经验,家庭,所出环境都是有影响的,因此对于同样内容的理解也是因人而异,值得注意的是,尽管当我们为对方基于某个事件而提出反馈时带有个人解读,但是具有感情色彩的判断是不建议的,尤其是负面的感情,因为它对反馈的效果大打折扣,甚至出现负面效果。这就要求提供反馈的人实事求是,反馈的内容是对方的行为,不要增加任何的主观判断。

      我们来看看这个场景:课堂上,老师看着台下睡成一片的同学。

      老师:“大家都醒醒,都很困吗?是不是不想听我的课?不想听的就出去!” **
      **老师:“大家都醒醒,都很困吗?是不是课程的内容有问题?如果有问题,大家有什么建议吗?”

      对于以上两种情形,显而易见后者更容易被同学们接受。 如果从接受者的角度来看待反馈,我们可以引入一个防御模型来解释同样的问题。 Defense 它有外,中,内三层分别为:行为,态度和价值观/信仰,同时内从对反馈的防御大于外层。 当对方在接受反馈时,如果内容仅仅包含行为的事实,那么这将是一个较为容易接受的反馈, 若是包含对态度的反馈,其效果可想而知。

    • 征求同意
      反馈不是一个单方面的活动,对方的接受程度则直接影响到反馈的效果,同时也为对方接受反馈提供了一些缓冲。试想一下,当对方正在全身心投入的讨论问题时,或者正在解决线上问题时,又或者刚刚分手,这些场景或许都不是合适的时机来给对方提供反馈。

    • 时效
      如果我们把时间当作横轴,把反馈的效果当作纵轴,原点为需要提供反馈的事件,那么这条曲线则是以指数递减的趋势。距离事件发生时越长,我们对当时环境,事件的影响已经做出决定的原因就越模糊,于是对于别人的反馈,当事人的收获也是随着时间的推移而快速减少。因此,应该尽可能快的给对方提供反馈。

    • 一对一
      这是比较推荐的提供反馈的方式,通常情况下一对一的方式是一种更加轻松,更加使人感到安全的方式,在这种环境下,对方更加容易接受提出的反馈。不仅如此,在这种环境下还能激发信任感,使双方能够进行更深层次的交流。

    反馈模版

    上文提到了提供反馈需要的各种手段和需要注意到的方面,其实要在短时间内考虑到所有方面也是不容易的, 因此我们总结了一种方式可以帮助大多数人更好的为别人提反馈。

    观察到。。。,
    感觉。。。,
    觉得呢?

    通过三步为你的反馈提供合适的对话窗口,首先描述一个事实,这个事实是你自己的观察,其次基于你们共同的上下文对该事实进行解读,并提出自己的看法,最后跟对方确认是否接受这样一个事实和看法。有两种可能(废话),如果对方接受,那么接下来的对话将顺理成章,大家一起讨论并制定接下来的行动以便加以改进;如果对方不接受,则需要进一步基于该事实而达成一致。这样做的好处主要有两个:以事实为基础不增加个人感情色彩的判断并且易于开口;另一个则是,即便双方看法不一致,但是也能就这一事实展开讨论,降低各说各话的可能性。

  • 14 Oct 2013

    终于感冒了,在最近较忙的工作,怀孕的老婆以及变冷的天气的共同作用下。 于是果断的发了病假邮件,在家休息一天。本以为可以轻松享受一天的闲适。 不过貌似习惯了忙碌的我,第一时间列举了明天要完成的事情,那些需要别人的协助,那些需要交代给别人。 做完这些看了看表,指针停留在凌晨1点的位置,不置可否的苦笑一声。 同时在心里默默发誓,以后一定要在12点之前睡觉,如果11:30那就更好了!

    根据中国传统医学解释,人体在12个时辰之中各个经络的活动时间是不同的, 23:00 - 01:00 属于足少阳胆经的活动时间,此时正在排毒代谢,如果此时没有睡觉, 等你的就是黑眼圈,和蜡黄粗糙的皮肤,所以女生们得特别注意!

    哦,貌似有些偏题了!好吧,回到正题。睡了,一夜无话。

    和往常一样,被闹钟叫醒了,8:30,习惯性的打开邮件,看看有什么有价值的更新消息, 强迫症啊,强迫症! 不过今天和别的其他一天有些不同,因为感觉自己是个旁观者,局外人。 于是思维被拉宽,拉长,拉高。 想想工作已经3年了,好快啊。

    每天都很忙,每天都貌似很充实。 但回过头来,仔细想想,总结一下这几年自己的职业旅程,貌似都无法清晰得回答:

    "我到底做了些什么?"
    "我想要什么?"

    如果再多想一下,好像现在的我和3年前的我没有区别,从工作状态,心理成熟度, 从职业规划,没有长进,当然生理上还是有的,我更老了,不过这才是可怕的的地方, 没有从过去的工作生活中汲取足够的经验,进行总结,从而形成自己的观点,指导前行的路, 并且坚持下去,持续改进。

    非常喜欢红牛的广告语:“你的能量超乎你想像”,是时候做出改变了。

    • 给自己一个目标
    • 夸夸自己
    • 不妨失败几次
    • 埋头苦干要不时的抬起头
    • 不要总往前看,你身后或许会有惊喜

    共勉吧。

  • 25 Sep 2013

    “微信,是一个生活方式”,这是微信的自我评价,是不是觉得如果那天不在朋友圈里分享一下自己的最新状态,并且收到几个赞和评价的话,会觉得空虚寂寞呢?它实实在在的改变了我们的生活方式。

    “微信,也是一个生意方式”,在微信成为我们日常必备之app的同时,它同样具备巨大的的商业潜力,或许不应该称为潜力,因为有很多人已经获利,名人们在微信上开设公众账户来吸金,商家来做推广,服务行业借此拓展渠道,甚至微信已经支持支付了, 还有越来越的自媒体在微信平台涌现出来。

    这篇文章就是介绍如何快速的成为公众平台开发者,由于个人只能申请订阅号,因此本文是以订阅号为例。 关于订阅号和服务号的区别,请参见微信公众平台服务号、订阅号的相关说明

    从微信用户角度简单来说: 订阅号主要用于信息辐射,典型的如各家新闻媒体。 服务号主要由于自助服务,典型的如招商银行。

    申请公众平台账户

    1. 微信公众平台填写注册信息

    basic info

    1. 按照提示激活邮箱

    activate email

    1. 上传个人照片,需要有清晰的身份证照片

    pic 4. 选择公众账户的类型,对于个人账户只能选择订阅号

    account

    1. 最后一会看到自己账户的所有信息,请上传账号的头像,否则无法完成开发者的申请

    information

    1. 等待审核通过,这个过程大约需要2~3天,当你收到如下通知,那么恭喜你,你已经成功的申请到了微信公众账户了

    validation

    1. OK, 激动人心的时刻到了,是时候进入开发模式了,点击导航栏的“高级功能”,你将会看到两种模式可供选择,请直接忽略编辑模式,进入“开发模式

    developer mode

    1. 注册公众账户的服务器

    这里需要两部分信息,服务器地址和用于验证的Token(用来验证请求来自微信服务器)。 如果你还没有自己的服务器,没有关系,为了完成这篇文章我特意申请了一个微信账户:

    名称:公众账号开发指南
    账户ID:we-chat-tutorial
    服务器地址:http://wechattutorial.herokuapp.com/
    

    这是一个用于示范的服务器,所有的源码都托管在github上,有兴趣的朋友可以拷贝一份,搭建一个服务器。下面我会讲到服务器的搭建。 register your server

    1. 成功就在眼前,当验证完成之后,请打开“开发者模式”,至此所有的账户申请就完成了

    done

    1. 关注你的公共账户 拿起你的手机扫一扫下面的二维码,然后你将会收到一个欢迎消息,接着试试“help”,该账号会返回相应的帮助信息。如果输入其他任何文本,该账户会返回预先定义的图文消息给你。再次声明一下,这不是在打广告,该账户仅仅是用来做样例用的。

    qrcode

    接下来,我们说说如何搭建这个服务器。

    搭建服务器

    微信公众平台是通过消息与公众账号服务器进行通讯,每个消息都会包含如下信息: 微信用户ID,开发者微信号,时间戳,消息类型(文字,链接,图文,音乐,事件),消息内容,消息ID。其中最常用的便是文字类型的消息和关注事件。如果以一个饭店的微信账户为例的话,典型的应用场景可以是这样的:用户输入“menu”,公众账户返回给用户菜单的图文消息。我自己也有一个微信公众账号,这个账号可以提供简单的澳洲商业房产搜索:

    用户输入“澳洲的任何你感兴趣的地址(如:Melbourne)”,公众账户会根据该地址帮你找到排名前5位的商业地产 说到这里有点广告植入的嫌疑,其实这个账号就是3天工作的产物,只是想用来验证一下自己的想法,与公众账号开发指南不同的是它的结果是真实数据。 au commercial

    代码

    所有的代码都托管在github上https://github.com/yangdong/wechat-tutorial.git 该服务器完成了对以下功能:
    1. 响应微信平台的验证请求
    2. 响应用户关注该公众账户
    3. 响应用户查询帮助信息
    4. 响应用户其他文字请求

    部署

    准备工作github账户 Heroku账户
    目标: 将github中的代码部署到Heroku
    工具 snap ci它是一个持续集成工具,能够帮助我们非常轻松的将github中的代码,部署到Heroku上,这样我们仅需要关注我们的业务代码,而无需关心部署的流程。 如果想要深入了解持续集成,可以参考Continuous Integration,同时这本书也不错持续集成
    LET'S GO
    1. Fork wechat-tutorial到自己的github
    2. 使用github账户登陆snap-ci
    snap ci login 3. 为刚刚fork的代码仓库创建一个snap-ci的工程
    snap ci create project

    snap ci会加载你托管在github中的所有仓库,我们选择wechat-tutorial snap ci we chat snap ci creating 4. 为该流水线创建所需要的构建流程,我们只需要增加部署到Heroku
    snap ci adding build stage

    我们选择“Heroku Deployment Stage”,在这一步中,需要你Heroku账户为snap-ci授权,以便于它能够创建和部署应用 snap ci adding heroku snap ci adding deploying wechat to heroku
    5. 等待构建
    恭喜你,已经完成99%的工作了,剩下的1%将由snap-ci为你完成,并且以后永远都是由它帮你完成,你成功的拥有了一个免费的不知疲倦的劳动力了。 snap ci waiting for build
    6. 大功告成
    当你看到绿色的“PASSED”字样时,你的所有部署工作就完成了,你现在就可以访问自己的公众账户服务器了。 snap ci build success

    如何验证你的服务器是否工作正常,很简单,在浏览器中输入“http://你的应用名称.herokuapp.com/?echostr=token”,当浏览器返回“token”时,就意味着你的服务器已经就绪。

    写到这里,如何申请微信公众账户,和服务器的搭建就介绍完全了。接下来所需要的就是修改服务器代码,以便适应自己的业务需求。如有问题,可以关注我的微博,或者发邮件给我don.yangdong@gmail.com, 谢谢!

  • 18 Jun 2013

    回顾

    上一篇文章中介绍了function在javascirpt作为一等公民所担任的重要责任,在不同 的上下文中它担任着不同的角色,在对象内部它可以是函数,同时又能充当名字空间,不仅如此所有的function都是闭包。看起来它的确是了不得,不过除此之外,function还能担当构造函数,亦或者说它同时还是一个类的声明。

    这篇文章的目的向大家详细介绍function是如何作为构造函数

    如何定义一个函数

    • 声明式

    函数定义最常用的方式之一。

    //声明函数
    function add(x, y) {
        return x + y;
    }
    
    //声明构造函数
    function Animal(name, age) {
        this.name = name;
        this.age = age;
    }
    
    Animal.prototype.bark = function() {return 'bark'};

    其实这两种发式完全一样,没有任何区别,你同样可以为add的prototype属性增加新的函数或者属性。不过两种方式是基于不同的用途产生的,我们之所以称后者为构造函数,仅仅因为它的命名函数实现

    命名: 对于构造函数我们遵循首字母大学的规则以区别普通函数和方法,这和java中对于类的定义是非常相似的。
    实现: 构造函数是我们用来生产实例对象的工具,它通长与new关键字连用,如

    var dog = new Animal('pipi', 3);
    dog; // Animal {name: "pipi", age: 3}

    同时你可能也注意到了Animal中使用到了this关键字,通长情况下this会指向函数的调用对象,也就是说如果你在浏览器中运行一下代码,你应该得到window对象:

    function getThis() {return this};
    getThis(); //window

    试想一下,如果你这样使用构造函数:

        
    var dog = Animal('pipi', 3);

    这段代码会产生什么有趣的结果呢?
    恭喜你!你中招了!
    你会发现,你的window对象新增加了两个属性, 同时没有任何对象产生:

    window.name === 'pipi'; //true
    window.age === 3        //true
    dog === undefined;      //true

    对比使用构造函数的两种方式,其实这都是new在作怪,当我们在像使用java类那样对构造函数new出javascript对象时,它帮我们完成了一些magic(这也是javascript new关键字被人诟病的地方),我们不妨来一次魔术揭秘:

    //魔术
    var dog = new Animal('pipi', 3);
    
    //揭秘
    function newAlternative(constructor, name, age) {
        var obj = {};
        //修改this,指向新对象obj
        constructor.call(obj, name, age);
        obj.__proto__ = constructor.prototype;
        return obj;
    }
    var dog = newAlternative(Animal, 'pipi', 3);
    dog; //Animal {name: "pipi", age: 3, bark: function}

    因此,我们需要非常细心的处理函数,如果它就是‘类’那么请根据潜规则,首字母大写它,并且在使用的时候一定要与new连用。

    • 匿名

    匿名函数广泛在javascript代码中使用,先看看这段代码:

    //定义处理元素的匿名函数
    [1,2].map(function(e) {return e + 2});
    
    //定义匿名构造函数
    var Animal = function(name, age) {
        this.name = name;
        this.age = age;
    }
    Animal.prototype.bark = function() {return 'bark'};
    
    Animal.name === ''; //true
    • Function

    相对与前两种方式,使用Function来定义一个新的function相对少见。如果说构造函数是为生成实例对象而生,那么Function就是为生成函数而生,它是生成函数的模板,构造函数,‘类’.

    var Animal = 
    new Function('name', 'age', 'this.name = name; this.age = age;');
    Animal.prototype.bark = function() {return 'bark'};

    虽然这种方式在实际开发中很少被用到,但是它对我们理解函数的生成过程有帮助作用,对比一下两组代码,我们不难发现Animal其实就是Function的实例对象,就如同dog是Animal的实例对象一样。

    Animal.__proto__ === Function.prototype //true
    
    var dog = new Animal('pipi', 3);
    dog.__proto__ === Animal.prototype;     //true

    总结

    函数在javascirpt中起着至关重要的作用,构造函数是其中一种特殊的函数,他通过和new关键字搭配使用,帮助我们完成看起来与普通面向对象相似的对象构造过程,不过这仅仅是想像而已,我们必须理解其中的奥秘才能是我们不会在编码过程中犯错。 有了对函数的理解,接下来我们变可以将解javascript中的另外一个非常关键的语言特性,继承机制--原型链,敬请期待。

  • 05 Feb 2012

    function作为javascript的核心技术之一,清晰的理解function的机制和用法,对我们进行javascript开发非常重要.

    今天本人就结合自己的实践为大家介绍一些function在javascript中的一些浅显用法.

    function是什么

    从Javascript对function的定义, function是一个由代码集合而成的对象.

    从中我们可看出,我们可以使用向C语言中的函数那样使用function,也可以对function进行面向对象编程.当然Javascript中function的强大还不止如此.

    如何使用function

    定义

    function myfunc(param) {
        //code
    }

    注意Javascript中的这两个function被认为是同一个:

    function func1() {return 'func1'; }
    function func1(name) { return name; }

    在运行时到底调用哪一个function取决于加载顺序,后一个加载的function会覆盖前一个.

    换句话说就是,function的参数都是可选参数,因此funciton的识别是不包括如参的,而函数入参处的声明是为了引用方便以及可读性. 以上的代码也等价于:

    function func1() {
        return arguments[0] || 'func1';
    }
    func(); //return 'func1'
    func('function'); //return 'function'

    function当作对象

    是的没错,在javascript中function就是对象,我们可以向使用一个对象那样使用function.

    它可以有自己的属性和方法.有如下的一个funciton:

    function nameOf(name) {
        return name.toUpperCase();
    }
    • function作为对象进行赋值
    var person = person || {};
    person.nameOf = nameOf;
    person.nameOf('yang dong') // return "YANG DONG"
    • 定义function的属性

    看看以下的代码, 你能从中的到什么信息:

    function nameOf() {return nameOf.blogger;}
    nameOf.blogger = "YANG_DONG";

    没错,function可以拥有自己的属性.

    考虑这样一种场景, 假如我们要统计某个function被调用的次数.那么我们有两种方式来实现:

    ++ 设定一个全局变量来记录,该funciton被调用的次数,每调用一次,该变量加1:

    var globalNameOfCounter = 0;
    nameOf();
    globalNameOfCounter ++;

    这样做看起来是没有问题的,在代码还是比较简单的时候,它可以工作的很好,但是随着代码越来越复杂,维护这段逻辑的成本会直线上升.

    主要是因为:globalNameOfCounter污染的global命名空间,并且破坏了代码的封装性.

    ++ 使用function的属性

    看看以下代码:

    function nameOf() {
    nameOf.counter++;
        return nameOf.blogger;
    }
    nameOf.blogger = 'YANG_DONG';
    nameOf.counter = 0;
    nameOf(); //nameOf.counter = 1;
    nameOf(); //nameOf.counter = 2;

    显而易见,第二种方式有着很好的封装性和维护性.function的属性的应用还不止如此.请看下文.

    function作为名字空间

    Javascript不支持名字空间(本人不太理解如此强大的语言为什么不支持名字空间呢,这是为什么呢?或许是它根本就不需要专有的机制来实现名字空间),

    不过我们依然可以使用其强大的funciton为我们支持名字空间.

    从上节我们知道function可以定义自己的属性,我们就可以利用该特性来生成名字空间.请看以下代码:

    nameOf.getBloggerName = function() {
    return nameOf.blogger;
    }

    此时在nameOf名字空间之下已经包含了:blogger,counter属性和function getBloggerName.

    • function作为method

    在javascript中function和method其实是没有什么本质区别的,如果非的区分两者的话,我想也就是this变量不同吧.

    function g() {return this;}
    var local = local || {};
    local.method = g; //修改this指向local
    local.method(); //返回local对象
    g(); //返回DOMWindow对象
    • function皆为closure

    在Javascript中所有的function都绑定了一个scope chain,因此它是一个保存了调用上下文的函数.看看下面的实例代码:

    var variable = 'global';
    function getVariable(){
    var variable = 'local',
    func = function() {
    return variable;
    };
    return func;
    }
    getVariable()(); //return local;

    当func被调用的时候,它所取的varible的值是调用上下文中的变量而并非与之同名的全局变量.

    总结

    如果用一句话概括今天对funciton的介绍,那么我想应该是: function是可以被调用执行的代码集对象.以上是function的一些应用场景,当然它还不止这些.

    比如: function作为构造函数(也就是funciton作为类),继承等.这些内容将在以后的blog中为大家介绍.

  • 06 Jun 2011

    熟悉敏捷的人,都知道回顾会议。它是一个在每个迭代或者项目结束时,进行的一个团队自省的活动。通过它我们可以知道在过去的一段时间内,什么方面是团队做的好的,还有那些方面不足,已经对于未来,我们团队有什么好的改进建议。

    通过这种方式,我们及时总结团队的得失,获取改进意见,并且制定出相应的措施,去维持团队做的好的部分,根据建议改正现有缺陷,尝试新的实践。

    接下来我要说的是一场比较特殊的回顾会议。 回顾会议经常出现我们的工作中,但是在生活中有人使用它吗? 最近我就经历了一场这样的回顾会议。

    • 背景

    我与女友已经恋爱8年了,我们的爱情始终是比较平淡的那种,没有轰轰烈烈的爱情,也没有大吵大闹。不过我们彼此深爱对方,被同学,朋友称为情侣楷模。这样的情况在最近发生了一些变化,我们彼此开始吵架,情绪变得烦躁,其中最主要的矛盾是围绕在我个人的懒惰, 不关心她和我们的宠物

    • 新的策略

    这已经不是一个新问题了,以往的策略就是“连哄带骗”,过了这个坎之后还是依旧。但是我这次我觉得不能在这样纵容自己了,应该从根本上解决这个问题,同时这也是改正字节缺点的一次好机会。于是乎,一场家庭回顾会议就此展开。

    • 材料准备

      • 白板。没有,使用洗衣机代替。
      • 白板笔。没有,使用水彩比代替。
      • 贴纸。没有,她边说,我边写。
      • 手机。用于计时。
    • 主持人

    本人。(后来发展成被批斗的对象)

    • 与会人

    女友和皮皮(我家小狗)

    • 会议既要

    Safety Check。直接掠过,彼此已经熟悉的不能在熟悉了。
    限定时间5分钟,写出觉得我们在过去两周之内做的好的,以及不好的,和改进意见。
    归类,并投票,选出优先级(票数最多)最高的话题进行讨论。
    根据讨论结果制定相应措施,并分配到个人。

    • 结论

    最终该回顾会议难免的沦为了对我的批斗会。 但是结果是好的,女友为此感到非常高兴。 因为原本那些不可预期的我的个人改正,现在终于有了着落,并且每一个措施都是实实在在的可以检验的。

    我找到了她所期望的方向。 我是木讷的人,不懂女孩的心思,但是这次回顾会议给了我一个天大的好机会。 让她直接表达出我应该怎么做,而不是我去猜啊猜,(猜了也猜不对)。

    一切有回到了应有的和谐。在接下来的几天里我按照当时所定制的action行动,效果还不是一般的好。

    皮皮始终一言不发,开心的对着我要尾巴。

  • 15 Feb 2011

    刚从学校毕业,上班近7个月,先后参加了3个项目,而这3个项目用的技术几乎是完全不 同的,WCF,.NET MVC还有Java Spring,对我来说这些全部都是全新的技术,在学校的时候根本就没有接触过。看着一群非常有激情的同事们在讨论采用什么技术能写出更好的代码,我是多么渴望的希望能够尽快的掌握这些技术,为我的团队作出自己的贡献。新加入这几个项目的开始是惊人的相似,几乎是一个模子刻出来的。

    • 尽最大的可能利用好每天的pair(结对编程)的机会,向他们学习,了解我们的代码的框架
    • 工作之余基本上都用来学习这些对我来说全新的技术,有问题google之,如无解,则在上班时间提出,总有人能够给我答案
    • 阅读已有代码。希望从其中找出关于某些知识点的实际应用,并与我所学的相互验证
    • 团队内部定期不定期的开展关于技术的session,每一节我都不会拉些来

    所有的这些action,无一不显示出我对这些技术迫切掌握的热情。每当解决一个问题,掌握一个知识点,看懂已有系统框架中的一处设计,或者发现code base中的一些可重构的代码,都是满怀欣喜的。当然这就更加的激励了我,看更多的代码,学习的更深入。一切都朝着我们的目标顺利前进。

    一切都看起来很美!!

    但是当我的注意力全部被学习这些技术的热情夺走的时候,我就忘记了思考。

    思考我做这件事的目的是什么?

    有没有更好的方式完成我的目标?

    目的已经清楚了,我想为团队做更大的贡献。是的,当我冷静下来的时候,我还是能够把握我们的目标的。掌握这些技术,无疑能使我给团队带来更多的贡献。看来我做的还可以。 好吧。那为了完成这个目的有没有更好的方式呢。那就的从我的目标说起,什么是对团队的贡献,多些代码?多修一些defect?这样当然是贡献了,但是当我在写代码的时候,我并没有考虑为什么要实现这样的功能,我们为客户提供这样的特性,能给他们带来什么样的价值。或者说我假想一个系统最终用户,在使用这些功能时到底会是一个什么情况。只知道写代码,而不知道为什么写,是一件很可怕的事情!!

    冷静下来之后,我再想,如果我在加入一个新团队的时候,这样做,情况有可能会大不一样:

    • 了解客户的业务,他们是怎么挣钱的

      只有了解到我们的可用的业务,才能有可能为他们提供有商业价值的软件,否则,一切都是未知。即便我们的客户已经对我们非常清晰的指出了他们所需要的功能,这样也是无法保证我们的交付是有价值的。如果说,我们没有能力了解客户所处的领域的业务,我们是否就可以让客户指挥我们给他们提供所想的功能呢。当然,此时的我们仅仅是一个提供商的角色,而不是一个合作伙伴。这两的区别就在于,后者能够为客户提供具有价值的咨询服务。

    • 做一个星期的QA,(当然时间是灵活的)

      在这前两个项目中,我遇到了相同的问题,我不知道如何使用我们的系统?我不知道我们到底提供哪些功能?谁将使用我们的系统?是否觉得有些好笑呢。事实是有这样感觉的团队成员不在少数。在新加入一个项目之后,不应该是急于写代码,而是首先熟悉如何使用这个系统,了解这个系统到底为客户提供了什么服务。在了解了这些context之后,编写代码才会有一个正确的方向。甚至我们在编写代码过程中,能够提出更好的业务领域的方案。

    • 跟BA/QA多多交流

      为什么没有说跟DEV多多交流呢,难道就不重要吗?当然不是,因为Dev间的交流从来都不容易被人忽视。我们公司提倡的是结对编程,Dev们每天都会有很多的交流。同时交换结对,也是我们的知识在所有的Dev中快速的分享。但是跟BA或者QA的交流可能在无意识间就有可能被忽视。这样的忽视不少见,结果可想而知,开发的代码有可能就无法满足业务需求。