Web全栈工程师的自我修养
余果
关于我
一个人在年少的时候,可能无法看到自己现在做的事情跟自己的未来会有什么关联。您无法预知未来,只能回顾。但是您需要有信心,当您很多年后回头看时,这些点点滴滴会连接在一起,让您朝自己的理想迈进。
Facebook只招全栈工程师
Web栈(Web-Stack)
App栈(App-Stack)
全栈工程师是指,一个能处理数据库、服务器、系统工程和客户端的所有工作的工程师。根据项目的不同,客户需要的可能是移动栈、Web栈,或者原生应用程序栈。
Web开发流程
对于有些经理来说,宁可雇用多个可管理的普通工程师,也不愿意聘请一个不可管理的天才工程师。
工程师职责不清导致效率低
工程师缺乏主人感导致产品质量差
工程师缺乏全局的视野影响个人成长
高级工程师需要有对设计的理解、对后台知识的了解,以及有跨团队推动项目的能力。长期研究专精的专业知识会让一个人视野变窄,变成“学术派”,而不是“实践派”。
更多角色导致项目效率低下
全栈工程师登上舞台
PaaS(Platform as a Service,平台即服务),就可以让创业公司的开发者省去架设和维护服务器的麻烦。
VPS(Virtual Private Server,虚拟专用服务器)是把一台物理服务器虚拟成多个虚拟专用服务器的服务。每个VPS都可分配独立的公网IP地址,运行独立的操作系统,拥有独立的磁盘空间、内存、CPU资源、进程和系统配置,模拟出“独占”使用计算资源的体验。
全栈工程师的发展前景
全栈工程师除了在一个专精知识领域有深入研究之外,还以知识广博和解决问题能力强著称。
解决问题,而不是醉心技术 公司存在的意义就是解决问题,公司要解决用户的问题,而员工要解决公司的问题
公司的问题可能是降低成本、扩大用户群、增加成交量、优化性能,
如果新计划不是您擅长的,怎么办?您应该马上开始学习新的技术,这就是我说的关注问题,而不是醉心技术。
DONE IS BETTER THAN PERFECT
如何成为全栈工程师
推荐采用“先精后广,一专多长”的流程来学习
先精后广,一专多长 围绕商业目标 关注用户体验
先精后广,一专多长
比如先从前端方向入手,掌握了基本的HTML、CSS、JavaScript之后,不要转头向服务器端语言或者App方向发展,而是深入到性能优化、SEO、多种框架、响应式页面等前端细节中去。经过一到两年的深入研究之后,再去学习其他方向。
很多程序员投出的简历都石沉大海,一个主要原因是由于求职者的简历没有亮点,或者说从工作经历中提取不出来一个亮点。
让我再次重复这一点,作为求职者,一定要在某个特定方向上有非常深入的理解。仅仅会做还不够,还要理解背后的原因,还有背后的背后的原因。
围绕商业目标
我的第一条建议是,在考虑做什么项目的时候,围绕商业利益作为目标。归根结底,技术是服务于商业目标的。
老板雇用一个员工,不是因为他能写程序,而是因为他能帮助自己赚钱。赚钱有两种方法:减少成本,或者增加收入。
程序员如果能加快内部系统的运行效率,让产品制作流程更加顺畅,就是减少成本。如果能让用户更容易地购买产品,或者提高服务质量吸引更多用户,就能增加收入。在老板看来,程序员只是一个昂贵的劳动力,他会不会写程序都没那么重要,重要的是能赚钱。
所谓“商业目标”要广义地去解读。对于直接制作产品,给用户使用的团队,就需要对外关注如何提高产品质量、降低产品成本;对内应该关注如何优化流程、减少错误率。如果团队输出的成果是公司内其他部门需要的原材料,就要关注下游的需求,研究如何更好地输出成果,如何在流程上使得输出产品的过程更顺畅。
当您只有一把锤子,您看什么都是钉子。而如果您痴迷于工具,反而看不到问题所在。因此,要先看看有哪些问题需要解决,然后再补充您的工具箱。永远从商业目标的角度来决定学习哪些东西,而不是纯粹为了锻炼技术能力而去学习。
全栈工程师希望丰富自己的工具箱,而不是用一把锤子处理所有工作。
关注用户体验
我的第二条建议是,从用户体验的角度考虑问题。
每一个糟糕的体验背后都蕴含着商机
优化性能的开发者是在积极地提升用户体验和交互;设计师有意用颜色、空间、大小和表单的排列方式让用户体验更顺畅好用;而内容运营者认为某些内容重要,某些内容不重要,也是在考虑如何提升用户的体验。
比如做一次演讲或者汇报,第一件要紧的事不应该是做PPT,而应该是调查听众,站在听众的角度去思考:听众知道什么信息,听众想知道什么。如果给您的老板汇报,您不能期望他了解您所做项目的技术细节,而且他想知道的也不是技术细节,而是项目进度和风险。但是如果在一个技术论坛上分享,您就不能期望听众都知道您的项目背景和目标,需要花一点时间去介绍,听众也不想知道太多细节的东西,只需要介绍一些决策和架构的大方向。
老板雇用您不是因为您能写代码(或者做工具),而是因为您能帮他赚钱。所以您要用一切办法,去优化流程解决痛点,做工具是一个可选的方法,但不应该是您的第一个想法,更不是唯一的办法。假使真的是做了一个工具,最终汇报邮件的时候,不要以“我做了一个工具……”开头,而应该以“我发现了一个问题……”开始。
创业公司做产品,CEO一定要是自己的目标用户。因为如果自己都不体验自己的产品,就很难发现用户在使用产品过程中遇到的糟糕体验。
网上有个段子,说一般的产品经理没办法把自己代入成“小白”用户,做出的东西只有他自己会用;高级产品经理经过半小时的冥想可以进入小白状态;张小龙和马化腾这样的大师级产品经理需要两分钟;而乔布斯可以随时切换大师级产品经理和小白的状态。这就是为什么他会说“stay hungry, stay foolish”。
“全栈工程师”,我要求的三个能力就是一专多长、关注商业目标、关注用户体验。
校园招聘
前端工程师要有一个基本常识,那就是结构、表现和行为要分离。技术层面上讲,网站的内容使用语义化的HTML标签,而不掺杂任何表现和逻辑;网站样式表现用CSS来描述,既能在多个页面之间复用,也可以根据不同用户来分别定义外观;页面行为逻辑用JavaScript来实现,这样保证浏览器在禁用JavaScript的时候,页面也能正常渲染和使用。
岗位优先于公司,即使在一个很好的公司里面,如果只是做着自己不喜欢也不擅长的工作,那能有什么前途呢
书里说的设计四大原则:对齐、对比、距离和重复。
实习
实习能提升自己的实践能力,可以认为是从学生到社会人士的一个身份过渡。
遭遇“野生程序员”
压缩源码和图片 JavaScript文件源代码可以采用混淆压缩的方式,CSS文件源代码进行普通压缩,JPG图片可以根据具体质量来压缩为50%到70%, PNG可以使用一些开源压缩软件来压缩,比如24色变成8色、去掉一些PNG格式信息等。 •选择合适的图片格式 如果图片颜色数较多就使用JPG格式,如果图片颜色数较少就使用PNG格式,如果能够通过服务器端判断浏览器支持WebP,那么就使用WebP格式和SVG格式。
合并静态资源 包括CSS、JavaScript和小图片,减少HTTP请求。 •开启服务器端的Gzip压缩 这对文本资源非常有效,对图片资源则没那么大的压缩比率。 •使用CDN 或者一些公开库使用第三方提供的静态资源地址(比如jQuery、normalize. css)。一方面增加并发下载量,另一方面能够和其他网站共享缓存。 •延长静态资源缓存时间 这样,频繁访问网站的访客就能够更快地访问。不过,这里要通过修改文件名的方式,确保在资源更新的时候,用户会拉取到最新的内容。 •把CSS放在页面头部,把JavaScript放在页面底部 这样就不会阻塞页面渲染,让页面出现长时间的空白。
Web性能优化这个词既可以解读成页面加载速度(Page Speed)的优化,也可以解读成页面渲染性能(Page Performance)的优化。
大公司还是创业公司
大公司能给您的 •较小的风险
技术最佳实践
垂直专精的技能 大公司专业分工很细,而且有更多技术沟通和沉淀的氛围,所以容易让人在垂直专精的技术方向有足够的发展。在小公司更能锻炼技术的广度,深度上缺乏锻炼的环境。但是其实二者的利弊,都是外界的,技术人员的个人成长除了工作时间的锻炼,还要靠下班后的时间,外界只是给予一个环境或者机会。
服务海量用户的经验
软技能 硬技能是指每个职位需要的专业技能,软技能则是通用的技能,比如沟通、影响力、项目管理和演讲等。越是大公司,越是看重影响力,
•人脉
心态 其实大公司能给予毕业生最大的优势,就是提供一个心智培育的土壤。
积累作品集
“If you do it right, open sourcing code is great advertising for you and your company.”(如果使用得当,开源代码是您和您的公司最好的广告。)
每次签入代码都保证比签出的时候更好,那么代码仓库会变得越来越好,这必然是一个不断变好的代码仓库。
如果您是擅长设计和编程的全栈工程师,并且对自己的设计能力非常有自信,那么同样推荐Dribbble。Dribbble是设计师的舞台,它的社交性让您的作品很容易传播和收获“赞”
GitHub Pages + Jekyll/Dexy
突出重点
通过社会化媒体,树立起个人的品牌,即使不拿名片出去,也有人知道自己,这才是应该努力的方向。有人说过,“人到三十,不要去找工作,要让工作来找自己”
前端视角
打开HttpWatch,然后随意访问一个网站。HttpWatch会按照浏览器请求的次序,列出打开这个网站的时候发生的请求细节。 •发出的请求列表。 •每个请求的开始时间。 •每个请求从开始到结束花费的时间。 •每个请求的类型(比如是文本、CSS、JS,还是图片或者字体等)。 •每个请求的状态码(比如是200、还是from cache、304、404等)。 •每个请求产生的流量消耗。 •每个请求gzip压缩前的体积,以及在本地gzip解压后的体积。
每一个前端工程师都知道的基本优化方法是:尽量减少同一域下的HTTP请求数,以及尽量减少每一个资源的体积。
IE6/7和Firefox2的设计规则是,同时只能对一个域名发起两个并发连接。新版本的各种浏览器普遍把这一上限设定为4至8个。
由于浏览器针对资源的域名限制并发连接数,而不是针对浏览器地址栏中的页面域名,所以很多静态资源可以放在其他域名下(不同的子域名也被认为是不同的域名)。如果您只有一台服务器,可以把这些不同的域名同时指向一个IP,也就提高了对这台服务器的并发连接数限制(不过要小心服务器压力过大)。 把静态资源放在非主域名下,这种做法除了可以增加浏览器并发,还有一个好处是,减少HTTP请求中携带的不必要的cookie数据。
把多个CSS合并为一个CSS,或者将图片组合为CSS贴图
尽量减少每一个资源的体积 我们不光要限制请求数,还要尽量减少每一个资源的体积。因为资源的体积越大,在传输中消耗的流量就越多,等待时间也越久。
对于比较大的文本资源,必须开启gzip压缩。因为gzip对于含有重复“单词”的文本文件,压缩率非常高,能有效提高传输过程。
后台视角
前端工程师对HTTP的关注点在于尽量减少同一域下的HTTP请求数,以及尽量减少每一个资源的体积。与之不同,后台工程师对于HTTP的关注在于让服务器尽快响应请求,以及减少请求对服务器的开销。
由于在操作系统中,生成进程、销毁进程、进程间切换都很消耗CPU和内存,因此当负载高时,性能会明显降低。
prefork和worker模式的最大区别就是,prefork的一个进程维持一个连接,而worker的一个线程维持一个连接。所以prefork更稳定但内存消耗也更大,worker没有那么稳定,因为很多连接的线程共享一个进程,当一个线程崩溃的时候,整个进程和所有线程一起死掉。但是worker的内存使用要比prefork低得多,所以很适合用在高HTTP请求的服务器上。
一方面是Nginx更加轻量级,占用更少的资源和内存;另一方面是Nginx处理请求是异步非阻塞的,而Apache则是阻塞型的,在高并发下Nginx能保持低资源、低消耗和高性能。
DDoS攻击 DDoS是Distributed Denial of Service的缩写,DDoS攻击翻译成中文就是“分布式拒绝服务”攻击。 简单来说,就是黑客入侵并控制了大量用户的计算机(俗称“肉鸡”),然后在这些计算机上安装了DDoS攻击软件。我们知道浏览器作为一种“善意”的客户端,限制了HTTP并发连接数。但是DDoS就没有这样的道德准则,每一个DDoS攻击客户端都可以自由设置TCP/IP并发连接数,并且连接上服务器之后,它不会马上断开连接,而是保持这个连接一段时间,直到同时连接的数量大于最大连接数,才断开之前的连接。 就这样,攻击者通过海量的请求,让目标服务器瘫痪,无法响应正常的用户请求,以此达到攻击的效果。 对于这样的攻击,几乎没有什么特别好的防护方法。除了增加带宽和提高服务器能同时接纳的客户数,另一种方法就是让首页静态化。
BigPipe
 现有的阻塞模型,黄色代表服务器生成页面,白色代表网络传输,紫色代表浏览器渲染页面。
