敏捷中的QA

说到QA,通常指的是质量保证(Quality Assurance)工程师,但我更喜欢定义敏捷中的QA为质量分析师(Quality Analyst),主要基于以下几个方面的原因:

  • 质量保证更偏向于工业说法,称参与软件测试的人员为质量分析师感觉更恰当;
  • 质量保证师更多的还是把测试当作软件质量的最后把关着、看门人,而敏捷中的QA更多的是建议提供者而非看门人,把QA称为质量分析师更能体现敏捷中团队对质量负责的原则;
  • 质量分析师更重视业务价值,关注业务价值的分析。

QA,质量分析师,显然与测试有关。敏捷中的QA,也就是与敏捷测试有关。敏捷测试就是在敏捷开发模式下对软件进行的测试,要求尽早测试、频繁测试,以及时提供反馈。敏捷测试要求团队对软件产品的质量负责,而不是某个带有QA头衔的特殊人员。敏捷中的QA可以是参与敏捷测试的所有团队人员,而并不一定是特定的专职的测试人员。

这听起来是不是有点特别?跟传统开发模式下的测试人员是不是有些不一样?别急,我们先来看看敏捷中的QA是如何进行日常工作的。

敏捷QA的日常活动

从迭代到发布,敏捷测试的生命周期各个阶段QA的活动主要有:测试分析,测试自动化策略分析、框架构建等,故事测试,迭代计划会议和客户演示,测试自动化的维护和执行等。如下图示:

1

QA通常不是仅仅工作在某个迭代,而是并行的同时工作在多个迭代:要对当前迭代的故事进行验收测试、探索性测试,和开发人员结对实现测试自动化;还要和业务人员结对分析下一个迭代的故事,编写验收标准和测试用例。

在单个迭代内部,伴随着故事生命周期,QA的活动有哪些呢?用户故事生命周期包括以下几个阶段:故事分析、故事计划、故事开发、故事验收、故事测试/探索性测试、系统测试和客户演示。QA参与故事的整个生命周期,在每个阶段都会发挥作用。

3

  • 故事分析阶段:需求澄清,业务场景和验收测试的确认
  • 故事计划阶段:拆分测试任务,在每个故事开发估算基础上考虑测试的时间和估算
  • 故事开发阶段:和开发人员结对实现自动化测试,和团队沟通发现的问题和缺陷
  • 故事验收阶段:开发人员开发完故事后,QA和业务分析人员要在开发机器上进行验收,以提供快速的反馈;同时还要对测试覆盖率(单元测试、组件集成测试、功能测试)进行确认和提出反馈
  • 故事测试/探索性测试阶段:执行自动化验收测试,执行探索性测试,强调会阻碍故事发布的因素,和团队就测试覆盖率进行沟通,为发现的缺陷添加自动化测试
  • 系统测试和客户演示阶段:执行端到端的系统测试,执行业务或集成的用户测试场景,和团队及客户就功能特性的质量和稳定性进行沟通,参与给客户演示功能和特性

正如前面提到的,在每个阶段,QA除了要独立进行测试,通常还需要跟不同的角色结对,包括业务分析人员、开发人员、以及客户。

4

  • QA与业务分析人员结对:通常在业务分析师分析用户故事的时候,QA要与业务分析人员结对编写验收标准。通过与业务分析人员结对,QA能够更好的理解领域知识,从而有利于定义合适的测试用例;QA从测试角度添加的验收测试用例可以帮助整个团队对产品功能性有更好的理解。
  • QA与开发人员结对:QA和开发人员分别能给团队带来不同的技能集,认识到这一点很重要。作为一个团队,最好通过平衡不同的技能集来获得共同的目标。这对于传统的瀑布式团队来说是一个很重要的心态改变。通常在实现测试自动化的时候,QA与开发人员结对是比较理想的方式。这样结对实现的自动化测试质量相对较高,有测试意识较强的QA参与能够保证自动化测试测得是真正需要测试的部分,而开发人员的编码能力有利于写出简洁可维护的自动化测试代码。另一方面,QA通过与开发人员结对,编码能力也会相应有所提高,而开发人员通过与QA结对,测试意识也会增强,更有利于编写质量较高的产品代码,更有利于形成全功能团队。
  • QA与客户结对:客户是业务领域专家,通过与客户结对,QA能够更好的从终端用户的角度理解系统,从而定义或者增加更多的端到端的测试用例;一旦QA理解了领域知识和终端用户的观点,其业务价值分析能力会有所提高,在团队需要的时候可以承担业务分析角色;在用户验收测试(UAT)阶段,QA通过与客户结对,帮助客户熟悉使用系统,在必要时可以帮助客户解决一些系统问题。

