Cgroup – Linux的IO资源隔离 (liwei.life)
跟内存管理那部分复杂度类似,IO的资源隔离要讲清楚也是比较麻烦的。这部分内容都是这样,配置起来简单,但是要理解清楚确没那么简单。这次是跟Linux内核的IO实现有关系。对于IO的速度限制,实现思路跟CPU和内存都不一样。CPU是针对进程占用时间的比例限制,内存是空间限制,而当我们讨论IO资源隔离的时候,实际上有两个资源需要考虑,一个是空间,另一个是速度。对于空间来说,这个很简单,大不了分区就是了。现实手段中,分区、LVM、磁盘配额、目录配额等等,不同的分区管理方式,不同的文件系统都给出了很多不同的解决方案。所以,空间的限制实际上不是cgroup要解决的问题,那就是说,我们在这里要解决的问题是:如何进行IO数据传输的速度限制。

限速这件事情,现实中有很多模型、算法去解决这个问题。比如,如果我们想控制高速公路上的汽车单位时间通过率,就让收费站每隔固定时间周期只允许通过固定个数的车就好了。这是一种非常有效的控制手段--漏斗算法。现实中这种算法可能在特定情况下会造成资源浪费以及用户的体验不好,于是又演化出令牌桶算法。这里我们不去详细分析这些算法,但是我们要知道,对io的限速基本是一个漏斗算法的限速效果。无论如何,这种限速都要有个“收费站”这样的设施来执行限速,那么对于Linux的IO体系来说,这个”收费站”建在哪里呢?
by @技术头条 2017-03-12 00:06 查看详情
史上最简单的Scala for推导教程 (growthprogrammer.com)
Scala 的 for 语法,本质上就是语法糖。并且十分简单,简单到简短的一篇文章,就可以说清楚。

Scala 中的 for 语句,都是帮你转换成类似 foreach、 map、 flatMap、 withFilter、 filter 之类的语法。并且整个转化过程是递归的,容易理解的。

看完下面是几个例子,你就能立马掌握。这几个例子,是结合了 Scala 官方的yield文档 改进过来的。

第一个例子,转换成 foreach

for(x <- c1) {...}
会被scalac翻译成

c1.foreach(x => {...})
注意,没有出现 yield 关键字。

再来一个:

for(x <- c1; y <- c2) {...}
会展开成:

c1.foreach(x => for(y <- c2) {...})
然后 scalac会再针对里面的 for 再进行转换,直到所有的 for 被转换完。

第二个例子,先 flatMap后 map

for(x <- c1) yield {...}
会被 scalac翻译成

c1.map(x => {...})
注意,这里出现了 yield关键字。

再来一个:

for(x <- c1; y <- c2) yield {...}

会展开成:

c1.flatMap(x => for(y <- c2) yield {...})

然后再展开成

c1.flatMap(x => c2.map( y => {...}))

注意这里多了一个 yield 关键字,所以会用 flatMap、 map 而不用 foreach。

并且,前面的都使用 forMap(比如 c1),最后面使用 map(比如 c2)。

好了,有无 yield的区别讲完了,这也是最重要的区别了,剩下的都很简单,而且不管有无 yield,概念都一样。

接着往下。

第三个例子,尝试 withFilter ,不行再 filter

for(x <- c; if cond) yield {...}
会翻译成

c.withFilter(x => cond).map(x => {...})
如果 c 没有 withFilter 方法,就使用 filter 方法:

c.filter(x => cond).map(x => {...})
第四个例子,加入其它值

for(x <- c; y = ...) yield {...}
会变成

c.map(x => (x, ...)).map((x,y) => {...})
结束

好了,scala 的 for 规则就结束了,就是这么简单。你肯定能记住。
by @技术头条 2017-03-12 00:06 查看详情
10 连抽保底的概率模型 (blog.codingnow.com)
网游里有很多抽卡、开箱子之类的赌性玩法,在最开始,游戏设计者实现的时候,仅仅给这些抽取概率简单的设置了一个值。比如抽卡抽出橙卡的概率是 10% ,那么就是说,玩家每次抽一张卡,有 90% 的可能是白卡,10% 的可能是橙卡。

