你要专业

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

我喜欢这个评价是因为它是我希望自己能展现的一个状态:成为一个靠谱的职场人。关于靠谱的职场人,《重来》的作者之一Jason有一个很精炼的描述:

Work ethic is about showing up, being on time, being reliable, doing what you say you’re going to do, being trustworthy, putting in a fair day’s work, respecting the work, respecting the customer, respecting the organization, respecting co-workers, not wasting time, not making work hard for other people, not creating unnecessary work for other people, not being a bottleneck, not faking work. Work ethic is about being a fundamentally good person that others can count on and enjoy working with. – Jason Fried

歌词大意是:职业精神就是可靠,言出必行,尊重工作,不要浪费时间,不给别人添麻烦等等。不过,精炼的描述往往失之可操作性不够强。就好比知道“高内聚,低耦合”并不能帮助你写好代码一样。在这篇文章里,我打算举一些日常工作中常见的例子,尝试通过Specification By Example的方式给靠谱的职场人下一个定义。

在职场中,靠谱的意思就是:成为一个别人会信赖并乐于和你一起工作的人。而人们喜欢和靠谱的人一起工作。

尊重你的工作

人们站在不同的立场看待同一件事情时,必然会产生分歧。这几乎在项目中随处可以见,比如对于某个Feature,客户认为必须实现,这样在年终的绩效考核中才有令领导满意的成绩;另一方面,对于交付团队来说,技术上难以实现或者工作量太大,难以在有限的时间内完成;开发团队钟爱新的流行的技术栈,而客户则相对保守,需要考虑培训成本等等其他方面的因素。如果再加上沟通不畅,很容易导致团队士气低落,甚至双方互相抱怨。

一份工作,既是企业(企业中的员工)赖以生存的条件,又是企业和服务对象共同为社会创造价值的载体。这个产品可以解决某些人的问题,提高效率,为社会带来价值。工作本身就是值得尊重的。如果你被指派到一个项目上,并且作为个人,你不认为这个项目违背了自己的价值观,那就应该全力以赴去完成它。另一方面,如果你认为项目的价值和自己的三观不匹配((比如,如果有人出钱让你去开发GFW之类的工具;或者一个工具用来监控员工的桌面等)),你完全可以选择不去参加这个项目。

新人常犯的一个错误是将遵循既有规则当成尊重。举个例子,在实际交付的时候,团队中的Tech Lead做出了一项你任务是错误的决策,作为团队成员,你可以据理力争,表达自己的看法,并提出自己的提议。另一方面,你也可以假装这个决策是超出你控制范围的,并且假装它是正确的,然后低头来按照决策来实施。在我看来,第二种看似尊重的行为是对团队和项目的非常的不尊重。退而言之,即使你的提议被拒掉,你也可以从中学到很多之前看不到的知识。一方面可以帮助你自己理清思路,看到自己方案的缺点,另一方面,你可以学习人们在实际项目中,如何对于不同的条件来做妥协。

与他人合作

一个人可以走的更快,一群人可以走的更远 — 非洲谚语

我们的日常工作中,总避免不了要和不同角色,不同经验的人一起工作。和单枪匹马独自作战不同的是,在一个群体中,个人的行为需要遵循一定的约定,需要和其他团队成员一起配合来完成任务。换句话说,要有团队合作精神。在和其他人一起工作时,第一要义是不要为别人制造更多的工作量。事实上,你应该在自己能力允许的前提下,尽可能让别人做最少的工作。相信我,你会希望自己和这样的人合作的。

我们从一个假象出来的场景出发,来看看如何在类似的场景中展现专业性:

CI服务器地址

设想这样一个场景:你所在的团队有一个微信群,大家很多问题都在群里提出并讨论。但是一些简单问题可能被频繁的问道,比如XXX服务器的地址是啥?前两天又有一个新人加入了团队,他今天在群里问了一个之前被回答过好几次的问题:谁知道CI服务器的地址,请发给我一下,多谢!

而这时候,你可以做什么呢?“我之前发过邮件给所有人了,你翻一下邮件”。

这是一个可行的方案,但是需要

  • 邮件标题的关键字 或者
  • 邮件正文关键字

而要做搜索本身动作,他需要打开邮件客户端或者在浏览器打开Web Mail,如果是访问Web Mail,他可能还要登录公司内网(输入密码),还可能要查看Okta推送的消息,这又需要打开手机,切换到Okta,点击确认。如果工作环境网络有vpn的隔离,情况可能会更复杂。

如果你花费1分钟帮他搜一下,然后把地址发给他,并告诉他用户名/密码就是域账号的用户名/密码,效果则会好很多。

