那么以后可能就是这样子。。。。
Growth: 全栈增长工程师指南 === 这是一本不止于全栈工程师的学习手册,它也包含了如何成为一个 Growth Hacker 的知识。 全栈工程师是未来 --- > 谨以此文献给每一个为成为优秀全栈工程师奋斗的人。 技术在过去的几十年里进步很快,也将在未来的几十年里发展得更快。今天技术的门槛下降得越来越快,原本需要一个团队做出来的Web应用,现在只需要一两个人就可以了。 同时,由于公司组织结构的变迁,以及到变化的适应度,也决定了赋予每个人的职责将会越来越多。尽管我们看到工厂化生产带来的优势,但是我们也看到了**精益思想**带来的变革。正是这种变革让越来越多的专家走向全栈,让组织内部有更好的交流。 你还将看到专家和全栈的两种不同的学习模式,以及全栈工程师的未来。 ###技术的革新史 从开始的 CGI 到 MVC 模式,再到前后端分离的架构模式,都在不断地降低技术的门槛。而这些门槛的降低,已经足以让一两个人来完成大部分的工作了。 ####CGI 二十年前的网站以静态的形式出现,这样的网站并不需要太多的人去维护、管理。接着,人们发明了 CGI (通用网关接口,英语:Common Gateway Interface)来实现动态的网站。下图是一个早期网站的架构图: ![CGI 网站架构](assets/article/prelude/cgi-arch.gif) 当时这种网站的URL类似于: ```bash https://www.phodal.com/cgi-bin/getblog ``` (PS:这个链接是为了讲解而存在的,并没有真实存在。) 用户访问上面的网页的时候就会访问,cgi-bin 的路径下对应的 getblog 脚本。你可以用 Shell 返回这个网页: ```bash #!/bin/sh echo Content-type: text/plain echo hello,world ``` Blabla,各种代码混乱地夹杂在一起。不得不说一句:这样的代码在2012年,我也看了有一些。简单地来说,这个时代的代码结构就是这样的: ![CGI脚本文件 ](assets/article/prelude/cgi-script.png) 这简直就是一场恶梦。不过,在今天好似那些 PHP 新手也是这样写代码的。 好了,这时候我们就可以讨论讨论 MVC 模式了。 ####MVC架构 我有理由相信 Martin Fowler 的《企业应用架构模式》在当时一定非常受欢迎。代码从上面的耦合状态变成了: ![MVC 架构](assets/article/prelude/caf_mvc_arch.png) 相似大家也已经对这样的架构很熟悉了,我们就不多解释了。如果你还不是非常了解的话,可以看看这本书后面的部分。 ####后台服务化与前端一致化架构 在今天看来,我们可以看到如下图所示的架构: ![后台服务化与前台一致化架构](assets/article/prelude/oneui-serviceful-arch.png) 后台在不知不觉中已经被服务化了,即只提供API接口和服务。前端在这时已经尽量地和 APP 端在结合,使得他们可以保持一致。 ###软件开发的核心难题:沟通 软件开发在过去的几十年里都是大公司的专利,小公司根本没有足够的能力去做这样的事。在计算机发明后的几十年里,开发软件是大公司才能做得起的。一般的非技术公司无法定制自己的软件系统,只能去购买现有的软件。而随着技术成本的下降,到了今天一般的小公司也可以雇佣一两个人来做同样的事。这样的演进过程还真是有意思: ![开发演进](assets/article/prelude/develop-history.png) 在这其中的每一个过程实质上都是为了解决沟通的问题。从瀑布到敏捷是为了解决组织内沟通的问题,从敏捷到精益不仅仅优化了组织内的沟通问题,还强化了与外部的关系。换句话说,精益结合了一部分的互联网思维。 ####瀑布式 在最开始的时候,我们预先设计好我们的功能,然后编码,在适当的时候发布我们的软件: ![预先式设计的瀑布流](assets/article/prelude/old-se.jpg) 然而这种开发方式很难应对市场的变化——当我们花费了几年的时间开发出了一个软件,而这个软件是几年前人们才需要的。同时,由于软件开发本身的复杂度的限制,复制的系统在后期需要大量的系统集成工作。这样的集成工作可能要花费上大量的时间——几星期、几个月。 ![瀑布流的沟通模型](assets/article/prelude/waterfall-process.png) 当人们意识到这个问题的时候,开始改进工作流程。出现了敏捷软件开发,这可以解释为什么产品经理会经常改需求。如果一个功能本身是没必要出现的话,那么为什么要花功夫去开发。但是如果一个功能在设计的初期就没有好好设计,那么改需求也是必然的。 ####敏捷式 现有的互联网公司的工作流程和敏捷软件开发在很多部分上是相似的,都有迭代、分析等等的过程: ![敏捷软件开发](assets/article/prelude/scrum.png) 但是据我的所知:国内的多数互联网公司是不写测试的、没有 Code Review 等等。当然,这也不是一篇关于如何实践敏捷的文章。敏捷与瀑布式开发在很大的区别就是:沟通问题。传统的软件开发在调研完毕后就是分析、开发等等。而敏捷开发则会强调这个过程中的沟通问题: ![敏捷软件开发的沟通模型](assets/article/prelude/scrum-communication.png) 在整个过程中都不断地强调沟通问题,然而这时还存在一个问题:组织结构本身的问题。这样的组织结构,如下图所示: ![组织结构](assets/article/prelude/scrum-issues.png) 如果市场部门/产品经理没有与研发团队坐一起来分析问题,那么问题就多了。当一个需求在实现的过程中遇到问题,到底是哪个部门的问题? 同样的如果我们的研发部门是这样子的结构: ![研发部门](assets/article/prelude/tech-org.png) 那么在研发、上线的过程中仍然会遇到各种的沟通问题。 现在,让我们回过头来看看大公司的专家与小公司的全栈。 ###大公司的专家与小公司的全栈 如果你经常看一些关于全栈和专家的技术文章的时候,你就会发现不同的人在强调不同的方向。大公司的文章喜欢强调成为某个领域的专家,小公司喜欢小而美的团队——全栈工程师。 如我们所见的:大公司和小公司都在解决不同类型的问题。大公司要解决性能问题,小公司都活下去需要依赖于近乎全能的人。并且,大公司和小公司都在加班。如果从这种意义上来说,我们可以发现其实大公司是在剥削劳动力。 **专家** 我们所见到的那些关于技术人员应该成为专家的文章,多数是已经成为某个技术领域里的专家写的文章。并且我们可以发现很有意思的一点是:他们都是**管理者**。管理者出于招聘的动机,因此更需要细分领域的专家来帮助他们解决问题。 **全栈** 相似的,我们所看到的那些关于成为全栈工程师的文章,多数是初创公司的CTO写的。而这些初创公司的CTO也多数是全栈工程师,他们需要招聘全栈工程师来帮助他们解决问题。 ####两种不同的学习模型 而不知你是否也注意到一点:专家们也在强调**“一专多长”**。因为单纯依靠于一个领域的技术而存在的专家已经很少了,技术专家们不得不依据于公司的需求去开拓不同的领域。毕竟“公司是指全部资本由股东出资构成,以营利为目的而依法设立的一种企业组织形式;”,管理人们假设技术本身是相通的,既然你在技术领域里有相当高的长板,那么进入一个新的技术也不是一件难的事。 作为一个技术人员,我们是这个领域中的某个子领域专家。而作为这样一个专家,我们要扩展向另外一个领域的学习也不是一件很难的事。借鉴于我们先前的学习经验,我们可以很快的掌握这个新子域的知识。如我们所见,我们可以很快地补齐图中的短板: ![木桶](assets/article/prelude/bucket.jpg) 在近来的探索中发现有一点非常有意思:如果依赖于20/80法则的话,那么成为专家和全栈的学习时间是相当的。在最开始的时候,我们要在我们的全栈工程和专家都在某个技术领域达到80分的水平。 那么专家,还需要80%的时间去深入这个技术领域。而全栈工程师,则可以依赖于这80%的时候去开拓四个新的领域: ![全栈与专家学习时间](assets/article/prelude/expert-vs-fullstack.png) 尽管理论上是如此,但是专家存在跨领域的学习障碍——套用现有模式。而全栈也存在学习障碍——如何成为专家,但是懂得如何学习新的领域。 ####解决问题的思路:不同的方式 有意思的是——成为专家还是成为全栈,取决于人的天性,这也是两种不同的性格决定的。成为管理者还是技术人员看上去就像一种简单的划分,而在技术人员里成为专家还是全栈就是另外一种划分。这取决于人们对于一个问题的思考方式:这件事情是借由外部来解决,还是由内部解决。下面这张图刚好可以表达我的想法: ![内向与外向思维](assets/article/prelude/in-out-thinking.jpeg) 而这种思维依据于不同的事情可能会发生一些差异,但是总体上来说是相似的。当遇到一个需要创轮子的问题时,我们就会看到两种不同的方式。 对于全栈工程师来说,他们喜欢依赖于外部的思维,用于产生颠覆式思维。如 AngularJS 这样的框架便是例子,前端结合后端开发语言 Java 的思维而产生。而专家则依赖于内部的条件,创造出不一样的适应式创新。如之前流行的 Backbone 框架,适应当时的情况而产生。 ###全栈工程师的未来:无栈 全栈工程师本身不应该仅仅局限于前端和后台的开发,而可以尝试去开拓更广泛的领域——因为全栈本身是依赖于工程师本身的学习能力,正是这种优秀的学习能力可以让他们可以接触更广泛的知识。 ####全栈的短板 如果你也尝试过面试过全栈工程师,你会怎么去面试他们呢?把你知道的所有的不同领域的问题都拿出来问一遍。是的,这就是那些招聘全栈工程师的公司会问你的问题。 人们以为全栈工程师什么都会,这是一个明显的误区——然而要改变这个误区很难。最后,导致的结果是大家觉得全栈工程师的水平也就那样。换句来说,人们根本不知道什么是全栈工程师。在平时的工作里,你的队伍都知道你在不同领域有丰富的知识。而在那些不了解你的人的印象里,就是猜测你什么都会。 因此,这就会变成一个骂名,也是一个在目前看来很难改变的问题。在这方面只能尽可能地去了解一些通用的问题,并不能去了解所有的问题。在一次被面试全栈工程师的过程中,有一个面试官准备了几个不同语言(JavaScript、Java、Python、Ruby)的问题来问我,我只想说 Ciao —— 意大利语:你好! 除了这个问题——人们不了解什么是全栈工程师。还有一个问题,就是刚才我们说的成为专家的老大难问题。 ####无栈 让我毫不犹豫地选择当全栈工程师有两个原因: 1. 这个世界充满了未解的迷,但是我只想解开我感兴趣的部分。 2. 没有探索,哪来的真爱?你都没有探索过世界,你就说这是你最喜欢的领域。 当我第一次看到全栈工程师这个名字的时候,我发现我已然是一个全栈工程师。因为我的学习路线比较独特: 中小学:编程语言 -> 高中:操作系统、内核、游戏编程 -> 大学: 硬件、Web 开发 -> 工作:后端 + 前端 而在当时我对 SEO 非常感兴趣,我发现这分析和 Marketing 似乎做得还可以。然后便往 Growth Hacking 发展了: ![Growth Hacking](assets/article/prelude/growth-hacking.jpg) 而这就是全栈学习带来的优势,学过的东西多,学习能力就变强。学习能力往上提的同时,你就更容易进入一个新的领域。 参考书籍 - 《精益企业: 高效能组织如何规模化创新》 - 《企业应用架构模式》 - 《敏捷软件开发》 - 《技术的本质》 基础知识篇 === 在我们第一次开始写程序的时候,都是以 Hello World 开始的。或者: ```c printf("hello,world"); ``` 又或许: ```javascript alert('hello,world'); ``` 过去的十几年里,试过用二十几种不同的语言,每个都是以 hello,world 作为开头。在一些特定的软件,如 Nginx,则是 **It Works**。 这是一个很长的故事,这个程序最早出现于1972年,由贝尔实验室成员布莱恩·柯林汉撰写的内部技术文件《A Tutorial Introduction to the Language B》之中。不久,同作者于1974年所撰写的《Programming in C: A Tutorial》,也延用这个范例;而以本文件扩编改写的《C语言程序设计》也保留了这个范例程式。工作时,我们也会使用类似于 hello,world 的 boilerplate 来完成基本的项目创建。 同时需要注意的一点是,在每个大的项目开始之前我们应该去找寻好开发环境。搭建环境是一件非常重要的事,它决定了你能不能更好地工作。毕竟环境是生产率的一部分。高效的程序员和低效程序员间的十倍差距,至少有三倍是因为环境差异。 因此在这一章里,我们将讲述几件事情: 1. 使用怎样的操作系统 2. 如何去选择工具 3. 如何搭建相应操作系统上的环境 4. 如何去学习一门语言 工具只是辅助 --- 一个好的工具确实有助于编程,但是他只会给我们带来的是帮助。我们写出来的代码还是和我们的水平保持着一致的。 什么是好的工具,这个说法就有很多了,但是有时候我们往往沉迷于事物的表面。有些时候 Vim 会比 Visual Studio 强大,当你只需要修改的是一个配置文件的时候,简单且足够快捷——在我们还未用 VS 打开的时候,我们已经用 Vim 做完这个活了。 > “好的装备确实能带来一些帮助,但事实是,你的演奏水平是由你自己的手指决定的。” -- 《REWORK》 ###WebStorm 还是 Sublime? 作为一个 IDE 有时候忽略的因素会过多,一开始的代码由类似于 Sublime text 之类的编辑器开始会比较合适。于是我们又开始陷入 IDE 及 Editor 之战了,无聊的时候讨论一下这些东西是有点益处的。相互了解一下各自的优点,也是不错的,偶尔可以换个环境试试。 刚开始学习的时候,我们只需要普通的工具,或者我们习惯了的工具去开始我们的工作。我们要的是把主要精力放在学习的东西上,而不是工具。刚开始学习一种新的语言的时候,我们不需要去讨论哪个是最好的开发工具,如 Java,有时候可能是 Eclipse,有时候可能是 Vim,如果我们为的只是去写一个 hello,world。在 Eclipse 上浪费太多的时间是不可取的,因为他用起来的效率可不比你在键盘上敲打来得快,当你移动你的手指去动你的鼠标的时候,我想你可以用那短短的时间完成编译,运行了。 ####工具是为了效率 寻找工具的目的和寻找捷径是一样的,我们需要更快更有效率地完成我们的工作,换句话说,我们为了获取更多的时间用于其他的事情。而这个工具的用途是要看具体的事物的,如果我们去写一个小说、博客的时候,word 或者 web editor 会比 tex studio 来得快,不是么。我们用 TEX 来排版的时候会比我们用 WORD 排版的时候来得更快,所以这个工具是相对而论的。有时候用一个顺手的工具会好很多,但是不一定会是事半功倍的。我们应该将我们的目标专注于我们的内容,而不是我们的工具上。 我们用 Windows 自带的画图就可以完成裁剪的时候,我们就没必要运行起 GIMP 或者 Photoshop 去完成这个简单的任务。效率在某些时候的重要性,会比你选择的工具有用得多,学习的开始就是要去了解那些大众推崇的东西。 ####了解、熟悉你的工具 Windows 的功能很强大,只是大部分人用的是只是小小一部分。而不是一小部分,即使我们天天用着,我们也没有学习到什么新的东西。和这个就如同我们的工具一样,我们天天用着他们,如果我们只用 Word 来写写东西,那么我们可以用 Abiword 来替换他。但是明显不太可能,因为强大的工具对于我们来说有些更大的吸引力。 如果你负担得起你手上的工具的话,那么就尽可能去了解他能干什么。即使他是一些无关仅要的功能,比如 Emacs 的煮咖啡。有一本手册是最好不过的,手册在手边可以即时查阅,不过出于环保的情况下,就不是这样子的。手册没有办法即时同你的软件一样更新,电子版的更新会比你手上用的那个手册更新得更快。 Linux 下面的命令有一大堆,只是我们常用的只有一小部分——20%的命令能够完成80%的工作。如同 CISC 和 RISC 一样,我们所常用的指令会让我们忘却那些不常用的指令。而那些是最实用的,如同我们日常工作中使用的 Linux 一样,记忆过多的不实用的东西,不比把他们记在笔记上实在。我们只需要了解有那些功能,如何去用他。 ###语言也是一种工具 越来越多的框架和语言出现、更新得越来越快。特别是这样一个高速发展的产业,每天都在涌现新的名词。如同我们选择语言一样,选择合适的有时候会比选得顺手的来得重要。然而,这个可以不断地被推翻。 当我们熟悉用 Python、Ruby、PHP 等去构建一个网站的时候,JavaScript 用来做网站后台,这怎么可能——于是 Node.js 火了。选择工具本身是一件很有趣的事,因为有着越来越多的可能性。 过去 PHP 是主流的开发,不过现在也是,PHP 为 WEB 而生。有一天 Ruby on Rails 出现了,一切就变了,变得高效,变得更 Powerful。MVC 一直很不错,不是么?于是越来越多的框架出现了,如 Django,Laravel 等等。不同的语言有着不同的框架,JavaScript 上也有着合适的框架,如 AngularJS。不同语言的使用者们用着他们合适的工具,因为学习新的东西,对于多数的人来说就是一种新的挑战。在学面向对象语言的时候,人们很容易把程序写成过程式的。 没有合适的工具,要么创造一个,要么选择一个合适的。 ####小结 学习 Django 的时候习惯了有一个后台,于是开始使用 Laravel 的时候,寻找 Administartor。需要编译的时候习惯用 IDE,不需要的时候用 Editor,只是因为有效率,嵌入式的时候 IDE 会有效率一点。 以前不知道 WebStorm 的时候,习惯用 DW 来格式化 HTML,Aptana 来格式化 JavaScript。 以前,习惯用 WordPress 来写博客,因为可以有移动客户端,使用电脑时就不喜欢打开浏览器去写。 等等 等 提高效率的工具 --- 在提交效率的 N 种方法里:有一个很重要的方法是使用快捷键。熟练掌握快捷键可以让我们随着自己的感觉编写程序——有时候如果我们手感不好,是不是就说明今天不适合写代码!笑~~ 由于我们可能使用不同的操作系统来完成不同的工具。下面就先说说一些通用的、不限操作的工具: ###快速启动软件 在我还不和道有这样的工具的时候,我都是把图标放在下面的任务栏里: ![Windows任务栏](assets/article/chapter1/windows-launch.png) 直到有一天,我知道有这样的工具。这里不得不提到一本书《卓有成效的程序员》,在书中提到了很多提高效率的工具。使用快捷键是其中的一个,而还有一个是使用快速启动软件。于是,我在 Windows 上使用了 Launcy: ![Launchy](assets/article/chapter1/launchy.png) 通过这个软件,我们可以在电脑上通过输入软件名,然后运行相关的软件。我们不再需要点击某个菜单,再从菜单里选中某个软件打开。 ###IDE 尽管在上一篇中,我们说过 IDE 和编辑器没有什么好争论的。但是如果是从头开始搭建环境的话,IDE 是最好的——编辑器还需要安装相应的插件。所以,这也就是为什么面试的时候会用编辑器的原因。 IDE 的全称是集成开发环境,顾名思义即它集成了你需要用到的一些工具。而如果是编辑器的话,你需要自己去找寻合适的工具来做这件事。不过,这也意味着使用编辑器会有更多的自由度。如果你没有足够的时间去打造自己的开发环境就使用 IDE 吧。 一般来说,他们都应该有下面的一些要素: - **快捷键** - **Code HighLight** - **Auto Complete** - **Syntax Check** 而如果是编辑器的话,就需要自己去找寻这些相应的插件。 IDE 一般是针对特定语言才产生的,并且优化更好。而,编辑器则需要自己去搭配。这也意味着如果你需要在多个语言上工作时,并且喜欢折腾,你可以考虑使用编辑器。 ###DEBUG 工具 不得不提及的是在有些 IDE 自带了 Debug 工具,这点可能使得使用 IDE 更有优势。在简单的项目是,我们可能不需要这样的 Debug 工具。因为我们对我们的代码库比较熟悉,一个简单的问题一眼就知道是哪里的问题。而对于那些复杂的项目来说,可能就没有那么简单了。特别是当你来到一个新的大中型项目,一个简单的逻辑在实现上可能要经过一系列的函数才能处理完。 这时候我们就需要 Debug 工具——对于前端开发来说,我们可能使用 Chrome 的 Dev Tools。但是对于后端来说,我们就需要使用别的工具。如下图所示的是 Intellij Idea 的 Debug 界面: ![Intellij Idea Debug](assets/article/chapter1/idea-debug.png) 在 Debug 的过程中,我们可以根据代码的执行流程一步步向下执行。这也意味着,当出现 Bug 的时候我们可以更容易找到 Bug。这就是为什么他叫 Debug 工具的原因了。 ###终端或命令提示符 在开始写代码的时候,使用 GUI 可能是难以戒掉的一个习惯。但是当你习惯了使用终端之后,或者说使用终端的工具,你会发现这是另外一片天空。对于 GUI 应用上同样的菜单来说,在终端上也会有同样的工具——只是你觉得记住更多的命令。而且不同的工具对于同一实现可能会不同的规范,而 GUI 应用则会有一致的风格。不过,总的来说使用终端是一个很有益的习惯——从速度、便捷性。忘了提到一点,当你使用 Linux 服务器的时候,你不得不使用终端。 ![Linux 终端截图](assets/article/chapter1/linux-server-console.jpg) 使用终端的优点在于我们可以摆脱鼠标的操作——这可以让我们更容易集中精力于完成任务。而这也是两种不同的选择,便捷还是更快。虽是如此,但是这也意味着学习 Linux 会越来越轻松。 ![Linux 与 Windows 的学习曲线](assets/article/chapter1/linux-learn-line.png) 虽然这是以 Linux 和 Windows 作了两个不同的对比,但是两个系统在终端工具上的差距是很大的。Linux 自身的哲学鼓励使用命令行来完成任务,这也意味着在 Linux 上会有更多的工具可以在命令行下使用。虽然 Windows 上也可以——如使用 CygWin 来完成,但是这看上去并不是那么让人满意! ###包管理 虽然包管理不仅仅存在于操作系统中,还存在着语言的包管理工具。在操作系统中安装软件,最方便的东西莫过于包管理了。引自 OpenSUSE 官网的说明及图片: ![包管理](assets/article/chapter1/pm.png) Linux 发行版无非就是一堆软件包 (package) 形式的应用程序加上整体地管理这些应用程序的工具。通常这些 Linux 发行版,包括 OpenSUSE,都是由成千上万不同的软件包构成的。 - 软件包: 软件包不止是一个文件,内含构成软件的所有文件,包括程序本身、共享库、开发包以及使用说明等。 - 元数据 (metadata) 包含于软件包之中,包含软件正常运行所需要的一些信息。软件包安装之后,其元数据就存储于本地的软件包数据库之中,以用于软件包检索。 - 依赖关系 (dependencies) 是软件包管理的一个重要方面。实际上每个软件包都会涉及到其他的软件包,软件包里程序的运行需要有一个可执行的环境(要求有其他的程序、库等),软件包依赖关系正是用来描述这种关系的。 我们经常会使用各式各样的包管理工具,来加速我们地日常使用。而不是 Google 某个软件,然后下载,接着安装。 环境搭建 --- 由于我近期工具在 Mac OS X 上,所以先以 Mac OS X 为例。 ###OS X **Homebrew** > 包管理工具,官方称之为 The missing package manager for OS X。 **Homebrew Cask** > brew-cask 允许你使用命令行安装 OS X 应用。 **iTerm2** > iTerm2 是最常用的终端应用,是 Terminal 应用的替代品。 **Zsh** Zsh 是一款功能强大终端(shell)软件,既可以作为一个交互式终端,也可以作为一个脚本解释器。它在兼容 Bash 的同时 (默认不兼容,除非设置成 emulate sh) 还有提供了很多改进,例如: - 更高效 - 更好的自动补全 - 更好的文件名展开(通配符展开) - 更好的数组处理 - 可定制性高 **Oh My Zsh** > Oh My Zsh 同时提供一套插件和工具,可以简化命令行操作。 **Sublime Text 2** > 强大的文件编辑器。 **MacDown** > MacDown 是 Markdown 编辑器。 **CheatSheet** > CheatSheet 能够显示当前程序的快捷键列表,默认的快捷键是长按⌘。 **SourceTree** > SourceTree 是 Atlassian 公司出品的一款优秀的 Git 图形化客户端。 **Alfred** > Mac 用户不用鼠标键盘的必备神器,配合大量 Workflows,习惯之后可以大大减少操作时间。 上手简单,调教成本在后期自定义 Workflows,不过有大量雷锋使用者提供的现成扩展,访问这里挑选喜欢的,并可以极其简单地根据自己的需要修改。 **Vimium** > Vimium 是一个 Google Chrome 扩展,让你可以纯键盘操作 Chrome。 相关参考: - [Mac web developer apps](https://gist.github.com/erikreagan/3259442) - [强迫症的 Mac 设置指南](https://github.com/macdao/ocds-guide-to-setting-up-mac) ###Windows **Chocolatey** > Chocolatey 是一个软件包管理工具,类似于 Ubuntu 下面的 apt-get,不过是运行在 Windows 环境下面。 **Wox** > Wox 是一个高效的快速启动器工具,通过快捷键呼出,然后输入关键字来搜索程序进行快速启动,或者搜索本地硬盘的文件,打开百度、Google 进行搜索,甚至是通过一些插件的功能实现单词翻译、关闭屏幕、查询剪贴板历史、查询编程文档、查询天气等更多功能。它最大的特点是可以支持中文拼音的模糊匹配。 **PowerShell** > Windows PowerShell 是微软公司为 Windows 环境所开发的壳程序(shell)及脚本语言技术,采用的是命令行界面。这项全新的技术提供了丰富的控制与自动化的系统管理能力。 **cmder** > cmder 把 conemu,msysgit 和 clink 打包在一起,让你无需配置就能使用一个真正干净的 Linux 终端!她甚至还附带了漂亮的 monokai 配色主题。 **Total Commander** > Total Commander 是一款应用于 Windows 平台的文件管理器 ,它包含两个并排的窗口,这种设计可以让用户方便地对不同位置的“文件或文件夹”进行操作,例如复制、移动、删除、比较等,相对 Windows 资源管理器而言方便很多,极大地提高了文件操作的效率,被广大软件爱好者亲切地简称为:TC 。 ###GNU/Linux **Zsh** Zsh 是一款功能强大终端(shell)软件,既可以作为一个交互式终端,也可以作为一个脚本解释器。它在兼容 Bash 的同时 (默认不兼容,除非设置成 emulate sh) 还有提供了很多改进,例如: - 更高效 - 更好的自动补全 - 更好的文件名展开(通配符展开) - 更好的数组处理 - 可定制性高 **Oh My Zsh** > Oh My Zsh 同时提供一套插件和工具,可以简化命令行操作。 **ReText** > ReText 是一个使用 Markdown 语法和 reStructuredText (reST) 结构的文本编辑器,编辑的内容支持导出到 PDF、ODT 和 HTML 以及纯文本,支持即时预览、网页生成以及 HTML 语法高亮、全屏模式,可导出文件到 Google Docs 等。 **Launchy** > Launchy 是一款免费开源的协助您摒弃 Windows “运行”的 Dock 式替代工具,既方便又实用,自带多款皮肤,作为美化工具也未尝不可。 环境搭建完毕!现在,就让我们来看看如何学好一门语言! 学好一门语言的艺术 --- ###一次语言学习体验 在我们开始学习一门语言或者技术的时候,我们可能会从一门 hello,world 开始。 好了,现在我是 Scala 语言的初学者,接着我用搜索引擎去搜索『Scala』来看看『Scala』是什么鬼: > Scala 是一门类 Java 的编程语言,它结合了面向对象编程和函数式编程。 接着又开始看『Scala 'hello,world'』,然后找到了这样的一个示例: ``` object HelloWorld { def main(args: Array[String]): Unit = { println("Hello, world!") } } ``` GET 到了5%的知识。 看上去这门语言相比于 Java 语言来说还行。然后我找到了一本名为『Scala 指南』的电子书,有这样的一本目录: - 表达式和值 - 函数是一等公民 - 借贷模式 - 按名称传递参数 - 定义类 - 鸭子类型 - 柯里化 - 范型 - Traits - ... 看上去还行, 又 GET 到了5%的知识点。接着,依照上面的代码和搭建指南在自己的电脑上安装了 Scala 的环境: ```bash brew install scala ``` Windows 用户可以用: ``` choco install scala ``` 然后开始写一个又一个的 Demo,感觉自己 GET 到了很多特别的知识点。 到了第二天忘了! ![Bro Wrong](assets/article/chapter1/wrong.jpg) 接着,你又重新把昨天的知识过了一遍,还是没有多大的作用。突然间,你听到别人在讨论什么是**这个世界上最好的语言**——你开始加入讨论了。 于是,你说出了 Scala 这门语言可以: - 支持高阶函数。lambda,闭包... - 支持偏函数。 match.. - mixin,依赖注入.. - 等等 虽然隔壁的 Python 小哥赢得了这次辩论,然而你发现你又回想起了 Scala 的很多特性。 ![最流行的语言](assets/article/chapter1/popular.jpg) 你发现隔壁的 Python 小哥之所以赢得了这场辩论是因为他把 Python 语言用到了各个地方——机器学习、人工智能、硬件、Web开发、移动应用等。而你还没有用 Scala 写过一个真正的应用。 让我想想我来能做什么?我有一个博客。对,我有一个博客,我可以用 Scala 把我的博客重写一遍: 1. 先找一 Scala 的 Web 框架,Play 看上去很不错,就这个了。这是一个 MVC 框架,原来用的 Express 也是一个 MVC 框架。Router 写这里,Controller 类似这个,就是这样的。 2. 既然已经有 PyJS,也会有 Scala-js,前端就用这个了。 好了,博客重写了一遍了。 感觉还挺不错的,我决定向隔壁的 Java 小弟推销这门语言,以解救他于火海之中。 『让我想想我有什么杀手锏?』 『这里的知识好像还缺了一点,这个是什么?』 好了,你已经 GET 到了90%了。如下图所示: ![Learn](assets/article/chapter1/learn.jpg) 希望你能从这张图上 GET 到很多点。 ###输出是最好的输入 上面那张图『学习金字塔』就是在说明——输出是最好的输入。 如果你不试着去写点博客、整理资料、准备分享,那么你可能并没有意识到你缺少了多少东西。虽然你已经有了很多的实践,然并卵。 因为你一直在完成功能、完成工作,你总会有意、无意地漏掉一些知识,而你也没有意识到这些知识的重要性。 ![Output is Input](assets/article/chapter1/output-input.png) 从我有限的(500+)博客写作经验里,我发现多数时候我需要更多地的参考资料才能更好也向人们展示这个过程。为了输出我们需要更多的输入,进而加速这个过程。 而如果是写书的时候则是一个更高水平的学习,你需要发现别人在他们的书中欠缺的一些知识点。并且你还要展示一些在别的书中没有,而这本书会展现这个点的知识,这意味着你需要挖掘得更深。 所以,如果下次有人问你如何学一门新语言、技术,那么答案就是写一本书。 ###如何应用一门新的技术 对于多数人来说,写书不是一件容易的事,而应用新的技术则是一件迫在眉睫的事。 通常来说,技术出自于对现有的技术的改进。这就意味着,在掌握现有技术的情况下,我们只需要做一些小小的改动就更可以实现技术升级。 而学习一门新的技术的最好实践就是用这门技术对现有的系统行重写。 第一个系统(v1): ``Spring MVC`` + ``Bootstrap`` + ``jQuery`` 那么在那个合适的年代里, 我们需要单页面应用,就使用了Backbone。然后,我们就可以用 Mustache + HTML 来替换掉 JSP。 第二个系统(v2): ``Spring MVC`` + ``Backbone`` + ``Mustache`` 在这时我们已经实现了前后端分离了,这时候系统实现上变成了这样。 第二个系统(v2.2): ``RESTful Services`` + ``Backbone`` + ``Mustache`` 或者 第二个系统(v2.2): ``RESTful Services`` + ``AngularJS 1.x`` Spring 只是一个 RESTful 服务,我们还需要一些问题,比如 DOM 的渲染速度太慢了。 第三个系统(v3): ``RESTful Services`` + ``React`` 系统就是这样一步步演进过来的。 尽管在最后系统的架构已经不是当初的架构,而系统本身的业务逻辑变化并没有发生太大的变化。 特别是对于如博客这一类的系统来说,他的一些技术实现已经趋于稳定,而且是你经常使用的东西。所以,下次试试用新的技术的时候,可以先从对你的博客的重写开始。 Web 编程基础 --- ###从浏览器到服务器 如果你的操作系统带有 cURL 这个软件(在 GNU/Linux、Mac OS 都自带这个工具,Windows 用户可以从[http://curl.haxx.se/download.html](http://curl.haxx.se/download.html)下载到),那么我们可以直接用下面的命令来看这看这个过程(-v 参数可以显示一次 http 通信的整个过程): ``` curl -v https://www.phodal.com ``` 我们就会看到下面的响应过程: ```bash * Rebuilt URL to: https://www.phodal.com/ * Trying 54.69.23.11... * Connected to www.phodal.com (54.69.23.11) port 443 (#0) * TLS 1.2 connection using TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 * Server certificate: www.phodal.com * Server certificate: COMODO RSA Domain Validation Secure Server CA * Server certificate: COMODO RSA Certification Authority * Server certificate: AddTrust External CA Root > GET / HTTP/1.1 > Host: www.phodal.com > User-Agent: curl/7.43.0 > Accept: */* > < HTTP/1.1 403 Forbidden < Server: phodal/0.19.4 < Date: Tue, 13 Oct 2015 05:32:13 GMT < Content-Type: text/html; charset=utf-8 < Content-Length: 170 < Connection: keep-alive <
hello,world
3. 保存为->"helloworld.html",
4. 双击打开这个文件。 正常情况下都应该是用你的默认浏览器打开。只要是一个正常工作的现代浏览器,都应该可以看到上面显示的是"Hello,world"。
这才是最短的 hello,world 程序,但是呢?在 Ruby 中会是这样子的
``` bash
2.0.0-p353 :001 > p "hello,world"
"hello,world"
=> "hello,world"
2.0.0-p353 :002 >
```
等等,如果你了解过 HTML 的话,会觉得这一点都不符合语法规则,但是他工作了,没有什么比安装完 Nginx 后看到 It works! 更让人激动了。
遗憾的是,它可能无法在所有的浏览器上工作,所以我们需要去调试其中的 bug。
####调试 hello,world
我们会发现我们的代码在浏览器中变成了下面的代码,如果你和我一样用的是 Chrome,那么你可以右键浏览器中的空白区域,点击审查元素,就会看到下面的代码。
``` html
hello,world
```
这个才是真正能在大部分浏览器上工作的代码,所以复制它到编辑器里吧。
####说说 hello,world
我很不喜欢其中的<\*>*>,但是我也没有找到别的方法来代替它们,所以这是一个设计得当的语言。甚至大部分人都说这算不上是一门真正的语言,不过 HTML 的原义是
> 超文本标记语言
所以我们可以发现其中的关键词是标记——markup,也就是说 HTML 是一个 markup,head 是一个 markup,body 也是一个 markup。
然而,我们真正工作的代码是在 body 里面,至于为什么是在这里面,这个问题就太复杂了。打个比方来说:
1. 我们所使用的汉语是人类用智慧创造的,我们所正在学的这门语言同样也是人类创造的。
2. 我们在自己的语言里遵循着 **桌子是桌子,凳子是凳子** 的原则,很少有人会问为什么。
###中文?
所以我们也可以把计算机语言与现实世界里用于交流沟通的语言划上一个等号。而我们所要学习的语言,并不是我们最熟悉的汉语语言,所以我们便觉得这些很复杂,但是如果我们试着用汉语替换掉上面的代码的话
```HTML
<语言>
<头><结束头>
<身体>你好,世界<结束身体>
<结束语言>
```
这看上去很奇怪,只是因为是直译过去的原因,也许你会觉得这样会好理解一点,但是输入上可就一点儿也不方便,因为这键盘本身就不适合我们去输入汉字,同时也意味着可能你输入的会有问题。
让我们把上面的代码代替掉原来的代码然后保存,打开浏览器会看到下面的结果
```HTML
<语言> <头><结束头> <身体>你好,世界<结束身体> <结束语言>
```
更不幸的结果可能是
```HTML
<璇█> <澶�><缁撴潫澶�> <韬綋>浣犲ソ锛屼笘鐣�<缁撴潫韬綋> <缁撴潫璇█>
```
这是一个编码问题,对中文支持不友好。
我们把上面的代码改为和标记语言一样的结构
```HTML
<语言>
<头>头>
<身体>你好,世界身体>
<结束语言>
```
于是我们看到的结果便是
```HTML
<语言> <头> <身体>你好,世界
```
被 Chrome 浏览器解析成什么样了?
``` html
<语言>
<头>
<身体>你好,世界
```
以
结尾的是注释,写给人看的代码,不是给机器看的,所以机器不会去理解这些代码。
但是当我们把代码改成
```HTML
Red
``` 只是, ``` javascript var para=document.getElementById("para"); para.style.color="blue"; ``` 将字体变成了蓝色,CSS+HTML 让页面有序的工作着,但是 JavaScript 却打乱了这些秩序,有着唯恐世界不乱的精彩,也难怪被冠以小三之名了——或许终于可以理解,为什么以前人们对于 JavaScript 没有好感了——不过这里要讲的是正室,也就是 CSS,这时还没有 JavaScript。 ![Red Fonts](assets/article/chapter1/redfonts.png) ###简介 这不是一篇专业讲述 CSS 的书籍,所以我不会去说 CSS 是怎么来的,有些东西我们既然可以很容易从其他地方知道,也就不需要花太多时间去重复。诸如重构等这些的目的之一也在于去除重复的代码,不过有些重复是不可少的,也是有必要的,而通常这些东西可能是由其他地方复制过来的。 到目前为止我们没有依赖于任何特殊的硬件或者是软件,对于我们来说我们最基本的需求就是一台电脑,或者可以是你的平板电脑,当然也可以是你的智能手机,因为他们都有个浏览器,而这些都是能用的,对于我们的 CSS 来说也不会有例外的。 CSS(Cascading Style Sheets),到今天我也没有记得他的全称,CSS 还有一个中文名字是层叠式样式表,事实上翻译成什么可能并不是我们关心的内容,我们需要关心的是他能做些什么。作为三剑客之一,它的主要目的在于可以让我们方便灵活地去控制 Web 页面的外观表现。我们可以用它做出像淘宝一样复杂的界面,也可以像我们的书本一样简单,不过如果要和我们书本一样简单的话,可能不需要用到 CSS。HTML 一开始就是依照报纸的格式而设计的,我们还可以继续用上面说到的编辑器,又或者是其他的。如果你喜欢 DreamWeaver 那也不错,不过一开始使用 IDE 可无助于我们写出良好的代码。 忘说了,CSS 也是有版本的,和 Windows,Linux 内核等等一样,但是更新可能没有那么频繁,HTML 也是有版本的,JS 也是有版本的,复杂的东西不是当前考虑的内容。 ####代码结构 对于我们的上面的 Red 示例来说,如果没有一个好的结构,那么以后可能就是这样子。 ```HTML如果没有一个好的结构
那么以后可能就是这样子。。。。
``` 虽然我们看到的还是一样的: ![No Style](assets/article/chapter1/nostyle.png) 于是我们就按各种书上的建议重新写了上面的代码 ```HTML如果没有一个好的结构
那么以后可能就是这样子。。。。
``` 总算比上面好看也好理解多了,这只是临时的用法,当文件太大的时候,正式一点的写法应该如下所示: ```HTML如果没有一个好的结构
那么以后可能就是这样子。。。。
``` 我们需要 ```HTML如果没有一个好的结构
那么以后可能就是这样子。。。。
``` 然后我们有一个像 app.js 一样的 style.css 放在同目录下,而他的内容便是 ```CSS .para{ font-size: 22px; color:#f00; text-align: center; padding-left: 20px; } .para2{ font-size:44px; color:#3ed; text-indent: 2em; padding-left: 2em; } ``` 这代码和 JS 的代码有如此多的相似 ```javascript var para={ font_size:'22px', color:'#f00', text_align:'center', padding_left:'20px', } ``` 而22px、20px以及#f00都是数值,因此: ```javascript var para={ font_size:22px, color:#f00, text_align:center, padding_left:20px, } ``` 目测差距已经尽可能的小了,至于这些话题会在以后讨论到,如果要让我们的编译器更正确的工作,那么我们就需要非常多这样的符号,除非你乐意去理解: ```lisp (dotimes (i 4) (print i)) ``` 总的来说我们减少了符号的使用,但是用 lisp 便带入了更多的括号,不过这是一种简洁的表达方式,也许我们可以在其他语言中看到。 ``` \d{2}/[A-Z][a-z][a-z]/\d{4} ``` 上面的代码,是为了从一堆数据中找出“某日/某月/某年”。如果一开始不理解那是正则表达式,就会觉得那个很复杂。 这门语言可能是为设计师而设计的,但是设计师大部分还是不懂编程的,不过相对来说这门语言还是比其他语言简单易懂一些。 ###样式与目标 如下所示,就是我们的样式 ```css .para{ font-size: 22px; color:#f00; text-align: center; padding-left: 20px; } ``` 我们的目标就是 > 如果没有一个好的结构 所以样式和目标在这里牵手了,问题是他们是如何在一起的呢?下面就是 CSS 与 HTML 沟通的重点所在了: ###选择器 我们用到的选择器叫做类选择器,也就是 class,或者说应该称之为 class 选择器更合适。与类选择器最常一起出现的是 ID 选择器,不过这个适用于比较高级的场合,诸如用 JS 控制 DOM 的时候就需要用到 ID 选择器。而基本的选择器就是如下面的例子: p.para{ color:#f0f; } 将代码添加到 style.css 的最下面会发现“如果没有一个好的结构”变成了粉红色,当然我们还会有这样的写法 p>.para{ color:#f0f; } 为了产生上面的特殊的样式,虽然不好看,但是我们终于理解什么叫层叠样式了,下面的代码的重要度比上面高,也因此有更高的优先规则。 而通常我们可以通过一个 p{ text-align:left; } 这样的元素选择器来给予所有的 p 元素一个左对齐。 还有复杂一点的复合型选择器,下面的是 HTML 文件如果没有一个好的结构
那么以后可能就是这样子。。。。
那么以后可能就是这样子。。。。