但大 R 玩家是大爷,需要小心伺候。如果感受不好,人跑了就亏大了。概率这个东西靠改进伪随机数发生器是解决不了体验问题的,大爷要是连抽 20 张都出不来橙卡,那是要怒删游戏的。

连抽 20 张 10% 概率橙卡一张都抽不到的机会多不?一张抽不中的概率是 0.9 ,20 张都抽不中的概率是 0.9 ^20 = 12.2% 。这可不算小数字啊。平均 8 个大 R 就会碰到一次,一下子赶跑了 1/8 的金主,这个责任小策划可担当不起。

所以、一般网游都会用各种规则来避免玩家出现连抽不中的尴尬。例如,我忘记是谁发明的 10 连抽规则:如果你购买一个大包连抽 10 次,我在规则上就保证里面一定至少有一张橙卡。实现它应该并不困难,按常规概率生成 10 张的卡包,如果里面没有橙卡,那么我加一张即可。

但如果我想把 10 抽保底的规则惠及日常抽卡的玩家该怎么做呢?

就是说,我希望任何玩家任何时候,接连抽了 10 张卡,我都想保证这 10 张卡里至少有一张橙卡。

首先,要说明的一点:如果你同时想保证橙卡掉落率是 10% ,也就是在极大范围内,比如系统投放了一万张卡片中,其中要有一千张橙卡。那么同时保证每 10 张卡里有至少一张橙卡的话,结果一定是完全不随机的,也就是必须每抽 9 张白卡,必出一张橙卡。

所以、如果即想要随机(出橙卡的概率稳定),又想有 10 张出一张的保底,那么橙卡投放量是一定超过 1/10 的。

我们之前的游戏用了个很粗暴的方案:记录玩家已经连续几次没有抽中,如果连续次数超过 9 ,就必给他一张橙卡。为什么我说这个方案粗暴,因为它其实破坏了抽卡的自然体验。虽然玩家的确更高兴了,但是概率却很不自然。不自然的方案(其实是生硬的打了个补丁)实现起来还容易出错,我们前段时间就因为实现 bug 多发放了很多稀有物品,这个 bug 就不展开说了。

下面来看看,为什么这么做不自然。

假设橙卡的掉率是 10% ,那么你在获得一张橙卡后,再抽下一张橙卡的概率就是 0.1 。下一张是白卡,再下一张是橙卡的概率是 0.9 * 0.1 ,下两张是白卡,第三张是橙卡的概率是 0.9^2 * 0.1 ……

后续有 10 张及 10 张以上的概率总共有多少呢?我算了一下,大约是 35% 左右。

我们把抽到两张橙卡之间会抽取到的白卡张数排成一个数列的话,这个数列的值的范围是 0 到正无穷。是的,非洲酋长可能永远抽不到橙卡。当然这只是理论值。

如果你读过大学,学的是理工科,没有逃课的话,就应该知道,这个数列是大致符合指数分布的。指数分布正是用来表示独立随机事件发生的时间间隔的。

当我们把这个数列中大于 9 的数字都强行改成 9 ,那么 9 的出现频率就陡然跳变,这是极不自然的。(分布不平滑)

从一致分布的随机数,转换为指数分布的随机数非常简单。如果你懒得自己推导,那么可以在爆栈网上找到公式 。

让我们回答前面的问题,如果我希望获得一个大约每 10 张卡里出一张橙卡的随机数列,除了每次 random 一个 [0,10) 的整数,判断证书是不是 0 以外,还有一个方法。那就是每次抽到一个橙卡后,都从一个指数分布的随机数列中取一个值出来,作为接下来会抽取到白卡的张数。按这个张数去发放白卡,等计数器减到 0 ,就发一张橙卡给玩家。这个白卡张数的数值范围是 [0, inf) 。

用 lua 实现的话,大概是这样的:

math.floor(math.log(1-math.random()) * (-rate)) 其中 rate = 10 。

好了,如果我们想加上 10 张保底,又想让间隔大致符合指数分布怎么办?简单:
function erand(rate)
while true do
local p = math.floor(math.log(1-math.random()) * (-rate))
if p < rate then
return p
end
end
end