访问外部API

如果我们把这个场景在稍微复杂化一点:有人在微信群问如何在Postman中访问获取所有网点信息的API。要访问这个API,客户端需要一个Endpoint和一些特定的HTTP Header。最简单的做法是发送一个截图。

不幸的是,Header中有一个叫做x-api-token,它的值是一个256个字符的hash。这时候图片就变得毫无用处了:你不会期望问问题的那个人用手敲一遍token吧?另一个方法是把API的Endpoint和所需的HTTP Header是分别以文本形式发送给他,(如果这个API需要多个header的话,你可能要复制粘贴好几次)。

再进一步,你可以通过一个cURL加命令行参数的方式将这些内容一次性发送给他:

$ curl -H "x-api-token: token" -H "Accept:application/json" https://host:port/top-security-resources/1

嗯,挺不错的。不过如果明天又有其他人问你要这个API的访问方式,你又要再来一遍,还是比较麻烦。你稍微翻了下Postman的帮助,发现它支持导出,还可以定义一些环境参数等。如果将这些内容都导出出来,然后放在代码仓库中,其他所有人就无需每次都找人要各种URL了。

显然,最后一种方法既满足当前的需求,又有很好的可扩展性,这样你就通过一个具体的问题,抽象出一个高阶的问题,并且为这个问题提供了一个可行的解决方案了。当然,这种方法的缺陷是会占用你很多时间,需要你学习额外的知识。不过,如果是我,我肯定愿意选择这种方式。

帮助团队里的测试

我记得我们曾经有一个研发平台项目,其中一个需求是实现租户代码怀味道识别的工具:这个工具的输入是平台上程序员提交的源代码,然后我们的工具会分析类和类之间的关系,然后给代码评定一个分数:比如集成层次不能太深,不能有多继承之类。代码本身并不难写,但是要测试时需要列举很多case,每一个case至少需要可以能编译通过,这要求测试同事还要会写合法的C++代码,也就意味着他们还需要C++的多继承,抽象类之类。

我花了一些时间(两个小时左右)为测试同事写了一个小工具:通过指定一些参数,比如类的继承层次,是否多继承之类,然后这个工具帮你生成一堆合法的可以编译通过的源代码:包括多个文件,文件之间的引用(比如头文件中定义接口,然后在实现代码中访问这些接口等等)。测试可以很容易通过它来生成测试用例,然后再来验证待验证的工具到底能不能识别这些怀味道。

自动化工具

另外一个有趣的例子是:很久前的一个项目,团队在开发一个大表单,大表单里有很多问题,大概分为三个页面:第一页需要填写一些个人信息,比如姓甚名谁家住何处等,第二页则会填更多的信息,而第二页的很多问题跟第一页相关,一些问题只需要在第一页选了A选项才会出现,而另外一些问题则仅仅为B场景设计等等。

然后某个新需求是在第三页添加一个新的问题(根据第二页的某个回答来决定要不要显示出来)。在实现过程中,开发人员需要手工填很多内容才能到达第三页,而这个过程还可能出错(比如第二页中需要去调用某个API来生成下拉列表内容,那个API有可能会挂掉),一出错又得重来一次(当时还没有HMR啊,State管理啊这些高级货,只能重新刷新)。团队意识到这个痛点之后,有人就开发了一个Chrome的扩展,这个扩展可以根据预设的答案自动填写表单(好像是模拟鼠标点击的方式),直到你想要停下来的那一个问题。这样就将开发中调试的时间大大缩短,还可以节省很多测试同事的工作量。

事实上,这类的场景在实际项目里会有很多。通过一些自己的努力,让团队里的其他角色、或者团队之外的你的下游系统、又或者未来的系统维护者的生活变得轻松一些,是靠谱的一个重要表现形式。

做好Desk Check

在敏捷开发中,当一个Story开发结束之后,我们会把开发,测试,BA,UX聚在一起来做Shoulder Check / Desk Check。这个实践可能很多团队都会坚持。但是做的流畅程度则千差万别,效果也自然大相径庭。

我现在还记得第一次做Desk Check时候的忙乱,由于事先没有准备好,当围观群众上来之后,我和peer还没有把Jira上的卡打开。当逐条过验收条件(AC)的时候,我们才发现漏掉了一条。然后在跨浏览器检查的时候,发现在Safari里页面上有个按钮在点击时毫无响应,这时候我和peer打开了dev-tools开始了现场debug等等。