BigPipe首先把HTML页面分为很多部分,然后在服务器和浏览器之间建立一条管道(BigPipe就是“大管道”的意思), HTML的不同部分可以源源不断地从服务器传输到浏览器。BigPipe首先输送的内容是框架性HTML结构,这个框架结构可能会定义每个Pagelet模块的位置和宽高,但是这些pagelet都是空的,就像只有钢筋混泥土骨架的毛坯房。  BigPipe页面的渲染流程。 服务器传输完框架性HTML结构之后,对浏览器说:“我这个请求还没结束,我们保持这个连接不要断开,不过您可以先用我给您的这部分来渲染。”
HTTP 1.1引入分块传输编码,允许服务器为动态生成的内容维持HTTP持久链接。如果一个HTTP消息(请求消息或应答消息)的Transfer-Encoding消息头的值为chunked,那么消息体由数量不确定的块组成——也就是说想发送多少块就发送多少块——并以最后一个大小为0的块为结束。
什么是缓存
存储频繁访问的数据(这里的数据是图书)。 •内存缓存减少磁盘I/O(不用到6楼去找书)。 •保存耗时的操作,以便下次使用(找书和整理书是耗时的操作)。
服务器缓存
MySQL查询缓存来提高速度,并且减少系统压力。MySQL默认不开启查询缓存,但我们可以通过修改MySQL安装目录中的my.ini来设置查询缓存
对于查询操作远远多于修改操作的数据库,开启数据库查询缓存是很有益的;但是对于修改操作很多的数据库,由于缓存经常会失效,就起不到加速的效果。不仅如此,由于数据库要花费时间写缓存,所以实际上速度更慢了。 这个问题就是“缓存命中率不高”,所以配置缓存之后第一件事就是查询命中率,如果命中率低,不如不做缓存。
文件I/O比起内存有以下几个好处。 •硬盘容量比内存大,所以可以缓存更多数据。 •数据更安全,断电之后数据还在。 •易于扩展,硬盘不够用的时候还可以添加硬盘。
浏览器缓存
HttpWatch是推荐对所有的静态资源都设置Expires。
按照HTTP规范,如果修改了请求资源的Query String,就应该被视为一个新的文件。 这个Query String可以被服务器端CGI或者应用程序理解,而且可以设置多个名值对(比如?foo=1&bar=2)。与缓存相关的一点是,如果Query String发生了改变,则被视为URL发生了改变。这时候,浏览器会认为这是一个新的资源。而对于服务器而言,如果有CGI或者应用程序捕捉或处理Query String,就会去处理,如果没有,就简单地忽略Query String,直接返回资源。
•对于动态生成的HTML页面使用HTTPS头:Cache-Control: no-cache。 •对于静态HTML页面使用HTTPS头:Last-Modified。 •其他所有的文件类型都设置Expires头,并且在文件内容有所修改的时候修改Query String。
•缓存会被挤出。 •文件有可能在运营商服务器上被劫持。
用户的宽带运营商为了提高速度,可能会在自己某节点服务器上缓存您的文件(比如style.css? v1),好处是当用户请求这个文件的时候,运营商无需来您的服务器上请求文件,而自己直接就给出了。 问题来了,如果您的Query String更新了(style.css? v2),按照HTTP规范,这理应被视为一个新的文件,但是运营商仍然可能会拿自己节点的缓存,而不是遵循规范。有点可恶对不对?这就是我们在用户量极大的情况下侦测到的情况,虽不太常见,但是有可能发生。所以,为了保证更新的文件下发到所有的用户,我们会使用更加强硬的方法:修改文件名,而不是仅仅修改Query String。
•对于动态生成的HTML页面使用HTTPS头:Cache-Control: no-cache。 •对于静态HTML页面使用HTTPS头:Last-Modified。 •其他所有的文件类型都设置Cache-Control头,并且在文件内容有所修改的时候修改文件名。
知识体系
越接近高级工程师,越考察对某个点的本质理解,以及在项目和团队中的引导作用,而不是对某工具的使用经验。
通过数据绑定,让开发者直接修改数据模型,而不用关心界面(DOM)更新
在出现一些热门框架时,建议开发者先去了解框架的创建初衷,合理使用,而不是盲目收集。
岗位细分
UI工程师更关注视觉上和交互上的体验,而前端工程师更关注逻辑和数据方面的体验,二者是上下游合作的关系。
设计师和开发人员之间沟通不畅、开发时间紧急和代码耦合的问题,导致设计还原的质量低。
一个转型故事
行动重于计划
如果您不想把手弄脏,就没法成为一个好外科医生。
一定要是自己的产品的用户
客户需求只有在实际使用中才能辨明,再多的前期调研也只能发现客户认为他们想要什么,而不是客户实际上想要什么。因此在不了解客户真实需求的情况下,只会多做多错
让市场认可您的能力,而不是让老板认可,因为老板会变,老板的标准不一致,而市场是一致的
有哪些方向
WebView的部分或者所有资源打包在App中 需要网络数据时,可以通过网络请求json或者体积比较小的数据格式,然后通过本地页面模板和资源来渲染。这种方法的缺点是,App发布包体积会变大。
需要加载的资源设置好预先加载 可以在App启动时从后台下载需要的资源,并缓存在手机沙盒中备用。这种方法的好处是不会增加包体积,不过第一次访问的时候可能因为没有预加载资源而导致等待时间比较久。 •使用HTML5 Manifest技术实现资源缓存 HTML5引入了应用程序缓存,这意味着Web App可进行缓存,并可在没有互联网连接时访问。这种方法的好处是,缓存所有资源到本地之后,如果希望更新WebView,可以在服务器上更新资源列表和Manifest文件。App检测到Manifest文件的修改,就知道资源已经更新,可以开始下载新的资源了。
不要把整个App的主要逻辑都使用WebView来实现 要结合原生技术和WebView各自的优缺点,根据不同的场景选择合适的技术。原生技术的优点在于能很好地操作App存储数据;实现页面间切换、高性能动画、大量数据的界面(比如可以无限滚动的图片流)。WebView的优点在于开发快、技术简单;前端开发者能够利用已有的CSS3和JavaScript知识;页面能够从服务器端更新;能够分享到社交平台;在多个平台上共用等。
WebView与原生代码通信 WebView中的逻辑是由JavaScript来实现的,而WebView之外的逻辑是由原生代码来实现的,二者之间如何实现通信呢?一个常见的例子是,点击WebView中的一个按钮,我希望弹出一个原生的警告框,应该怎么实现呢。 在Android中,可以使用WebView.addJavascriptInterface方法来实现互相通信。WebView的addJavascriptInterface方法有两个参数,第一个参数就是我们一般会实现一个自己定义的类,类里面有要提供给JavaScript访问的方法;第二个参数是一个JavaScript对象名,它在WebView中作为刚才我们自定义的类的一个实例。 在原生代码中定义好类和对象之后,就可以在WebView中通过JavaScript调用原生代码了。调用模式为window.对象名.方法名(),或者是javascript:对象名.方法名()。 在iOS中,原生代码没有这样简便的方法,想要接收WebView中的函数调用时,需要使用WebView的shouldStartLoadWithRequest委托。 首先,在希望发起通信的WebView中设置这样一个自定义协议的链接:<a href="myapp://somepagename">一个按钮</a>这是一个非常简单的链接,不过链接的协议是我自定义的myapp,也可以是任何其他与App相关的名字。 然后在调用该WebView的原生代码中,添加对该WebView的委托监听: 
-(BOOL)WebView:(UIWebView *)WebView shouldStartLoadWithRequest:
(NSURLRequest *)request navigationType:(UIWebViewNavigationType)
navigationType{
NSURL *url = [request URL];
if( [[url scheme] isEqualToString:@"myapp"] )
{
//NSString *slug = [url path];
//slug就是刚才的somepagename
//得到了这个信息,我们可以做一些原生的操作了
}
return YES;
} 发生了什么?首先我们自定义了一个协议名称myapp,然后在WebView中发起了一个以该协议开头的请求myapp://somepagename。WebView发起任何请求之前都会通过外部shouldStartLoadWithRequest的“过滤”。所以在这里的函数体中,我们增加了对协议的判断,如果是我们自定义的协议,就不要跳转过去了,直接执行自己定义的逻辑即可。
持续集成
构建持续集成的开发流程中,就要考虑版本控制、包管理、依赖关系、架构优化、自动化发布等一系列问题。
版本控制
最佳实践是频繁地提交,而不要等到代码没问题了再一次性提交。
对于可能损坏主干原则的代码,不要直接提交到主干,而是创建一个分支,在分支中频繁提交。
我们团队的主干原则是“主干对应的代码必须是可以发布并且不会产生bug的”,如果不能保证新增的或者修改的代码符合这一原则,就在分支提交代码。任何人破坏这一原则引起bug,就请大家吃饭。
•不要把逻辑的修改和代码格式化操作混在一起
不相干的代码分开提交 也就是说不要在一次提交里修复两个bug。
[插图]
包管理
一个程序只做一件事,并做好。
GTD(Getting Things Done)原则建议您对一个大的项目进行拆分,分为很多小的可执行和评估的子任务,这样每一件小事情都可以做得很好,效率也会提高。
关于dependencies和devDependencies的区别,假设一个人下载了您的模块并且在代码中使用,他只需要您的功能,并不需要您的测试代码,或者文档构建器。这时候最好把这些开发阶段使用的包放在devDependencies中。
根据semver的规范,版本号用小数点分隔为三个数字。比如v3.2.1中3是主要版本号,2是次要版本号,1是补丁。 •主要版本号:有API变更导致不兼容旧版本的时候使用。 •次要版本号:新增功能,但是向前兼容的情况下使用。 •补丁:修复向前兼容的bug时使用。 在npm的package.json中可以用一些语法指定需要某个模块的哪个版本。 •1.2.3, =1.2.3:指定版本为1.2.3。 •>1.2.3, <1.2.3:大于/小于1.2.3。 •>=1.2.3, <=1.2.3:大于等于/小于等于1.2.3。 •1.2.3 - 2.3.4:大于1.2.3并且小于2.3.4。 •~1.2.3:合理地靠近1.2.3,等价于>=1.2.3-0 <1.3.0-0,1.3.0-beta不满足这个判断条件。 •~1.2:等价于>=1.2.0-0 <1.3.0-0,所有以1.2开头的版本,同样等价于1.2.x。 •~1:等价于>=1.0.0-0 <2.0.0-0,所有以1开头的版本,等价于1.x。 •*:任意版本。
构建工具
像是硬币的两面,一面朝浏览器,关注性能、缓存、减少重复、保持一致;一面朝前端团队,关注维护、发布流程。
最小知识原则 一个组件或者对象不应该知道其他组件或者对象的内部实现细节。
DRY 特殊的功能只能在一个组件中实现,在其他的组件中不应该有副本。
最小化预先设计,只设计必需的内容
通过良好的层级,让文件易于找到 有时候我们会基于项目来区分代码库,有时候为了让多个项目共享组件和代码,会使用扁平的目录层级。我们需要根据项目具体的情况来选择。 •在代码层面,有一致且可执行的命名规则 从路径名到文件名都有一致的前缀、后缀、版本规则。整个团队有一致的命名风格和注释风格。
Make的目的是把大量的脚本命令组合起来放在一个makefile文件中,工程师只需要运行这个makefile就可以把多个目标编译到一个文件中,彻底从依赖跟踪的繁琐工作中解脱出来。
Make的基本模型是:定义一个任务时,首先声明依赖关系,然后说明根据这些依赖,调用哪些应用程序,来生成目标文件。因为每一步都需要使用不同的应用程序,调用不同的数据,所以这里面需要设置依赖关系。 另一方面,使用包管理工具可以把项目需要用的第三方包,以及每一个包的特定版本,都集中在一个配置文件中。
 包管理和构建工具都需要依赖关系。