让产生出来的数字小于 10 的时候重来一次就好了。如果你担心这里死循环(实际并不会),也可以加上循环上限:

function erand(rate)
for i = 1, 100 do -- 100 可以随便写
local p = math.floor(math.log(1-math.random()) * (-rate))
if p < rate then
return p
end
end
return rate-1
end

当然,一旦加上了 10 张保底,单张出橙卡的概率就大大增加了,增加到多少呢?大约是 21%。如果你希望保持 10% 左右的投放率,那么保底张数大约应该设置在 23 张左右。

ps. 今天在公司群里讨论这个问题时,雷先生提了这么一个问题,说是可以用来做数值策划的面试题:

已知橙卡的抽取率是 10% ,抽一次卡是 1 块钱;而 10 连抽的包可以帮你按同样概率连抽 10 次,但如果没有抽到橙卡的话,系统会补偿一张橙卡给你,换掉 10 张白卡中的一张。

假设白色一文不值,只有橙卡值钱。

那么请问:这个 10 连抽的包到底价值多少?
by @技术头条 2017-03-12 00:04 查看详情
分享一个即插即用的私藏缓动动画JS小算法 (www.zhangxinxu.com)
……实际开发的时候,使用的最多的还是最初的那个她,不仅是因为她给我带来了很多美好的回忆,更重要的是这么多年过去了,她一直保持着那份简单,和外面的那些妖艳*货完全不一样。

而这个相伴自己最久,最无法忘怀的、使用最多的她就是本文要分享的私藏的动画小算法……
by @技术头条 2017-03-12 00:02 查看详情
Cgroup – Linux内存资源管理 (liwei.life)
无论从任何角度看,Linux的内存管理都是一坨麻烦的事情,当然我们也可以用一堆、一片、一块、一筐来形容这个事情,但是毫无疑问,用一坨来形容它简直恰当无比。在理解它之前,我甚至不会相信精妙的和恶心可以同时形容同一件事情,是的,在我看来它就是这样的。其实我只是做个铺垫,让大家明白,我们下面要讲的内容,绝不是一个成体系的知识,所以,学习起来也确实很麻烦。甚至,我写这个技术文章之前一度考虑了很久该怎么写?从哪里开始写?思考了半天,还是不能免俗,我们无奈,仍然先从free命令说起:

[root@zorrozou-pc ~]# free
total used free shared buffers cached
Mem: 131904480 6681612 125222868 0 478428 4965180
-/+ buffers/cache: 1238004 130666476
Swap: 2088956 0 2088956

这个命令几乎是每一个使用过Linux的人必会的命令,但越是这样的命令,似乎真正明白的人越少(我是说比例越少)。一般情况下,对此命令的理解可以分这几个阶段:

我擦,内存用了好多,6个多G,可是我什么都没有运行啊?为什么会这样?Linux好占内存。

嗯,根据我专业的眼光看出来,内存才用了1G多点,还有很多剩余内存可用。buffers/cache占用的较多,说明系统中有进程曾经读写过文件,但是不要紧,这部分内存是当空闲来用的。

free显示的是这样,好吧我知道了。神马?你问我这些内存够不够,我当然不知道啦!我特么怎么知道你程序怎么写的?

如果你的认识在第一种阶段,那么请你继续补充关于Linux的buffers/cache的知识。如果你处在第二阶段,好吧,你已经是个老手了,但是需要提醒的是,上帝给你关上一扇门的同时,肯定都会给你放一条狗的。是的,Linux的策略是:内存是用来用的,而不是用来看的。但是,只要是用了,就不是没有成本的。有什么成本,凭你对buffer/cache的理解,应该可以想的出来。一般我比较认同第三种情况,一般光凭一个free命令的显示,是无法判断出任何有价值的信息的,我们需要结合业务的场景以及其他输出综合判断目前遇到的问题。当然也可能这种人给人的第一感觉是他很外行,或者他真的是外行。

