不做代码审查又怎样?

从一次回顾会议开始

“要不……我们不做……代码审查……试试?”还记得当有人抛出这个建议时周围同学的表情,那种表情用两个字加两个标点符号就可以形容:“什么?!”

对了,先介绍一下背景,这是项目一次普通的回顾会议,我们正在讨论的是如何让代码审查更有效率、更有效果。我们做代码审查的方式比较简单直接,就是每日站会后,大家围在一台开发机周围,逐一轮换讲解昨天所有提交的内容,就像下图中的那样。还有,这是一个已经超过7年的比较大型的项目,代码审查是我们从项目开始就坚持的一个实践,所以当有人提议废除它的时候,这在很多同学心里是想都没想过的事情。

代码审查是一个很好的实践,可以帮助团队里的同学了解其他同学在做什么,可以分享项目的上下文,可以分享技术上的一些小魔法,可以发现很多潜在的代码缺陷,可以提高代码质量,还可以有很多很多好处……

但是,在真正的实施过程中,很多情况下并不像想象的那般美好,经常出现例如有些同学由于跟不上其他人讲解的速度(毕竟不是自己写的)或是没有相关的上下文(例如刚加入项目的新成员),或是由于提交没有被很好的切分和组织,导致整个过程都处于游离状态(就像下图中的我……毫无摆拍痕迹),而代码审查的效果也打了折扣,渐渐的变成了一个流程,一个过场, 一个习惯。

00

于是团队里就有人站了出来,引导大家去发现背后的问题,也就引来了这样一场激烈的讨论。在讨论中,有些同学坚持在说代码审查还是很有用的,有这样那样的好处,需要保持下去;有些同学则非常实际地指出了执行上的各种困难和问题。讨论异常激烈,直到有人小心翼翼地提出了文章开头的那个建议,一片哗然后大家都陷入沉寂:是啊,不做代码审查了,我们会失去或是得到什么呢?

沟通的收益和成本

在我看来,代码审查所暴露出的问题本质上就是如何权衡沟通的成本和收益的问题

在软件开发过程的发展中,无论是从一开始的瀑布,后来的敏捷,还是当下的精益。都有很大一部分篇幅是在强调沟通或者说是强调沟通方式的演进,都是为了解决已有沟通方式所带来的各种限制和问题。

例如在我们自己的项目中就采用以下的实践来促进团队内外的沟通,包括:迭代计划会(Iteration Planning Meeting),每日站会(Daily Standup),代码评审会(Code Review),回顾会议(Retrospective Meeting);还有XP中的结对编程(Pair programming),现场客户 ( On-site Customer )等。

而沟通的好处是可以得到快速的反馈,无论是80年之前就出现的PDCA环还是前两年大热的精益创业,都是在强调快速反馈和基于反馈的快速迭代,通过这种方式来消除生产和创业过程中造成的各种浪费。

但是(对,又是但是……),沟通也是有成本的,而且成本一般都还不低,相信这点也不需要多解释,大家肯定都经历过各种各样效率极低令人抓狂的讨论或是会议。

在沟通的成本和收益同时摆在我们面前,如何做出选择?如何才能设计一套刚刚好的沟通体系,平衡收益与成本,来满足团队和项目的需要呢?

沟通金字塔

在读《重构》的时候,我深深地体会到:这个世界上没有什么是不变的,包括变化本身。所以要想得到解脱,我们就需要从简单的对与错,好与坏的漩涡中跳脱出来,用变化的眼光来看待周围的事物,并做好一直变化的准备。

而面对沟通成本与收益的选择困境时,我第一个想到的就是测试金字塔。了解测试金字塔的同学肯定都知道,测试金字塔是一个很好的工具,它帮助我们从单一的测试选择困境中跳脱出来,将各种不同类型的测试建立起关联、纳入一个统一的体系,从而让我们可以在一个更高的维度来系统的思考和审视每一种测试的策略,关注点也从简单的“该不该”变为了“如何变化”。

01

至于“如何变化”?我们可以通过在金字塔上添加一层新的测试种类来弥补整体测试策略中粒度太粗的问题;也可以根据项目情况通过移除一层测试种类,用其上层或是下层的测试来覆盖其测试用例,来减少成本;也可以通过将某个测试用例在金字塔中向上层或是向下层移动来寻找收益与成本的平衡。

举个实际点儿的例子,例如我可以将一些基于UI的集成测试用例下移,用成本更低的单元测试来覆盖从而减少成本,加快反馈速度;也可以将一个单元测试用例上移,用基于UI的测试来增加其稳定性和体现的业务价值。