敏捷QA的这些日常活动,的确反映出敏捷QA的日常工作内容和方式都跟传统开发模式下的测试人员有很多不同。下面为大家来详细介绍一下两者的不同,以及敏捷测试对QA的要求有哪些。

敏捷QA与传统测试人员有何不同

我们分别从团队构成、测试阶段、工作方式、关注点、业务知识来源以及发布计划制定几个方面,来看看敏捷QA与传统测试人员有哪些不同:

传统测试人员 敏捷QA
单独的测试团队 多角色开发团队的一员
在开发流程后期才开始测试 测试贯穿于整个开发流中
通常是独立工作 QA和不同角色进行结对
被当作最后也是唯一的质量保证 关注并强调风险
缺乏与业务人员的直接沟通 和业务人员直接沟通
没有机会参与发布计划制定 参与发布计划的制定

从上表的对比可以看到,敏捷QA是特殊的,主要体现在:

  • 敏捷QA是提出建议者而非看门人,需要在参与的每个阶段提出自己的建议,而不是等到开发流程最后来对系统进行验证;不仅要验证开发设计是否满足需求,还要发现需求是否能真正体现业务价值,分析是否有不恰当或缺失的需求。比如说,敏捷QA在跟业务人员结对编写验收标准的时候发现故事分析过程中漏掉的需求,在跟开发人员结对过程中跟开发人员讨论某个测试放在哪层实现比较合理等。
  • 发现风险,并将风险与团队及客户沟通。QA参与整个开发流程,对系统整体的认识和把握可以说是团队里边最全面的,因此也更容易看到系统存在的风险。
  • 及时向团队提供关于产品质量的反馈,便于调整。在每个迭代结束时候,QA需要分析统计该迭代的缺陷,并结合自己通过测试对系统质量的了解,及时跟团队反馈,讨论分析质量下降的原因以尽快作出改进,或总结质量上升的经验,鼓励团队再接再厉。
  • 在制定产品和版本的发布计划的时候,QA可以根据自己对产品质量的了解,从测试人员独有的视角提出一些关键的建议。
  • QA通过参与开发流程的每个阶段,能够协助团队从内部提升质量,让质量融入到产品开发中来。比如:在故事验收阶段对测试覆盖率的确认。

这些特殊性对敏捷QA也提出了更高的要求,需要做到:

  • 具有丰富的产品知识和对用户业务目标的准确了解
  • 对不同系统和数据库所用到的技术知识的了解
  • 和不同角色以及客户进行有效沟通
  • 主动验证质量目标并及时说出自己的想法
  • 编写测试计划,列出需要执行的活动并进行估算
  • 自动化测试的能力和对测试工具的基本了解
  • 在团队内部进行知识分享,协助整个团队参与到测试活动中来
  • 持续提供并获取反馈

本文转载自:http://www.infoq.com/cn/articles/agility-of-qa

Share

闲谈集群管理模式

docker很火很红,简直到了没有道理的地步了。docker为什么这么红?因为它是一种可以用来掀桌子的技术。在部署自动化这条产业上的工人和机床制造商们,看家护院的 cmdb,分布式脚本执行等所谓核心技术即便不会变成明日黄花,也会沦为二流技术。仅仅把 docker 当成一个轻量级 vmware 来使用,是没法看穿其实质的。要理解 docker 的意义,不能从 docker 是什么,能够干什么说起。让我们先来回忆一下集群管理模式的发展历程,以及这些落后的模式的种种弊端。