无论如何,free命令确实给我门透露了一些有用的信息,比如内存总量,剩余多少,多少用在了buffers/cache上,Swap用了多少,如果你用了其它参数还能看到一些其它内容,这里不做一一列举。那么这里又引申出另一些概念,什么是buffer?什么是cache?什么是swap?
by @技术头条 2017-03-12 00:02 查看详情
聊聊设计模式(3):门面模式 (www.barretlee.com)
Facade,中文译为门面、外观,所以本文要讲的 Facade Pattern 翻译时经常看到有两个名字,门面模式和外观模式。
by @技术头条 2017-03-12 00:01 查看详情
3个经常被问到的 JavaScript 面试题 (www.css88.com)
JavaScript是所有现代浏览器的官方语言。 因此,JavaScript 问题出现在各种开发人员的面试中。

本文不是讲述最新的JavaScript库,日常的开发实践或任何新的 ES6 函数。 相反,在讨论JavaScript时,经常会在面试中出现这3个问题。 我自己被问到过这些问题,我的朋友告诉我他们也被到问过。

当然,你在JavaScript面试前不应该只学习这3个问题 – 这里有很多 方法 可以让你更好地准备即将到来的面试 – 但面试官可能会问到下面是3个问题,来判断你对JavaScript语言的理解和DOM的掌握程度。

让我们开始吧!请注意,我们将在下面的示例中使用原生 JavaScript,因为你的面试官通常想看看你在没有第三方库(比如jQuery)的帮助下,是如何理解 JavaScript 和 DOM 的。
by @技术头条 2017-03-12 00:00 查看详情
【死磕Java并发】—–Java内存模型之总结 (cmsblogs.com)
经过四篇博客阐述,我相信各位对Java内存模型有了最基本认识了,下面LZ就做一个比较简单的总结。

总结

JMM规定了线程的工作内存和主内存的交互关系,以及线程之间的可见性和程序的执行顺序。一方面,要为程序员提供足够强的内存可见性保证;另一方面,对编译器和处理器的限制要尽可能地放松。JMM对程序员屏蔽了CPU以及OS内存的使用问题,能够使程序在不同的CPU和OS内存上都能够达到预期的效果。

Java采用内存共享的模式来实现线程之间的通信。编译器和处理器可以对程序进行重排序优化处理,但是需要遵守一些规则,不能随意重排序。
原子性:一个操作或者多个操作要么全部执行要么全部不执行;
可见性:当多个线程同时访问一个共享变量时,如果其中某个线程更改了该共享变量,其他线程应该可以立刻看到这个改变;
有序性:程序的执行要按照代码的先后顺序执行;

在并发编程模式中,势必会遇到上面三个概念,JMM对原子性并没有提供确切的解决方案,但是JMM解决了可见性和有序性,至于原子性则需要通过锁或者Synchronized来解决了。

如果一个操作A的操作结果需要对操作B可见,那么我们就认为操作A和操作B之间存在happens-before关系,即A happens-before B。

happens-before原则是JMM中非常重要的一个原则,它是判断数据是否存在竞争、线程是否安全的主要依据,依靠这个原则,我们可以解决在并发环境下两个操作之间是否存在冲突的所有问题。JMM规定,两个操作存在happens-before关系并不一定要A操作先于B操作执行,只要A操作的结果对B操作可见即可。

在程序运行过程中,为了执行的效率,编译器和处理器是可以对程序进行一定的重排序,但是他们必须要满足两个条件:1 执行的结果保持不变,2 存在数据依赖的不能重排序。重排序是引起多线程不安全的一个重要因素。

同时顺序一致性是一个比较理想化的参考模型,它为我们提供了强大而又有力的内存可见性保证,他主要有两个特征:1 一个线程中的所有操作必须按照程序的顺序来执行;2 所有线程都只能看到一个单一的操作执行顺序,在顺序一致性模型中,每个操作都必须原则执行且立刻对所有线程可见。
by @技术头条 2017-03-11 23:58 查看详情
图解java String的不变性 (www.javaranger.com)
字符串一旦在内存中创建,就不能改变。我们应该知道字符串的所有方法都不能改变它自己,而是返回一个新的字符串。