看,我们讨论的内容从简单的要不要写UI测试、需要写多少单元测试测试已经被转换到对于整体策略的变化和调整上来了。那对于代码审查的问题能否也通过金字塔这个工具转换到更大的空间上寻求突破呢?这就是沟通金字塔

02

相比于测试金字塔中的“UI--Service--UT,“Iteration Planning Meeting(见上图)-- Code Review(见上上上图)-- Pair programming(见下图)”就可以类比成沟通金字塔,和测试金字塔一样更靠近金字塔顶端的(例如迭代计划会)沟通频率越低,成本越高,但越接近业务;越靠近金字塔底端的(例如结对编程)沟通频率越高,成本越低,越接近实现。这几种不同的沟通方式所沟通的内容肯定也会有所重叠,通过将各个层次的沟通方式进行组合来保证我们团队的整体沟通质量,就像通过金字塔中的各种测试层次的组合来保证产品质量的一样。

03

如果可以这么类比的话,那我们对于沟通质量的管理也应该是动态的、系统的、从整体上出发的。例如就可以通过在沟通金字塔中添加一层新的沟通机制来弥补沟通粒度过粗的问题,例如QA Team现在在做的每周例会就是一个好的例子;也可以将一些沟通内容通过层次(上下)的调整,甚至是通过直接减少一层沟通方式来优化我们的整体沟通效率,例如我们可以通过增加结对编程的Switch频度来替换掉成本更高的代码审查。而目标就是通过不断地动态调整和优化沟通结构,试图寻求一个沟通成本,沟通收益,沟通效率平衡的沟通环境。

回到问题上来

如果沟通金字塔的理论说的通,那代码评审就不再是一个:“必须要做的敏捷实践”,而只是沟通金字塔上的一层而已。那它的存在必然是为了弥补上下层沟通之间的空隙,那这个空隙到底是什么呢?是什么样的沟通是结对编程所不能覆盖,而用类似于迭代计划这种更高层的沟通机制覆盖又不太经济的呢?为了让团队重新找回这个答案,我们最终决定试一试:停止代码审查一个月,在这一个月的时间我们去体会没有代码审查的得与失,在一个月之后重新举行回顾会议再来讨论是否要继续做代码审查

在一个月后如期进行的回顾会议上,团队又重新讨论了这个议题,最终觉得通过这一个月的尝试,在还无法做到更频繁地Switch Pair的情况下,代码审查还是很有必要的。例如在这个月中,大家对于其他人在做的工作了解变少,集成出现了很多冲突;缺陷的数量也有所增加,其中有些是很明显的错误,很容易通过代码审查的方式发现并在前期消除;代码质量也有明显下降,出现了测试的缺失和很多代码坏味道。

而另一方面为了让代码审查能够真正的发挥其作用和价值,经过讨论我们也优化了代码审查的方式,让大家更有参与感,更有效率,也更有乐趣(见下图抓拍)。

04

交付价值 Over 遵循实践

日本剑道有个心诀,叫守 破 离: 1.“守”:最初阶段须遵从老师教诲,认真练习基础,达到熟练的境界。 2.“破”:基础熟练后,试着突破原有规范让自己得到更高层次的进化。 3.“离”:在更高层次得到新的认识并总结,自创新招数另辟出新境界。

守固然重要,但如果不能在守得基础上寻求突破,领会其中的奥秘和背后的道理,则始终无法达到离的新境界。在中国的武术中也有“无招胜有招”的说法,这里的无招就是指在将招数融会贯通之后,能够运用招式背后的原理,打破招数的限制,随机应变,自由应对。

而反观我们自己,是不是已经慢慢的不知不觉的被困在“守”的围城之内,变成了猴子定律中最后的那群猴子,只知道去拿香蕉会被打,也会跟着其他猴子去打那些试图拿香蕉的新猴子,但是为什么要这么做?我们已经忘了,或从来都没有知道过。

所以,不要以为遵循了敏捷提倡的一些实践我们就是敏捷的,不要以为遵循了精益的实践我们就是精益的。在我们没有理解并追求其背后真正价值的时候,只不过是平添了另外一份成本而已,不如不做。

Share

IT小小鸟生存指南——新年了做个计划吧

新年伊始,又到了做年度总结,新年展望的时候。最近和很多同事亲切友好得交换了反馈,发现很多朋友都会对自己有着同样的埋怨:“想的太多,做的太少,对自己渐渐失去信心”,“做事情东抓一把西抓一把,比较随意也比较分散,一年过去也说不上做了什么,更谈不上有什么收获”,而我给的建议也大多就是一个:“新年了,做个计划吧”

