1、一个优秀的程序员,要给一个“优秀的程序员”一个明确的定义,无疑是一件非常困难的事情。擅长抽象思维、动手能力强、追求效率、喜欢自动化、愿意继续学习、对代码质量追求高等,这些维度都有其合理性,但都略带抽象和主观。(图片来自:http://t.cn/R6I1yhJ)一个程序员好不好,我也有自己的标准,就是对命令行的熟悉程度/喜爱程度。这个特征可以很好地指示TA是否是一个好的(或潜在的)程序员。我周围有很多非常优秀的程序员,他们都非常擅长在命令行上工作。那么熟悉命令行意味着什么呢?简单来说,90%的日常工作都可以在命令行完成。当然,喜欢/习惯使用命令行可能只是表象,其背后的本质才是优秀程序员之所以优秀的原因。2.自动化Perl语言的领导者LarryWall有一句名言:程序员的三大美德是:Laziness、Impatience和Hubris。只有懒惰才会驱使程序员尽可能将日常工作自动化,解放双手,节省时间。相比较而言,不得不说,GUI应用天生就是为了让自动化变得困难而设计的(这里不是贬义,GUI有自己完全不同的目标群体)。(图片来自:http://t.cn/R6IBgYV)GUI强调与人的直接交互:通过视觉手段多层次呈现信息,以视觉元素引导,***系统在后台进行实际处理,并直观地呈现最终结果。这种对交互过程的更多强调使得自动化变得非常困难。另一方面,由于GUI是为交互而设计的,它的响应不能太快,至少要让操作者有反应(甚至有些用户操作需要人为地加一些延迟来提高用户体验)。3、程序员的日常工作程序员除了写代码,还有很多事情要做,比如自动化测试、基础设施配置和管理、持续集成/持续发布环境,甚至有些团队还需要做一些运维相关的工作.相关的东西(在线问题监控、环境监控等)。开发/测试基础设施管理持续集成/持续发布运维(监控)工作和娱乐这一系列工作的背后,隐含着对自动化的需求。在做上述工作时,优秀的程序员会尽量自动化,有工具就用工具;如果没有,开发一个新工具。这种尽可能使一切自动化的哲学起源于UNIX世界。UNIX哲学的实际体现是通过命令行完成的。哪里有壳,哪里就有办法。4.UNIX编程哲学关于UNIX哲学,市面上其实有多种版本,这里列出一个比较详细的。有不同的版本,但有很多共同点:小即是美让程序做好一件事尽早创建原型(然后逐步进化)数据应保存为文本文件,避免可定制性低的用户在看这些条目,我们发现它们实际上使自动化一切成为可能。这里有一些小例子,让我们看看命令行工具如何通过应用这些哲学来简化工作并提高效率。一旦掌握了这些技巧,就再也离不开它,也无法再容忍各种低效复杂的GUI工具。5.命令行如何提高效率高级计算器在我编程生涯的早期,我读到的最激动人心的书是《UNIX编程环境》。与基本UNIX世界中的其他大部头相比,这本书实际上是相对较小的。大二的时候,这本书已经出版快22年了(中文版也有7年了),有些内容已经过时了,比如main函数没有返回值,外参列表等.,但是当我了解到HOC(高阶计算器)的整个开发过程时,我还是被深深震撼了。简而言之,这个HOC语言的开发过程需要以下组件:词法分析器lex语法分析器yacc标准数学库stdlib此外还有一些自定义函数等,最后通过make连接在一起。我按照书上的解释,把书前面的代码全部敲了一遍。所有的操作都是在一台很老的IBMThinkPadT20上完成的,都是在命令行下进行的(当然是在命令行下听歌)。这也是我第一次完全被UNIX的理念所打动:每个工具只做一件事,做好一件事。这些工具可以协同工作,一切都是面向文本的。一些各司其职的小工具协同完成一个程序设计语言程序的预编译、编译、链接、二进制生成等动作。YFLAGS=-dOBJS=hoc.ocode.oinit.omath.osymbol.ohoc5:$(OBJS)cc$(OBJS)-lm-ohoc5hoc.ocode.oinit.osymbol.o:hoc.hcode.oinit.osymbol.o:x.tab.hx.tab.h:y.tab.h-cmp-sx.tab.hy.tab.h||cpy.tab.hx.tab.hpr:hoc.yhoc.hcode.cinit.cmath.csymbol.c@pr$?@touchprclean:rm-f$(OBJS)[xy].tab.[ch]虽然现在看,这本书的很多内容已经过时了(尤其是距第一次出版将近30年),有兴趣的朋友可以看看。这里有一个Lex/Yacc的小例子,有兴趣的朋友可以看看。当然,如果你使用最先进的IDE(典型的GUI工具),其背后的原理是一样的:生成一个Makefile并在后台调用它。6、在基础设施自动化开发过程中,工程师还需要关注一个问题:软件运行的环境。学生时代刚开始学习Linux的时候,我会在Windows机器上安装一个虚拟机软件VMWare,然后在VMWare中安装一个RedhatLinux9。这样,当我不小心把Linux弄坏时,我只需要重新安装它,而不影响我的其他数据(如课程作业、文档等)。但是每次都要重新安装,非常麻烦。需要找到iso镜像文件,挂载到本地虚拟光驱,然后用VMWare安装。而这些动作都是在GUI中完成的,每次都要做很多重复的事情:找到镜像文件,使用虚拟光驱软件挂载,启动VMWare,安装Linux,配置个人偏好,配置用户名称/密码等。一旦熟练,我可以在30-60分钟内安装和配置一个新环境。1、Vagrant后来发现了Vagrant,它支持开发者通过配置来描述机器,然后通过命令行安装启动,比如如下配置:VAGRANTFILE_API_VERSION="2"Vagrant.configure(VAGRANTFILE_API_VERSION)do|config|config.vm.box="precise64"config.vm.network"private_network",:ip=>"192.168.2.100"end定义一个虚拟机,使用UbuntuPrecise64的镜像,然后配置一个网络地址192.168.2.100,定义好后,我只需要执行:$vagrantup我的机器几分钟就可以安装好,因为这个动作是在命令行中完成的,我在持续集成环境中也可以做同样的事情–只有一个命令是必须的。定义的文件可以在团队内共享,可以放入版本管理。团队中的任何成员都可以在几分钟内获得像我这样的环境。2.Ansible一般来说,一个全新的操作系统对于一个软件项目来说基本上是没有用的。为了使应用程序正常工作,我们需要很多东西。比如Web服务器,Java环境,cgi路径等。除了安装一些软件,还有很多配置工作要做,比如apachehttpd服务器的文档根路径,JAVA_HOME环境变量,以及很快。(图片来自:http://t.cn/R6IBZKm)这些工作完成后,一个环境就准备好了。记得在上一个项目中,不小心把测试环境的Tomcat目录给删了。结果又找了一个同事花了三四个小时才恢复环境(包括重装Tomcat,配置一些JAVA_OPTS,应用deployment等)。幸运的是,我们有很多工具可以帮助开发者完成环境的自动化准备,比如Chef、Puppet、Ansible。只需一些简单的配置,然后结合命令行应用,整个过程就可以自动化:-name:setupcustomrepoapt:pkg=python-pycurlstate=present-name:enablecarboncopy:dest=/etc/default/graphite-carboncontent='CARBON_CACHE_ENABLED=true'-name:installgraphiteanddepsapt:name={{item}}state=presentwith_items:packages-name:installgraphiteanddepspip:name={{item}}state=presentwith_items:python_packages-name:setupapachecopy:src=apache2-graphite。confdest=/etc/apache2/sites-available/defaultnotify:restartapache-name:configurewsgifile:path=/etc/apache2/wsgistate=directory上面的配置说明了安装graphite-carbon、配置apahce等大量手工劳动。开发人员现在只需执行:$ansible即可自动化整个过程。现在如果我不小心删除了Tomcat,重新配置一个新的只需要几分钟。当然,整个过程仍然是自动的。这在GUI下是完全无法想象的,尤其是在自定义内容如此之多的场景下。7.持续集成/持续发布在日常的开发任务中,除了实际的编码和环境配置之外,另一大部分内容就是持续集成/持续发布。在命令行的帮助下,这个动作也可以非常高效和自动化。Jenkins持续集成/持续发布已经是很多企业IT的基本配置。各种团队使用持续集成环境来编译代码、静态检查、执行单元测试、端到端测试、生成报告、打包、部署到测试环境等等。比如在Jenkins环境中,在之前的版本中,配置一个构建任务需要大量的GUI操作,而在新版本中,大部分操作已经可以写成脚本。这样,自动化就成为可能。复制现有的管道,或者修改一些配置、命令、变量等,不再需要用鼠标点击。而且,这些代码可以纳入项目代码库,与其他代码一起管理和维护,变更历史更容易跟踪和回滚(在GUI上,尤其是基于web的,回滚操作基本不可能)。node{defmvnHomestage('Preparation'){//fordisplaypurposesgit'https://github.com/jglick/simple-maven-project-with-tests.git'mvnHome=tool'M3'}stage('Build'){sh"'${mvnHome}/bin/mvn'-Dmaven.test.failure.ignorecleanpackage"}stage('Results'){junit'**/target/surefire-reports/TEST-*.xml'archive'target/*.jar'}}上面的groovy脚本定义了三个阶段,每个阶段都有自己的命令。这种代码控制方式显然比GUI编辑更高效,自动化也成为可能。八、运维工作1、自动化监控Graphite是一个强大的监控工具,但其背后的思想却很简单:根据时间线存储数据,将数据渲染成图,并定期刷新定期发送给Graphite,剩下的交给石墨。比如可以消费这样的数据:Name,比如instance.prod.cpu.load,这里表示prod实例的CPU负载,第二个字段表示数据的值,最后一个字段表示时间戳。这样,Graphite会按照时间顺序绘制同名下的所有值。(图片来自:http://t.cn/R6IxKYL)默认情况下,Graphite会监听一个网络端口,用户通过网络向这个端口发送信息,然后Graphite会持久化信息并定期刷新。总之发送数据只需要一个命令:echo"instance.prod.cpu.load23`date+%s`"|nc-q0graphite.server2003date+%s会生成当前时间戳,然后通过echo命令拼写即可成一个完整的字符串,比如:instance.prod.cpu.load231484638812然后把这个字符串通过网络发送到graphite.server的2003端口|这样,数据就记录在了graphite.server上。2.定时任务如果我们想每隔几秒自动发送数据给graphite.server,我们只需要修改这行命令:获取当前CPU负载获取当前时间戳并做一个字符串发送给graphite.server重复步骤1-4每5分钟在端口2003上获取CPU负载。在大多数系统中很容易:ps-A-o%cpu这里的参数:-A表示统计当前所有进程-o%cpu表示只在cpu一栏显示%值这样就给出了每个进程的CPU负载数正在占用:%CPU12.08.21.2...下一步是将这些数字相加。这可以通过awk命令轻松完成:$awk'{s+=$1}END{prints}'例如,要计算1、2和3的和:$echo"1\n2\n3"|awk'{s+=$1}END{prints}'两者可以通过管道连接:$ps-A-o%cpu|awk'{s+=$1}END{prints}'我们来测试一下效果:$ps-A-o%cpu|awk'{s+=$1}END{prints}'28.6看起来不错。有这个脚本,可以通过crontab定时调用:#!/bin/bashSERVER=graphite.serverPORT=2003LOAD=`ps-A-o%cpu|awk'{s+=$1}END{prints}'`echo"instance.prod.cpu.load${LOAD}`date+%s`"|nc-q0${SERVER}${PORT}当然如果你使用Grafana等强调UI的工具也可以很轻松的做的更酷:(来源:http://t.cn/R6IxsFu)想一想如何用GUI应用程序完成这些任务。九、娱乐命令行的MP3播放器最早的时候有一个命令行工具叫mpg123,就是用来播放MP3文件的。然而,这个工具是商业的,所以有人写了一个名为mpg321的工具,它基本上是mpg123的开源克隆。不过后来mpg123本身也开源了,后面就不说了。把我所有mp3文件的路径存成一个文件,相当于我的播放列表:$ls/Users/jtqiu/Music/*.mp3>favorites.list$catfavorites.list.../Users/jtqiu/Music/RollingInTheDeep-Adele.mp3/Users/jtqiu/Music/Wavin'Flag-K'Naan.mp3/Users/jtqiu/Music/BlueLotus-许玮.mp3...那我把这个歌单给mpg321后台播放:$mpg321-q--listfavorites.list&[1]10268这样我就可以边听音乐边写代码了。如果听腻了,只需要将这个后台任务切换到前台fg,然后关掉即可:$fg[1]+10268runningmpg321-q--listfavorites.list十。总结综上所述,优秀的程序员可以借助命令行特性成倍(有时跨越数量级)提高工作效率,从而有更多时间思考、学习新技能或开发新工具来帮助自动化工作。这就是优秀的程序员之所以优秀的原因。然而,面向手动和原始的图形界面会减慢进程,许多本可以自动化的任务淹没在“简单的GUI”中。(图片来自:http://cargocollective.com/)***再补充一点,这篇文章的重点是强调一个优秀的程序员和命令行的关系,而不是去比较GUI的优缺点程序和命令行。当然,GUI程序也有其使用场景,比如3D建模、GIS系统、设计师创作、图文并茂的文字处理软件、电影播放器??、网络浏览器等等。应该说,命令行与优秀程序员的关系更多的是相关性而非因果性。在程序员的日常工作中,涉及到更多需要命令行工具支持的场景。如果走极端,在不合适的场景下强行使用命令行,不顾效率,就有点大材小用了,适得其反。【本文为专栏作家《ThoughtWorks》原创稿件,微信公众号:Thinkworker,转载请联系原作者】点此查看该作者更多好文