如果我们想要一个可变的字符串,我们应该使用StringBuffer 或者 StringBuilder。否则会浪费gc时间,应为每次都会创建新的字符串对象。
by @技术头条 2017-03-11 23:57 查看详情
大风车Android客户端的架构演进 (f2e.souche.com)
大风车从第一版发布开始到现在已经走过了两个多年头,陆续上线发布了二十多个版本,从一开始的提供web容器包装h5的简陋版本,发展到现在由九个专职原生开发同学及数位前端同学支持的12w行(统计数据来自SonarQube)代码的规模。架构的可用性半衰期随着业务体量的增长而缩短,那么如何支撑现有业务的维护及后续的业务开发是对我们的一大挑战,而本人作为经历了从零开始的开发人员,下面带大家回顾一下这两年来的大风车Android客户端的架构变化。
by @技术头条 2017-03-11 23:57 查看详情
我理解中的“大前端”/“大无线” (f2e.souche.com)
最近,我所在的团队做了一些结构调整,其实我一直想讲讲这次调整,希望能够带给同行一些思考,但因调整后很多事情还未走上正轨,一直拖延着,现在终于有时间把一些想法写下来记录成文字。

今天早晨,还看到一篇文章,讲“大前端”,文中展望了近年来“前端”影响的领域,从美工时代刀耕火种的时代到现在延伸到 NodeJS ,ReactNative甚至桌面端,以及传统前端的时代,听来的确让人非常兴奋和自豪,但是作为一名理性的工程师,对于这种自High的论调一定要抱有谨慎的态度。

其实在技术选型上我是一个激进却又保守的人,所以,我同大家伙一样,对于JS语言冒出来的给人无限想象的能力非常的敏锐和兴奋,但是在落地到真正的业务中的时候却要仔细权衡好它的真正的“价值”。此处的价值更多针对的是“对公司整体业务的价值”,而不是对团队或者个人的价值或是其他,所以,引入一个技术栈,绝非看起来那样简单,“新技术”可能会给你的团队或者业务带来加持,但是更多时候,外界的人云亦云却往往会夸大某个技术的价值,然后同时刻意避免谈及这些技术带来的问题,就是我们通常所说的“脱离场景讨论技术”,而且通常带来的问题比解决的问题还要多得多,这时候如果抱着“扩大前端团队的话语权”或者“做一步看一步毕竟业界都在这样玩”的态度,那就和“技术创造价值”的本意相违背了。

其实,大家会发现我所在的团队并不是一个保守的团队,从外面看,我们始终走在最前沿,但是从内部看,其实我们一直在关注“技术创造价值”这件事情的本质,所以我们给前端团队强化了很多职能,但是却走了一些不同的道路,之所以会这样,其实就是基于我们针对每个技术栈所做的思考,接下来我会举几个例子来讲。

其实我今天本来想讲的事情,并不只是“前端”,而是这次团队组织架构调整后的“大无线”,为什么要从“大前端”到“大无线”,也是基于最大化价值输出的考虑,这是后话。