想清楚不做的事更重要

我们通常以为自己了解自己,清楚自己喜欢做什么,要做什么,所以觉得不需要做计划就可以很好地管理自己。我原来也是这样认为,但是一旦我开始尝试将想做的事情写下来的时候,我才发现想做的东西实在是太多了:大的方面包括公司贡献、项目贡献、团队发展、个人成长、家庭等方面,细节一展开吓自己一跳:旅游、健身、看书、写作、翻译、做播客、内部培训、外部演讲、项目推动、学一门新语言、Recruiter Support、Marketing Support……

每一个项目展开又是一大片,此时我才意识到,我做不了所有的事情,开始对计划进行删减,裁剪到一个相对靠谱的范围,通过做计划搞清楚不做什么比搞清楚要做什么有时候更重要,这样可以让我们更加专注,不会被各种诱惑所影响,做事也更有质量。

01

给今年一个主题

李开复老师在去年写过一篇《李开复:如何设计你的2015年度计划》,其中提到了Facebook的创办人扎克伯格每年都一项年度计划并执行的很好。所以开复老师也推荐计划不要多,选择一项可行的目标就好。我认为对于大多数人,一年只计划一件事情应该是不够的,但是确实需要给接下来的一年定一个主题,例如:前端之年、设计之年、安全之年、团队之年还是社区之年……找一个今年主要想发力的方向,给自己个目标和指导原则。

制定验收条件

往往我们写计划都是这样式儿的:“今年要健身”,“今年要提高一下前端”,“今年要多读书”,“今年要多分享”,“今年要多帮助招聘”。我们知道一般这样的计划都很难被执行的很好,因为过于宽泛了,无法验证,也就是我们常说的无法测试。所以做计划要像写用户故事(User Story)一样制定验收条件(Acceptance Criteria)

例如上面的计划可以写成:“每周健身3次”,“组织一次三周三页面的培训”,“读30本书”,“每季度做一次内部分享”,“参与支持至少一次校招或社招”,这样的计划更明确也更容易跟踪和验证。

02

知行合一

大多数计划的完成之日,也就是其历史使命完成之时,其作用主要体现在对于未来一年的美好憧憬而已,可以使身心都得到短暂的放松。

制定计划而不执行,还不如不做计划。为了充分发挥计划的威力,我个人的做法是根据全年计划先制定出第一个月的任务(Task),纳入到GTD体系中执行。因为计划已经被设计成可验证的,所以这种划分会非常的简单,例如一年计划要读30本书,那在第一个月就需要读三本书,我会为拆分出的每一项建立一个ToDo来跟踪这项任务,这样就形成了一月份的具体任务。

每个月的最后一天,也会有一个任务提醒我及时回顾这个月的任务执行情况,一方面将已完成的任务总结写入Evernote中的《个人2016年大事记》中,一方面根据全年的计划和当月的任务完成情况来制定下一个月的具体计划。这样逐月交替,计划就可以充分发挥其价值,来帮助我更好的来管理自己。

03

成功从管理好自己开始

总之无论是做计划还是时间管理,任务管理,都是一个自我管理的过程。所谓自我管理,我的理解就是用现在的自己管理未来的自己,而同时现在的自己也被过去的自己所管理。以小见大,管理自己的策略和管理一个团队管理一个公司是有很多相似之处的:规划战略,制定目标,划分计划,分解变为可执行可验证的任务,跟踪实施,响应变化,反思总结。所以,无论你有何种远大的目标,就先从管理好自己开始吧。

Share

技术雷达 : 关于技术趋势的分析报告

就在刚刚过去的2015年11月份,ThoughtWorks又发布了最新一版的技术雷达。技术雷达是什么,来源以及如何运用,可以参考Neal Ford的一篇文章《Build Your Own Technology Radar》中文翻译】,这里就不再赘述。在本期的技术雷达中,提出了四个最新的技术动态,分别为:“Docker引爆容器生态系统”、“微服务及相关工具受到追捧”、“JavaScript工具正在趋于平稳”、“安全是每一个人的问题”。本文就主要围绕这四个最新的技术动态,阐述一下笔者个人的理解和分析。

Docker引爆容器生态系统

Docker现在非常火,作为一个开源的应用容器引擎,它的出现让容器技术的使用和管理变得非常简单,也促使更多的人开始关注和意识到容器技术的真正价值和威力。由于其基于LXC的轻量级虚拟化技术,相比于KVM之类传统的虚拟机技术最明显的特点就是启动快,资源利用率高。启动一个容器只需要几秒钟,在一台普通的PC上甚至可以启动成百上千的容器,这都是传统虚拟机技术很难做到的。目前容器技术已经被广泛应用在软件开发的各个阶段各个领域,例如用于管理开发环境、用于测试、构建项目和实施持续集成,当然也可以作为传统云平台虚拟化的替代方案,实现更为轻量更具弹性的云计算平台。