手工管理时代

IP地址是放在 excel 表里的。管理是靠登陆跳板机,用 SSH 连接服务器。手工执行命令做新的服务器部署,已有服务器的程序版本升级,以及各种配置刷新修改的工作。
弊端不言而喻,主要有这么几点:

  • 缺乏一致性,因为是手工操作所以服务器之间总是有一些差异
  • 效率低下,一个人可以管理的服务器数量非常有限

自动化大跃进时代

业务数量的增长,很快使得机器的数量超过手工操作维护的极限。无论再烂的团队,只要业务长到这个份上了,必然会出现大量的自动化工具用脚本自动化执行的方式快速地支撑业务。这个时代是一个黄金时代,运维真正长脸的时代。因为没有自动化的运维技术,业务就会遇到瓶颈。自动化技术的引入,切实地体现成了业务的收益。
这时代的特征是两个关键的系统

  • 把本地 excel 表格里的 IP 地址用数据库的方式管理起来,称之为 CMDB
  • 基于 ssh 或者 agent 的分布式脚本执行平台

效率低下了不再是主要问题,主要的弊端变为了:

  • 大量的脚本,杂乱无章,内容重复,质量难以保证,最终给故障留下隐患
  • 没有对现网预期状态的定义和管理,所有的现网状态都是脚本日积月累的产物,导致服务器状态漂移,产生雪花服务器(每个机器都不一样),进而给业务稳定性留下隐患

这些弊端短期对业务来说并没有立竿见影的伤害,属于内伤型的。而且很多隐患即便暴露了也会流于强调纪律,强调运维意识云云。很少会有人去追究背后的运维理念的问题。结果就是大部分公司都停留在这个阶段了。毕竟运维是一个足够用即可的支撑领域。运维搞得再高科技,特高可用,未必和创业公司的成功有多少直接联系。

开发闹革命时代

伴随 devops 同时出现的是 infrastructure as code 的提法。简单来说就是一帮开发杀到运维领域之后,看见这些运维居然是这样去管理现网状态的。于是他们把写代码的经验带过来,将现网状态建立成模型(所谓 code),把预期的状态提交到版本控制中。就像写代码一样,去管理服务器配置。
很多后台开发主导的小创业公司直接跳过了上个时代,运维自动化体系从一开始就是基于 puppet 和 chef 来搞的。平心而论,用 puppet 的更多是缺少历史包袱,而不是因为运维问题有多复杂。很多管理的机器数量不超过十台,却在如何使用 puppet/chef 上浪费大把时间的团队也是有的。相反很多大公司因为有沉重的历史包袱,和庞大的传统运维团队,这种开发闹革命的路反而走不通。
这种做法主要是解决了脚本的管理问题,而且因为直接定义了现网状态,服务器之间的一致性也会好很多。但是光鲜亮丽的模型背后本质上还是一堆脚本来驱动的。上个时代的弊端只是经过了包装和改良,并没有办法根除

  • 应用预期状态到现网依靠的还是跑脚本。而且与之前不同,现在更多的是跑别人写的cookbook了,质量也是良莠不齐的
  • 虽然定义了预期的现网状态,但是起点不同(比如从a=>c, b=>c)需要做的升级操作可能完全是不同的。要编写一个面面俱到的升级脚本其实非常困难。

还有哪些问题?