这次调整,最大的三个动作就是, NodeJS 的职能变化/ReactNative的引入/专门的架构组职能,然后包含其他一些小动作。
by @技术头条 2017-03-11 23:56 查看详情
CentOS 6下Android SDK碰到提示”libc.so.6: version `GLIBC_2.14′ not found”的解决方法 (www.sunnyu.com)
在CentOS 6的机器上安装了Android的开发环境,碰到如下一些问题和解决方法
1. Android Studio 添加Android SDK时,提示缺少JDK 1.5、JDK 1.6 或 JDK 1.7, 但是机器上已经安装好JDK 1.6, JDK 1.7,还是提示同样的问题
解决方法,软件的提示信息Bug,其实是缺少 JDK 1.8(这个提示Bug应该会在后续版本被修订), 下载安装JDK 1.8,添加JDK 1.8后,再添加Android SDK,一切正常。
2. 新建一个简单Android项目,编译,提示”libc.so.6: version `GLIBC_2.14′ not found” 的错误信息
下载使用的是Android SDK Ver 25.2.5 Platform Tools Ver 25.0.3 Build Tools Ver 25.0.2
google搜索,确认是libc库的版本低的原因,CentOS 的libc版本文v2.14 要CentOS 7 才有支持 GLiBC_2.14,
解决方法要么重装系统使用CentOS 7, 要么逐个试验降低SDK版本,直到可以不要GLIBC_2.14的可用SDK版本。
既不想重装系统到CentOS7, 也不想逐个往下试验低版本SDK,
搜索网络后找到一个解决方法,也就是在其他目录编译安装一个并行的glibc 2.14版本,然后使用LD_LIBRARY_PATH临时指定到这个新安装的libc目录
by @技术头条 2017-03-11 23:56 查看详情
使用CSS offset-path让元素沿着不规则路径运动 (www.zhangxinxu.com)
在web端,要让一个元素按照特定的路径运动,在之前,基本上只能借助于SVG SMIL animation来实现,但是,随着浏览器的发展,CSS代码也能实现这样的功能,本文就将介绍如何使用CSS中的offset-path属性让元素沿着不规则路径运动。有demo有截图还有gif演示,总之,希望本文的内容能够对您的学习有所帮助。
by @技术头条 2017-03-11 23:54 查看详情
【死磕Java并发】—–J.U.C之AQS:CLH同步队列 (cmsblogs.com)
CLH同步队列是一个FIFO双向队列,AQS依赖它来完成同步状态的管理,当前线程如果获取同步状态失败时,AQS则会将当前线程已经等待状态等信息构造成一个节点(Node)并将其加入到CLH同步队列,同时会阻塞当前线程,当同步状态释放时,会把首节点唤醒(公平锁),使其再次尝试获取同步状态。
by @技术头条 2017-03-11 23:52 查看详情
JavaScript中的工厂函数 (www.css88.com)
不学习函数和对象,你不可能成为一名JavaScript程序员,并且当他们一起使用时,是构建块,我们需要从一个称为组合(composition)的强大对象范例开始。今天我们来看一些惯用的模式,使用工厂函数来组成函数,对象和 Promises 。

愚人码头注:组合模式是将一批子对象组织为树形结构,一条顶层的命令会在操作树中所有的对象。

当一个函数返回一个对象时,我们称之他为 工厂函数(factory function)。
by @技术头条 2017-03-11 23:50 查看详情
MySQL工具推荐 | 基于MySQL binlog的flashback工具 (imysql.com)
相信您应该遇到过因为误操作破坏数据库的问题,比如忘了带WHERE条件的UPDATE、DELETE操作,然后就需要进行传统方式的全量 & 增量恢复。现在,给您介绍一下MySQL中的flashback玩法,也可以做到像Oracle的flashback那样。

目前MySQL的 flashback(又称 闪回)一般是利用binlog完成的,能快速完成恢复且无需停机维护。

第一个实现该功能的是阿里云的 彭立勋,他在MySQL 5.5版本上就已实现,并将其开源及提交给MariaDB,为社区提供了非常优秀的参考模型。
by @技术头条 2017-03-11 23:41 查看详情
今天你检查备份了吗? (imysql.com)
引爆各大技术群的事情就是网易游戏《炉石传说》游戏数据库发生宕机并引发数据丢失事故,最终决定回档并后续补偿玩家损失。详情可见官网公告:http://hs.blizzard.cn/articles/16/8565

我以前也在搜狐畅游负责游戏数据库维护,也遇到过因为服务器故障最终导致回档的事故,不过都没像这次炉石搞这么大动作。在这里我并不想借机调侃消费他们或搞营销,只想和大家一起聊聊作为DBA,应该注意哪些事。
by @技术头条 2017-03-11 23:40 查看详情
FAQ系列 | 纳尼,mysqldump导出的数据居然少了40万? (imysql.com)
用mysqldump备份数据时,加上 -w 条件选项过滤部分数据,发现导出结果比实际少了40万,什么情况?

我的朋友小文前几天遇到一个怪事,他用mysqldump备份数据时,加上了 -w 选项过滤部分数据,发现导出的数据比实际上少了40万。
by @技术头条 2017-03-11 23:40 查看详情
【翻译】借助SVG实现背景透明JPG图片 (www.zhangxinxu.com)
人物往往色彩丰富,有时候会遇到需要背景透明的场景,结果PNG24图片尺寸太大,PNG8质量太差,JPG尺寸最小效果还好,但是背景又不透明,有没有什么办法就有JPG的小尺寸好效果,同时背景透明呢?本文的处理技巧可能会对你解决相关问题提供一些思路。
by @技术头条 2017-03-11 23:32 查看详情
继续说说“在家办公” (www.raychase.net)
​我在几年前写过一点对于在家办公的理解,经过最近几年的感受,时不时地需要在家办公,零零散散陆陆续续有了一些新的感受。