虽然上文提到的这些应用场景都是非常有价值的,但还不能体现Docker或是说容器技术如此火爆的原因。我们知道Container通常翻译为容器,但是还有另一个翻译就是集装箱,集装箱被很多人称为是21世纪最伟大的发明之一,它的发明和广泛使用甚至改变了世界的货物运输体系,促进了经济的全球化发展,《集装箱改变世界》这本书就是讲述了集装箱是如何改变世界的。而我们现在所提的容器技术和Docker,是不是也在致力于改变软件的世界,改变我们开发、测试、构建、部署、运维所有这些的现有方式呢?我觉得是有可能的,因为无论是集装箱还是容器技术都为我们带来了两个重要的好处:一致性和隔离

屏幕快照 2015-12-05 下午9.27.22

我们知道一个产品是否可以正常提供服务,只去确保软件本身没有问题是远远不够的,需要同时保证软件、基础设施(例如硬件、操作系统和运行环境)以及配置的正确性和可靠性。而传统的软件开发方式,对于这三个方面的管理是分离的,再加上三者之间错综复杂的关系,就造成了我们常常挂在嘴边的“环境问题”。但是通过使用容器技术,我们如果将软件、基础设施和配置作为一个整体使用容器进行封装,产生一个个已经同时包含了软件以及其运行环境的经过严格测试检验的“包”。这样当部署“包”的时候就不需要再考虑环境的问题,也不需要关心现在部署的是一个Web服务还是一个数据库服务,要做的只是把一个个容器标准化地安装到指定的容器引擎即可。

屏幕快照 2015-12-05 下午9.26.07

可能正是大家都看到了容器技术以及Docker对于软件开发各个领域正在带来的改变,容器技术的生态系统也在经历着一个快速发展的阶段,涉及到开发辅助、集群管理、服务编排、内容发现、云平台搭建等各种工具框架都一一呈现在我们面前,其中像Google和Amazon这样的巨头也都在第一时间发布了各自与容器相关的服务和框架。

1224-王健-3

微服务及相关工具受到追捧

如果大家关注Docker,也肯定会经常听到一种与之相关的架构,也就是微服务架构:

“微服务架构是一种架构模式,它提倡将单一应用程序划分成一组小的服务,服务之间互相协调、互相配合,为用户提供最终价值。每个服务运行在其独立的进程中,服务与服务间采用轻量级的通信机制互相沟通(通常是基于HTTP协议的RESTful API)。每个服务都围绕着具体业务进行构建,并且能够被独立的部署到生产环境、类生产环境等。另外,应当尽量避免统一的、集中式的服务管理机制,对具体的一个服务而言,应根据业务上下文,选择合适的语言、工具对其进行构建。”

这是Martin Fowler给出的对于微服务架构的定义,其中提到了微服务架构的四个特点:

  • 将单一的应用程序划分成一组小的服务
  • 每个服务运行在其独立的进程中
  • 轻量级的通信机制
  • 独立的部署到生产环境

我看过很多非常成功的公司在分享其系统架构演进历程时,往往最后都会落脚于服务拆分和业务服务化。其实这也不算是什么新的概念了,几年前流行的SOA面向服务架构就已经为我们描绘了一个服务化架构的美好前景。那为什么又提出了一种新的微服务架构呢?对于这个问题Martin Fowler在他的那篇《Microservices》也给出了他的回答。简要来说就是虽然这两种技术都是以服务化和组件化为目标,但是架构理念和技术策略上有太多的不同。例如上边提到的微服务架构的主要特点以及其倡导的演进式架构设计,去中心化的架构风格,采用轻量化通信机制,强调独立部署等都是与SOA所提倡的技术和思路有很大区别。微服务架构也更契合现代的技术发展趋势,例如RESTful API的流行,嵌入式应用服务器的应用,持续集成、持续交付的普及,容器技术爆发,组件化的趋势,云平台的发展等。