一致性和稳定性是最大的问题。服务器开机之后,常年是不重装系统的。无数人在上面跑过脚本,执行过命令,定位过问题。服务器实际的状态是没有办法精确管控的。infrastructure as code 是一种改良,但是仍未根除这个问题。每一次在服务器上跑脚本其实就是一种赌博,因为没有两台服务器是完全一样的。在本地测试可行的脚本,未必在另外一台上不会引起问题。这不是强调一下代码里不能 rm * ,而要 rm path/* 就可以解决的问题。

版本管理其实一直是没有的。做过开发的人,可能还会用 git/svn 来作为部署的基线,基本的版本都会提交到仓库里。更多的一线运维用的还是 rsync 的模式。rsync 的意思就是要安装一个新服务器,需要找一台“与之最像”的服务器。然后把文件拷贝到新服务器上,把配置修改一下,启动完事。携程出事了,我个人猜测应该与版本管理混乱有关系。

故障替换是非常困难的。先不说故障替换,就是故障机剔除就是一个头疼的事情。比如 zookeeper。各个客户端都硬编码三个 ip 地址。一旦其中一个 ip 挂掉了。zookeepr按照高可用协议可以保持正常,但是长期来说这个挂掉的ip还是要从各个使用方里剔除的。这个就且改了。一旦业务的高可用做得不好,需要运维来搞一些接告警之后替换故障机的事情,那就是各种脚本折腾各种配置文件的节奏了。

Docker 是如何掀桌子的

两点神论,进入到 Docker 时代之后

  • CMDB 不再至关重要了。CMDB 连同IP,以及服务器资源变成底层蓝领工人关心的问题了。上层的后台开发和业务运维不再需要也无法再以 IP 为中心的 CMDB 来管理配置。
  • 分布式脚本执行平台从核心作业系统退居二线。很简单,服务器不再需要变更了,常规的上新服务器,发布新版本都不再依赖脚本在一个已有的服务器上执行去修改状态。而是创建一个新的容器。

Docker的实质是一个真正的版本管理工具。在 Docker 之前版本管理是各种拼凑的解决方案。什么是版本,服务器是由三部分组成:版本、配置、数据。所谓版本就是操作系统,以及操作系统的配置。各种第三方包,开发给的可执行文件,和一部分配置文件。这些的集合是一个版本,其实就是一个完整的可执行环境。除此之外一般就是一个数据库,里面放了两部分内容,一部分是管理员可以从页面上修改的配置,一部分是业务数据。在 puppet 时代的版本,是一个申明文件。这个申明文件执行的时候,需要先从某个 ISO 安装出一个操作系统,然后用 apt-get/yum 从某个镜像源安装一堆系统的包,然后用 pip/bundle 安装一堆 python/ruby 语言层面的包,最后才是开发给你的 git/svn/某个不知名的tar.gz。你以为这些东西每次拼装出来的东西都是同样的版本么?其实未必。想当年某墙干掉 github 的时候,不知道多少人无法做发布了。Docker 打包出的连系统在一起的镜像,其实是对版本的最好阐述。

使用 Docker 之后不再需要修改现网的 container 了。一个 container 如果需要升级,那么就把它干掉,再把预先做好的新的镜像发布成一个新的 container 替换上去。分布式脚本执行,变成了分布式容器替换了。当然这种标准化的操作,用 mesos + marathon 已经完美解决了。

使用 Docker 之后,无法再基于 IP 做管理了。倒不是给每个 container 分配一个 IP 分配不过来,而是 IP 代表的静态模型无法跟上时代了。基于 IP 管理,就意味你会基于 SSH 登陆这个 IP 来管理。这种思想从骨子里就是落后的了。进程,进程组,模块,set 这些才是管理的粒度。至于进程是跑在哪个 IP 上的哪个容器里,不再重要了。一图可以说明这个问题:

1

 

上面这个扩容的按钮点完之后有让你填 IP 吗?没有!你只需要告诉marathon,我要32个进程实例。它就会去找这些资源运行这 32 个实例。业务最终需要的是 32 个进程,而不是 32 个 IP。IP只是运行进程需要的资源而已。实际运行的时候进程可能是在一个IP上启动了32个端口,也可能是随机分配了5个IP,每个各跑了一些端口。当然这些分配都是可以通过“约束”的方式表达的。而不是让你去搞32个IP来,再跑个脚本去这些IP上部署这些进程。

The Missing Piece

拼图游戏就差最后这一块了。Docker 做为一个版本工具是绝对合格的。Marathon 以 Docker 的方式托管所有进程也是靠谱的。但是还不完整:

  • Docker镜像作为版本发布到现网之后是无法运行的,因为任何一个应用起码都有好几个服务要互相访问。这些硬编码在镜像里的 IP 地址换了一个环境是无法执行的。一个版本里任何配置都可以硬编码,就是 IP 地址和端口是没硬编码的。
  • 扩容缩容可以很容易创建和销毁容器,但是引用了这个容器的服务器的其他容器怎么办呢?
  • 发布,故障替换都是同样的问题

解决方案可以看这两张图:

2

3

方案其实非常简单。把 app1 => app2 的网络访问关系,改成 app1 =local=> haproxy =network=> haproxy =local=> app2。通过在容器本地部署 haproxy “托管所有的端口”,也就是用 haproxy 在进程之间做联线,而不是每个进程自己去负责连接网络上的其他进程。

试想一下之前是在配置文件里硬编码 10.0.0.1:3306 是某台数据库。硬编码是不对的,是要打屁股的。所以我们把硬编码的 ip 地址改成 127.0.0.1:10010。这一次我们不再硬编码任何 IP 了,我们只硬编码一个特殊的端口号。每个进程都有一堆特殊的本地端口号用于访问自己需要的上下游服务。这个端口号背后的进程到底在哪个 IP,哪个 端口,哪个 container 里执行。做为使用方不需要修改任何代码(比如兼容什么 zookeeper/etcd 神马的),也不用关心。甚至这个端口后面是多个远程的IP构成一个基于客户端的高可用。代理甚至还可以做一些出错换一个后端再重试的事情。

有了这种神器之后,扩容所容,发布变更,故障替换都很轻松了。容器随便新增,随便删除。网络结构变化了之后,刷新各个地方的 haproxy 配置就是了。各种灰度,各种零停机替换方案都可以搞起。

名字服务与网络

类似的方案有很多。最底层的方案是 SDN/IP 漂移,以及网络的bonding。这种方案的特点是保持 IP 地址作为最传统的名字服务,妄图延续其生命。
上层一点的方案是 DNS。再上层一些的方案是 Zookeeper。
各种方案争的就是服务如何注册自己,如何彼此发现这个点。各种方案的优缺点可以自己去读:

http://nerds.airbnb.com/smartstack-service-discovery-cloud/
https://blog.docker.com/tag/smartstack/

btw,airbnb 在 13 年就把这套方案投入生产了。

最有意思的是把这种 haproxy 的方案与基于 SDN 的 IP 漂移方案做对比。haproxy 的就是替网络做应用层进程之间联线的事情,通过引入 haproxy 让这种联线更具有灵活性。 而 SDN 的方案是说,你现在的业务进程之间是通过 IP 之间静态链接的,这种连接不够灵活没关系,路由器帮你整。一个 IP 挂掉了,可以把IP漂移到另外一台机器上去继续使用。其实就是在一个场景下实现两个进程的重新联线,突破两 IP 之间静态互访的限制,给基于 IP 的部署方案续命。

两者底层的技术是相通的。所谓 IP 漂移最后靠的是现代牛逼的CPU,和软件路由技术。最后玩的都是用户态转发,dpdk神马的。所以 haproxy 慢,转发效率有问题神马的,长期来看都不会是问题。用软件来联线,是趋势。连路由器都开始这么玩了,连硬件厂商都开始卖软件了。

The Final Battle

集群管理纯粹变成进程管理,IP不再重要,状态不再重要。CMDB会变得越来越边缘化。
发布变更不再是去修改服务器,而是新建销毁容器,以及更新进程间网络联线关系。分布式作业系统会越来越少用,跳板机就更加不允许使用了。

记住“immutable servers”这个提法吧,它终将会得到历史的认可。

经原文作者同意转载,文章转自:http://segmentfault.com/a/1190000002882567

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

哪里才是中国最真实的农村?

北京-周妮娜-Nina当我们与6月说再见的时候,P3的“你我同行”系列活动也已完整告一段落。从上半年双月P3工作坊[1]以及三次“下农村”[2]体验活动,我相信每个人心中或许和我一样,一方面向往着“采菊东篱下、悠然见南山”的郝堂村生活意境,但当看到蒲城或是巴中市花溪乡走马村那种村落凋零、文化跌落或是农村社会断裂时,另一方面却更加充满了对农村“贫困”回归的失落,失落的背后是更多地思考真正的乡村未来是什么?我们能为现在的农村建设做点什么?中国拥有6亿农村人口,包括其中的7000万贫困人口和6100万留守儿童,而我们在郝堂、蒲城以及走马村所看到的也不是“贫困”问题的全部,但是在三个案例中,让我产生了三点特别深切的感受:

第一,扶贫进程中的民间组织力量。早在联合国提出将减少贫困作为千年目标以及中国政府主导的农村改革失灵的时候,越来越多的民间组织(NGO)从事扶贫,长期驻扎并活跃在一线贫困农村,不但地域上覆盖了很多难以到达的区域,而且从影响力看来,更加得到了贫困村民的高度认可。民间组织显然成为权利和资本拥有者的政府部门的补充剂,但其角色更像是发起者、协调者和激励者。例如,小母牛在巴中花溪乡走马村的十年陪伴式发展,除了带着强烈的自身使命和价值观深入农村,更是将农民作为主体实现自治。小母牛在激活外部资源时,更是以赋权的方式保证了乡村的活力——集体修山路、改造凉亭和组织妇女表演队等等。

第二,建筑师和学者等专业人士的长期投入。郝堂村的土屋设计使我看到了那些拥有乡土情怀的建筑设计师们对中国乡土问题的深刻理解,以及对自然和乡村文化的尊重。有别于斥巨资设计的“密云古北水镇”式的供城市精英专门消费的“乡村”不同,更加有异于那些带着工业革命成果的“专业”城市设计思维的建筑师所打造的城镇, 郝堂村的改建则依然以农民为主体,使本无特殊景观资源的村落成为最美乡村。这个例子也更加说明了,当我们在行动前应该直面真实、倾听乡村的历史和人文、倾听村民的想法并共同发现创造的空间,将我们的解决方案融入自然和本土文化,而不是站在专业制高点俯视农村建设。

第三,农村也是我们大可作为的土壤。如今的经济发展离不开网络,而在村庄的探访也令我们看到了真实的网络“难民”和数字鸿沟带来的发展不平等——走马村柏林湾和蒲城村民或是因为文化程度低而无法享受网络资源带来的社会红利,又或是由于经济贫困而不能承担昂贵的信息化设备和服务,这些都是横亘在农村信息化发展的屏障。如果我们能为他们设计一款有用的非IT类产品或者工具,或是用我们的声音呼吁公众的关注,甚至最终影响决策者们增加贫困人群的“信息化”补贴等等,这些都是具有强烈现实意义的。

最后,大家也许还会有这样的疑问,我们到底应该把我们的力量投入在哪些农村?到底哪些贫困人群是我们真正要帮助的?思考这两个问题是特别有意义的事情,当我们无法忽视那些发展道路上受限的空心村事实的时候,一时间我也难以给出明确的答案。但是,如果说我们为郝堂村做点什么是锦上添花,那么更加专注蒲城、走马村甚至大凉山这些具有典型当代农村的贫穷、脏乱差和基础设施缺失的地区,则是济困解危、救人于水火。

[1]P3委员会于今年2月、4月和6月分别邀请了外部嘉宾分享了关于农村问题中的三个议题,即如何利用畜牧业帮助农村增收,新农村建设和留守儿童问题。

[2]上半年的三次下农村体验活动包括郝堂农村参访以及蒲城、花溪乡走马村的农村问题调研。

Share