首先要明确的是,团队的支持是最重要的。需要一个宽松的团队氛围,能够获得足够的信任,这些都是软基础。如果同事和上司不信任,这件事情是不可能办成的。对于那些把员工视为不可靠、不安全因素的公司,在家办公也是难以实现的。

开发环境。以往我一个不愿意在家办公的重要原因是,我的开发环境都部署在desktop上面,从家里无论是通过Microsoft Remote Desk还是NoMachine之类的连接(我还试过一些别的持有图形界面连接的方式),都不够理想,一顿一顿的,写代码很难受。现在已经用上了云主机,机器性能比较强大,总结下来一个比较理想的方式是,在本地(例如我的Mac)上面开发,并且进行配置管理,比如Git提交代码和发送code review。但是所有的编译、构建、连接、测试、开发环境部署等等全部放到云主机去进行。这之间使用一个同步工具来完成,我目前用的是公司一些热心工程师写的一个同步小工具——即选定了Mac上的一个工作文件夹,其下的所有改动全部自动同步到云主机去,我不需要显式执行任何脚本。

硬件和设备。我对于显示器要求不太高,虽然在家和公司都配置了比较大的显示器,但是我已经习惯了小小的Mac屏幕。在家办公需要安全可靠的VPN,避免在这些硬件网络的问题上耽误时间是非常重要的。无论是在公司还是在家,笔记本电脑始终是除了网络之外第一位重要的硬件。我想起一些同事的抱怨,公司不愿意给配备好的笔记本电脑。其实一个好的笔记本电脑才多少钱,一台咖啡机才多少钱,提升的效率能创造多少价值,我始终不明白为什么那么多人算不过来这笔账呢。

关于会议和问题讨论。这是一个不太好解决的问题,也是我觉得工程师绝大多数时间一定要待在公司里的一个重要原因。虽说现在各种视频音频通信设备已经足够发达,但是面对面的沟通和使用这些设备来沟通依然有着鸿沟般的距离。我所在的大的团队有两个子团队,一个在西雅图,一个在纽约,为了达到面对面沟通讨论问题的效果,经常需要有同事往返这两个城市出差。有了问题,一个转身的距离就可以立即发起询问和讨论,手边就是稿纸和白板,这是在家里办公很难做到的。

氛围。这看起来是一个不怎么被人提起的原因,但是却非常重要。孩子出生以后,这一点更加明显,我当然愿意在家办公以节省交通的时间开销。可是问题是在家里办公干扰因素确实很多,例如孩子哭闹。虽然在公司也不得不面对一些容易被打断的困难,但毕竟也是工作的氛围浓重,和在家还是不一样的。还有一个是上下班一路上的氛围,我可以坐在车里安静地思考问题,整理头绪,看起来这件事情哪里都可以做,但是只有在上下班路上才可以保持头脑直接和放松的状态,因为大多别的事情也做不了。在家里诱惑太多,在单位杂事太多。

时间和空间。在家办公的一大好处是有更多时间,可以更自如地分配时间。本来就省下了通勤的时间,白天的时间可以更自如地分配。有时碰到恶劣天气,待在家里可以免去很多天气因素带来的烦恼。有时候在公司很难找到一处安静的地方思考问题,而思考和讨论像是两个极端,有时不打照面却都不可或缺,有时则一起出现。在家里显然更适合需要安静和空间的思考,在放松状态下做决定。

说到最后,无论如何,虽然现阶段在家办公还只是一个有时为之的选项,并不适宜成为常态(我并不认为37Signals这样的公司所实践的值得推广),但是如果说天下之大,要有哪一个高新技术行业最能够给予在家办公的福利的话,软件工程师们应该是相当有资格说这话了。
by @技术头条 2017-03-11 23:06 查看详情