在引入微服务架构前,系统往往是以一个大的单体应用的形式存在的。此时任何功能的修改都需要重新构建部署整个应用,并且当需要水平扩展时也只能通过扩展整个应用的方式进行,无法做更细粒度的调度和控制。而当切换成微服务架构后,单一功能的修改只需要重新构建部署相应地服务即可,其他服务并不会受到影响。如果某个服务需要水平扩展时,我们也只需要扩展此服务即可。由此可见,微服务架构相比于传统的单体应用架构,可以极大的提高我们的资源利用效率和系统弹性。再加上通过服务化我们可以更容易的以组件的方式组合和重用现有服务,快速地构建出新的服务,使企业和产品更具竞争力。

1224-王健-4

微服务架构还有很多其他的好处:例如我们可以为不同的服务使用异构的技术架构,用最适合的技术解决最适合的业务问题(例如在某些服务中使用关系型数据库,而在某些服务中使用NoSQL数据库);相对于单体应用因为每个服务都更小更简单,所以维护难度和成本也会比传统的大的单体应用要低得多;还有根据康威定律,这种新的服务架构甚至会改变我们软件开发的组织方式向小而精的多功能自组织团队和全栈式演进,前段、后端、运维、DBA这种角色划分方式也许也会因此而成为历史。

微服务架构之所以经常会和容器技术一起被提及,是因为容器技术为微服务架构提供了一个非常匹配的基础设施,从而可以将这种架构的威力最大化的激发出来。设想一下,假如我们有一个产品采用微服务架构,并将每类服务及其运行环境打包为容器,部署于像AWS ECS这类弹性容器服务里。就可以实现通过实时监控每类服务的负载情况,通过自动化的方式快速按需对每类服务基于容器技术进行快速高效的水平扩展或是撤销,这样我们的架构就是一个高度自动化、高弹性、高资源利用率的应用架构,相比于传统的单体应用也将具备很大的竞争优势。

有得必有失,微服务架构有着这么多的好处,但同样也会引入一些新问题,最直接的就是分布式本身所引入的复杂性。例如如何保证服务间的契约,如何快速开发服务,如何保证轻量级通讯协议的可靠性等等。对于这些问题也有着相对应的解决方案,本期雷达就推荐了很多的工具和技术来辅助进行微服务架构下的软件开发。

1224-王健-5

JavaScript工具正在趋于平稳

如果大家关注往期的技术雷达,肯定可以感受到JavaScript的火爆程度。例如在2014年1月刊就提出了“JavaScript战车一往无前”,以及在2014年7月刊又提出了“JavaScript大爆发,框架遍地开花,创新目不暇接”的最新动态。JavaScript如今继续保持着它强劲的势头,但是我们也能感觉到无论是社区还是我们自己团队,大家在经历过暴风雨的波澜后,慢慢平静下来,无论对于JavaScript的框架、工具还是一些最佳实践上的认同也在慢慢的趋于一致。

1224-王健-6

 

ECMAScript 2015目前在雷达上已经被列入了“采用”的阶段。意味着已经没有什么障碍和疑虑再阻止我们使用这个最新的规范,在JavaScript平台上享受一个现代语言为我们带来的简洁、便利和强大。在构建工具和包管理工具的选择上,NPM和Webpack也逐渐成为越来越多人选择的对象。

而对于前端框架的选择上,React.js热的发烫,它喊着“Rethinking Best Practices”的口号,举着组件化的大旗,让每个人目瞪口呆之后,又开始重新审视我们的前端开发实践。如果说容器化实现了基础设施的组件化,而微服务架构提供了架构层面的组件化方案,那ReactJS就把组件化带到了前端开发……哦对了,还有移动开发领域。

1224-王健-7

安全是每一个人的问题

安全越来越受到大家的重视,从“SSL心脏滴血”到“Xcode Ghost”,再到时常出现的用户(商业)隐私信息泄露,钓鱼诈骗,恶性攻击等安全事件。让我们越来越切身地感受到安全对于企业和个人的重要性。并且随着互联网和软件行业的高速发展,安全形势也变得越来越严峻:从硬件安全到操作系统安全,从工具安全到依赖组件的安全, 从网络安全到应用安全,从代码安全到密码安全。任何一个点的疏忽都可能为企业和个人带来毁灭性的打击和伤害。

与安全形势变得越来越严峻形成鲜明对比的就是以往我们在产品设计和开发过程中对于安全无论是在意识上还是在使用的技术上都远远达不到要求。对于安全的关注更多的是以一种“看门人”的方式进行的,也就是在开发和设计过程中往往很少考虑安全的问题,仅仅靠上线前的一段很短的时间,通过一些工具扫描安全漏洞,然后集中修复的方式。这种方式往往让团队处于非常被动的处境,很容易遗漏安全问题,产生安全风险,或是根本没有时间修复所有的安全问题就草率冒险上线。