在后来的项目中,我特别注重这个实践,努力让Desk Check变得流畅无碍。你前期准备的越充分,在Desk Check的时候就越顺畅。比如,在把所有人都召集过来之前,自己先把所有AC过一遍,如果有Feature测试的话,就把测试用例大概过一遍,看看能不能覆盖所有AC。在Check的开始前,先把Story描述一遍,特别是业务场景,业务价值。这个过程可以对着Jira卡来过,如果有新的讨论,也需要顺手同步到Jira的comments里,以便未来参考。由于参加Desk Check的QA和BA可能手头都有很多任务并行处理,所以你需要快速的将上下文分享出来,让大家在同一理解水平上,这样后续的Check才有可能顺畅。

如果Story涉及跨浏览器,那么你最好可以将各个浏览器都打开,而且切换到需要showcase的页面上。这些前期的准备工作,可以减少参与者的上下文切换成本,可以让大家迅速进入到验收中,而且出错甚少。事实上,大部分问题在你的准备中都已经解决了,剩余的小问题则可以在后续的Story开发过程中顺手修复。

测试数据准备

BA对系统的理解是基于现实世界中的业务来的,因此在数据准备上一定要小心,比如10位数字的身份证号码,带有字母的手机号等等。即使是测试数据,也应该认真对待,尽量避免使用随机的文本来填写表单,否则结果页面看起来会非常不专业。

在有些场景下,比如你需要测试当文本超过一定长度会显示省略号,你仍然需要仔细设计文本,让其看起来更为实际。当你读到一个名称为“锟斤拷锟斤拷锟斤拷…”的产品时,你会做何感想?

事实上,一些工具可以帮你简化测试数据的准备,而且可以确保专业性。比如Ruby里的Faker(Perl中的Data:Faker的Ruby移植版)https://github.com/stympy/faker,它可以帮你生成很多常见的数据实例,比如

require 'faker'

Faker::Name.name      #=> "Christophe Bartell"
Faker::Bank.iban #=> "GB76DZJM33188515981979"
Faker::Internet.email #=> "kirsten.greenholt@corkeryfisher.info”

使用类似的工具,只需要编写一些微小的代码,就可以生成更贴近业务场景的测试数据,从而让显得更加专业。

设计中的细节

同样的道理,UX在设计稿中,需要考虑很多细节,比如

  • 常见的拼写错误
  • 业务术语的正确使用
  • 理解数字的含义
  • 视觉一致性(字体的选用,相同元素的字号,颜色暗示等)

这些细节可以让观众体会到你的认真和用心,而由于视觉的特殊性,一个微小的纰漏都可能被放大成严重的问题。比如在某一份设计中,所有的标题都采用24号深灰色的Consolas字体,但是在另一处,字号变成了18,而且加粗了。这种错误很容易别识别,从而让人产生不好的印象。

业务语言

而对于用错术语,或者没有完全理解业务时,对数字的解读则会产生更严重的问题。比如在广告行业,广告主比较关心的一个指标是Frequency,计算Frequency的方式是用PV(Page View)/UV(Unique View),也就是每个用户的平均点击量。页面的总访问量肯定比访问这些页面的人数要多(抽屉原理),那么它们的比值也肯定会大于1。如果UX不理解这个业务含义,可能会在设计稿上标识0.68之类的数字。

类似的,如果你在绘制一个Pie Chart,那么最起码所有部分之和加起来要等于100%,而且大致的占比要正确,比如应该避免出现:数值为25%但是视觉上比例却接近1/3等等。

对开发者友好

此外,在设计稿中,能为不同的场景设计出相应的变体(variation)也会大大降低开发者和UX之间来回讨论的工作量。比如在一个产品列表的设计中,列表中的第一个条目展示正常情况(happy path),而第二个显示当某些元素缺失时的展现(空值,非法值等),而第三个条目显示当标题超长之后是应该折行还是显示省略号等。

每一个细节事实上都在为你的靠谱程度打分,也会潜在的影响别人是否愿意信赖并乐于与你一同工作。

小结

文章中列举了一些实际项目中的例子,有关于如何做好开发实践的技巧,有关于帮助团队里的其他人更方便工作的意识,有关于对开发者友好的设计细节。所有这些例子中的技巧,事实上都与这样一个事实有关:要在职场中成为一个靠谱的人,意味着即使对团队内部,你也需要扮演一个专业服务者的角色。你需要更多的站在他人的角度来考虑问题,在合理的范围内,尽量的减少别人和你合作时的工作量。此外,你需要处理好很多细节,职业性体现在很多的细节中,从测试数据中的asdfasdf,到设计稿中的typo,都可能暴露你是否在用心对待工作。

文中提及的这些值得践行的技巧事实上与具体技术关联甚弱,你可以很容易的举一反三,并在实际场景中灵活运用,成为一个专业而靠谱的职业人。