Gulp基于Node.js的流的概念,所以前一个任务的输出就是后一个任务的输入。 从语法风格上来讲,编写任务的过程更像是“编程”,而不是“编写配置”。Gulp通过对接前一个任务的输入和后一个任务,就像一个管道,二者可以同时进行,不输出在磁盘中,没有多余的中间产物,性能更加高效。
编程语言是什么
将编程语言编译成机器码有两种传统的方法:使用编译器(compiler)预先编译,或者使用解释器(interpreter,也叫直译器)一边编译一边运行。
在管理界有两种假说。 一种假设“人性本恶”,即所有的员工都讨厌工作,只要没有监督,就一定会偷懒怠工,绝大多数人没有雄心壮志,怕担责任,宁可被领导骂。多数人必须用强制办法乃至惩罚、威胁,使他们为达到组织目标而努力。这叫做X理论。 另一种假设“人性本善”,即所有的员工都热爱工作,只要给他们创造舒适的环境、合理的授权和适当的激励,他们就会发挥很高的生产力,能力的限制和惩罚不是让人为组织目标而努力的唯一办法。这叫做Y理论。
相信X理论的管理者会设置很多的规章制度——要求上下班打卡,限定工作范围,重视金钱奖励,同样也重视惩罚。支持Y理论的管理者会提供生理需求之外的福利——重视鼓励和授权,扩大工作范围,设置灵活的上下班时间,等等。
管理界经过科学的实验和调查发现,与传统工厂或者机械劳动厂商中X理论发挥更大效用相比,在互联网公司或者智力活动占多数的公司中,Y理论更加适用。
全栈工程师最佳实践
有些时候我们的技术选型步骤是:先选择框架,然后选择语言。
VPS
字体资源的跨域限制,Firefox为了防止其他网站盗用某个网站的字体,所以限制了只有来自一个域名的自定义字体才能正常显示。要修复这一点,只要在字体的输出HTTPS头中设置允许所有域调用自己就可以了。如何修改呢?在Apache的配置文件中就可以修改。
实践
简单来说,大体步骤有以下几点。 •新建一个普通用户,以后都不要用root登录了。 •使用SSH的名值对的登录方法,禁用用户名和密码的登录方法。 •禁用root账户通过SSH登录。 •安装一个防火墙。 •安装Fail2Ban,杜绝字典攻击。
为什么要进行DNS解析?DNS是互联网的一项服务。它作为将域名和IP地址相互映射的一个分布式数据库,能够让人更方便地访问互联网。 当DNS客户端需要查询程序中使用的名称时,它会查询DNS服务器来解析该名称。有时,客户端也可使用从先前的查询获得的缓存信息在本地应答查询。DNS服务器可使用其自身的资源记录信息缓存来应答查询。DNS服务器也可代表请求客户端查询或联系其他DNS服务器,以便完全解析该名称,并随后将应答返回至客户端。这个过程称为递归。 另外,客户端自己也可尝试联系其他的DNS服务器来解析名称。当客户端执行此操作时,它会根据来自服务器的参考答案,使用其他的独立查询。这个过程称为迭代。
设计模式
实现单例模式的思路是:一个类能返回对象一个引用(永远是同一个)和一个获得该实例的方法(必须是静态方法,通常使用getInstance这个名称)。当调用这个方法时,如果类持有的引用不为空就返回这个引用;如果类持有的引用为空,就创建该类的实例,并将实例的引用赋予该类保持的引用。
var createMask = function(){
var mask;
return function(){
return mask ||(mask = document.body.appendChild
(document.createElement('div'));
}
}();
除了单例模式,这个例子中还用到了“惰性初始化模式”:推迟对象的创建、数据的计算等是需要耗费较多资源的操作,只有在第一次访问的时候才执行。因为DOM操作是浏览器中消耗比较大的操作,所以延迟背景蒙层DOM的生成能够提高页面性能。
架构模式
架构模式教我们如何架构一个系统,它的关注点在于以下两点。 •多个职位(比如后台开发和前端开发)可以平行工作同时进行。 •构建一个软件系统的多种技术。
 MVC架构模式。
设计原则
作者就设定了几条设计原则,包括“不做重复的事”(Don't Repeat Yourself)和“惯例优于设置”(Convention Over Configuration
DRY是“Don't Repeat Yourself”的缩写。意思是说,在一个系统里,对于任何数据或者变量,都应该配置在有且只有一个地方,其他的地方都应该引用这里的数据。这样,需要改动数据的时候,只需调整这一处,所有的地方就都变更过来了。
三次法则(rule of three)是代码重构的一条经验法则,涉及当代码片段出现重复时,如何决定是否用一个新的子程序替代它。三次法则的要求是,允许按需直接复制粘贴代码一次,但如果相同的代码片段重复出现三次以上,就需要将其提取出来做成一个子程序。
“惯例优于设置”,它的本质是说,开发人员仅需规定应用中不符约定的部分。例如,如果模型中有个名为Sale的类,那么数据库中对应的表就会默认命名为sales。只有在偏离这一约定时,例如将该表命名为"products_sold",才需要写有关这个名字的配置。 如果您所用工具的约定与您的期待相符,便可省去配置;反之,可以修改配置,来达到所期待的方式。
KISS是“Keep it simple, stupid”的缩写,意思是说软件设计当中应该注重简约的原则。这一原则认为,大部分系统的设计越简单越好,有不必要的复杂性都应该避免。如果一个系统非常复杂,就应该分解为多个简单的组件,做好足够的分解和抽象。
•较简单的系统更容易构造、运行和维护。 •较简单的解决方法总是更具弹性、柔性。 •较简单的系统更便宜。 •较简单的系统更容易实现、更快地获得回报。 •较简单的方法更讨用户的欢心。 •较简单的系统更容易分阶段地执行。
•较简单的系统更容易被理解。
最少知道原则,常常用在面向对象软件设计中,它是“松耦合原则”的一个具体实例,是指在面向对象编程中,每一个软件单元应该尽可能少地与其他单元发生作用。
每一个单元都应该只知道关于其他单元的有限信息:那些与自己密切相关的单元。每一个单元应该和自己的朋友讲话;不跟陌生人讲话。
高效工程师
Move fast and break things”(快速行动,打破常规)
Move fast, with Stable infra(快速行动,稳定架构)”
为什么需要高效
知识工作者并不生产具有效用的产品,他生产的是知识、创意和信息。
最后,高效的工程师能够拿更多时间运动和休息,这对于长期稳定的工作投入是有帮助的。低效工程师长期熬夜带来的副作用完全抵消了工作时长上的投入。
提速100倍
如果您平时没有做重要的事情,就会发现自己常常在做紧急的事情。如果您平时没有注意锻炼身体,就会常常去医院,花费更多时间。如果没有培养后辈,为每个项目设置接班人,就会常常需要到处救火。如果您没有配置好版本管理系统就开始工作,就会浪费更多时间去找回丢失的代码。如果偷懒硬编码(hard code)了一些变量在代码中,后续一定会花费更多时间去调试。
 时间管理四象限。
第一象限是重要又紧迫的事情。比如线上出现严重bug、服务器出现安全漏洞、用户的投诉,等等。对于这些问题,是考验自己的经验和判断力的时候,用自己最好的判断力,立即执行。不过也要意识到,在这一象限的问题往往是第二象限的问题没有制定好的计划而滑落过来的,如果大部分的工作都落在第一象限,说明还是在“瞎忙”。 第二象限是紧急但不重要的事情。比如会议、一些可转交的需求,等等。这种事情往往会由于对方强烈的呼声让您认为它处于第一象限,有一种“这事很重要”的错觉。我们花很多时间在这里打转,其实只是在满足他人的需求,而没有关注自己的职责。对于这种事情应该请他人代劳,不一定是自己的下属,还可以是平级的同事。有一些会议不一定需要自己去参加的,可以提前跟主持人(项目经理)沟通。 第三象限是重要但不紧急的事情。比如一些线上体验优化计划、团队的长期发展方向和个人培训等。有一次老板提出了线上的一个体验问题,我们以为这是第一象限的问题,马上执行。结果老板说,这个事情不需要您们这么快去执行,希望可以做深入一点的调研。建议工程师把80%的工作投入到该象限中,避免“瞎忙”。
Facebook的每周三是没有会议的日子(No Meeting Wednesdays),每一个团队成员都知道,除非万不得已,不要在这一天安排任何会议。事实证明这对团队的效率很有好处,它鼓励所有人(包括产品经理)成为“做事情的人”而不是“计划事情的人”,而且所有人都有一整块的时间工作。对于远程工程师来说,还可以选择在家里工作,根本不用出现在办公室。
我在跟Facebook的工程师聊天的时候,发现他们都很注重锻炼身体,每天早上开始工作之前都会花一个小时跑步和健身,然后洗澡吃早餐,再开始一小段高效的工作时间。下午的工作时间中也会穿插一些运动和甜点时间,等等,不会像国内的工程师们,需要长时间地坐在电脑前。这种状态的转换让他们的效率得到了很大的提升。
“番茄工作法”是由弗朗西斯科-西里洛于1992年创立的一种微观时间管理方法。使用番茄工作法,选择一个待完成的任务,将番茄时间设为25分钟,专注工作,中途不允许做任何与该任务无关的事,直到番茄时钟响起,然后在纸上画一个X,短暂休息一下(5分钟就行),每4个番茄时段则多休息一会儿。
设计师们是典型的浪漫主义者,他们的世界里没有公式、没有定理、永远没有标准答案,更多的是用发散的思维去构思创意,更容易产生好想法。而工程师注重逻辑的严谨性、技术的可行性,他们往往用“我是否能够做到”和“我要花多少时间才能做到”这个思维在思考。
笔跟纸是最灵活、最容易修改、成本最低的头脑风暴方式。
在一个项目和人力都很稳定的团队中,有两种原因会导致加班。一种是糟糕的项目管理,领导失职,没有安排好工作。第二种是员工能力不够,效率不高,没有按时完成目标。在这两种情况下,我都建议您跟领导去沟通,
拿工作时长来拼,这还是体力劳动时代打工者的心态在作祟。
科学家和工程师
视觉设计师关注设计模块和整体氛围,只需要给出一份为PC设计的视觉设计稿。让有一定设计理论基础的前端工程师,根据拿到的PC设计稿,利用流式布局和媒体查询等技术,直接创建可以适配多个平台的页面,也就是一个“响应式”的页面。
设计基础
这件事告诉我们,当我们知道一个“东西”的名字,就会在看到这个“东西”的时候,立马意识到它。但是如果我们不知道它的名字,可能一辈子也不会认识它。这就是约书亚树原理。
设计的四大基本理论是:亲密性、对齐、重复、对比。
这4个设计理论分别是什么意思呢? •亲密:关系亲密的元素要放在一起,关系疏远的元素则要分开。位置的亲密性直接表现出意义的相关性。 •对齐:左对齐、右对齐、上对齐、下对齐。斜线对齐比较简单,居中对齐很难处理,新手不要尝试。 •重复:视觉上使用重复的图形和元素、线条和颜色等。比如QQ空间重复使用的黄色跟黑色、微信的绿色、京东的红色等。 •对比:如果两个元素(的大小或者颜色)不一样,就让它完全不一样,产生视觉冲击力。
Facebook的品牌设计故事
对于网页图标的图片格式,不同的系统和浏览器有不一样的支持度。我推荐使用ico格式,因为ico格式可以在一个文件中同时设置16x16像素和32x32像素的图片,根据需要来显示。ico格式的生成也非常简单,使用Photoshop,将一个32x32像素的普通图片直接保存为ico,就可以生成一个拥有两个图层(32x32像素图层,16x16像素图层)的ico格式文件。ico文件里面图形的默认位深为32位(RGBA,代表支持半透明)。
有兴趣就够了吗
对于所有刚开始工作的年轻人,我告诉您们: 老板给您任务,根本不关心您有什么理由,只关心您完成没有。
管理者要做的事情比执行者更多,但是因为管理者能管理好自己的时间,做事讲究优先级,懂得授权和请求他人帮助,所以能避免“瞎忙”。让自己“不忙”,可是一个技术活。
学一点管理
没有在最开始做出合理的时间评估
•没有根据人员的强项来安排任务 我不了解下属的强项,在他们没有足够经验的前提下就完全授权,项目的失败几乎是必然的。除了授予工作、任务和责任以外,还要授予知识和资源。作为有经验者,我完全没有给他们提供帮助,这是我失职的地方。
对于一个预计2个月的中期项目,理想的沟通频率是每周沟通至少两次,如果两周才沟通一次,失败也是可以预期的。
管理者学会这么一种创建组织的方式:若某人在某一方面具有特长,就要让他充分发挥这一特长;而不应该期望另寻万能的天才来达成绩效。
有效的管理者知道他们的时间用在什么地方。 •有效的管理者重视对外界的贡献。 •有效的管理者善于利用长处,包括自己的长处、上司的长处、同事的长处和下属的长处。 •有效的管理者集中精力于少数重要的领域,在这少数重要的领域中,如果能有优秀的绩效就可以产生卓越的成果。 •最后,有效的管理者必须善于做有效的决策。
对于有意愿但是能力不够的,要教会他做事的方法,提升其学习能力,这部分员工是很有潜力的,往往是年轻毕业生居多。
对于有能力但是意愿不够的,就要多进行情感上的沟通,看看对方情绪不够积极的原因是什么,对待这部分员工会困难一点,需要领导有很强的沟通能力。 既有意愿又有能力的员工,比例比较小,如果发现了,要大力培养,作为后备人才来储备。 对于既没有能力也没有意愿的员工,尽早开除比较好。这种员工就像蛀虫,会腐蚀一个团队。
沟通:被忽视的竞争力
其实应聘者也可以跟面试官搞好关系,然后咨询改进意见,不要问“我被拒绝的原因是什么?”而是问“我在面试中的表现怎么样?”这样往往面试官会愿意给出一些建议。
良好的沟通是:“针对目标听众”“有方法地”“表达自己的想法”
授权给平级同事的时候,最好的方法就是诉诸对方的利益。如果一件事情可以对双方的KPI都有好处,那么对方也愿意帮您一起分担这个任务。如果您把不擅长的事情授权给对方,而作为交换,能给对方一些资源,那也是诉诸利益的一个好方法。 其次的方法就是把问题上升到上级领导,让上级领导安排资源,但是这种方法不能经常用,否则上司会认为您不会主动解决问题,只会提出问题。被授权的那一方也觉得您在拿领导压制他,可能会存在负面情绪。通过跟对方主动沟通,并且在邮件和RTX群中多赞赏对方,就能唤起对方的积极性。 针对同事的沟通目标往往是请求对方帮助。需要对方做事,原则就是“度己度人”,那么针对上司呢?有以下几种情况。 •汇报:求上司表扬。 •请求:需要上司做事。 •询问:需要知道上司对于某项任务的要求。
重点是,因为上司时间很紧迫,所以要在第一句话就告诉上司您的目的,不要掖着藏着,既想请求上司的帮助,又要求表扬。 无论您的想法多么复杂,已经进行了多么复杂的推演,最终您要沟通的时候,要注意两点:一是让自己要表达的立场足够简单;二是围绕着这唯一的立场去沟通。
用最悲观的假设来思考听众的目标。您应该假设听众对您分享的技术完全没兴趣。以这一目标来进行的话,您可能会有自己的答案。
其次,您要有一个鲜明的立场,并让这个立场简单,并且演讲始终围绕这个立场。
不要有太多文字
设定进度 让听众知道自己在哪里,比如一开始就告诉听众您的演讲时间,或者在幻灯片中设置进度表。听众注意力只能坚持十分钟,所以不要太久。 •对待错误:放松
有条件的话,录像并对比提高 不要相信别人的评价,碍于面子,别人不会提出不好的评价。