而现在有越来越多的团队将安全引入到开发的整个生命周期当中,作为一等公民来看待和重视,将安全作为软件质量的一个重要组成部分。例如在软件的早期就通过引入威胁建模(Threat Modeling)的方式为产品做整体的安全建模,并将建模成果以验收说明的方式写入用例文档或是用户故事中。而开发人员也会在实现每个功能时将对安全的关注作为设计和实现的一部分,并为安全编写相关的自动化测试,纳入持续集成系统中保持对于安全的持续验证和关注。

1224-王健-8

关于安全,本期技术雷达也推荐了很多的工具和技术,涉及产品安全、代码安全、密码安全、网络安全、操作系统安全等安全领域。借助于这些工具和理念,可以帮助我们构建出更加安全的产品和服务。

1224-王健-9

 写在最后

以上就是对于本期技术雷达中四个最新动态的一些理解和分析。除此之外,本期的技术雷达还包含了其他很多领域和工具,包括架构设计、大数据、DevOps、数据库技术、持续交付、测试技术等等待你我去探索。

Share

浅谈快捷键

又是一个小的分享,落笔成文。开始其实是想做一个文本编辑器的分享,不过在准备过程中,发现编辑器之争很多时候争的却是快捷键系统的设计。总觉快捷键系统的默认设计虽然是编辑器一个很重要的区别,但因为其可以通过插件或是配置的方式转换(例如Evil-Mode),所以快捷键系统的设计不再是某个编辑器的特性,而是一套独立于编辑器之外的系统。而运用好快捷键可以让日常工作生活的效率大幅提升,事半功倍,俗话说,天下武功唯快不破嘛。

回想第一次接触键盘应该就是小学时代玩过的打字机了,通过敲击键盘上的某一个按键,驱动一个撞针,将该按键对应的字符的字模打击到色带上,从而在纸上打出该字符,知道为什么我们现在叫“打字”了吧。回想那个时候其实是没有快捷键这么个东西的,连换行这种事情都不是通过按键而是通过手动去移动卷纸的那个机械轴来完成的。

1

随着计算机技术的发展,先后出现了电子打字机(又称文字处理机)和个人计算机(PC),打出来的字不再是印到纸上,而是显示在显示器中。既然是在显示器上,就使编辑功能可以更加强大,我们每按下一个按键做的事情就变成了两种:输入对应的字符或对电脑下达一个命令(移动光标,选择一段文字,删除一个字符等)。

2

而随着人机交互界面和鼠标的发展,我们对电脑下命令这件事有了一个更简单的方式。就是将命令做成可交互的界面元素,例如按钮,然后通过用鼠标点击的方式。这大大的降低了电脑的使用难度,也促使了计算机逐渐走进了千家万户。于此同时,键盘作为输入设备界的老大哥,被成功减负,又逐渐回归了字符输入的功用。

3

可好景不长,随着软件(包括操作系统)越来越复杂,用鼠标点选的效率问题慢慢呈现,毕竟一些常用操作每次都要去移动鼠标点击还是比较低效的。于是我们又想到了键盘这个老大哥,三顾茅庐,重出江湖,键盘又慢慢的替鼠标分担起一些对电脑下达命令的职责,也就有了众人皆知的一些快捷键,例如Ctrl+C。

5

一些电脑的重度使用者(例如程序员和文字工作者),经过对比,发现快捷键对于鼠标来讲还是要快捷得多。毕竟在键盘上按几个键比用鼠标在分辨率日益变高的显示屏上点击一个区域要快速的多,还不包括找到命令对应的按钮以及手从键盘移动到鼠标,再从鼠标移动回键盘所消耗的时间。而快速则保证了我们的思路不会打断,输入(IO)能尽量不托大脑(CPU)的后腿。因此,我们就开始追求起所谓的全键盘操作

正所谓理想很丰满,现实很骨感。随着软件的发展,一个软件能接受的命令动辄就是成百上千的,如何用区区只有100个左右的按键来映射就变成了一个需要解决的问题。率先面对这个问题的就是文本编辑器,所以我们来看看Vim和Emacs是如何来解决这个问题的。

Vim(江湖人送外号:编辑器之神),引入了模式。既然我们在按下一个或多个按键的时候,可能是输入也可能是发送命令,这本身不就是存在这个多个状态么?所以在Vim里就干脆直接加入了模式(又称模态)。也就是编辑器存在不同模式状态(普通、输入、选择),而按键也在不同的模式可以被定义成不同的功能。

Emacs(江湖人送外号:神之编辑器),区别于Vim,默认采用了另一套更容易被大众所接受的快捷键体系来解决快捷键设计的问题,也就是通过快捷键的组合来解决。例如打开一个文件的快捷键是Ctrl+X Ctrl+F。这种快捷键的设计好处是不需要关注当前的编辑器模式了,但缺点是需要按更多的键,可以简单的理解每次按下Ctrl就是在做一次短暂的模式切换。

这是两种快捷键体系设计思路,但是对于我们有什么用呢?随着Vim和Emacs多年的圣战和两者神一般的地位。这两套快捷键体系潜移默化的影响着之后众多的软件的快捷键设计。而我本人所使用的软件中,像Readkit、Airmail类似的软件的快捷键就是混合了Vim和Emacs的一些经典元素的,而Gmail、Trello和Github这种常用的有点逼格的网站都一定程度的借鉴了Vim或Emacs的快捷键,如果使用Chrome还可以使用cVim这种神器,而MacOS更是原生就支持Emacs的一些核心快捷键。所以说理解学习这两种快捷键体系,对我们将大有好处。

设计并使用好系统级别的全局快捷键,也可以大幅提高我们的日常工作生活效率。我使用的是MacOS系统,将日常常用的功能通过Quicksilver和Alfred软件的功能定义成为系统级别的全局快捷键。总之打磨出一套适合自己全局快捷键是一件费心费力但绝对值得去尝试的一件事,下面是我自己录的一段演示视频。(由于优酷上传的视频被屏蔽,所以只提供YouTube视频链接)

https://www.youtube.com/watch?v=ZA9S7GPuj1E#action=share

快捷键作为我们对电脑发号施令的一种方式,已经比使用鼠标点击的方式快捷的多。那还有没有比快捷键更快的方式呢?答案就是自动完成。

说起来很玄乎,但其实很简单。回想一下我们天天做的事情里有多少是在反复重复的:切换应用的时候切换输入法、讲PPT的时候经常要把电脑从休眠唤醒、离开电脑的时候要锁屏,回来的时候还要解锁、浏览各个网站的时候需要重复地输入密码。

而以上的事情其实都可以通过软件来自动处理。例如可以使用Keyboard Pilot软件自动完成软件切换时的输入法切换、可以使用Caffeine可以避免电脑自动休眠、使用MacID连接手机后可以根据手机与电脑的距离自动锁定解锁电脑、使用1Password来自动帮我们输入密码。这样的例子还有很多,为了让生活每天变的好一点儿,值得我们去不断探索。

同时需要记住,在达成同样目标的前提下,比“做的快”还快的就是“不用做”,快捷键如此,开发软件如此,生活亦如此。

-注:本文中引用的图片全部来自网络,视频为原创,由于优酷上传的视频被屏蔽,所以只提供YouTube视频链接。

Share

IT小小鸟生存指南-学习起步篇

经常跟公司的年轻人聊天(说起来好伤悲),他们大多在充满激情的同时表达出自己对于学习的迷茫。面对快速发展的技术被迷晕了双眼,不知道学什么,也不知掉怎么学,不知道从哪开始,也不知道学到何时为止。前两天也在知乎上回答了一个类似的问题,想想应该把自己的一些经历和问题以及对于这些问题自己的思考梳理一下,分享出来。

小小鸟们需要面对的第一个问题往往都是不知道该学什么?面对扑面而来的各种技术,框架,术语,各种三个字母或是四个字母的天书一样的单词,感觉一下就被淹没在浩瀚的技术海洋中。看着大牛们的各种口吐莲花,对于各种技术信手拈来,运用自如,羡慕之余也不禁畅想着自己何时才有这么一天。

为了实现心中的目标,很多人捧起了各种神书,什么设计模式,什么算法导论,什么编译原理;而有些人则搞起了各种新潮的技术,什么Angular、ReactJS、Go、Node、Swift、Spark,他们都以为自己已经拿到了通往成功的钥匙,不过看了一阵发现,该听不懂的还是听不懂,书看的进展缓慢,狗熊掰棒子一样忘的比记得还快,技术淘汰的速度超过了自己学习的速度。怎么破?我给的建议其实很简单,就是:

1. 工作用什么学什么;2. 先上手后学习;3. 无目标不学习,学到够用就停止

1. 工作用什么学什么

为什么建议从工作入手?因为这样可以最大化的借势,达到事半功倍的学习效果。曾经有只小小鸟做着一个C#的工作,但总觉得没有搞Ruby啥的高大上,用着IDE,总觉得没有用Emacs&Vim高大上,所以就白天硬着头皮用IDE搞C#,晚上下班后风风火火用Emacs搞Ruby。一年过去,累的跟狗一样,结果工作也没有干好,自己想学的东西因为没有使用场景也总感觉停于表面。后来痛定思痛,决定集中火力专心学学C#,将自己的学习与工作的方向调整到一致(而不是像之前总是忘两个方向使力,结果都相互抵消掉了)。最后发现反而事半功倍,工作也出成绩了,对于编程语言本身的理解也深度了许多。再去看Ruby或是其他更新的语言,反而轻松了很多,对,这个小小鸟就是我。

说起来简单,但是很多人还是会很纠结,生怕站错了队伍,选错了方向,选错了语言,选错了技术,输在了起跑线,就像我当年一样。走过来我才发现,其实作为当时的自己,无论学什么的效果应该都是差不多的,所谓殊途同归,触类旁通。而对于现在的自己,我已经有能力做出对于自己正确的选择,反而不会纠结。所以做不出选择只能代表自己不够强大,也代表此时的选择可能对自己的意义也没有那么大。念念不忘必有回响,学什么都是有用的,但一个重要的前提是学习的驱动力是兴趣而不是简单的作为一个挣钱的工具,引用罗辑思维里说过的一句话:“没有兴趣你将一事无成”。所以,我的建议是:

结论:工作用什么,学什么,以点带面,顺势而为,将自己学的东西与工作契合,利用所有时间学习。

2. 先上手后学习

很多计算机知识都非常抽象难于理解,什么模式、内聚、解耦、架构、分层、并发、异步、静态、动态、过程、对象、函数、逻辑,还包括各种各样的语言和原则。这些抽象的概念是很难简单的通过“学习”可以完全理解的,因为它们都是从问题中来的,都是人们为了解决某一个问题想出来的解决方案。但是就像猴子定律中的猴子们一样,我们已经慢慢忘了最开始不能去拿香蕉的原因,已经忘了问题,而将解决方案视为圣典,而后来的猴子们(小小鸟)在完全脱离了问题的前提下,单单去学习这些解决方案自然会觉得很抽象也很痛苦。

所以,作为勇敢的小小鸟,应该多问几个为什么(参考5why分析法),甚至勇敢的去摘一次那只香蕉,就当自私一点为了自己,知其然也要知其所以然。记住,那些“约定俗成”、“就应该这么干”、“大家都是这么做的”、“我们一直都是这么做的”都是狗屎,除非能说出问题给出原因,否则任何脱离问题给出的解决方案都是耍流氓。

结论:直接上手实践,遇到问题,先尝试自己解决,再带着问题去学习,这样的学习才会更有效率,理解也才会更深刻。

3. 学到何时为止?

大牛们经常会指点我们学什么,但是一般不会告诉我们学到何时为止。而面对一本本厚厚的书,和外面各种新技术新框架的诱惑,我们不禁自问,这得学到什么时候啊。我们知道在设计上有种说法叫过度设计,那如何避免过度学习呢?过度设计是指去设计那些现在用不到的功能或结构,而过度学习则是指去学习那些现在掌握运用不了的知识。

TDD(测试驱动开发)是一种可以一定程度上避免过度设计的实践,追求刚刚好的实现和设计,无测试不开发,无味道不重构。而对于学习,为了避免过度学习,追求刚刚好的学习,可不可以引用TDD的思路,无目标不学习,一旦目标实现,这次学习就停止了,这个时候可以对这段时间的学习进行归纳整理,然后再制定下一个目标,由此持续的学习。

测试驱动开发:写一个测试 => 实现让测试通过 => 重构优化 (不断重复这个过程形成环路)
目标驱动学习:定一个目标 => 学习让目标实现 => 整理总结 (不断重复这个过程形成环路)

结论:无目标不学习,学到够用就停止

最后

其实大牛们也是从小小鸟成长来的,自然也曾面对过同样的问题。但他们凭借对于技术的兴趣和热爱,禁得起诱惑,耐得住寂寞,守得住自我,日积月累自然就成就了自己。所以地球是圆的,技术也是圆的,无论那个方向,都会走到你想要的那个点,只要你在不停地一直往前走,正所谓可以十日不将军,不可一日不拱卒。

准备的很多内容其实还有很多问题没有展开,比如学习的深度与广度如何协调提高;如何面对层出不穷忽上忽下的新技术;时间如何管理规划;知识如何整理沉淀;要不要做计划,怎么做计划;如何走向大牛之路。一篇肯定写不完了,所以准备来个系列,慢慢写吧,欲速则不达,第一篇就算是学习起步篇,希望能有所帮助,未完待续……

Share