IT牛人博客聚合网站 发现IT技术最优秀的内容, 寻找IT技术的价值 http://www.udpwork.com/ zh_CN http://www.udpwork.com/about hourly 1 Thu, 26 Apr 2018 11:40:26 +0800 <![CDATA[一个贪错了地方 一个怕错了方向]]> http://www.udpwork.com/item/16809.html http://www.udpwork.com/item/16809.html#reviews Wed, 25 Apr 2018 00:21:10 +0800 魏武挥 http://www.udpwork.com/item/16809.html

前北大教师沈阳的事,没完。

余震当量级,不比沈阳弄出来的地震小。

一位本科生与她几位同学,要求北大公布当年调查沈阳事件的详细情况,后者看来非常紧张。

这位本科生写下了她的遭遇,成为中文互联网上相当热议的事件。

人们先是转发文章,然后是截屏做长图转发,然后再把图片倒过来斜过去转发。

稍许了解点北大的人都知道,当年沈阳事件处理,恰逢北大建校100周年。

而今天,则是120周年。

两个甲子,同样大日子。

沈阳是一种贪婪。

仗着自己手上的一点点微末师权,对其学生动手动脚,实施性侵,无非就是下半身那点不上台面的欲望。

贪错了地方。

北大则是一种恐惧。

生怕120周年搞出点丑闻,面子过不去。今天的学生,早已不是二十年前沈阳做教师时候的学生。

惧错了方向。

我一个朋友这么说:

本来沈阳的事情跟本届校领导关系不大,完全可以转危为机,错失这个机会不算,学生申请信息公开,也完全可以以公开点赞加引导的方式解决。然而,一切让位于维稳,现在小事变大事。看他们120周年拿什么来庆祝!当然,他们还是会照样开校庆大会,但我觉得,要逆转如此颓势,惟有校庆公开表彰岳同学这一条路了,因为她才是北大精神的护法。当然,他们肯定不会这么干,依然会步步紧逼岳同学。

我告诉这位立志今年要嫁出去的梨视频某单身未婚女青年:你想多了。

如果北大当下领导这么想问题,那就是贪所致:更彰显北大精神。但其实他们是害怕,是恐惧。所以不会这么想,更不会这么干。

沈阳事件爆发后,我曾和几个朋友私下里说过类似的话:你们是没见过高校行政体系龌龊起来又多龌龊的,与沈阳相比,毫不逊色。

这个体系里具体到个体,可能没那么恶。整个体系行起恶来,是一个制度推动的恶。

这里有个词可以形容这样的体系:矫枉过正。

比如说,部级领导说:这次校庆要尽可能多展示优点。局级领导就说:不要暴露缺点。处级领导就说:任何一个小缺点也要防患于未然;科级领导就说:呀,那里有个学生好像需要去沟通一下;股级领导就说:赶紧让那个学生闭嘴;干事就立刻半夜一点钟去找人父母了。

每一级都将恐惧放大,最终你看到的,是一个张牙舞爪但其实内心深处怕到极点的体系恶魔。

色厉内荏。

公号“猛的号”,今天推出一篇文章:呵,清华教授说《无问西东》很虚无

标题是和清华的李彬教授有关,但正文也浓墨重彩地提到了北大这件事。

号主明显是对新传学界颇有微词的前媒体实务派人士。ta这么写道:

业界已经气若游丝,学界还在那里自娱自乐,要么翻历史故纸堆来验证理论的伟光正,要么一知半解地套用西方话语来装大尾巴狼。

而我前述那位恨嫁友人也说,你看看你们学界,从沈阳到今天北大修理这个学生,你们哪路教授发过言了?

学界的虚无主义真是严重到不行。

说起来我推荐这篇文章,主要是想推荐底下被置顶的留言:

一束光照进铁塔,铁塔里的肮脏龌龊被显现,这束光便有了罪。

我查了查,具体出处不是太详实,疑似来自暴走王尼玛。后者因此而被下架。

这句留言真是应景之至。

以下贴一段对话。

我一个朋友问我的看法。

人民日报公号矩阵里的评论号“人民日报评论”也推文一篇:如何聆听“年轻的声音”? | 锐评

小心翼翼地摆了一个和稀泥姿态,劝说两头都换位思考一下。

又有朋友和我说,这算是一个定性了:是对话问题,不是本质冲突。

这句话我同意。

但接下来这句话我倒不是很同意:这个议题算脱敏了。

脱敏了么?

不见得吧。

人日说得你我说不得的事,又不是没有过。

在今日份的刷屏日报上,新榜创始人徐达内说:人民日报出来谈北大,总没人敢删了吧

挺对的,人日当然是不太容易被删的。

我这种高校里的小讲师,那就看看这篇能活多久吧。

甚至这个号。

—— 首发 扯氮集 ——

作者执教于上海交通大学媒体与传播学院,天奇阿米巴基金管理合伙人

一个贪错了地方 一个怕错了方向最先出现在扯氮集

]]>

前北大教师沈阳的事,没完。

余震当量级,不比沈阳弄出来的地震小。

一位本科生与她几位同学,要求北大公布当年调查沈阳事件的详细情况,后者看来非常紧张。

这位本科生写下了她的遭遇,成为中文互联网上相当热议的事件。

人们先是转发文章,然后是截屏做长图转发,然后再把图片倒过来斜过去转发。

稍许了解点北大的人都知道,当年沈阳事件处理,恰逢北大建校100周年。

而今天,则是120周年。

两个甲子,同样大日子。

沈阳是一种贪婪。

仗着自己手上的一点点微末师权,对其学生动手动脚,实施性侵,无非就是下半身那点不上台面的欲望。

贪错了地方。

北大则是一种恐惧。

生怕120周年搞出点丑闻,面子过不去。今天的学生,早已不是二十年前沈阳做教师时候的学生。

惧错了方向。

我一个朋友这么说:

本来沈阳的事情跟本届校领导关系不大,完全可以转危为机,错失这个机会不算,学生申请信息公开,也完全可以以公开点赞加引导的方式解决。然而,一切让位于维稳,现在小事变大事。看他们120周年拿什么来庆祝!当然,他们还是会照样开校庆大会,但我觉得,要逆转如此颓势,惟有校庆公开表彰岳同学这一条路了,因为她才是北大精神的护法。当然,他们肯定不会这么干,依然会步步紧逼岳同学。

我告诉这位立志今年要嫁出去的梨视频某单身未婚女青年:你想多了。

如果北大当下领导这么想问题,那就是贪所致:更彰显北大精神。但其实他们是害怕,是恐惧。所以不会这么想,更不会这么干。

沈阳事件爆发后,我曾和几个朋友私下里说过类似的话:你们是没见过高校行政体系龌龊起来又多龌龊的,与沈阳相比,毫不逊色。

这个体系里具体到个体,可能没那么恶。整个体系行起恶来,是一个制度推动的恶。

这里有个词可以形容这样的体系:矫枉过正。

比如说,部级领导说:这次校庆要尽可能多展示优点。局级领导就说:不要暴露缺点。处级领导就说:任何一个小缺点也要防患于未然;科级领导就说:呀,那里有个学生好像需要去沟通一下;股级领导就说:赶紧让那个学生闭嘴;干事就立刻半夜一点钟去找人父母了。

每一级都将恐惧放大,最终你看到的,是一个张牙舞爪但其实内心深处怕到极点的体系恶魔。

色厉内荏。

公号“猛的号”,今天推出一篇文章:呵,清华教授说《无问西东》很虚无

标题是和清华的李彬教授有关,但正文也浓墨重彩地提到了北大这件事。

号主明显是对新传学界颇有微词的前媒体实务派人士。ta这么写道:

业界已经气若游丝,学界还在那里自娱自乐,要么翻历史故纸堆来验证理论的伟光正,要么一知半解地套用西方话语来装大尾巴狼。

而我前述那位恨嫁友人也说,你看看你们学界,从沈阳到今天北大修理这个学生,你们哪路教授发过言了?

学界的虚无主义真是严重到不行。

说起来我推荐这篇文章,主要是想推荐底下被置顶的留言:

一束光照进铁塔,铁塔里的肮脏龌龊被显现,这束光便有了罪。

我查了查,具体出处不是太详实,疑似来自暴走王尼玛。后者因此而被下架。

这句留言真是应景之至。

以下贴一段对话。

我一个朋友问我的看法。

人民日报公号矩阵里的评论号“人民日报评论”也推文一篇:如何聆听“年轻的声音”? | 锐评

小心翼翼地摆了一个和稀泥姿态,劝说两头都换位思考一下。

又有朋友和我说,这算是一个定性了:是对话问题,不是本质冲突。

这句话我同意。

但接下来这句话我倒不是很同意:这个议题算脱敏了。

脱敏了么?

不见得吧。

人日说得你我说不得的事,又不是没有过。

在今日份的刷屏日报上,新榜创始人徐达内说:人民日报出来谈北大,总没人敢删了吧

挺对的,人日当然是不太容易被删的。

我这种高校里的小讲师,那就看看这篇能活多久吧。

甚至这个号。

—— 首发 扯氮集 ——

作者执教于上海交通大学媒体与传播学院,天奇阿米巴基金管理合伙人

一个贪错了地方 一个怕错了方向最先出现在扯氮集

]]>
0
<![CDATA[Uber是如何重新思考GPS定位的(尤其是在城市峡谷中) - 旁观者]]> http://www.udpwork.com/item/16808.html http://www.udpwork.com/item/16808.html#reviews Tue, 24 Apr 2018 19:24:00 +0800 旁观者 http://www.udpwork.com/item/16808.html 【摘要】Uber针对GPS定位在城市峡谷环境中表现不佳做了优化,如可以通过卫星信号信噪比(缩写为SNR)和3D地图来判断出你在马路的左侧还是右侧。阅读全文

]]>
【摘要】Uber针对GPS定位在城市峡谷环境中表现不佳做了优化,如可以通过卫星信号信噪比(缩写为SNR)和3D地图来判断出你在马路的左侧还是右侧。阅读全文

]]>
0
<![CDATA[2018微博内部技术分享春晚专场]]> http://www.udpwork.com/item/16807.html http://www.udpwork.com/item/16807.html#reviews Tue, 24 Apr 2018 18:32:10 +0800 鸟窝 http://www.udpwork.com/item/16807.html 这是公司内部分享的各部门春晚保障的技术分享。我将其中的和公司隐私相关的数据删除了,只保留了技术的介绍,总结了一些知识点。

Tim开场白。

双十一、微信红包和微博的区别(无法预期)。

三条军规。

孟兆飞 混合云架构下微博春晚保障

流量

  • 突发流量: 日常、异常
  • 春晚
  • 央视合作

万台扩容挑战

  • 联路长
  • 依赖多
  • 高并发

15分钟1000台全公司随时随地

自动化

  • 智能弹性
  • 混合云平台
  • 监控信息
  • 容量评估

双仓库(公司内网、阿里云)

高可用

传统扩容,由于资源限制会失败

优化扩容:基于多种策略

DCP高可用双机房

春节保障

春节X台扩容、云上X台
流量监控

DNS问题、扩容 (16台支持万台client) UDP session?

全链路压测。演练。共享池。重点监控。

熊超 让红包飞春晚55万qps解决方案

超预期

战队红包

业务

满N万开奖

  • 瞬间QPS高
  • 参与人数越多,开奖越快
  • 瞬间开奖
  • 参与规则复杂,单次参与动作资源交互次数10+

实现

5台扫描, 扔队列, 30台队列机, 64组redis, 发奖发私信等

前端: 缓存、不可缓存

红包雨

业务

3次机会,10分钟任意点

  • 参与用户多
  • 拼手速、qps 55万
  • 每次点击都有请求
  • 中出数量巨大, 5次红包雨1.6亿

实现

  • 传送门 检查用户等,加密防刷、垃圾用户过滤、入口处错峰
  • 抽奖: 特别快的请求、根据用户区分奖项
  • 中出
  • 队列机

优化

  • 代码: 重复资源链接重用、耗时步骤优化、根据日志
  • DBA: 监控平台

压测评估

温情 陈新伍 春节百万答题

两三周紧急开发。

背景

大家都在做,拉新拉活。

产品经理介绍这个产品。

技术挑战

  • 快速扩所容
  • 快速下发push设计

简介

  • 视频流
  • 消息互动
  • 问答

发题阶段 -> 答题阶段 -> 颁奖阶段

技术挑战

  • 消息实时性
  • 同步答题、实时到达率

  • 每秒千万推送

  • 百万在线

长连推送

  • 百万长连接
  • 水平弹性伸缩

    • 无状态服务
    • 减少资源的依赖
  • 消息分发队列: Reids的PubSub (apiServer -> redis)

问答服务

  • 上行: 接口https
  • 下行方案:
    • 互动消息下发
    • 轮训 (西瓜视频)
    • 加入房间时全量下发(容易漏题)
    • 视频流(SEI)下发(丢包)

微博方案: 1为主,2为辅

发题方案:

  • Push+ACK: 有条件重传
  • Push + Push: 无条件重传

轮训:长链接断后自动重连降级

发题设计:根据服务器NTP, 题目和视频校准同时弹出

答题阶段

  • 客户端答题服务器判题
  • 复活
  • 答题结果推送
  • 答题汇总
  • 汇总推送

10万级别的qps

判题方案:

  • 异步判题
  • 随机重试机制

服务压测

  • 第一场就全量push,无灰度
  • 峰值速度快,第一题为峰值
  • 百万用户

关里 微博搜索架构

架构

trigger -> 数据转换 -> 预处理 -> 数据分发 --> 索引库

各种检索模块

热点爆发白页

数据分层:优质、筛选、全量

自动扩容、自动降级

1000多亿次数据需要索引

单机7、8亿

朱伟 支撑百亿级请求的微博广告运维技术实践

运维在微博广告体系中的价值。

人工 -> 工具 -> DevOps -> AiOps

  • 监控: 数据采集、清洗、存储。Filebeat -> kafka -> OLS -> Druid, kafka -> graphite, kafka -> logstash -> ES, 多存储graphite,druid,ES, clickhouse
]]>
这是公司内部分享的各部门春晚保障的技术分享。我将其中的和公司隐私相关的数据删除了,只保留了技术的介绍,总结了一些知识点。

Tim开场白。

双十一、微信红包和微博的区别(无法预期)。

三条军规。

孟兆飞 混合云架构下微博春晚保障

流量

  • 突发流量: 日常、异常
  • 春晚
  • 央视合作

万台扩容挑战

  • 联路长
  • 依赖多
  • 高并发

15分钟1000台全公司随时随地

自动化

  • 智能弹性
  • 混合云平台
  • 监控信息
  • 容量评估

双仓库(公司内网、阿里云)

高可用

传统扩容,由于资源限制会失败

优化扩容:基于多种策略

DCP高可用双机房

春节保障

春节X台扩容、云上X台
流量监控

DNS问题、扩容 (16台支持万台client) UDP session?

全链路压测。演练。共享池。重点监控。

熊超 让红包飞春晚55万qps解决方案

超预期

战队红包

业务

满N万开奖

  • 瞬间QPS高
  • 参与人数越多,开奖越快
  • 瞬间开奖
  • 参与规则复杂,单次参与动作资源交互次数10+

实现

5台扫描, 扔队列, 30台队列机, 64组redis, 发奖发私信等

前端: 缓存、不可缓存

红包雨

业务

3次机会,10分钟任意点

  • 参与用户多
  • 拼手速、qps 55万
  • 每次点击都有请求
  • 中出数量巨大, 5次红包雨1.6亿

实现

  • 传送门 检查用户等,加密防刷、垃圾用户过滤、入口处错峰
  • 抽奖: 特别快的请求、根据用户区分奖项
  • 中出
  • 队列机

优化

  • 代码: 重复资源链接重用、耗时步骤优化、根据日志
  • DBA: 监控平台

压测评估

温情 陈新伍 春节百万答题

两三周紧急开发。

背景

大家都在做,拉新拉活。

产品经理介绍这个产品。

技术挑战

  • 快速扩所容
  • 快速下发push设计

简介

  • 视频流
  • 消息互动
  • 问答

发题阶段 -> 答题阶段 -> 颁奖阶段

技术挑战

  • 消息实时性
  • 同步答题、实时到达率

  • 每秒千万推送

  • 百万在线

长连推送

  • 百万长连接
  • 水平弹性伸缩

    • 无状态服务
    • 减少资源的依赖
  • 消息分发队列: Reids的PubSub (apiServer -> redis)

问答服务

  • 上行: 接口https
  • 下行方案:
    • 互动消息下发
    • 轮训 (西瓜视频)
    • 加入房间时全量下发(容易漏题)
    • 视频流(SEI)下发(丢包)

微博方案: 1为主,2为辅

发题方案:

  • Push+ACK: 有条件重传
  • Push + Push: 无条件重传

轮训:长链接断后自动重连降级

发题设计:根据服务器NTP, 题目和视频校准同时弹出

答题阶段

  • 客户端答题服务器判题
  • 复活
  • 答题结果推送
  • 答题汇总
  • 汇总推送

10万级别的qps

判题方案:

  • 异步判题
  • 随机重试机制

服务压测

  • 第一场就全量push,无灰度
  • 峰值速度快,第一题为峰值
  • 百万用户

关里 微博搜索架构

架构

trigger -> 数据转换 -> 预处理 -> 数据分发 --> 索引库

各种检索模块

热点爆发白页

数据分层:优质、筛选、全量

自动扩容、自动降级

1000多亿次数据需要索引

单机7、8亿

朱伟 支撑百亿级请求的微博广告运维技术实践

运维在微博广告体系中的价值。

人工 -> 工具 -> DevOps -> AiOps

  • 监控: 数据采集、清洗、存储。Filebeat -> kafka -> OLS -> Druid, kafka -> graphite, kafka -> logstash -> ES, 多存储graphite,druid,ES, clickhouse
]]>
0
<![CDATA[如何编码事务]]> http://www.udpwork.com/item/16806.html http://www.udpwork.com/item/16806.html#reviews Tue, 24 Apr 2018 16:55:27 +0800 老王 http://www.udpwork.com/item/16806.html 我说的事务指的是一般的数据库事务,而不是什么分布式事务之类高大上的概念。听起来很简单,但是即便如此,想实现的优雅一点也不是一件容易的事情。 

假设有一个 QA 系统,当用户在上面提问的时候,系统保存问题,然后更新用户的提问数,最后触发一个问题已经被创建的异步事件来解耦逻辑(代码均使用 Lumen 框架):

<?php

try {
    DB::beginTransaction();

    $question->content = '...';
    $question->save();

    $user->questions_count += 1;
    $user->save();

    DB::commit();

    event(new QuestionCreatedEvent($question));
} catch (Exception $e) {
    DB::rollBack();
}

?>

随着业务逻辑越来越复杂,会出现很多问题,其一:事务处理相关代码的割裂感会越来越严重;其二:事务处理相关逻辑会重复散落在很多地方,很容易遗漏或错乱。

如何解决问题?学院派面对此类问题,多半会搞出一个新的 service 层,专门用来处理事务,不过对我来说太重了,我需要的是更轻量级的方案,从 PSR-15中可以找到答案,其中的 Middleware 机制构造出了一个类似洋葱皮的结构,通过它我们可以很容易的把事务处理的功能包裹在 controller 之上。

中间件

让我们看看如何实现事务处理的洋葱皮中间件:

<?php

namespace App\Http\Middlewares;

use Closure;
use Exception;

use Illuminate\Http\Request;
use Illuminate\Http\Response;

class TransactionMiddleware
{
    protected static $methods = [
        Request::METHOD_DELETE,
        Request::METHOD_PATCH,
        Request::METHOD_POST,
        Request::METHOD_PURGE,
        Request::METHOD_PUT,
    ];

    public function handle($request, Closure $next)
    {
        $method = $request->getMethod();

        if (! in_array($method, static::$methods)) {
            return $next($request);
        }

        $db = app('db');

        $db->beginTransaction();

        $result = $next($request);

        if ($result->getStatusCode() < Response::HTTP_BAD_REQUEST) {
            $db->commit();
        } else {
            $db->rollBack();
        }

        return $result;
    }
}

?>

说明:如上代码之所以没有使用 Lumen 中看是更简单的 DB::transaction() 方法,是因为在框架的工作流程中,异常在到达中间件之前就已经被处理消化掉了,所以在中间件里是捕获不到异常的,好在我们可以通过判断响应码来实现同样的效果。

激活事务处理的洋葱皮中间件之后,业务逻辑代码会得到极大简化:

<?php

$question->content = '...';
$question->save();

$user->questions_count += 1;
$user->save();

event(new QuestionCreatedEvent($question));

?>

如此一来,业务代码完全不用考虑事务处理了,中间件会通过 HTTP 方法来判断该请求是不是一个「写」请求,进而决定提交事务还是回滚事务。

不过洋葱皮中间件也带来了一个意想不到的问题:因为事务处理是包裹在外层的,所以 event 这个异步操作也被包裹到其中了,比如说:当我们创建了一个新问题,执行到异步的 event 的时候,事务本身还没有提交,于是在异步处理 event 的进程里,很可能取不到这个新创建的问题,从而导致失败。

为了解决这个问题,我们可以新建一个 register_event 方法来替换原本的 event 方法:

<?php

if (! function_exists('register_event')) {
    function register_event($event, $payload = [], $halt = false)
    {
        if (app()->runningInConsole()) {
            return event($event, $payload, $halt);
        }

        register_shutdown_function(function ()
            use ($event, $payload, $halt) {

            return event($event, $payload, $halt);
        });
    }
}

?>

如此一来,虽然异步事件相关的代码还是包裹在事务处理中的,但是它的执行时机却通过 register_shutdown_function 延迟到了最后,也就是说事务提交后才会执行,自然就不会出问题了。至于代码里为什么要判断是不是运行在命令行,其实是为了兼容 Lumen 测试框架中的 expectsEvents 方法,不是本文的重点,我就不多说了。

]]>
我说的事务指的是一般的数据库事务,而不是什么分布式事务之类高大上的概念。听起来很简单,但是即便如此,想实现的优雅一点也不是一件容易的事情。 

假设有一个 QA 系统,当用户在上面提问的时候,系统保存问题,然后更新用户的提问数,最后触发一个问题已经被创建的异步事件来解耦逻辑(代码均使用 Lumen 框架):

<?php

try {
    DB::beginTransaction();

    $question->content = '...';
    $question->save();

    $user->questions_count += 1;
    $user->save();

    DB::commit();

    event(new QuestionCreatedEvent($question));
} catch (Exception $e) {
    DB::rollBack();
}

?>

随着业务逻辑越来越复杂,会出现很多问题,其一:事务处理相关代码的割裂感会越来越严重;其二:事务处理相关逻辑会重复散落在很多地方,很容易遗漏或错乱。

如何解决问题?学院派面对此类问题,多半会搞出一个新的 service 层,专门用来处理事务,不过对我来说太重了,我需要的是更轻量级的方案,从 PSR-15中可以找到答案,其中的 Middleware 机制构造出了一个类似洋葱皮的结构,通过它我们可以很容易的把事务处理的功能包裹在 controller 之上。

中间件

让我们看看如何实现事务处理的洋葱皮中间件:

<?php

namespace App\Http\Middlewares;

use Closure;
use Exception;

use Illuminate\Http\Request;
use Illuminate\Http\Response;

class TransactionMiddleware
{
    protected static $methods = [
        Request::METHOD_DELETE,
        Request::METHOD_PATCH,
        Request::METHOD_POST,
        Request::METHOD_PURGE,
        Request::METHOD_PUT,
    ];

    public function handle($request, Closure $next)
    {
        $method = $request->getMethod();

        if (! in_array($method, static::$methods)) {
            return $next($request);
        }

        $db = app('db');

        $db->beginTransaction();

        $result = $next($request);

        if ($result->getStatusCode() < Response::HTTP_BAD_REQUEST) {
            $db->commit();
        } else {
            $db->rollBack();
        }

        return $result;
    }
}

?>

说明:如上代码之所以没有使用 Lumen 中看是更简单的 DB::transaction() 方法,是因为在框架的工作流程中,异常在到达中间件之前就已经被处理消化掉了,所以在中间件里是捕获不到异常的,好在我们可以通过判断响应码来实现同样的效果。

激活事务处理的洋葱皮中间件之后,业务逻辑代码会得到极大简化:

<?php

$question->content = '...';
$question->save();

$user->questions_count += 1;
$user->save();

event(new QuestionCreatedEvent($question));

?>

如此一来,业务代码完全不用考虑事务处理了,中间件会通过 HTTP 方法来判断该请求是不是一个「写」请求,进而决定提交事务还是回滚事务。

不过洋葱皮中间件也带来了一个意想不到的问题:因为事务处理是包裹在外层的,所以 event 这个异步操作也被包裹到其中了,比如说:当我们创建了一个新问题,执行到异步的 event 的时候,事务本身还没有提交,于是在异步处理 event 的进程里,很可能取不到这个新创建的问题,从而导致失败。

为了解决这个问题,我们可以新建一个 register_event 方法来替换原本的 event 方法:

<?php

if (! function_exists('register_event')) {
    function register_event($event, $payload = [], $halt = false)
    {
        if (app()->runningInConsole()) {
            return event($event, $payload, $halt);
        }

        register_shutdown_function(function ()
            use ($event, $payload, $halt) {

            return event($event, $payload, $halt);
        });
    }
}

?>

如此一来,虽然异步事件相关的代码还是包裹在事务处理中的,但是它的执行时机却通过 register_shutdown_function 延迟到了最后,也就是说事务提交后才会执行,自然就不会出问题了。至于代码里为什么要判断是不是运行在命令行,其实是为了兼容 Lumen 测试框架中的 expectsEvents 方法,不是本文的重点,我就不多说了。

]]>
0
<![CDATA[推荐一篇长篇八卦 讲芯片和OS的]]> http://www.udpwork.com/item/16803.html http://www.udpwork.com/item/16803.html#reviews Mon, 23 Apr 2018 13:36:34 +0800 魏武挥 http://www.udpwork.com/item/16803.html

前两天我看到一篇文章,标题是这样的:上海交大这位“长江学者”,应该为中兴困局负责。

我在“刷屏”里说,这篇文章的用心极其低劣。

交大的汉芯事件,是交大建国后最大的丑闻,丢人丢到了火星上。但汉芯事件并不能为中兴困局负责。

这里的逻辑是这样的:如果当年搞项目验收的专家们认真点,最多能做的事是:阻止了这个丑闻的发生。但他们的认真,并不能使得中兴就有所谓自己的国产的芯片。

而且,中兴困局,大部是咎由自取,不守规则,并不是什么芯片到底是美国产还是中国产的问题。

此文的低劣之处,在于摆明了想蹭热点,却无话可说,只好把汉芯事件再翻出来。

百度一下,东拼西凑,马上就可以成文,还标了个原创。

我再次感慨了一句,百度为内容创业是做出了贡献的,可惜,很多内容创业者都是以diss百度来成就十万加的。

 

八卦不好写的,我上一篇就这么断言了。

我今天向大家推荐的长篇八卦,一段关于国产芯片和操作系统的往事,长达万字,点过去看的时候请做好心理准备,而且排版比我这里还要惨不忍睹,几追王五四。

作者梁宁,有互联网女侠的称号,公号梁宁-闲花照水录。闲花照水录是博客时代有名的互联网博客,梁女侠堪称圈内老司机。

梁宁这篇八卦,是她亲历所得,绝非百度而来。

这一仗如果简单来说,就是我们搞定了总理,没有搞定用户体验。

这句话是前半篇的文眼。

芯片不是一个独立的东西,它不能吃不能穿,它的价值在于别的东西(比如OS)对它的依赖。

利用行政手段和类似举国体制的方式,突击芯片,不是不能成功,就好像你要搞定总理,总是有方法的,说到底总理也就是一个人。

但这样的芯片,无法形成别的东西对它的依赖。

梁宁这样写道:

CPU做出来了,再自己做原型,然后自己做产品。做完产品,发现没有配套软件可用。

芯片、OS、通用软件,一间小公司拼命挣扎,十几个院士联名上书。

没用的。

这不是培养一个举重运动员,单点突破即可。

 

搞不定的依然是操作系统,差距大的依然是生态。

这是梁宁后半篇的文眼。

培养一个举重运动员,不是生态打法。满世界找个好苗子,闷头训练十余载,一放出去就惊天动地。

生态不是这么干的。

一个生态的形成,差不多可以用这样的标准来衡量:如果这家核心公司倒闭,世界上有越多人(非这家公司)会从此失业甚至长期失业,这家公司生态就越强大。

诺基亚造手机不是生态,所以诺基亚的手机部分完蛋了,最多也就是资本市场的损失。

微软的的确确是生态,所以微软至今不倒。

在那位印度裔CEO手上,甚至还迸发出了新一春。

是的,我们能制造智能手机,中国绝对是安卓系智能手机大国。

但我们造不出安卓生态。

有趣的事是,在三大手机OS发源地美国,也就苹果奉行软硬通吃的道路,在那里造手机。

安卓系,大概除了google偶尔还玩玩概念机,美国人都把这种非生态的事,扔给亚洲人玩了。

 

中国互联网也是有生态的。

阿里有电商生态,正在努力搞金融生态、物流生态,腾讯有微信生态。最近马化腾八年前就唠叨过的企业文档协作被腾讯SNG弄了出来,还是想扩张生态。

但他们并不是从搞定总理开始的。

生态是市场形成的,不是行政命令规定成的。

从芯片到OS,国家可以扶持,但不能主导。

再牛逼的政府,都不能和市场作对。

同样的,再牛逼的政府,都无法制造生态。

就算制造出来,都是伪生态。

 

科学技术是第一生产力。

这句话没什么大错。但这句话漏了一点东西,结果误导了很多人。

科学技术要市场化后才是第一生产力。

如何市场化。

我三年前写过一篇东西,旧文重看,我个人以为,依然有现实意义。

中国可以这样“超越”美国

 

—— 首发 扯氮集 ——

作者执教于上海交通大学媒体与设计学院,天奇阿米巴创投基金管理合伙人

刷屏终于允许pro进行免费设置了。无需敲门码,欢迎扫二维码follow

推荐一篇长篇八卦 讲芯片和OS的最先出现在扯氮集

]]>

前两天我看到一篇文章,标题是这样的:上海交大这位“长江学者”,应该为中兴困局负责。

我在“刷屏”里说,这篇文章的用心极其低劣。

交大的汉芯事件,是交大建国后最大的丑闻,丢人丢到了火星上。但汉芯事件并不能为中兴困局负责。

这里的逻辑是这样的:如果当年搞项目验收的专家们认真点,最多能做的事是:阻止了这个丑闻的发生。但他们的认真,并不能使得中兴就有所谓自己的国产的芯片。

而且,中兴困局,大部是咎由自取,不守规则,并不是什么芯片到底是美国产还是中国产的问题。

此文的低劣之处,在于摆明了想蹭热点,却无话可说,只好把汉芯事件再翻出来。

百度一下,东拼西凑,马上就可以成文,还标了个原创。

我再次感慨了一句,百度为内容创业是做出了贡献的,可惜,很多内容创业者都是以diss百度来成就十万加的。

 

八卦不好写的,我上一篇就这么断言了。

我今天向大家推荐的长篇八卦,一段关于国产芯片和操作系统的往事,长达万字,点过去看的时候请做好心理准备,而且排版比我这里还要惨不忍睹,几追王五四。

作者梁宁,有互联网女侠的称号,公号梁宁-闲花照水录。闲花照水录是博客时代有名的互联网博客,梁女侠堪称圈内老司机。

梁宁这篇八卦,是她亲历所得,绝非百度而来。

这一仗如果简单来说,就是我们搞定了总理,没有搞定用户体验。

这句话是前半篇的文眼。

芯片不是一个独立的东西,它不能吃不能穿,它的价值在于别的东西(比如OS)对它的依赖。

利用行政手段和类似举国体制的方式,突击芯片,不是不能成功,就好像你要搞定总理,总是有方法的,说到底总理也就是一个人。

但这样的芯片,无法形成别的东西对它的依赖。

梁宁这样写道:

CPU做出来了,再自己做原型,然后自己做产品。做完产品,发现没有配套软件可用。

芯片、OS、通用软件,一间小公司拼命挣扎,十几个院士联名上书。

没用的。

这不是培养一个举重运动员,单点突破即可。

 

搞不定的依然是操作系统,差距大的依然是生态。

这是梁宁后半篇的文眼。

培养一个举重运动员,不是生态打法。满世界找个好苗子,闷头训练十余载,一放出去就惊天动地。

生态不是这么干的。

一个生态的形成,差不多可以用这样的标准来衡量:如果这家核心公司倒闭,世界上有越多人(非这家公司)会从此失业甚至长期失业,这家公司生态就越强大。

诺基亚造手机不是生态,所以诺基亚的手机部分完蛋了,最多也就是资本市场的损失。

微软的的确确是生态,所以微软至今不倒。

在那位印度裔CEO手上,甚至还迸发出了新一春。

是的,我们能制造智能手机,中国绝对是安卓系智能手机大国。

但我们造不出安卓生态。

有趣的事是,在三大手机OS发源地美国,也就苹果奉行软硬通吃的道路,在那里造手机。

安卓系,大概除了google偶尔还玩玩概念机,美国人都把这种非生态的事,扔给亚洲人玩了。

 

中国互联网也是有生态的。

阿里有电商生态,正在努力搞金融生态、物流生态,腾讯有微信生态。最近马化腾八年前就唠叨过的企业文档协作被腾讯SNG弄了出来,还是想扩张生态。

但他们并不是从搞定总理开始的。

生态是市场形成的,不是行政命令规定成的。

从芯片到OS,国家可以扶持,但不能主导。

再牛逼的政府,都不能和市场作对。

同样的,再牛逼的政府,都无法制造生态。

就算制造出来,都是伪生态。

 

科学技术是第一生产力。

这句话没什么大错。但这句话漏了一点东西,结果误导了很多人。

科学技术要市场化后才是第一生产力。

如何市场化。

我三年前写过一篇东西,旧文重看,我个人以为,依然有现实意义。

中国可以这样“超越”美国

 

—— 首发 扯氮集 ——

作者执教于上海交通大学媒体与设计学院,天奇阿米巴创投基金管理合伙人

刷屏终于允许pro进行免费设置了。无需敲门码,欢迎扫二维码follow

推荐一篇长篇八卦 讲芯片和OS的最先出现在扯氮集

]]>
0
<![CDATA[最近有个体悟,想和大家分享一下]]> http://www.udpwork.com/item/16804.html http://www.udpwork.com/item/16804.html#reviews Mon, 23 Apr 2018 13:33:26 +0800 魏武挥 http://www.udpwork.com/item/16804.html

这是我最近四篇公号文章的阅读量。

对于我这样粉丝不超过6万的足底号来说,这样的阅读量,其实可以满意。

这四篇文章,有两个套路。

第一个套路,我曾经在过去的文章里提到过,diss一种观念。具体到这篇文章,就是diss一种现象。

的确,《大学,难道不应该禁止师生恋吗》是用沈阳事件破题的,但讨论的却是师生恋。这里的摆渡,存在一个漏洞:沈阳事件不一定就是师生恋,有可能就是强奸。但这个漏洞,从我文章的反馈来看,应该说,没人注意到。

diss一种现象,符合《我今天想到一个起量的写作技巧》中的套路。

第二个套路,各位可以非常明晰地看到,我写了三篇八卦,有一位好友甚至留言说,本号要转做人物八卦了。

《一个猛人退休了》,是浙报前一把手高海浩的八卦。文头文尾的细节,还被大号小小引(xi)用(gao)了。

《王晓峰这个人》,是摩拜CEO王晓峰的八卦。

《梨视频喜提6亿巨资》,是梨视频邱兵的八卦。

如果我改成:高海浩时代浙报媒体融合之路、摩拜为什么选择投入美团、梨视频的短视频商业打法,诸如此类,老实讲,我写得累死,可看性也一点木有吧?:)

我甚至在《一个猛人退休了》中,故意神秘兮兮地用了很多字母来替代人(并不是什么敏感非要这么干,纯属故作神秘),大大增加了八卦的玄妙感。

对本号来说,此篇八卦访问量很高,超越了我历史上写赵何娟的八卦——那篇文章还是踩在风口上写的,当时钛媒体报道赛龙公司一事成为舆论热点——关于这件事我也反思过,我当时的标题是《我所认识的钛媒体》,如果改成《我所认识的赵何娟》,大概访问量还多个一两成吧。

 

昨天和人吃饭,聊起最近很火的三和大神,这是一组系列文章,公号是故事硬核。

聊的话题是严肃内容该如何生存。

聊着聊着,我发现一个事实:这个世界,并没有什么真正所谓严肃的事。

如果你用一种很通俗的写法,那就叫八卦。

如果你非要端着用一种比较有逼格的写法,那就叫新闻,逼格更高一点,就叫硬新闻。

只有严肃或不严肃的方法,并不存在什么严肃的事或者不严肃的事。

三和那帮人的生存状态,还不够三俗的。

 

昨儿腾讯大家头条文章,就是把一件很不严肃的事写出了很严肃的感觉,

看看标题各位就应该懂了:春情抄——日系桃色电影兴衰考。这个标题,是不是有一种荷尔蒙在呼喊你点击下去的感觉。

非把爱情动作片搞成什么日系桃色电影,还“春情抄”(我估计作者肯定上了年纪,看过山口百惠演的<春琴抄>,那是爱情但木有动作的片子)。行业八卦非说成兴衰,还“考”。

这个逼装的,必须给满分。

顺便说一句,这文章的作者竟然不是阑夕,我个人表示惊讶。

八卦并不是说不加以考证——不加考证的叫流言——它只是写法上,有些三俗,有些所谓的窥私感。

写三和大神,我视野中最早的一个公号是我朋友花总,他那个公号上第一篇就是写他混迹在三和大神中的事。

他把预览版给我看过,我当时第一个反应其实没和他说:这文章一点都不好看。第二个反应和他说了:被删的可能性很大。果不其然。

花总写装逼指南大概写惯了,写得非常让人不好懂。他以前那个装逼指南也是这样,你要是不太了解咖啡行业,你压根就很难看懂他对喝咖啡装逼到底是怎么装的。但花总的装逼指南,写法还是很轻松的,不懂也可以看个乐呵。三和那篇,真得好生沉闷。

被删再加上不太好理解,花总那个号第一篇没打响。

大概吸取了经验教训,最近那个号连续几篇讲北朝鲜的八卦,就好看多了。

所以,八卦其实不好写的。

不要看不起八卦。

 

八卦对于我来说,有两个缺点。

第一是写起来其实很累。真正八卦写的好的人(不是到处引用,而是有一手八卦),需要长期的社交达人式的积累。不然哪里来那么多八卦。花总写朝鲜,那是肉身前往的。

我的朋友林军,曾经立志要写互联网八卦史,他有一个一万小时采访计划,就是找各种互联网公司的关键人物侃大山,但说好要录音在先——我表示被他访谈过。后来这个事他没坚持一万小时,但手上的积累,足以让他成书一本:沸腾十五年。

我没这耐心。

第二个是八卦写得好,就是流量大号,看的人很多,但和鄙人定位不符。鄙人总是定位成所谓专家型,不是媒体人型。走的是观点输出套路,而不是事实输出套路(八卦也是事实嘛)。

但好八卦的确能起量。

故而,以后,本号的八卦还会努力写几篇,但会少很多,我也没那么多一手八卦。

什么一气写三篇八卦,这种事以后应该不会有了。

 

八卦起量,比较好的生存方式是流量换广告(或者什么软文),卖的是告知力。

一般类型的八卦比较难做直接收费。

但高端八卦,或者叫硬新闻,可以尝试收费了。

硬新闻的需求受众不会太广,因为大多数人看看是个什么事外加一些花边,就够了。想要高清楚到底怎么回事怎么个来龙去脉,是一小部分人的需求。

财新那个一年498的财新通,卖的就是相当高端的。。。好吧。。。硬新闻。

在一个声贝超过70的喧嚣地带,财新记者小吴(我认识她很多年,今年才晓得她到底还是姓吴,不是什么稀奇古怪的一个复姓)声嘶力竭地不遗余力地向我推荐一个收费内容:wenews。

按照她的说法,这是财新旗下一个高端金融八卦。

小吴向我推荐的时候,给了我一个二维码,我扫码付钱,她是有分成的。据她说,我再去卖几个我购买的成本就可以捞回来。

我到现在也没搞清楚怎么弄到我这个微商码,我也忘记一年要多少钱了,诸位自己搜wenews吧。

高端金融八卦哦。

财新出品哦,这八卦值得信赖哟。

但我心里是认为,这货,应该免费啊。哈哈哈。纯属心疼自己的银子。

 

—— 首发 扯氮集 ——

作者执教于上海交通大学媒体与传播学院,天奇阿米巴创投基金管理合伙人

最近有个体悟,想和大家分享一下最先出现在扯氮集

]]>

这是我最近四篇公号文章的阅读量。

对于我这样粉丝不超过6万的足底号来说,这样的阅读量,其实可以满意。

这四篇文章,有两个套路。

第一个套路,我曾经在过去的文章里提到过,diss一种观念。具体到这篇文章,就是diss一种现象。

的确,《大学,难道不应该禁止师生恋吗》是用沈阳事件破题的,但讨论的却是师生恋。这里的摆渡,存在一个漏洞:沈阳事件不一定就是师生恋,有可能就是强奸。但这个漏洞,从我文章的反馈来看,应该说,没人注意到。

diss一种现象,符合《我今天想到一个起量的写作技巧》中的套路。

第二个套路,各位可以非常明晰地看到,我写了三篇八卦,有一位好友甚至留言说,本号要转做人物八卦了。

《一个猛人退休了》,是浙报前一把手高海浩的八卦。文头文尾的细节,还被大号小小引(xi)用(gao)了。

《王晓峰这个人》,是摩拜CEO王晓峰的八卦。

《梨视频喜提6亿巨资》,是梨视频邱兵的八卦。

如果我改成:高海浩时代浙报媒体融合之路、摩拜为什么选择投入美团、梨视频的短视频商业打法,诸如此类,老实讲,我写得累死,可看性也一点木有吧?:)

我甚至在《一个猛人退休了》中,故意神秘兮兮地用了很多字母来替代人(并不是什么敏感非要这么干,纯属故作神秘),大大增加了八卦的玄妙感。

对本号来说,此篇八卦访问量很高,超越了我历史上写赵何娟的八卦——那篇文章还是踩在风口上写的,当时钛媒体报道赛龙公司一事成为舆论热点——关于这件事我也反思过,我当时的标题是《我所认识的钛媒体》,如果改成《我所认识的赵何娟》,大概访问量还多个一两成吧。

 

昨天和人吃饭,聊起最近很火的三和大神,这是一组系列文章,公号是故事硬核。

聊的话题是严肃内容该如何生存。

聊着聊着,我发现一个事实:这个世界,并没有什么真正所谓严肃的事。

如果你用一种很通俗的写法,那就叫八卦。

如果你非要端着用一种比较有逼格的写法,那就叫新闻,逼格更高一点,就叫硬新闻。

只有严肃或不严肃的方法,并不存在什么严肃的事或者不严肃的事。

三和那帮人的生存状态,还不够三俗的。

 

昨儿腾讯大家头条文章,就是把一件很不严肃的事写出了很严肃的感觉,

看看标题各位就应该懂了:春情抄——日系桃色电影兴衰考。这个标题,是不是有一种荷尔蒙在呼喊你点击下去的感觉。

非把爱情动作片搞成什么日系桃色电影,还“春情抄”(我估计作者肯定上了年纪,看过山口百惠演的<春琴抄>,那是爱情但木有动作的片子)。行业八卦非说成兴衰,还“考”。

这个逼装的,必须给满分。

顺便说一句,这文章的作者竟然不是阑夕,我个人表示惊讶。

八卦并不是说不加以考证——不加考证的叫流言——它只是写法上,有些三俗,有些所谓的窥私感。

写三和大神,我视野中最早的一个公号是我朋友花总,他那个公号上第一篇就是写他混迹在三和大神中的事。

他把预览版给我看过,我当时第一个反应其实没和他说:这文章一点都不好看。第二个反应和他说了:被删的可能性很大。果不其然。

花总写装逼指南大概写惯了,写得非常让人不好懂。他以前那个装逼指南也是这样,你要是不太了解咖啡行业,你压根就很难看懂他对喝咖啡装逼到底是怎么装的。但花总的装逼指南,写法还是很轻松的,不懂也可以看个乐呵。三和那篇,真得好生沉闷。

被删再加上不太好理解,花总那个号第一篇没打响。

大概吸取了经验教训,最近那个号连续几篇讲北朝鲜的八卦,就好看多了。

所以,八卦其实不好写的。

不要看不起八卦。

 

八卦对于我来说,有两个缺点。

第一是写起来其实很累。真正八卦写的好的人(不是到处引用,而是有一手八卦),需要长期的社交达人式的积累。不然哪里来那么多八卦。花总写朝鲜,那是肉身前往的。

我的朋友林军,曾经立志要写互联网八卦史,他有一个一万小时采访计划,就是找各种互联网公司的关键人物侃大山,但说好要录音在先——我表示被他访谈过。后来这个事他没坚持一万小时,但手上的积累,足以让他成书一本:沸腾十五年。

我没这耐心。

第二个是八卦写得好,就是流量大号,看的人很多,但和鄙人定位不符。鄙人总是定位成所谓专家型,不是媒体人型。走的是观点输出套路,而不是事实输出套路(八卦也是事实嘛)。

但好八卦的确能起量。

故而,以后,本号的八卦还会努力写几篇,但会少很多,我也没那么多一手八卦。

什么一气写三篇八卦,这种事以后应该不会有了。

 

八卦起量,比较好的生存方式是流量换广告(或者什么软文),卖的是告知力。

一般类型的八卦比较难做直接收费。

但高端八卦,或者叫硬新闻,可以尝试收费了。

硬新闻的需求受众不会太广,因为大多数人看看是个什么事外加一些花边,就够了。想要高清楚到底怎么回事怎么个来龙去脉,是一小部分人的需求。

财新那个一年498的财新通,卖的就是相当高端的。。。好吧。。。硬新闻。

在一个声贝超过70的喧嚣地带,财新记者小吴(我认识她很多年,今年才晓得她到底还是姓吴,不是什么稀奇古怪的一个复姓)声嘶力竭地不遗余力地向我推荐一个收费内容:wenews。

按照她的说法,这是财新旗下一个高端金融八卦。

小吴向我推荐的时候,给了我一个二维码,我扫码付钱,她是有分成的。据她说,我再去卖几个我购买的成本就可以捞回来。

我到现在也没搞清楚怎么弄到我这个微商码,我也忘记一年要多少钱了,诸位自己搜wenews吧。

高端金融八卦哦。

财新出品哦,这八卦值得信赖哟。

但我心里是认为,这货,应该免费啊。哈哈哈。纯属心疼自己的银子。

 

—— 首发 扯氮集 ——

作者执教于上海交通大学媒体与传播学院,天奇阿米巴创投基金管理合伙人

最近有个体悟,想和大家分享一下最先出现在扯氮集

]]>
0
<![CDATA[离开舒适区]]> http://www.udpwork.com/item/16805.html http://www.udpwork.com/item/16805.html#reviews Mon, 23 Apr 2018 08:00:00 +0800 李忠 http://www.udpwork.com/item/16805.html 什么是舒适区

简单来说就是待着很舒服的一个区域。不会有太大的压力,做的事情也没什么挑战,从大脑层面来说就是不太需要前额叶皮层的参与,通过基底核(自动处理系统)就能搞定大部分事情。

这些还是偏感性层面,后来看到王兴的一句话,觉得可以比较好的形容这种状态:

如果我一整天都没看到、想到、或做过什么值得在饭否上说的事,那这一天就太浑浑噩噩了。

一直待在舒适区有什么问题么?

停留在舒适区并没有什么问题,甚至是一件必要的事。就像爬山爬累了,需要找个地方歇一歇,看看风景,聊聊天,恢复精力,但不宜长时间停留。

这是知乎上的一个回答

有一种类人猿,他们比我们的人类祖先有更多的先天优势,比如有很结实的牙齿足以去消化一些纤维很粗的球茎植物,所以他们可以不用去到处进行一些危险的觅食活动,满足于一直靠啃食球状食物为生,而我们的祖先没有这些先天的优势,只能不断进行一些危险的冒险尝试,比如偷袭食肉性猛兽,和它们搏斗,常常因此而丢掉自己的性命,但是我们的祖先从未停止过这些冒险探索,从一次又一次的成功和失败中积累知识和经验,而那些相对于人类有更多先天优势的旁系类人猿一直未作其他尝试都是以球茎植物为生,地球上的环境变化了,球状植物大量减少,所以最后这种类人猿物种由于找不到充足的食物而逐渐消失,最后走到今天的是本来先天条件并不占优势的人类,并且发展壮大了起来。

一直待在舒适区其实就是处于一个不变性系统,这个系统可能就当前来看运行地还不错,但它不具有「反脆弱性」。所谓反脆弱性系统是指那些能够在波动性、随机性、混乱、压力状态下生存下来并且成长的系统。蜡烛的反脆弱性就较低,一股风或几滴水就可能把它浇灭,而火则能够抵抗更大强度的水,甚至能借风成长。

现实世界充满了变数,尤其是科技的参与,加速了进化的脚步。由于骨针的发明,兽皮可以被缝制为衣服,体毛就被「进化」掉了。在集装箱出现之前,码头的工人可以通过贩卖劳动力来换取相应的报酬,集装箱出现之后,这些劳动力就不需要了,尽管他们也抗争过,但毕竟改变不了趋势。科技跟人类的进化一直交织在一起,随着互联网、手机、AI、机器人的出现,它越来越成为了那个「看不见的手」。

同时,科技还有另一种玩法,通过满足短期快感,来形成上瘾性依赖。Rick and Morty 里有一个场景,不断给 Rick 播放一些温馨的画面,然后通过这个过程中产生的物质作为添加剂来制作威化饼干,是不是某些 App 有点像。

「物竞天择,适者生存」的基本规律一直在运行着,而科技大大地加速了这个过程。

为什么会长时间停留在舒适区?

我觉得主要有 3 个原因:

  1. 惯性。
  2. 对未知的恐惧。
  3. 不知道去哪里。

惯性

惯性是很强大的力量,用得最顺手的东西就有更高的使用可能,比如思考或做事方式,甚至对于外人看来不理想的生活也能非常适应。这是一把双刃剑,提高效率的同时,也容易形成定势,「自省」可以帮助意识到这点。

对未知的恐惧

人类最古老而强烈的情绪,便是恐惧;而最古老最强烈的恐惧,便是对未知的恐惧。

— Howard Phillips Lovecraft

未知就意味着风险,而大多数人对于风险总是采取回避的策略。可是细想一下,如果生活中充满了确定性,那乐趣何在?

其实可以考虑下 EV,也就是期望值。有 20% 做成的可能性,因此带来的价值是 100,和 100% 的成功率,但价值是 5,哪个更可取?

陌生度越高,风险也就越大,借一笔钱给陌生人和给朋友,承受的风险是不一样的。这里貌似陷入了一个悖论:只有真正地去做某件事才能加深对它的了解,但如果对它不够了解,就有可能选择不做了。互联网出现后,这种尝试成本其实已经很低了,需要的资料网上一搜便有,有了一定的了解,这种恐惧感就会慢慢降低。

不知道去哪里

可能是有限的信息源导致的狭窄的可选项,或者是心理偏见排除了不少潜在的可选项。合适的选项应该是自己的特点和跟这些特点匹配的行业的交集。这里难的是客观地认识自己。

离开舒适区可能收获什么

痛苦

第一个收获很可能是痛苦。

There are two kinds of pain. The sort of pain that makes you strong, or useless pain. The sort of pain that’s only suffering.

这是纸牌屋里的一段台词,哪种痛苦属于「only suffering」呢,我觉得是「未经反思的痛苦」。就像我们会 review 线上故障,找到系统中存在的问题,来避免下次再犯。不反思,就很有可能同样的痛苦一再出现。

生存率

其次是提升生存率,在自然选择这个游戏中的生存率。在打怪升级过程中积累的技能对于应对变化的环境大有裨益。

避免无聊

还有一些人,他们已经拥有了足够的自由度和应变能力,那么跳出舒适圈最大的收获可能是「避免无聊」。毕竟物质匮乏和精神无聊是人类的两大痛苦根源。

如何离开舒适区

以「做自我介绍」为例,我相信不少人是不太习惯在众人面前做自我介绍的,对于他们来说这就是一个离开舒适区的行为。我觉得可以从三个层面进行分解。

基础(动力+压力)

这个是回答为什么要离开舒适区,比如为什么要做好自我介绍。需要有合适的动力和压力。

通常我们不愿做好某件事,往往是缺少了压力或动力。从动力角度来讲,可能是台下坐着你喜欢的小姐姐,从压力角度,可以是领导正看着呢。

这两种力的力度要合适,压力过大容易焦虑,动力过大容易翻车。

信念(总能找到一条路+熟能生巧)

信念可以帮助我们迈出那一步,比如创业,有时动力和压力都有了,但还是不敢。这时总得信一点什么,最好是经过自己验证同时对于离开舒适圈有帮助的。我相信的两条是:总能找到一条路以及熟能生巧。

对于陌生的事情,只要勤加练习,找到诀窍,至少不会做得太差,顶多比别人多花点时间。

有一个大概的创业想法,但不确定合不合适,一些细节也不知道该如何处理,那就继续想,找人聊,总能找到突破口。上天不会给一个你解决不了的问题的。

做事(反馈循环 + 进化)

在反馈循环中不断地进化,最核心的是快速进化的能力。Airbnb 的创始人最开始只是因为付不起房租,决定出租房间里的 3 张气垫床。有客户上门之后,发现将房间出租这个 idea 有搞头,接下来不断进化,就成了现在的这个巨头了。

这种反馈可以是来自自己,比如掌握了某个知识点,也可以是来自外部。很少有想法一开始就完美,也很难一开始就把某件事做到满意,这并不重要。上线运行起来,收集用户的反馈,然后做出调整,可能就找到了一条之前根本没想过的路子。

成果检验

通常自己能感受到那种成长,如果要客观来看的话,「特定领域的不可替代性」或许是个不错的衡量方式。要么拓宽了特定领域(更多的可选项),或者提升了不可替代性。

]]>
什么是舒适区

简单来说就是待着很舒服的一个区域。不会有太大的压力,做的事情也没什么挑战,从大脑层面来说就是不太需要前额叶皮层的参与,通过基底核(自动处理系统)就能搞定大部分事情。

这些还是偏感性层面,后来看到王兴的一句话,觉得可以比较好的形容这种状态:

如果我一整天都没看到、想到、或做过什么值得在饭否上说的事,那这一天就太浑浑噩噩了。

一直待在舒适区有什么问题么?

停留在舒适区并没有什么问题,甚至是一件必要的事。就像爬山爬累了,需要找个地方歇一歇,看看风景,聊聊天,恢复精力,但不宜长时间停留。

这是知乎上的一个回答

有一种类人猿,他们比我们的人类祖先有更多的先天优势,比如有很结实的牙齿足以去消化一些纤维很粗的球茎植物,所以他们可以不用去到处进行一些危险的觅食活动,满足于一直靠啃食球状食物为生,而我们的祖先没有这些先天的优势,只能不断进行一些危险的冒险尝试,比如偷袭食肉性猛兽,和它们搏斗,常常因此而丢掉自己的性命,但是我们的祖先从未停止过这些冒险探索,从一次又一次的成功和失败中积累知识和经验,而那些相对于人类有更多先天优势的旁系类人猿一直未作其他尝试都是以球茎植物为生,地球上的环境变化了,球状植物大量减少,所以最后这种类人猿物种由于找不到充足的食物而逐渐消失,最后走到今天的是本来先天条件并不占优势的人类,并且发展壮大了起来。

一直待在舒适区其实就是处于一个不变性系统,这个系统可能就当前来看运行地还不错,但它不具有「反脆弱性」。所谓反脆弱性系统是指那些能够在波动性、随机性、混乱、压力状态下生存下来并且成长的系统。蜡烛的反脆弱性就较低,一股风或几滴水就可能把它浇灭,而火则能够抵抗更大强度的水,甚至能借风成长。

现实世界充满了变数,尤其是科技的参与,加速了进化的脚步。由于骨针的发明,兽皮可以被缝制为衣服,体毛就被「进化」掉了。在集装箱出现之前,码头的工人可以通过贩卖劳动力来换取相应的报酬,集装箱出现之后,这些劳动力就不需要了,尽管他们也抗争过,但毕竟改变不了趋势。科技跟人类的进化一直交织在一起,随着互联网、手机、AI、机器人的出现,它越来越成为了那个「看不见的手」。

同时,科技还有另一种玩法,通过满足短期快感,来形成上瘾性依赖。Rick and Morty 里有一个场景,不断给 Rick 播放一些温馨的画面,然后通过这个过程中产生的物质作为添加剂来制作威化饼干,是不是某些 App 有点像。

「物竞天择,适者生存」的基本规律一直在运行着,而科技大大地加速了这个过程。

为什么会长时间停留在舒适区?

我觉得主要有 3 个原因:

  1. 惯性。
  2. 对未知的恐惧。
  3. 不知道去哪里。

惯性

惯性是很强大的力量,用得最顺手的东西就有更高的使用可能,比如思考或做事方式,甚至对于外人看来不理想的生活也能非常适应。这是一把双刃剑,提高效率的同时,也容易形成定势,「自省」可以帮助意识到这点。

对未知的恐惧

人类最古老而强烈的情绪,便是恐惧;而最古老最强烈的恐惧,便是对未知的恐惧。

— Howard Phillips Lovecraft

未知就意味着风险,而大多数人对于风险总是采取回避的策略。可是细想一下,如果生活中充满了确定性,那乐趣何在?

其实可以考虑下 EV,也就是期望值。有 20% 做成的可能性,因此带来的价值是 100,和 100% 的成功率,但价值是 5,哪个更可取?

陌生度越高,风险也就越大,借一笔钱给陌生人和给朋友,承受的风险是不一样的。这里貌似陷入了一个悖论:只有真正地去做某件事才能加深对它的了解,但如果对它不够了解,就有可能选择不做了。互联网出现后,这种尝试成本其实已经很低了,需要的资料网上一搜便有,有了一定的了解,这种恐惧感就会慢慢降低。

不知道去哪里

可能是有限的信息源导致的狭窄的可选项,或者是心理偏见排除了不少潜在的可选项。合适的选项应该是自己的特点和跟这些特点匹配的行业的交集。这里难的是客观地认识自己。

离开舒适区可能收获什么

痛苦

第一个收获很可能是痛苦。

There are two kinds of pain. The sort of pain that makes you strong, or useless pain. The sort of pain that’s only suffering.

这是纸牌屋里的一段台词,哪种痛苦属于「only suffering」呢,我觉得是「未经反思的痛苦」。就像我们会 review 线上故障,找到系统中存在的问题,来避免下次再犯。不反思,就很有可能同样的痛苦一再出现。

生存率

其次是提升生存率,在自然选择这个游戏中的生存率。在打怪升级过程中积累的技能对于应对变化的环境大有裨益。

避免无聊

还有一些人,他们已经拥有了足够的自由度和应变能力,那么跳出舒适圈最大的收获可能是「避免无聊」。毕竟物质匮乏和精神无聊是人类的两大痛苦根源。

如何离开舒适区

以「做自我介绍」为例,我相信不少人是不太习惯在众人面前做自我介绍的,对于他们来说这就是一个离开舒适区的行为。我觉得可以从三个层面进行分解。

基础(动力+压力)

这个是回答为什么要离开舒适区,比如为什么要做好自我介绍。需要有合适的动力和压力。

通常我们不愿做好某件事,往往是缺少了压力或动力。从动力角度来讲,可能是台下坐着你喜欢的小姐姐,从压力角度,可以是领导正看着呢。

这两种力的力度要合适,压力过大容易焦虑,动力过大容易翻车。

信念(总能找到一条路+熟能生巧)

信念可以帮助我们迈出那一步,比如创业,有时动力和压力都有了,但还是不敢。这时总得信一点什么,最好是经过自己验证同时对于离开舒适圈有帮助的。我相信的两条是:总能找到一条路以及熟能生巧。

对于陌生的事情,只要勤加练习,找到诀窍,至少不会做得太差,顶多比别人多花点时间。

有一个大概的创业想法,但不确定合不合适,一些细节也不知道该如何处理,那就继续想,找人聊,总能找到突破口。上天不会给一个你解决不了的问题的。

做事(反馈循环 + 进化)

在反馈循环中不断地进化,最核心的是快速进化的能力。Airbnb 的创始人最开始只是因为付不起房租,决定出租房间里的 3 张气垫床。有客户上门之后,发现将房间出租这个 idea 有搞头,接下来不断进化,就成了现在的这个巨头了。

这种反馈可以是来自自己,比如掌握了某个知识点,也可以是来自外部。很少有想法一开始就完美,也很难一开始就把某件事做到满意,这并不重要。上线运行起来,收集用户的反馈,然后做出调整,可能就找到了一条之前根本没想过的路子。

成果检验

通常自己能感受到那种成长,如果要客观来看的话,「特定领域的不可替代性」或许是个不错的衡量方式。要么拓宽了特定领域(更多的可选项),或者提升了不可替代性。

]]>
0
<![CDATA[如何把 Blogger 文章导入到 Facebook Instant Article]]> http://www.udpwork.com/item/16802.html http://www.udpwork.com/item/16802.html#reviews Mon, 23 Apr 2018 07:01:34 +0800 Cat Chen http://www.udpwork.com/item/16802.html Facebook Instant Article in Pages Manager

如果你跟我一样还在用 Blogger 这么远古的工具来写博客,同时又想追赶一下 Facebook Instant Article 的潮流,那你可以跟着我这篇文章做一遍来把 Blogger 的文章导入到 Instant Article。

启用 Instant Article

假设你跟我一样已经有一个在用的 Blogger 博客了,你不需要在 Blogger 上做什么改动,直接开始注册 Instant Article 就可以了。打开Facebook Instant Article的入口页面,然后点击注册。Facebook 会问你要为哪个 Page 启用 Instant Article,你选一个就是了。我用Cat Chen Posts这个页面来导出我所有的 Blogger 文章,所以我就选择了这个 Page。如果你还没有 Page 的话,可以先创建一个,因为没有 Page 是不能创建 Instant Article 的。但只要在 Page 上把一篇文章转化为 Instant Article 了,之后在个人帐号分享这篇文章的链接也会显示为 Instant Article。

关联域名

接下来你需要跟随 Facebook Instant Article 的配置工具来一步一步完成配置。首先,你要把自己的 BlogSpot 网站关联到你的 Page 下面来。Facebook 会让你把这样一行加到你的 BlogSpot 模板上:

<meta property="fb:pages" content="{page-id}" />

每一个具体 Page 的{page-id}都不一样,你复制粘贴 Facebook 配置工具上显示的那一行就可以了。把这一行复制下来后,你可以去 Blogger 里配置 Theme,选择修改 HTML,然后把这一行贴到<head>...</head>里面。之后把你 BlogSpot 的域名填到 Facebook 配置工具里去,Facebook 就会抓取你 BlogSpot 的首页并且进行验证。(如果你之前在 Google Webmasters 之类的服务做过类似的域名认证操作,这一步应该很容易。)

导入 RSS

接下来要把 Blogger 的 RSS 导入到 Facebook。如果你的 RSS 没有搞过什么花样,这是非常简单的事情。但如果你像我一样在 RSS 上做过各种优化,那这一步可以很复杂。

FeedBurner

如果你像我一样启用了 FeedBurner,你会发现 FeedBurner 导出的 RSS 可能是 Facebook 不愿意接受的格式,因为 FeedBurner 的优化加了太多东西进去。(但如果不加任何优化的话,Facebook 是可以接受的。)你可以使用 BlogSpot 自带的 feed,但既然你用了 FeedBurner 你很可能跟我一样让 BlogSpot 把自带的 feed 重定向到 FeedBurner,这时候如何才能获取到 BlogSpot 自带的 feed 呢?关键在于 querystring。以我自己的 feed 为例:

http://chinese.catchen.me/feeds/posts/default?alt=rss&redirect=false

加上?alt=rss会强制输出符合 Facebook 期望的 RSS 格式。加上?redirect=false或禁用 FeedBurner 重定向。两者都用上,就能让 Facebook 得到一个它能够解析和接受的 RSS。

合并多个 RSS

我用有多个 Blogger,因此我有多个 RSS 但 Facebook 只接受一个,这怎么办呢?这个问题可以用RSS Mix解决。把多个 RSS 的地址输入进去,它会生成一个 RSS,然后把这个合并后的 RSS 给 Facebook 就可以了。

提交审核

搞掂 RSS 后,就可以把 RSS 地址交给 Facebook 了。直接填进去 Production RSS Feed 是没问题的,将来要测试新版本的 RSS 可以用 Development RSS Feed。如果 RSS 里面已经有至少 10 篇文章,那就可以提交审核了,否则还需要写满 10 篇文章才能提交审核。

我把博客提交审核时没有遇到任何问题,但因为审核这个事情因人而异所以很难说你会不会遇到什么问题。如果遇到问题的话可以根据 Facebook 的提示进行修改。审核一旦通过了,你就可以把 Production RSS Feed 里面的内容发布为 Instant Article 了。

发布 Instant Article

尽管 Facebook 从 RSS 中读取了文章,但并不会自动把 Instant Article 发出去。你需要去 Production Articles 里面查看 RSS 导入了的文章,然后把你想要发布的发布出去,不发布的话它们会当作草稿一直存着。

在发布之前,你可能会看到某些文章标题旁边有个感叹号,那意味着 Facebook 在解析这篇文章时遇到了问题,不解决这些问题这篇文章就无法被发布出去。这时候你需要做的事情就是编辑文章 HTML,然后把问题都解决掉。具体哪些问题会出现,要看你在 Blogger 中使用的 HTML 有多复杂。尽管 Facebook 使用的 Instant Article 格式也是 HTML,但其实只是一个 HTML 子集,如果你使用的 HTML 超出了这个子集 Facebook 就会尝试进行调整,如果调整后还是有问题你就会看到那个感叹号。

我最常遇到的问题是图片嵌入在段落内。Facebook Instant Article 规定图片必须放在<figure>...</figure>里面,如果你在写作时只是用了<img />,那 Facebook 就会尝试智能地在外面包一层<figure>...</figure>。但如果你原本的<img />是嵌套在<p>...</p>里面的话,那 Facebook 处理后就会变成了<p><figure><img /></figure></p>。由于 Instant Article 中的<p>...</p>和<figure>...</figure>是互斥的,只能是平级关系,不能互相嵌套,所以 Facebook 就会报错。(错误信息还很奇怪,Facebook 会告诉你元素内没有文本,但其实意思是<p>...</p>内不能嵌套<figure>...</figure>。)解决的办法很简单,把外面那层<p>...</p>去掉就可以了。

除了上述问题外,你还可能遇到其他跟 Instant Article HTML 子集不兼容的问题。Facebook 提供的错误信息不一定容易理解,但自行搜索一下总能找到答案。只要把问题都解决了,文章就能够当作 Instant Article 发布了。

测试 Instant Article 效果

最简单的测试方式是用 Facebook Pages Manager (iOS|Android)。在里面打开自己的 Page,如果看到文章下面有个 Instant Article 的闪电符号那意味着文章成功发布为 Instant Article 了。点击进去就能看到文章以 Instant Article 渲染的样子,如果跟自己想要的样子不一样可以回去继续修改 HTML。这篇文章开头的截图就是来自 Facebook Pages Manager,里面显示的是我之前一篇文章的 Instant Article 版本。

]]>
Facebook Instant Article in Pages Manager

如果你跟我一样还在用 Blogger 这么远古的工具来写博客,同时又想追赶一下 Facebook Instant Article 的潮流,那你可以跟着我这篇文章做一遍来把 Blogger 的文章导入到 Instant Article。

启用 Instant Article

假设你跟我一样已经有一个在用的 Blogger 博客了,你不需要在 Blogger 上做什么改动,直接开始注册 Instant Article 就可以了。打开Facebook Instant Article的入口页面,然后点击注册。Facebook 会问你要为哪个 Page 启用 Instant Article,你选一个就是了。我用Cat Chen Posts这个页面来导出我所有的 Blogger 文章,所以我就选择了这个 Page。如果你还没有 Page 的话,可以先创建一个,因为没有 Page 是不能创建 Instant Article 的。但只要在 Page 上把一篇文章转化为 Instant Article 了,之后在个人帐号分享这篇文章的链接也会显示为 Instant Article。

关联域名

接下来你需要跟随 Facebook Instant Article 的配置工具来一步一步完成配置。首先,你要把自己的 BlogSpot 网站关联到你的 Page 下面来。Facebook 会让你把这样一行加到你的 BlogSpot 模板上:

<meta property="fb:pages" content="{page-id}" />

每一个具体 Page 的{page-id}都不一样,你复制粘贴 Facebook 配置工具上显示的那一行就可以了。把这一行复制下来后,你可以去 Blogger 里配置 Theme,选择修改 HTML,然后把这一行贴到<head>...</head>里面。之后把你 BlogSpot 的域名填到 Facebook 配置工具里去,Facebook 就会抓取你 BlogSpot 的首页并且进行验证。(如果你之前在 Google Webmasters 之类的服务做过类似的域名认证操作,这一步应该很容易。)

导入 RSS

接下来要把 Blogger 的 RSS 导入到 Facebook。如果你的 RSS 没有搞过什么花样,这是非常简单的事情。但如果你像我一样在 RSS 上做过各种优化,那这一步可以很复杂。

FeedBurner

如果你像我一样启用了 FeedBurner,你会发现 FeedBurner 导出的 RSS 可能是 Facebook 不愿意接受的格式,因为 FeedBurner 的优化加了太多东西进去。(但如果不加任何优化的话,Facebook 是可以接受的。)你可以使用 BlogSpot 自带的 feed,但既然你用了 FeedBurner 你很可能跟我一样让 BlogSpot 把自带的 feed 重定向到 FeedBurner,这时候如何才能获取到 BlogSpot 自带的 feed 呢?关键在于 querystring。以我自己的 feed 为例:

http://chinese.catchen.me/feeds/posts/default?alt=rss&redirect=false

加上?alt=rss会强制输出符合 Facebook 期望的 RSS 格式。加上?redirect=false或禁用 FeedBurner 重定向。两者都用上,就能让 Facebook 得到一个它能够解析和接受的 RSS。

合并多个 RSS

我用有多个 Blogger,因此我有多个 RSS 但 Facebook 只接受一个,这怎么办呢?这个问题可以用RSS Mix解决。把多个 RSS 的地址输入进去,它会生成一个 RSS,然后把这个合并后的 RSS 给 Facebook 就可以了。

提交审核

搞掂 RSS 后,就可以把 RSS 地址交给 Facebook 了。直接填进去 Production RSS Feed 是没问题的,将来要测试新版本的 RSS 可以用 Development RSS Feed。如果 RSS 里面已经有至少 10 篇文章,那就可以提交审核了,否则还需要写满 10 篇文章才能提交审核。

我把博客提交审核时没有遇到任何问题,但因为审核这个事情因人而异所以很难说你会不会遇到什么问题。如果遇到问题的话可以根据 Facebook 的提示进行修改。审核一旦通过了,你就可以把 Production RSS Feed 里面的内容发布为 Instant Article 了。

发布 Instant Article

尽管 Facebook 从 RSS 中读取了文章,但并不会自动把 Instant Article 发出去。你需要去 Production Articles 里面查看 RSS 导入了的文章,然后把你想要发布的发布出去,不发布的话它们会当作草稿一直存着。

在发布之前,你可能会看到某些文章标题旁边有个感叹号,那意味着 Facebook 在解析这篇文章时遇到了问题,不解决这些问题这篇文章就无法被发布出去。这时候你需要做的事情就是编辑文章 HTML,然后把问题都解决掉。具体哪些问题会出现,要看你在 Blogger 中使用的 HTML 有多复杂。尽管 Facebook 使用的 Instant Article 格式也是 HTML,但其实只是一个 HTML 子集,如果你使用的 HTML 超出了这个子集 Facebook 就会尝试进行调整,如果调整后还是有问题你就会看到那个感叹号。

我最常遇到的问题是图片嵌入在段落内。Facebook Instant Article 规定图片必须放在<figure>...</figure>里面,如果你在写作时只是用了<img />,那 Facebook 就会尝试智能地在外面包一层<figure>...</figure>。但如果你原本的<img />是嵌套在<p>...</p>里面的话,那 Facebook 处理后就会变成了<p><figure><img /></figure></p>。由于 Instant Article 中的<p>...</p>和<figure>...</figure>是互斥的,只能是平级关系,不能互相嵌套,所以 Facebook 就会报错。(错误信息还很奇怪,Facebook 会告诉你元素内没有文本,但其实意思是<p>...</p>内不能嵌套<figure>...</figure>。)解决的办法很简单,把外面那层<p>...</p>去掉就可以了。

除了上述问题外,你还可能遇到其他跟 Instant Article HTML 子集不兼容的问题。Facebook 提供的错误信息不一定容易理解,但自行搜索一下总能找到答案。只要把问题都解决了,文章就能够当作 Instant Article 发布了。

测试 Instant Article 效果

最简单的测试方式是用 Facebook Pages Manager (iOS|Android)。在里面打开自己的 Page,如果看到文章下面有个 Instant Article 的闪电符号那意味着文章成功发布为 Instant Article 了。点击进去就能看到文章以 Instant Article 渲染的样子,如果跟自己想要的样子不一样可以回去继续修改 HTML。这篇文章开头的截图就是来自 Facebook Pages Manager,里面显示的是我之前一篇文章的 Instant Article 版本。

]]>
0
<![CDATA[每周分享第 1 期]]> http://www.udpwork.com/item/16801.html http://www.udpwork.com/item/16801.html#reviews Sun, 22 Apr 2018 23:14:57 +0800 阮一峰 http://www.udpwork.com/item/16801.html 这里记录过去一周,我看到的值得分享的东西。

长久以来,我一直用各种方式,尝试整理我的收藏夹。最近想到,把它写成文章,共享出来,也许效果更好。

语雀

语雀(yuque.com)是阿里巴巴集团内部最大的文档平台,也是阿里系知识管理和团队协作的主要工具之一。

今天(4月23日)是世界读书日,语雀选在今天放开注册,不再需要邀请码,用户可以直接注册,跟阿里的正式员工一样使用所有功能。

为了配合世界读书日,语雀还邀请了一些互联网知名人士,写下他们的推荐书单,比如蚂蚁金服 CTO 的程立

新闻

1、InstagramTwitter限制第三方调用 API

4月4日,Instagram 无预警地宣布,立即废止一大批API,像用户的 follower、like 等数据都无法再拿到了。同时宣布,每个用户的每小时 API 请求数量限制,从 5000 降低为 200。另外,还计划从2018年12月11日起,不再允许第三方 App 获取它的公开内容。

稍早,Twitter 也宣布,2018年6月19日之后,将不再提供 streaming services,这意味着第三方客户端 Tweetbot、Tweetings、Twitterrific 将无法自动刷新时间轴,必须用户自己手动刷新,才能看到新内容。有人做了一个网站apps-of-a-feather.com呼吁 Twitter 改变这个决定。

这些大型社交媒体想要表达的意思已经很清楚了:我们不欢迎第三方客户端。

2、程序员月薪 7 万可落户北京

3月21日,北京市发布《关于优化人才服务促进科技创新推动高精尖产业发展的若干措施》,其中有这样一条内容:

在本市行政区域内的高新技术企业、创新型总部企业、新型研发机构等科技创新主体中承担重要工作,近3年每年应税收入超过上一年度全市职工平均工资一定倍数的(企业注册在城六区和北京经济技术开发区的为8倍,注册在本市其他区域的为6倍)。

根据北京市统计局、市人力社保局发布数据,2016年度北京市职工年平均工资为92477元,月平均工资为7706元。而近日某招聘网站新鲜出炉的《2018旺季人才趋势报告》中显示,北京市平均月薪达到10712元。由此估算出月薪至少要 7 万可申请办理人才引进。

3、Travis-CI 的离奇错误清空生产数据库

Travis-CI 公布了3月13日生产数据库出错的调查报告。一个开发者执行了生产环境的检查以后,在同一个 Session 里面运行测试。由于数据库地址是环境变量给出的,这时 Session 里面的数据库地址的环境变量指向生产环境,导致测试脚本清空了生产环境的数据库。

4、硅谷房价每个工作日上涨800美元

根据统计,距离硅谷最近的大城市圣何塞,去年100万美元左右的普通房屋,每个工作日价格上涨798美元,一年上涨了20万美元,是全美房价上涨之冠。亚军是旧金山,每个工作日上涨481美元;季军是西雅图(微软总部所在地),上涨434美元。

教程

1、[免费电子书]《Machine Learning Yearning》,by 吴恩达

吴恩达(Andrew Ng)是斯坦福大学的教授,人工智能领域的权威,曾经担任过百度的首席科学家。

他的新书《Machine Learning Yearning》现在可以免费订阅。今后几个月里面,他每完成一个部分,你就会得到邮件通知,可以立即读到。根据说明,这本书大概100页左右,每章的长度很短,非常容易阅读。内容主要关于如何实现你自己的机器学习项目,重点不是算法,而是如何运用算法到真实项目。

2、[免费视频教程]《Foundations of Data Science》,by 加州大学伯克利分校

加州大学伯克利分校的视频课程《Foundations of Data Science》(数据科学基础),现在上网了。报名学习是免费的,如果需要证书才收费。

课程分成三个部分,每个部分需要5个星期学习,都由加大的老师亲自教授。整个课程针对初学者,不需要任何统计学或编程的基础。

3、[文章]Programming Blockchains Step-by-Step, by Gerald Bauer

介绍如何使用 Ruby 语言从零开始写一个区块链实现,代码非常好懂,并有各种基础概念的解释。

4、[文章]Low Level Bit Hacks You Absolutely Must Know, by Peter Krumins

位运算(bit operation)的用途,有很多例子。

5、[文章]React - Basic Theoretical Concepts

React 官方关于 React 原始设计思想的解释。

6、[图片]React v16.3 生命周期的示意图

7、[电子书]Google 面试自学手册

一份爱好者整理的 Google 面试准备指南。

8、[文章]Chrome DevTools 的一些使用技巧

9、[文章]Color: From Hexcodes to Eyeballs

人眼如何感受到色彩,读懂这篇文章需要一点物理学知识。

文摘

1、一线开发程序员总结出的开发经验,by 康亮

2011年在百度浏览器团队时遇到几件让人影响深刻的事情。 有一次开会,产品拿出 Google 某个产品的 DEMO,里面有一段很酷炫 3D 效果,要求开发加上,只给2天时间,大家目瞪口呆。后续的开发为了赶节奏,导致非常多的 bug,又为了修改 bug,leader 将所有的 bug 按照人员平均分配,导致不同模块间的同学相互修改......实在难以想象。好比让做花卷的厨子,去修改西湖醋鱼的味道。

最初的现象是:bug 下降得慢,延伸 bug 反而增加,每个人都累的半死,代码风格极其杂乱,为了赶工导致的临时方案层出不穷。

到了中期:人员离职越来也多,代码难以维护,新加的需求与之前的临时方案冲突。

到了后期:想做一些修复,想调整架构,又要保证正常运行,其难度好比在一架飞行的飞机上拆换零件。

然后我也急忙离职了。。。。实在看不到成功的可能性。

2、为什么我们不用 Git?,by SQLite

SQLite 不使用Git版本控制系统,而是使用Fossil。Fossil 和 Git 都是区块链式的版本控制系统,都是分布式,都将内容存储为由加密哈希标识的一系列不可变的提交。Git 非常流行,许多开发人员不熟悉其他任何版本管理工具。然而,SQLite 更喜欢Fossil,本文解释为什么。

3、美国的数据真相

美国人均预期寿命连续两年下降。如果不告诉你国家名字,只是让你猜测的话,你一定会认为,这发生在某个战乱中的国家。不幸的是,这种事情恰恰就发生在美国。

2016年,零资产或者负资产家庭已经达到30.4%。也就是说,只要你有一块钱存款而么有负债,即使你是个流浪汉,你也比30%的美国家庭富有。

美国人到底有多穷?69%的美国人,存款少于1000美元。好多人说美国人很富有,确实,如果你找到了一个好职业,你的收入会很高很高。但是实际上,绝大多数美国人很穷,只能靠救济和福利过活。一半的美国人,他们的年平均收入低于25000美元。美国平均收入40000多,中位数收入只有25000美元。中位数是什么意思?50%收入高于这个数字,50%收入低于这个数字。

4、《环球时报》:发展国产芯片 这事不能再拖了

从现在起,我们可以靠美国芯片活得很好的幻想应该破灭了。中国有组织科技攻关的能力,也有推动国产芯片逐渐替代外来芯片所需要的动员力,最重要的就是决心。

特朗普政府在帮助我们下这个决心。如果中国真的转换了思路,也许过多少年之后,我们会感谢美国今天做出的限制决定,庆幸它促使中国早一点恢复了清醒。

一旦中国加速研发使用国产芯片的工作全面上路,美国方面的态度也将随之软下来。美国半导体产品还可以进入中国,但到那时主动权将牢牢掌握在我们自己的手里。

工具

1、Spectrum

开源的社区软件,形式非常新颖美观。

2、jsonstore.io

通过 HTTP Header 读写 JSON 数据的免费 datastore。

3、flamebearer

Node 应用的火焰图生成工具,用于性能分析。

4、DNS Performance Test

DNS 响应时间的命令行比较脚本。

5、merge-images

多张图片合成一张图片的浏览器 JS 库,使用了 Canvas。

6、Tabler

一个基于 Bootstrap4 的面板(dashboard)组件库。

7、Etherpad

老牌的多人实时编辑协同工具。

新奇

1、Braille Neue

Braille Neue 是布里叶盲文系统与正常字母的结合,无障碍设计的典范,为什么没有人早点想到这个点子呢。

2、Macbook 一美元改成触摸屏

一个非常牛的项目,作者在 Macbook 的摄像头上面,架了一块镜子。然后,自动捕捉并识别手指的坐标。

3、Jelly Mario Bros

水母版的《超级马里奥》网页游戏,所有东西都会像水母一样升缩。

4、小狗 USB

本周金句

人生就像玻璃窗上的苍蝇,前途一片光明,却找不到出路。

欢迎订阅

这个专栏会同步更新在我的个人网站微信公众号语雀

微信搜索"阮一峰的网络日志 "或者扫描二维码,即可手机订阅。

(完)

文档信息

]]>
这里记录过去一周,我看到的值得分享的东西。

长久以来,我一直用各种方式,尝试整理我的收藏夹。最近想到,把它写成文章,共享出来,也许效果更好。

语雀

语雀(yuque.com)是阿里巴巴集团内部最大的文档平台,也是阿里系知识管理和团队协作的主要工具之一。

今天(4月23日)是世界读书日,语雀选在今天放开注册,不再需要邀请码,用户可以直接注册,跟阿里的正式员工一样使用所有功能。

为了配合世界读书日,语雀还邀请了一些互联网知名人士,写下他们的推荐书单,比如蚂蚁金服 CTO 的程立

新闻

1、InstagramTwitter限制第三方调用 API

4月4日,Instagram 无预警地宣布,立即废止一大批API,像用户的 follower、like 等数据都无法再拿到了。同时宣布,每个用户的每小时 API 请求数量限制,从 5000 降低为 200。另外,还计划从2018年12月11日起,不再允许第三方 App 获取它的公开内容。

稍早,Twitter 也宣布,2018年6月19日之后,将不再提供 streaming services,这意味着第三方客户端 Tweetbot、Tweetings、Twitterrific 将无法自动刷新时间轴,必须用户自己手动刷新,才能看到新内容。有人做了一个网站apps-of-a-feather.com呼吁 Twitter 改变这个决定。

这些大型社交媒体想要表达的意思已经很清楚了:我们不欢迎第三方客户端。

2、程序员月薪 7 万可落户北京

3月21日,北京市发布《关于优化人才服务促进科技创新推动高精尖产业发展的若干措施》,其中有这样一条内容:

在本市行政区域内的高新技术企业、创新型总部企业、新型研发机构等科技创新主体中承担重要工作,近3年每年应税收入超过上一年度全市职工平均工资一定倍数的(企业注册在城六区和北京经济技术开发区的为8倍,注册在本市其他区域的为6倍)。

根据北京市统计局、市人力社保局发布数据,2016年度北京市职工年平均工资为92477元,月平均工资为7706元。而近日某招聘网站新鲜出炉的《2018旺季人才趋势报告》中显示,北京市平均月薪达到10712元。由此估算出月薪至少要 7 万可申请办理人才引进。

3、Travis-CI 的离奇错误清空生产数据库

Travis-CI 公布了3月13日生产数据库出错的调查报告。一个开发者执行了生产环境的检查以后,在同一个 Session 里面运行测试。由于数据库地址是环境变量给出的,这时 Session 里面的数据库地址的环境变量指向生产环境,导致测试脚本清空了生产环境的数据库。

4、硅谷房价每个工作日上涨800美元

根据统计,距离硅谷最近的大城市圣何塞,去年100万美元左右的普通房屋,每个工作日价格上涨798美元,一年上涨了20万美元,是全美房价上涨之冠。亚军是旧金山,每个工作日上涨481美元;季军是西雅图(微软总部所在地),上涨434美元。

教程

1、[免费电子书]《Machine Learning Yearning》,by 吴恩达

吴恩达(Andrew Ng)是斯坦福大学的教授,人工智能领域的权威,曾经担任过百度的首席科学家。

他的新书《Machine Learning Yearning》现在可以免费订阅。今后几个月里面,他每完成一个部分,你就会得到邮件通知,可以立即读到。根据说明,这本书大概100页左右,每章的长度很短,非常容易阅读。内容主要关于如何实现你自己的机器学习项目,重点不是算法,而是如何运用算法到真实项目。

2、[免费视频教程]《Foundations of Data Science》,by 加州大学伯克利分校

加州大学伯克利分校的视频课程《Foundations of Data Science》(数据科学基础),现在上网了。报名学习是免费的,如果需要证书才收费。

课程分成三个部分,每个部分需要5个星期学习,都由加大的老师亲自教授。整个课程针对初学者,不需要任何统计学或编程的基础。

3、[文章]Programming Blockchains Step-by-Step, by Gerald Bauer

介绍如何使用 Ruby 语言从零开始写一个区块链实现,代码非常好懂,并有各种基础概念的解释。

4、[文章]Low Level Bit Hacks You Absolutely Must Know, by Peter Krumins

位运算(bit operation)的用途,有很多例子。

5、[文章]React - Basic Theoretical Concepts

React 官方关于 React 原始设计思想的解释。

6、[图片]React v16.3 生命周期的示意图

7、[电子书]Google 面试自学手册

一份爱好者整理的 Google 面试准备指南。

8、[文章]Chrome DevTools 的一些使用技巧

9、[文章]Color: From Hexcodes to Eyeballs

人眼如何感受到色彩,读懂这篇文章需要一点物理学知识。

文摘

1、一线开发程序员总结出的开发经验,by 康亮

2011年在百度浏览器团队时遇到几件让人影响深刻的事情。 有一次开会,产品拿出 Google 某个产品的 DEMO,里面有一段很酷炫 3D 效果,要求开发加上,只给2天时间,大家目瞪口呆。后续的开发为了赶节奏,导致非常多的 bug,又为了修改 bug,leader 将所有的 bug 按照人员平均分配,导致不同模块间的同学相互修改......实在难以想象。好比让做花卷的厨子,去修改西湖醋鱼的味道。

最初的现象是:bug 下降得慢,延伸 bug 反而增加,每个人都累的半死,代码风格极其杂乱,为了赶工导致的临时方案层出不穷。

到了中期:人员离职越来也多,代码难以维护,新加的需求与之前的临时方案冲突。

到了后期:想做一些修复,想调整架构,又要保证正常运行,其难度好比在一架飞行的飞机上拆换零件。

然后我也急忙离职了。。。。实在看不到成功的可能性。

2、为什么我们不用 Git?,by SQLite

SQLite 不使用Git版本控制系统,而是使用Fossil。Fossil 和 Git 都是区块链式的版本控制系统,都是分布式,都将内容存储为由加密哈希标识的一系列不可变的提交。Git 非常流行,许多开发人员不熟悉其他任何版本管理工具。然而,SQLite 更喜欢Fossil,本文解释为什么。

3、美国的数据真相

美国人均预期寿命连续两年下降。如果不告诉你国家名字,只是让你猜测的话,你一定会认为,这发生在某个战乱中的国家。不幸的是,这种事情恰恰就发生在美国。

2016年,零资产或者负资产家庭已经达到30.4%。也就是说,只要你有一块钱存款而么有负债,即使你是个流浪汉,你也比30%的美国家庭富有。

美国人到底有多穷?69%的美国人,存款少于1000美元。好多人说美国人很富有,确实,如果你找到了一个好职业,你的收入会很高很高。但是实际上,绝大多数美国人很穷,只能靠救济和福利过活。一半的美国人,他们的年平均收入低于25000美元。美国平均收入40000多,中位数收入只有25000美元。中位数是什么意思?50%收入高于这个数字,50%收入低于这个数字。

4、《环球时报》:发展国产芯片 这事不能再拖了

从现在起,我们可以靠美国芯片活得很好的幻想应该破灭了。中国有组织科技攻关的能力,也有推动国产芯片逐渐替代外来芯片所需要的动员力,最重要的就是决心。

特朗普政府在帮助我们下这个决心。如果中国真的转换了思路,也许过多少年之后,我们会感谢美国今天做出的限制决定,庆幸它促使中国早一点恢复了清醒。

一旦中国加速研发使用国产芯片的工作全面上路,美国方面的态度也将随之软下来。美国半导体产品还可以进入中国,但到那时主动权将牢牢掌握在我们自己的手里。

工具

1、Spectrum

开源的社区软件,形式非常新颖美观。

2、jsonstore.io

通过 HTTP Header 读写 JSON 数据的免费 datastore。

3、flamebearer

Node 应用的火焰图生成工具,用于性能分析。

4、DNS Performance Test

DNS 响应时间的命令行比较脚本。

5、merge-images

多张图片合成一张图片的浏览器 JS 库,使用了 Canvas。

6、Tabler

一个基于 Bootstrap4 的面板(dashboard)组件库。

7、Etherpad

老牌的多人实时编辑协同工具。

新奇

1、Braille Neue

Braille Neue 是布里叶盲文系统与正常字母的结合,无障碍设计的典范,为什么没有人早点想到这个点子呢。

2、Macbook 一美元改成触摸屏

一个非常牛的项目,作者在 Macbook 的摄像头上面,架了一块镜子。然后,自动捕捉并识别手指的坐标。

3、Jelly Mario Bros

水母版的《超级马里奥》网页游戏,所有东西都会像水母一样升缩。

4、小狗 USB

本周金句

人生就像玻璃窗上的苍蝇,前途一片光明,却找不到出路。

欢迎订阅

这个专栏会同步更新在我的个人网站微信公众号语雀

微信搜索"阮一峰的网络日志 "或者扫描二维码,即可手机订阅。

(完)

文档信息

]]>
0
<![CDATA[沟通杂想]]> http://www.udpwork.com/item/16799.html http://www.udpwork.com/item/16799.html#reviews Sun, 22 Apr 2018 18:34:18 +0800 bang http://www.udpwork.com/item/16799.html 一个人做一个项目,效率是最高的,各模块间的接口,前后端联调,产品策略,视觉还原,灰度部署方案,运营方案,都在一个人脑里,各块以毫秒级速度进行沟通,瞬间能完成,这里的沟通成本是没有的。

一旦涉及到团队合作做一个项目,沟通成本就上来了,随着项目越来越大,分工越来越细,项目的沟通也细分了很多个层级,同个小团队间的沟通最快,然后是跨团队,跨部门,跨事业群,跨公司。而这里的沟通往往除了项目本身确定性的方案对齐外,更多的是其他额外的不确定因素,像任务排期(优先级不统一)、权力和意愿(不配合,层层批准)、信息不对称(不知道谁负责,不知道为什么这样做)、意见不统一等,导致沟通成本不可控,一个中大型公司很大一部分工作就花在研究如何减少沟通成本上。

技术层面上,接口封装就是减少沟通成本,省去不同模块的的开发者之间沟通细节的成本。全栈也是种减少沟通成本的方式,一个前端页面,是跟其他页面需要沟通协调的内容多,还是跟后端联调接口的沟通多?大部分情况是后者,所以如果前后端一个人做,可以省去这里的沟通成本。产品PRD/运营方案文档/统一的视觉规范等自然也是为了减少沟通而产生的。

非技术层面上,很多组织架构的调整都是在寻找减少沟通成本以提高效率,像腾讯早期各产品的交互和视觉设计由一个部门负责,其他产品团队以提需求的方式跟设计团队合作,好处是专业度高和风格统一,结果每个产品跨部门沟通成本太高,现在都改成各个产品线配自己的设计团队。对于大公司,目前看到的比较好的常见做法是,大型固定的业务成立部门,备齐所有工种人员,包括技术产品设计运营等,需求在部门内完成,减少跨部门沟通成本。各工种仍是独立自己的团队,比如技术团队/产品团队,保持自己的专业度,而做一个个具体项目时,通常需要各团队人员协作完成,可以各团队抽人组成虚拟组,配一号位人员总体负责,减少因为跨团队跨组带来的沟通成本。不过这个虚拟组和一号位人员得有组织上/实际行动保证才能起作用,否则真的是纯虚拟了,变成仍然是跨团队沟通。

一些公司的精英招聘策略也是能有效减少沟通成本,若一个人能力强工作效率高,产出能顶两个人,那实际上加上减少的沟通成本,带来的收益远不止两倍,而若招平庸或差一些的人,跟团队间沟通效率不匹配,带来的沟通成本上升效率下降也不止一个人力的范围内。一个组织大了就一定会有各种人相关的问题需要解决,精英小团队各种好,不好的是招聘困难,以及在铺业务时还是会面临人力不足问题导致扩招,难以控制。

]]>
一个人做一个项目,效率是最高的,各模块间的接口,前后端联调,产品策略,视觉还原,灰度部署方案,运营方案,都在一个人脑里,各块以毫秒级速度进行沟通,瞬间能完成,这里的沟通成本是没有的。

一旦涉及到团队合作做一个项目,沟通成本就上来了,随着项目越来越大,分工越来越细,项目的沟通也细分了很多个层级,同个小团队间的沟通最快,然后是跨团队,跨部门,跨事业群,跨公司。而这里的沟通往往除了项目本身确定性的方案对齐外,更多的是其他额外的不确定因素,像任务排期(优先级不统一)、权力和意愿(不配合,层层批准)、信息不对称(不知道谁负责,不知道为什么这样做)、意见不统一等,导致沟通成本不可控,一个中大型公司很大一部分工作就花在研究如何减少沟通成本上。

技术层面上,接口封装就是减少沟通成本,省去不同模块的的开发者之间沟通细节的成本。全栈也是种减少沟通成本的方式,一个前端页面,是跟其他页面需要沟通协调的内容多,还是跟后端联调接口的沟通多?大部分情况是后者,所以如果前后端一个人做,可以省去这里的沟通成本。产品PRD/运营方案文档/统一的视觉规范等自然也是为了减少沟通而产生的。

非技术层面上,很多组织架构的调整都是在寻找减少沟通成本以提高效率,像腾讯早期各产品的交互和视觉设计由一个部门负责,其他产品团队以提需求的方式跟设计团队合作,好处是专业度高和风格统一,结果每个产品跨部门沟通成本太高,现在都改成各个产品线配自己的设计团队。对于大公司,目前看到的比较好的常见做法是,大型固定的业务成立部门,备齐所有工种人员,包括技术产品设计运营等,需求在部门内完成,减少跨部门沟通成本。各工种仍是独立自己的团队,比如技术团队/产品团队,保持自己的专业度,而做一个个具体项目时,通常需要各团队人员协作完成,可以各团队抽人组成虚拟组,配一号位人员总体负责,减少因为跨团队跨组带来的沟通成本。不过这个虚拟组和一号位人员得有组织上/实际行动保证才能起作用,否则真的是纯虚拟了,变成仍然是跨团队沟通。

一些公司的精英招聘策略也是能有效减少沟通成本,若一个人能力强工作效率高,产出能顶两个人,那实际上加上减少的沟通成本,带来的收益远不止两倍,而若招平庸或差一些的人,跟团队间沟通效率不匹配,带来的沟通成本上升效率下降也不止一个人力的范围内。一个组织大了就一定会有各种人相关的问题需要解决,精英小团队各种好,不好的是招聘困难,以及在铺业务时还是会面临人力不足问题导致扩招,难以控制。

]]>
0
<![CDATA[Vim 8 下 C/C++ 开发环境搭建]]> http://www.udpwork.com/item/16798.html http://www.udpwork.com/item/16798.html#reviews Sun, 22 Apr 2018 06:38:07 +0800 skywind http://www.udpwork.com/item/16798.html 挺多人问怎么在 Vim 中搭建 C/C++ 开发环境,我本来想找篇文章发给人家,结果网上看了一圈,要不就是内容太过陈旧,要不就是太过零碎,不成体系。2018 年了,Vim 8 发布已经一年半,各大 Linux 发行版和 Mac OS X自带的 Vim 都已经跟进到 8了,不少文章还在介绍一些十年前的老方法。于是有了这篇文章。

那如何高效的再 Vim 8 中开发 C/C++ 项目呢?假设你已经有一定 Vim 使用经验,并且折腾过 Vim 配置,能够相对舒适的在 Vim 中编写其他代码的时候,准备在 Vim 开始 C/C++ 项目开发,或者你已经用 Vim 编写了几年 C/C++ 代码,想要更进一步,让自己的工作更加顺畅的话,本文就是为你准备的:

插件管理

为什么把插件管理放在第一个来讲呢?这是比较基本的一个东西,如今 Vim 下熟练开发的人,基本上手都有 20-50 个插件,遥想十年前,Vim里常用的插件一只手都数得过来。过去我一直使用老牌的Vundle来管理插件,但是随着插件越来越多,更新越来越频繁,Vundle 这种每次更新就要好几分钟的东西实在是不堪重负了,在我逐步对 Vundle 失去耐心之后,我试用了vim-plug,用了两天以后就再也回不去 Vundle了,它支持全异步的插件安装,安装50个插件只需要一分钟不到的时间,这在 Vundle 下面根本不可想像的事情,插件更新也很快,不像原来每次更新都可以去喝杯茶去,最重要的是它支持插件延迟加载:

" 定义插件,默认用法,和 Vundle 的语法差不多
Plug 'junegunn/vim-easy-align'
Plug 'skywind3000/quickmenu.vim'

" 延迟按需加载,使用到命令的时候再加载或者打开对应文件类型才加载
Plug 'scrooloose/nerdtree', { 'on':  'NERDTreeToggle' }
Plug 'tpope/vim-fireplace', { 'for': 'clojure' }

" 确定插件仓库中的分支或者 tag
Plug 'rdnetto/YCM-Generator', { 'branch': 'stable' }
Plug 'nsf/gocode', { 'tag': 'v.20150303', 'rtp': 'vim' }

定义好插件以后一个::PlugInstall命令就并行安装所有插件了,比 Vundle 快捷不少,关键是 vim-plug 只有单个文件,正好可以放在我 github 上的 vim 配置仓库中,每次需要更新 vim-plug 时只需要:PlugUpgrade,即可自我更新。

抛弃 Vundle 切换到 vim-plug 以后,不仅插件安装和更新快了一个数量级,大量的插件我都配置成了延迟加载,Vim 启动速度比 Vundle 时候提高了不少。使用 Vundle 的时候一旦插件数量超过30个,管理是一件很痛苦的事情,而用了 vim-plug 以后,50-60个插件都轻轻松松。

符号索引

现在有好多 ctags 的代替品,比如 gtags, etags 和 cquery。然而我并不排斥 ctags,因为他支持 50+ 种语言,没有任何一个符号索引工具有它支持的语言多。同时 Vim 和 ctags 集成的相当好,用它依赖最少,大量基础工作可以直接通过 ctags 进行,然而到现在为止,我就没见过几个人把 ctags 用对了的。

就连配置文件他们都没写对,正确的 ctags 配置应该是:

set tags=./.tags;,.tags

这里解释一下,首先我把 tag 文件的名字从tags换成了.tags,前面多加了一个点,这样即便放到项目中也不容易污染当前项目的文件,删除时也好删除,gitignore 也好写,默认忽略点开头的文件名即可。

前半部分./.tags;代表在文件的所在目录下(不是:pwd返回的 Vim 当前目录)查找名字为.tags的符号文件,后面一个分号代表查找不到的话向上递归到父目录,直到找到.tags文件或者递归到了根目录还没找到,这样对于复杂工程很友好,源代码都是分布在不同子目录中,而只需要在项目顶层目录放一个.tags文件即可;逗号分隔的后半部分.tags是指同时在 Vim 的当前目录(:pwd命令返回的目录,可以用:cd ..命令改变)下面查找.tags文件。

最后请更新你的 ctags,不要再使用老旧的 Exuberant Ctags,这货停止更新快十年了,请使用最新的Universal CTags代替之,它在 Exuberant Ctags 的基础上继续更新迭代了近十年,如今任然活跃的维护着,功能更强大,语言支持更多。

自动索引

过去写几行代码又需要运行一下 ctags 来生成索引,每次生成耗费不少时间。如今 Vim 8 下面自动异步生成 tags 的工具有很多,这里推荐最好的一个:vim-gutentags,这个插件主要做两件事情:

  • 确定文件所属的工程目录,即文件当前路径向上递归查找是否有.git,.svn,.project等标志性文件(可以自定义)来确定当前文档所属的工程目录。
  • 检测同一个工程下面的文件改动,能会自动增量更新对应工程的.tags文件。每次改了几行不用全部重新生成,并且这个增量更新能够保证.tags文件的符号排序,方便 Vim 中用二分查找快速搜索符号。

vim-gutentags 需要简单配置一下:

" gutentags 搜索工程目录的标志,碰到这些文件/目录名就停止向上一级目录递归
let g:gutentags_project_root = ['.root', '.svn', '.git', '.hg', '.project']

" 所生成的数据文件的名称
let g:gutentags_ctags_tagfile = '.tags'

" 将自动生成的 tags 文件全部放入 ~/.cache/tags 目录中,避免污染工程目录
let s:vim_tags = expand('~/.cache/tags')
let g:gutentags_cache_dir = s:vim_tags

" 配置 ctags 的参数
let g:gutentags_ctags_extra_args = ['--fields=+niazS', '--extra=+q']
let g:gutentags_ctags_extra_args += ['--c++-kinds=+px']
let g:gutentags_ctags_extra_args += ['--c-kinds=+px']

" 检测 ~/.cache/tags 不存在就新建
if !isdirectory(s:vim_tags)
    silent! call mkdir(s:vim_tags, 'p')
endif

有了上面的设置,你平时基本感觉不到 tags 文件的生成过程了,只要文件修改过,gutentags 都在后台为你默默打点是否需要更新数据文件,你根本不用管,还会帮你:

setlocal tags+=... 

为当前文件添加上对应的 tags 文件的路劲而不影响其他文件。得益于 Vim 8 的异步机制,你可以任意随时使用 ctags 相关功能,并且数据库都是最新的。需要注意的是,gutentags 需要靠上面定义的 project_root 里的标志,判断文件所在的工程,如果一个文件没有托管在 .git/.svn 中,gutentags 找不到工程目录的话,就不会为该野文件生成 tags,这也很合理。想要避免的话,你可以在你的野文件目录中放一个名字为.root的空白文件,主动告诉 gutentags 这里就是工程目录。

最后啰嗦两句,少用CTRL-]直接在当前窗口里跳转到定义,多使用CTRL-W ]用新窗口打开并查看光标下符号的定义,或者CTRL-W }使用 preview 窗口预览光标下符号的定义。

我自己还写过不少关于 ctags 的 vimscript,例如在最下面命令行显示函数的原型而不用急着跳转,或者重复按ALT+;在 preview 窗口中轮流查看多个定义,不切走当前窗口,不会出一个很长的列表让你选择,有兴趣可以刨我的vim dotfiles

编译运行

再 Vim 8 以前,编译和运行程序要么就让 vim 傻等着结束,不能做其他事情,要么切到一个新的终端下面去单独运行编译命令和执行命令,要么开个 tmux 左右切换。如今新版本的异步模式可以让这个流程更加简化,这里我们使用AsyncRun插件,简单设置下:

Plug 'skywind3000/asyncrun.vim

" 自动打开 quickfix window ,高度为 6
let g:asyncrun_open = 6

" 任务结束时候响铃提醒
let g:asyncrun_bell = 1

" 设置 F10 打开/关闭 Quickfix 窗口
nnoremap <F10> :call asyncrun#quickfix_toggle(6)<cr>

该插件可以在后台运行 shell 命令,并且把结果输出到 quickfix 窗口:

最简单的编译单个文件,和 sublime 的默认 build system 差不多,我们定义 F9 为编译单文件:

nnoremap <silent> <F9> :AsyncRun gcc -Wall -O2 "$(VIM_FILEPATH)" -o "$(VIM_FILEDIR)/$(VIM_FILENOEXT)" <cr>

其中$(...)形式的宏在执行时会被替换成实际的文件名或者文件目录

这样按 F9 就可以编译当前文件,同时按 F5 运行:

nnoremap <silent> <F5> :AsyncRun -raw -cwd=$(VIM_FILEDIR) "$(VIM_FILEDIR)/$(VIM_FILENOEXT)" <cr>

用双引号引起来避免文件名包含空格,-cwd=$(VIM_FILEDIR)的意思时在文件文件的所在目录运行可执行,后面可执行使用了全路径,避免 linux 下面当前路径加./而 windows 不需要的跨平台问题。

参数-raw表示输出不用匹配错误检测模板 (errorformat) ,直接原始内容输出到 quickfix 窗口。这样你可以一边编辑一边 F9 编译,出错了可以在 quickfix 窗口中按回车直接跳转到错误的位置,编译正确就接着执行。

接下来是项目的编译,不管你直接使用 make 还是 cmake,都是对一群文件做点什么,都需要定位到文件所属项目的目录,AsyncRun 识别当前文件的项目目录方式和 gutentags相同,从文件所在目录向上递归,直到找到名为.git,.svn,.hg或者.root文件或者目录,如果递归到根目录还没找到,那么文件所在目录就被当作项目目录,你重新定义项目标志:

let g:asyncrun_rootmarks = ['.svn', '.git', '.root', '_darcs', 'build.xml'] 

然后在 AsyncRun 命令行中,用<root>或者$(VIM_ROOT)来表示项目所在路径,于是我们可以定义按 F7 编译整个项目:

nnoremap <silent> <F7> :AsyncRun -cwd=<root> make <cr>

并且按 F8 运行它:

nnoremap <silent> <F8> :AsyncRun -cwd=<root> -raw make run <cr>

当然,你的 makefile 中需要定义怎么 run ,接着按 F6 执行测试:

nnoremap <silent> <F6> :AsyncRun -cwd=<root> -raw make test <cr>

如果你使用了 cmake 的话,还可以照葫芦画瓢,定义 F4 为更新 Makefile 文件,如果不用 cmake 可以忽略:

nnoremap <silent> <F4> :AsyncRun -cwd=<root> cmake . <cr>

由于 C/C++ 标准库的实现方式是发现在后台运行时会缓存标准输出直到程序退出,你想实时看到 printf 输出的话需要fflush(stdout)一下,或者程序开头关闭缓存:setbuf(stdout, NULL);即可。

同时,如果你开发 C++ 程序使用std::cout的话,后面直接加一个std::endl就强制刷新缓存了,不需要弄其他。而如果你在 Windows 下使用 GVim 的话,可以弹出新的 cmd.exe 窗口来运行刚才的程序:

nnoremap <silent> <F5> :AsyncRun -cwd=$(VIM_FILEDIR) -mode=4 "$(VIM_FILEDIR)/$(VIM_FILENOEXT)" <cr>
nnoremap <silent> <F8> :AsyncRun -cwd=<root> -mode=4 make run <cr>

在 Windows 下使用-mode=4选项可以跟 Visual Studio 执行命令行工具一样,弹出一个新的 cmd.exe窗口来运行程序或者项目,于是我们有了下面的快捷键:

  • F4:使用 cmake 生成 Makefile
  • F5:单文件:运行
  • F6:项目:测试
  • F7:项目:编译
  • F8:项目:运行
  • F9:单文件:编译
  • F10:打开/关闭底部的 quickfix 窗口

恩,编译和运行基本和 NotePad++ / GEdit 的体验差不多了。如果你重度使用 cmake 的话,你还可以写点小脚本,将 F4 和 F7 的功能合并,检测 CMakeLists.txt 文件改变的话先执行 cmake 更新一下 Makefile,然后再执行 make,否则直接执行 make,这样更自动化些。

动态检查

代码检查是个好东西,让你在编辑文字的同时就帮你把潜在错误标注出来,不用等到编译或者运行了才发现。我很奇怪 2018 年了,为啥网上还在到处介绍老旧的syntastic,但凡见到介绍这个插件的文章基本都可以不看了。老的 syntastic 基本没法用,不能实时检查,一保存文件就运行检查器并且等待半天,所以请用实时 linting 工具ALE

大概长这个样子,随着你不断的编辑新代码,有语法错误的地方会实时帮你标注出来,侧边会标注本行有错,光标移动过去的时候下面会显示错误原因,而具体错误的符号下面会有红色波浪线提醒。Ale 支持多种语言的各种代码分析器,就 C/C++ 而言,就支持:gcc, clang, cppcheck 以及 clang-format 等,需要另行安装并放入 PATH下面,ALE能在你修改了文本后自动调用这些 linter 来分析最新代码,然后将各种 linter 的结果进行汇总并显示再界面上。

同样,我们也需要简单配置一下:

let g:ale_linters_explicit = 1
let g:ale_completion_delay = 500
let g:ale_echo_delay = 20
let g:ale_lint_delay = 500
let g:ale_echo_msg_format = '[%linter%] %code: %%s'
let g:ale_lint_on_text_changed = 'normal'
let g:ale_lint_on_insert_leave = 1
let g:airline#extensions#ale#enabled = 1

let g:ale_c_gcc_options = '-Wall -O2 -std=c99'
let g:ale_cpp_gcc_options = '-Wall -O2 -std=c++14'
let g:ale_c_cppcheck_options = ''
let g:ale_cpp_cppcheck_options = ''

基本上就是定义了一下运行规则,信息显示格式以及几个 linter 的运行参数,其中 6,7 两行比较重要,它规定了如果 normal 模式下文字改变以及离开 insert 模式的时候运行 linter,这是相对保守的做法,如果没有的话,会导致 YouCompleteMe 的补全对话框频繁刷新。

记得设置一下各个 linter 的参数,忽略一些你觉得没问题的规则,不然没法看。默认错误和警告的风格都太难看了,你需要修改一下,比如我使用 GVim,就重新定义了警告和错误的样式,去除默认难看的红色背景,代码正文使用干净的波浪下划线表示:

let g:ale_sign_error = "\ue009\ue009"
hi! clear SpellBad
hi! clear SpellCap
hi! clear SpellRare
hi! SpellBad gui=undercurl guisp=red
hi! SpellCap gui=undercurl guisp=blue
hi! SpellRare gui=undercurl guisp=magenta

不同项目之间如果评测标准不一样还可以具体单独制定 linter 的参数,具体见 ALE 帮助文档了。我基本使用两个检查器:gcc 和 cppcheck,都可以在 ALE 中进行详细配置,前者主要检查有无语法错误,后者主要会给出一些编码建议,和对危险写法的警告。

我之前用 syntastic 时就用了两天就彻底删除了,而开始用 ALE 后,一用上就停不下来,头两天我还一度觉得它就是个可有可无的点缀,但是第三天它帮我找出两个潜在的 bug 的时候,我开始觉得没白安装,用上一段时间以后,让我编写 C/C++ 代码时充满了惬意的感觉。

修改比较

这是个小功能,在侧边栏显示一个修改状态,对比当前文本和 git/svn 仓库里的版本,在侧边栏显示修改情况,以前 Vim 做不到实时显示修改状态,如今推荐使用vim-signify来实时显示修改状态,它比 gitgutter 强,除了 git 外还支持 svn/mercurial/cvs 等十多种主流版本管理系统。

没注意到它时,你可能觉得它不存在,当你有时真的看上两眼时,你会发现这个功能很贴心。最新版 signify 还有一个命令:SignifyDiff,可以左右分屏对比提交前后记录,比你命令行 svn/git diff 半天直观多了。并且对我这种同时工作在 subversion 和 git 环境下的情况契合的比较好。

Signify 和前面的 ALE 都会在侧边栏显示一些标记,默认侧边栏会自动隐藏,有内容才会显示,不喜欢侧边栏时有时无的行为可设置强制显示侧边栏:set signcolumn=yes。

文本对象

相信大家用 Vim 进行编辑时都很喜欢文本对象这个概念,diw删除光标所在单词,ciw改写单词,vip选中段落等,ci"/ci(改写引号/括号中的内容。而编写 C/C++ 代码时我推荐大家补充几个十分有用的文本对象,我使用 textobj-user 全家桶:

Plug 'kana/vim-textobj-user'
Plug 'kana/vim-textobj-indent'
Plug 'kana/vim-textobj-syntax'
Plug 'kana/vim-textobj-function', { 'for':['c', 'cpp', 'vim', 'java'] }
Plug 'sgur/vim-textobj-parameter'

它新定义的文本对象主要有:

  • i,和a,:参数对象,写代码一半在修改,现在可以用di,/ci,一次性删除/改写当前参数
  • ii和ai:缩进对象,同一个缩进层次的代码,可以用vii选中,dii/cii删除或改写
  • if和af:函数对象,可以用vif/dif/cif来选中/删除/改写函数的内容

最开始我不太想用额外的文本对象,一直在坚持 Vim 固有的几个默认对象,生怕手练习惯了肌肉形成记忆到远端没有环境的 vim 下形成依赖改不过来,后来我慢慢发现挺有用的,比如改写参数,以前是比较麻烦的事情,这下流畅了很多,当我发现自己编码效率得到比较大的提升时,才发现习惯依赖不重要,行云流水才是真重要。以前看到过无数次都选择性忽略的东西,有时候试试可能会有新的发现。

编辑辅助

大家都知道 color 文件定义了众多不同语法元素的色彩,还有一个关键因素就是语法文件本身能否识别并标记得出众多不同的内容来?语法文件对某些东西没标注,你 color 文件确定了颜色也没用。因此 Vim 下面写 C/C++ 代码,语法高亮准确丰富的话能让你编码的心情好很多,这里推荐vim-cpp-enhanced-highlight插件,提供比 Vim 自带语法文件更好的 C/C++ 语法标注,支持 cpp11/14/17。

前面编译运行时需要频繁的操作 quickfix 窗口,ale查错时也需要快速再错误间跳转(location list),就连文件比较也会用到快速跳转到上/下一个差异处,unimpaired插件帮你定义了一系列方括号开头的快捷键,被称为官方 Vim 中丢失的快捷键。

我们好些地方用到了 quickfix / location 窗口,你在 quickfix 中回车选中一条错误的话,默认会把你当前窗口给切走,变成新文件,虽然按 CTRL+O 可以返回,但是如果不太喜欢这样切走当前文件的做法,可以设置 switchbuf,发现文件已在 Vim 中打开就跳过去,没打开过就新建窗口/标签打开,具体见帮助。

Vim最爽的地方是把所有 ALT 键映射全部留给用户了,尽量使用 Vim 的 ALT键映射,可以让冗长的快捷键缩短很多,请参考:《Vim和终端软件中支持ALT映射》。

代码补全

传统的 Vim 代码补全基本以 omni 系列补全和符号补全为主,omni 补全系统是 Vim 自带的针对不同文件类型编写不同的补全函数的基础语义补全系统,搭配 neocomplete 可以很方便的对所有补全结果(omni补全/符号补全/字典补全)进行一个合成并且自动弹出补全框,虽然赶不上 IDE 的补全,但是已经比大部分编辑器补全好用很多了。然而传统 Vim 补全还是有两个迈不过去的坎:语义补全太弱,其次是补全分析无法再后台运行,对大项目而言,某些复杂符号的补全会拖慢你的打字速度。

新一代的 Vim 补全系统,YouCompleteMeDeoplete,都支持异步补全和基于 clang 的语义补全,前者集成度高,后者扩展方便。对于 C/C++ 的话,我推荐 YCM,因为 deoplete 的 clang 补全插件不够稳定,太吃内存,并且反应比较慢。所以 C/C++ 的补全的话,请直接使用 YCM,没有之一,而使用 YCM的话,需要进行一些简单的调教:

let g:ycm_add_preview_to_completeopt = 0
let g:ycm_show_diagnostics_ui = 0
let g:ycm_server_log_level = 'info'
let g:ycm_min_num_identifier_candidate_chars = 2
let g:ycm_collect_identifiers_from_comments_and_strings = 1
let g:ycm_complete_in_strings=1
let g:ycm_key_invoke_completion = '<c-z>'
set completeopt=menu,menuone

noremap <c-z> <NOP>

let g:ycm_semantic_triggers =  {
            \ 'c,cpp,python,java,go,erlang,perl': ['re!\w{2}'],
            \ 'cs,lua,javascript': ['re!\w{2}'],
            \ }

这样可以输入两个字符就自动弹出语义补全,不用等到.或者->才触发,同时关闭了预览窗口和代码诊断这些 YCM 花边功能,保持清静,对于原型预览和诊断我们后面有更好的解决方法,YCM这两项功能干扰太大。

上面这几行配置具体每行的含义,可以见:《YouCompleteMe 中容易忽略的配置》。另外我在 Windows 下编译了一个版本,你用 Windows 的话无需下载VS编译,点击这里。我日常开发使用 YCM 辅助编写 C/C++, Python 和 Go 代码,基本能提供 IDE 级别的补全。

函数列表

不再建议使用tagbar, 它会在你保存文件的时候以同步等待的方式运行 ctags (即便你没有打开 tagbar),导致vim操作变卡,特别是 windows下开了反病毒软件扫描的话,有时候保存文件卡5-6秒。2018年了,我们有更好的选择,比如使用国人开发的LeaderF来显示函数列表:

全异步显示文件函数列表,不用的时候不会占用你任何屏幕空间,将 ALT+P 绑定到:LeaderfFunction这个命令上,按 ALT+P 就弹出当前文件的函数列表,然后可以进行模糊匹配搜索,还可以按 TAB 进入列表选择窗口,上下移动光标选择,按回车立马完成跳转并同时关闭列表。

Leaderf 的函数功能属于你想要它的时候它才会出来,不想要它的时候不会给你捣乱。

文件切换

文件/buffer模糊匹配快速切换的方式,比你打开一个对话框选择文件便捷不少,过去我们常用的 CtrlP 可以光荣下岗了,如今有更多速度更快,匹配更精准以及完美支持后台运行方式的文件模糊匹配工具。我自己用的是上面提到的LeaderF,除了提供函数列表外,还支持文件,MRU,Buffer名称搜索,完美代替 CtrlP,使用时需要简单调教下:

let g:Lf_ShortcutF = '<c-p>'
let g:Lf_ShortcutB = '<m-n>'
noremap <c-n> :LeaderfMru<cr>
noremap <m-p> :LeaderfFunction<cr>
noremap <m-n> :LeaderfBuffer<cr>
noremap <m-m> :LeaderfTag<cr>
let g:Lf_StlSeparator = { 'left': '', 'right': '', 'font': '' }

let g:Lf_RootMarkers = ['.project', '.root', '.svn', '.git']
let g:Lf_WorkingDirectoryMode = 'Ac'
let g:Lf_WindowHeight = 0.30
let g:Lf_CacheDirectory = expand('~/.vim/cache')
let g:Lf_ShowRelativePath = 0
let g:Lf_HideHelp = 1
let g:Lf_StlColorscheme = 'powerline'

let g:Lf_NormalMap = {
    \ "File":   [["<ESC>", ':exec g:Lf_py "fileExplManager.quit()"<CR>'],
    \            ["<F6>", ':exec g:Lf_py "fileExplManager.quit()"<CR>'] ],
    \ "Buffer": [["<ESC>", ':exec g:Lf_py "bufExplManager.quit()"<CR>'],
    \            ["<F6>", ':exec g:Lf_py "bufExplManager.quit()"<CR>'] ],
    \ "Mru":    [["<ESC>", ':exec g:Lf_py "mruExplManager.quit()"<CR>']],
    \ "Tag":    [["<ESC>", ':exec g:Lf_py "tagExplManager.quit()"<CR>']],
    \ "Function":    [["<ESC>", ':exec g:Lf_py "functionExplManager.quit()"<CR>']],
    \ "Colorscheme":    [["<ESC>", ':exec g:Lf_py "colorschemeExplManager.quit()"<CR>']],
    \ }

这里定义了 CTRL+P 在当前项目目录打开文件搜索,CTRL+N 打开 MRU搜索,搜索你最近打开的文件,这两项是我用的最频繁的功能。接着 ALT+P 打开函数搜索,ALT+N 打开 Buffer 搜索:

LeaderF 是目前匹配效率最高的,高过 CtrlP/Fzf 不少,敲更少的字母就能把文件找出来,同时搜索很迅速,使用 Python 后台线程进行搜索匹配,还有一个 C模块可以加速匹配性能,需要手工编译下。LeaderF在模糊匹配模式下按 TAB 可以切换到匹配结果窗口用光标或者 Vim 搜索命令进一步筛选,这是 CtrlP/Fzf 不具备的,更多方便的功能见它的官方文档。

文件/MRU 模糊匹配对于熟悉的项目效率是最高的,但对于一个新的项目,通常我们都不知道它有些什么文件,那就谈不上根据文件名匹配什么了,我们需要文件浏览功能。如果你喜欢把 Vim 伪装成 NotePad++ 之类的,那你该继续使用NERDTree进行文件浏览,但你想按照 Vim 的方式来,推荐阅读这篇文章:

Oil and vinegar – split windows and project drawer

然后向我一样开始使用vim-dirvish,进行一些配置,比如当前文档按-号就能不切窗口的情况下在当前窗口直接返回当前文档所在的目录,再按一次减号就返回上一级目录,按回车进入下一级目录或者再当前窗口打开光标下的文件。进一步映射<tab>7,<tab>8和<tab>9分别用于在新的 split, vsplit 和新标签打开当前文件所在目录,这样从一个文件如手,很容易找到和该文件相关的其他项目文件。

最后一个是 C/C++ 的头文件/源文件快速切换功能,有现成的插件做这事情,比如a.vim,我自己没用,因为这事情太简单,再我发现 a.vim 前我就觉得需要这个功能,然后自己两行 vim 脚本就搞定了。

参数提示

这个功能应人而异,有人觉得不需要,有人觉得管用。写 C/C++ 时函数忘了可以用上面的 YCM 补全,但很多时候是参数忘记了怎么办?YCM的参数提示很蛋疼,要打开个 Preview 窗口,实在是太影响我的视线了,我自己写过一些参数提醒功能,可以在最下面的命令行显示当前函数的参数,不过这是基于 tags 的,搭配前面的 gutentags,对其他语言很管用,但对 C/C++ 我们可以使用echodoc插件:

它可以无缝的和前面的 YCM 搭配,你用 YCM 时 tab 补全了一个函数名后,只要输入左括号,下面命令行就会里面显示出该函数的参数信息,唯一需要设置的是使用set noshowmode关闭模式提示,就是底部 —INSERT— 那个,我们一般都用 airline / lightline 之类的显示当前模式了,所以默认模式提示可以关闭,INSERT 模式下的命令行,完全留给 echodoc 显示参数使用。

更多阅读

2018年了,用点新方法,网上那些 Vim 开发 C/C++ 的文章真的都可以淘汰了。

更多参考:《Vim 中文版入门到精通》 和《Vim 中文速查表》。本文主要是针对 C/C++ 环境搭建的插件介绍,关于基本使用,欢迎参考上面这些链接。篇幅有限,这里只能谈一部分内容,对大多数人已经够了,如果你想继续深入的话,还可以慢慢折腾诸如 git 集成,帮助文档集成,调试,rtags 以及 lsp 这些东西。

]]>
挺多人问怎么在 Vim 中搭建 C/C++ 开发环境,我本来想找篇文章发给人家,结果网上看了一圈,要不就是内容太过陈旧,要不就是太过零碎,不成体系。2018 年了,Vim 8 发布已经一年半,各大 Linux 发行版和 Mac OS X自带的 Vim 都已经跟进到 8了,不少文章还在介绍一些十年前的老方法。于是有了这篇文章。

那如何高效的再 Vim 8 中开发 C/C++ 项目呢?假设你已经有一定 Vim 使用经验,并且折腾过 Vim 配置,能够相对舒适的在 Vim 中编写其他代码的时候,准备在 Vim 开始 C/C++ 项目开发,或者你已经用 Vim 编写了几年 C/C++ 代码,想要更进一步,让自己的工作更加顺畅的话,本文就是为你准备的:

插件管理

为什么把插件管理放在第一个来讲呢?这是比较基本的一个东西,如今 Vim 下熟练开发的人,基本上手都有 20-50 个插件,遥想十年前,Vim里常用的插件一只手都数得过来。过去我一直使用老牌的Vundle来管理插件,但是随着插件越来越多,更新越来越频繁,Vundle 这种每次更新就要好几分钟的东西实在是不堪重负了,在我逐步对 Vundle 失去耐心之后,我试用了vim-plug,用了两天以后就再也回不去 Vundle了,它支持全异步的插件安装,安装50个插件只需要一分钟不到的时间,这在 Vundle 下面根本不可想像的事情,插件更新也很快,不像原来每次更新都可以去喝杯茶去,最重要的是它支持插件延迟加载:

" 定义插件,默认用法,和 Vundle 的语法差不多
Plug 'junegunn/vim-easy-align'
Plug 'skywind3000/quickmenu.vim'

" 延迟按需加载,使用到命令的时候再加载或者打开对应文件类型才加载
Plug 'scrooloose/nerdtree', { 'on':  'NERDTreeToggle' }
Plug 'tpope/vim-fireplace', { 'for': 'clojure' }

" 确定插件仓库中的分支或者 tag
Plug 'rdnetto/YCM-Generator', { 'branch': 'stable' }
Plug 'nsf/gocode', { 'tag': 'v.20150303', 'rtp': 'vim' }

定义好插件以后一个::PlugInstall命令就并行安装所有插件了,比 Vundle 快捷不少,关键是 vim-plug 只有单个文件,正好可以放在我 github 上的 vim 配置仓库中,每次需要更新 vim-plug 时只需要:PlugUpgrade,即可自我更新。

抛弃 Vundle 切换到 vim-plug 以后,不仅插件安装和更新快了一个数量级,大量的插件我都配置成了延迟加载,Vim 启动速度比 Vundle 时候提高了不少。使用 Vundle 的时候一旦插件数量超过30个,管理是一件很痛苦的事情,而用了 vim-plug 以后,50-60个插件都轻轻松松。

符号索引

现在有好多 ctags 的代替品,比如 gtags, etags 和 cquery。然而我并不排斥 ctags,因为他支持 50+ 种语言,没有任何一个符号索引工具有它支持的语言多。同时 Vim 和 ctags 集成的相当好,用它依赖最少,大量基础工作可以直接通过 ctags 进行,然而到现在为止,我就没见过几个人把 ctags 用对了的。

就连配置文件他们都没写对,正确的 ctags 配置应该是:

set tags=./.tags;,.tags

这里解释一下,首先我把 tag 文件的名字从tags换成了.tags,前面多加了一个点,这样即便放到项目中也不容易污染当前项目的文件,删除时也好删除,gitignore 也好写,默认忽略点开头的文件名即可。

前半部分./.tags;代表在文件的所在目录下(不是:pwd返回的 Vim 当前目录)查找名字为.tags的符号文件,后面一个分号代表查找不到的话向上递归到父目录,直到找到.tags文件或者递归到了根目录还没找到,这样对于复杂工程很友好,源代码都是分布在不同子目录中,而只需要在项目顶层目录放一个.tags文件即可;逗号分隔的后半部分.tags是指同时在 Vim 的当前目录(:pwd命令返回的目录,可以用:cd ..命令改变)下面查找.tags文件。

最后请更新你的 ctags,不要再使用老旧的 Exuberant Ctags,这货停止更新快十年了,请使用最新的Universal CTags代替之,它在 Exuberant Ctags 的基础上继续更新迭代了近十年,如今任然活跃的维护着,功能更强大,语言支持更多。

自动索引

过去写几行代码又需要运行一下 ctags 来生成索引,每次生成耗费不少时间。如今 Vim 8 下面自动异步生成 tags 的工具有很多,这里推荐最好的一个:vim-gutentags,这个插件主要做两件事情:

  • 确定文件所属的工程目录,即文件当前路径向上递归查找是否有.git,.svn,.project等标志性文件(可以自定义)来确定当前文档所属的工程目录。
  • 检测同一个工程下面的文件改动,能会自动增量更新对应工程的.tags文件。每次改了几行不用全部重新生成,并且这个增量更新能够保证.tags文件的符号排序,方便 Vim 中用二分查找快速搜索符号。

vim-gutentags 需要简单配置一下:

" gutentags 搜索工程目录的标志,碰到这些文件/目录名就停止向上一级目录递归
let g:gutentags_project_root = ['.root', '.svn', '.git', '.hg', '.project']

" 所生成的数据文件的名称
let g:gutentags_ctags_tagfile = '.tags'

" 将自动生成的 tags 文件全部放入 ~/.cache/tags 目录中,避免污染工程目录
let s:vim_tags = expand('~/.cache/tags')
let g:gutentags_cache_dir = s:vim_tags

" 配置 ctags 的参数
let g:gutentags_ctags_extra_args = ['--fields=+niazS', '--extra=+q']
let g:gutentags_ctags_extra_args += ['--c++-kinds=+px']
let g:gutentags_ctags_extra_args += ['--c-kinds=+px']

" 检测 ~/.cache/tags 不存在就新建
if !isdirectory(s:vim_tags)
    silent! call mkdir(s:vim_tags, 'p')
endif

有了上面的设置,你平时基本感觉不到 tags 文件的生成过程了,只要文件修改过,gutentags 都在后台为你默默打点是否需要更新数据文件,你根本不用管,还会帮你:

setlocal tags+=... 

为当前文件添加上对应的 tags 文件的路劲而不影响其他文件。得益于 Vim 8 的异步机制,你可以任意随时使用 ctags 相关功能,并且数据库都是最新的。需要注意的是,gutentags 需要靠上面定义的 project_root 里的标志,判断文件所在的工程,如果一个文件没有托管在 .git/.svn 中,gutentags 找不到工程目录的话,就不会为该野文件生成 tags,这也很合理。想要避免的话,你可以在你的野文件目录中放一个名字为.root的空白文件,主动告诉 gutentags 这里就是工程目录。

最后啰嗦两句,少用CTRL-]直接在当前窗口里跳转到定义,多使用CTRL-W ]用新窗口打开并查看光标下符号的定义,或者CTRL-W }使用 preview 窗口预览光标下符号的定义。

我自己还写过不少关于 ctags 的 vimscript,例如在最下面命令行显示函数的原型而不用急着跳转,或者重复按ALT+;在 preview 窗口中轮流查看多个定义,不切走当前窗口,不会出一个很长的列表让你选择,有兴趣可以刨我的vim dotfiles

编译运行

再 Vim 8 以前,编译和运行程序要么就让 vim 傻等着结束,不能做其他事情,要么切到一个新的终端下面去单独运行编译命令和执行命令,要么开个 tmux 左右切换。如今新版本的异步模式可以让这个流程更加简化,这里我们使用AsyncRun插件,简单设置下:

Plug 'skywind3000/asyncrun.vim

" 自动打开 quickfix window ,高度为 6
let g:asyncrun_open = 6

" 任务结束时候响铃提醒
let g:asyncrun_bell = 1

" 设置 F10 打开/关闭 Quickfix 窗口
nnoremap <F10> :call asyncrun#quickfix_toggle(6)<cr>

该插件可以在后台运行 shell 命令,并且把结果输出到 quickfix 窗口:

最简单的编译单个文件,和 sublime 的默认 build system 差不多,我们定义 F9 为编译单文件:

nnoremap <silent> <F9> :AsyncRun gcc -Wall -O2 "$(VIM_FILEPATH)" -o "$(VIM_FILEDIR)/$(VIM_FILENOEXT)" <cr>

其中$(...)形式的宏在执行时会被替换成实际的文件名或者文件目录

这样按 F9 就可以编译当前文件,同时按 F5 运行:

nnoremap <silent> <F5> :AsyncRun -raw -cwd=$(VIM_FILEDIR) "$(VIM_FILEDIR)/$(VIM_FILENOEXT)" <cr>

用双引号引起来避免文件名包含空格,-cwd=$(VIM_FILEDIR)的意思时在文件文件的所在目录运行可执行,后面可执行使用了全路径,避免 linux 下面当前路径加./而 windows 不需要的跨平台问题。

参数-raw表示输出不用匹配错误检测模板 (errorformat) ,直接原始内容输出到 quickfix 窗口。这样你可以一边编辑一边 F9 编译,出错了可以在 quickfix 窗口中按回车直接跳转到错误的位置,编译正确就接着执行。

接下来是项目的编译,不管你直接使用 make 还是 cmake,都是对一群文件做点什么,都需要定位到文件所属项目的目录,AsyncRun 识别当前文件的项目目录方式和 gutentags相同,从文件所在目录向上递归,直到找到名为.git,.svn,.hg或者.root文件或者目录,如果递归到根目录还没找到,那么文件所在目录就被当作项目目录,你重新定义项目标志:

let g:asyncrun_rootmarks = ['.svn', '.git', '.root', '_darcs', 'build.xml'] 

然后在 AsyncRun 命令行中,用<root>或者$(VIM_ROOT)来表示项目所在路径,于是我们可以定义按 F7 编译整个项目:

nnoremap <silent> <F7> :AsyncRun -cwd=<root> make <cr>

并且按 F8 运行它:

nnoremap <silent> <F8> :AsyncRun -cwd=<root> -raw make run <cr>

当然,你的 makefile 中需要定义怎么 run ,接着按 F6 执行测试:

nnoremap <silent> <F6> :AsyncRun -cwd=<root> -raw make test <cr>

如果你使用了 cmake 的话,还可以照葫芦画瓢,定义 F4 为更新 Makefile 文件,如果不用 cmake 可以忽略:

nnoremap <silent> <F4> :AsyncRun -cwd=<root> cmake . <cr>

由于 C/C++ 标准库的实现方式是发现在后台运行时会缓存标准输出直到程序退出,你想实时看到 printf 输出的话需要fflush(stdout)一下,或者程序开头关闭缓存:setbuf(stdout, NULL);即可。

同时,如果你开发 C++ 程序使用std::cout的话,后面直接加一个std::endl就强制刷新缓存了,不需要弄其他。而如果你在 Windows 下使用 GVim 的话,可以弹出新的 cmd.exe 窗口来运行刚才的程序:

nnoremap <silent> <F5> :AsyncRun -cwd=$(VIM_FILEDIR) -mode=4 "$(VIM_FILEDIR)/$(VIM_FILENOEXT)" <cr>
nnoremap <silent> <F8> :AsyncRun -cwd=<root> -mode=4 make run <cr>

在 Windows 下使用-mode=4选项可以跟 Visual Studio 执行命令行工具一样,弹出一个新的 cmd.exe窗口来运行程序或者项目,于是我们有了下面的快捷键:

  • F4:使用 cmake 生成 Makefile
  • F5:单文件:运行
  • F6:项目:测试
  • F7:项目:编译
  • F8:项目:运行
  • F9:单文件:编译
  • F10:打开/关闭底部的 quickfix 窗口

恩,编译和运行基本和 NotePad++ / GEdit 的体验差不多了。如果你重度使用 cmake 的话,你还可以写点小脚本,将 F4 和 F7 的功能合并,检测 CMakeLists.txt 文件改变的话先执行 cmake 更新一下 Makefile,然后再执行 make,否则直接执行 make,这样更自动化些。

动态检查

代码检查是个好东西,让你在编辑文字的同时就帮你把潜在错误标注出来,不用等到编译或者运行了才发现。我很奇怪 2018 年了,为啥网上还在到处介绍老旧的syntastic,但凡见到介绍这个插件的文章基本都可以不看了。老的 syntastic 基本没法用,不能实时检查,一保存文件就运行检查器并且等待半天,所以请用实时 linting 工具ALE

大概长这个样子,随着你不断的编辑新代码,有语法错误的地方会实时帮你标注出来,侧边会标注本行有错,光标移动过去的时候下面会显示错误原因,而具体错误的符号下面会有红色波浪线提醒。Ale 支持多种语言的各种代码分析器,就 C/C++ 而言,就支持:gcc, clang, cppcheck 以及 clang-format 等,需要另行安装并放入 PATH下面,ALE能在你修改了文本后自动调用这些 linter 来分析最新代码,然后将各种 linter 的结果进行汇总并显示再界面上。

同样,我们也需要简单配置一下:

let g:ale_linters_explicit = 1
let g:ale_completion_delay = 500
let g:ale_echo_delay = 20
let g:ale_lint_delay = 500
let g:ale_echo_msg_format = '[%linter%] %code: %%s'
let g:ale_lint_on_text_changed = 'normal'
let g:ale_lint_on_insert_leave = 1
let g:airline#extensions#ale#enabled = 1

let g:ale_c_gcc_options = '-Wall -O2 -std=c99'
let g:ale_cpp_gcc_options = '-Wall -O2 -std=c++14'
let g:ale_c_cppcheck_options = ''
let g:ale_cpp_cppcheck_options = ''

基本上就是定义了一下运行规则,信息显示格式以及几个 linter 的运行参数,其中 6,7 两行比较重要,它规定了如果 normal 模式下文字改变以及离开 insert 模式的时候运行 linter,这是相对保守的做法,如果没有的话,会导致 YouCompleteMe 的补全对话框频繁刷新。

记得设置一下各个 linter 的参数,忽略一些你觉得没问题的规则,不然没法看。默认错误和警告的风格都太难看了,你需要修改一下,比如我使用 GVim,就重新定义了警告和错误的样式,去除默认难看的红色背景,代码正文使用干净的波浪下划线表示:

let g:ale_sign_error = "\ue009\ue009"
hi! clear SpellBad
hi! clear SpellCap
hi! clear SpellRare
hi! SpellBad gui=undercurl guisp=red
hi! SpellCap gui=undercurl guisp=blue
hi! SpellRare gui=undercurl guisp=magenta

不同项目之间如果评测标准不一样还可以具体单独制定 linter 的参数,具体见 ALE 帮助文档了。我基本使用两个检查器:gcc 和 cppcheck,都可以在 ALE 中进行详细配置,前者主要检查有无语法错误,后者主要会给出一些编码建议,和对危险写法的警告。

我之前用 syntastic 时就用了两天就彻底删除了,而开始用 ALE 后,一用上就停不下来,头两天我还一度觉得它就是个可有可无的点缀,但是第三天它帮我找出两个潜在的 bug 的时候,我开始觉得没白安装,用上一段时间以后,让我编写 C/C++ 代码时充满了惬意的感觉。

修改比较

这是个小功能,在侧边栏显示一个修改状态,对比当前文本和 git/svn 仓库里的版本,在侧边栏显示修改情况,以前 Vim 做不到实时显示修改状态,如今推荐使用vim-signify来实时显示修改状态,它比 gitgutter 强,除了 git 外还支持 svn/mercurial/cvs 等十多种主流版本管理系统。

没注意到它时,你可能觉得它不存在,当你有时真的看上两眼时,你会发现这个功能很贴心。最新版 signify 还有一个命令:SignifyDiff,可以左右分屏对比提交前后记录,比你命令行 svn/git diff 半天直观多了。并且对我这种同时工作在 subversion 和 git 环境下的情况契合的比较好。

Signify 和前面的 ALE 都会在侧边栏显示一些标记,默认侧边栏会自动隐藏,有内容才会显示,不喜欢侧边栏时有时无的行为可设置强制显示侧边栏:set signcolumn=yes。

文本对象

相信大家用 Vim 进行编辑时都很喜欢文本对象这个概念,diw删除光标所在单词,ciw改写单词,vip选中段落等,ci"/ci(改写引号/括号中的内容。而编写 C/C++ 代码时我推荐大家补充几个十分有用的文本对象,我使用 textobj-user 全家桶:

Plug 'kana/vim-textobj-user'
Plug 'kana/vim-textobj-indent'
Plug 'kana/vim-textobj-syntax'
Plug 'kana/vim-textobj-function', { 'for':['c', 'cpp', 'vim', 'java'] }
Plug 'sgur/vim-textobj-parameter'

它新定义的文本对象主要有:

  • i,和a,:参数对象,写代码一半在修改,现在可以用di,/ci,一次性删除/改写当前参数
  • ii和ai:缩进对象,同一个缩进层次的代码,可以用vii选中,dii/cii删除或改写
  • if和af:函数对象,可以用vif/dif/cif来选中/删除/改写函数的内容

最开始我不太想用额外的文本对象,一直在坚持 Vim 固有的几个默认对象,生怕手练习惯了肌肉形成记忆到远端没有环境的 vim 下形成依赖改不过来,后来我慢慢发现挺有用的,比如改写参数,以前是比较麻烦的事情,这下流畅了很多,当我发现自己编码效率得到比较大的提升时,才发现习惯依赖不重要,行云流水才是真重要。以前看到过无数次都选择性忽略的东西,有时候试试可能会有新的发现。

编辑辅助

大家都知道 color 文件定义了众多不同语法元素的色彩,还有一个关键因素就是语法文件本身能否识别并标记得出众多不同的内容来?语法文件对某些东西没标注,你 color 文件确定了颜色也没用。因此 Vim 下面写 C/C++ 代码,语法高亮准确丰富的话能让你编码的心情好很多,这里推荐vim-cpp-enhanced-highlight插件,提供比 Vim 自带语法文件更好的 C/C++ 语法标注,支持 cpp11/14/17。

前面编译运行时需要频繁的操作 quickfix 窗口,ale查错时也需要快速再错误间跳转(location list),就连文件比较也会用到快速跳转到上/下一个差异处,unimpaired插件帮你定义了一系列方括号开头的快捷键,被称为官方 Vim 中丢失的快捷键。

我们好些地方用到了 quickfix / location 窗口,你在 quickfix 中回车选中一条错误的话,默认会把你当前窗口给切走,变成新文件,虽然按 CTRL+O 可以返回,但是如果不太喜欢这样切走当前文件的做法,可以设置 switchbuf,发现文件已在 Vim 中打开就跳过去,没打开过就新建窗口/标签打开,具体见帮助。

Vim最爽的地方是把所有 ALT 键映射全部留给用户了,尽量使用 Vim 的 ALT键映射,可以让冗长的快捷键缩短很多,请参考:《Vim和终端软件中支持ALT映射》。

代码补全

传统的 Vim 代码补全基本以 omni 系列补全和符号补全为主,omni 补全系统是 Vim 自带的针对不同文件类型编写不同的补全函数的基础语义补全系统,搭配 neocomplete 可以很方便的对所有补全结果(omni补全/符号补全/字典补全)进行一个合成并且自动弹出补全框,虽然赶不上 IDE 的补全,但是已经比大部分编辑器补全好用很多了。然而传统 Vim 补全还是有两个迈不过去的坎:语义补全太弱,其次是补全分析无法再后台运行,对大项目而言,某些复杂符号的补全会拖慢你的打字速度。

新一代的 Vim 补全系统,YouCompleteMeDeoplete,都支持异步补全和基于 clang 的语义补全,前者集成度高,后者扩展方便。对于 C/C++ 的话,我推荐 YCM,因为 deoplete 的 clang 补全插件不够稳定,太吃内存,并且反应比较慢。所以 C/C++ 的补全的话,请直接使用 YCM,没有之一,而使用 YCM的话,需要进行一些简单的调教:

let g:ycm_add_preview_to_completeopt = 0
let g:ycm_show_diagnostics_ui = 0
let g:ycm_server_log_level = 'info'
let g:ycm_min_num_identifier_candidate_chars = 2
let g:ycm_collect_identifiers_from_comments_and_strings = 1
let g:ycm_complete_in_strings=1
let g:ycm_key_invoke_completion = '<c-z>'
set completeopt=menu,menuone

noremap <c-z> <NOP>

let g:ycm_semantic_triggers =  {
            \ 'c,cpp,python,java,go,erlang,perl': ['re!\w{2}'],
            \ 'cs,lua,javascript': ['re!\w{2}'],
            \ }

这样可以输入两个字符就自动弹出语义补全,不用等到.或者->才触发,同时关闭了预览窗口和代码诊断这些 YCM 花边功能,保持清静,对于原型预览和诊断我们后面有更好的解决方法,YCM这两项功能干扰太大。

上面这几行配置具体每行的含义,可以见:《YouCompleteMe 中容易忽略的配置》。另外我在 Windows 下编译了一个版本,你用 Windows 的话无需下载VS编译,点击这里。我日常开发使用 YCM 辅助编写 C/C++, Python 和 Go 代码,基本能提供 IDE 级别的补全。

函数列表

不再建议使用tagbar, 它会在你保存文件的时候以同步等待的方式运行 ctags (即便你没有打开 tagbar),导致vim操作变卡,特别是 windows下开了反病毒软件扫描的话,有时候保存文件卡5-6秒。2018年了,我们有更好的选择,比如使用国人开发的LeaderF来显示函数列表:

全异步显示文件函数列表,不用的时候不会占用你任何屏幕空间,将 ALT+P 绑定到:LeaderfFunction这个命令上,按 ALT+P 就弹出当前文件的函数列表,然后可以进行模糊匹配搜索,还可以按 TAB 进入列表选择窗口,上下移动光标选择,按回车立马完成跳转并同时关闭列表。

Leaderf 的函数功能属于你想要它的时候它才会出来,不想要它的时候不会给你捣乱。

文件切换

文件/buffer模糊匹配快速切换的方式,比你打开一个对话框选择文件便捷不少,过去我们常用的 CtrlP 可以光荣下岗了,如今有更多速度更快,匹配更精准以及完美支持后台运行方式的文件模糊匹配工具。我自己用的是上面提到的LeaderF,除了提供函数列表外,还支持文件,MRU,Buffer名称搜索,完美代替 CtrlP,使用时需要简单调教下:

let g:Lf_ShortcutF = '<c-p>'
let g:Lf_ShortcutB = '<m-n>'
noremap <c-n> :LeaderfMru<cr>
noremap <m-p> :LeaderfFunction<cr>
noremap <m-n> :LeaderfBuffer<cr>
noremap <m-m> :LeaderfTag<cr>
let g:Lf_StlSeparator = { 'left': '', 'right': '', 'font': '' }

let g:Lf_RootMarkers = ['.project', '.root', '.svn', '.git']
let g:Lf_WorkingDirectoryMode = 'Ac'
let g:Lf_WindowHeight = 0.30
let g:Lf_CacheDirectory = expand('~/.vim/cache')
let g:Lf_ShowRelativePath = 0
let g:Lf_HideHelp = 1
let g:Lf_StlColorscheme = 'powerline'

let g:Lf_NormalMap = {
    \ "File":   [["<ESC>", ':exec g:Lf_py "fileExplManager.quit()"<CR>'],
    \            ["<F6>", ':exec g:Lf_py "fileExplManager.quit()"<CR>'] ],
    \ "Buffer": [["<ESC>", ':exec g:Lf_py "bufExplManager.quit()"<CR>'],
    \            ["<F6>", ':exec g:Lf_py "bufExplManager.quit()"<CR>'] ],
    \ "Mru":    [["<ESC>", ':exec g:Lf_py "mruExplManager.quit()"<CR>']],
    \ "Tag":    [["<ESC>", ':exec g:Lf_py "tagExplManager.quit()"<CR>']],
    \ "Function":    [["<ESC>", ':exec g:Lf_py "functionExplManager.quit()"<CR>']],
    \ "Colorscheme":    [["<ESC>", ':exec g:Lf_py "colorschemeExplManager.quit()"<CR>']],
    \ }

这里定义了 CTRL+P 在当前项目目录打开文件搜索,CTRL+N 打开 MRU搜索,搜索你最近打开的文件,这两项是我用的最频繁的功能。接着 ALT+P 打开函数搜索,ALT+N 打开 Buffer 搜索:

LeaderF 是目前匹配效率最高的,高过 CtrlP/Fzf 不少,敲更少的字母就能把文件找出来,同时搜索很迅速,使用 Python 后台线程进行搜索匹配,还有一个 C模块可以加速匹配性能,需要手工编译下。LeaderF在模糊匹配模式下按 TAB 可以切换到匹配结果窗口用光标或者 Vim 搜索命令进一步筛选,这是 CtrlP/Fzf 不具备的,更多方便的功能见它的官方文档。

文件/MRU 模糊匹配对于熟悉的项目效率是最高的,但对于一个新的项目,通常我们都不知道它有些什么文件,那就谈不上根据文件名匹配什么了,我们需要文件浏览功能。如果你喜欢把 Vim 伪装成 NotePad++ 之类的,那你该继续使用NERDTree进行文件浏览,但你想按照 Vim 的方式来,推荐阅读这篇文章:

Oil and vinegar – split windows and project drawer

然后向我一样开始使用vim-dirvish,进行一些配置,比如当前文档按-号就能不切窗口的情况下在当前窗口直接返回当前文档所在的目录,再按一次减号就返回上一级目录,按回车进入下一级目录或者再当前窗口打开光标下的文件。进一步映射<tab>7,<tab>8和<tab>9分别用于在新的 split, vsplit 和新标签打开当前文件所在目录,这样从一个文件如手,很容易找到和该文件相关的其他项目文件。

最后一个是 C/C++ 的头文件/源文件快速切换功能,有现成的插件做这事情,比如a.vim,我自己没用,因为这事情太简单,再我发现 a.vim 前我就觉得需要这个功能,然后自己两行 vim 脚本就搞定了。

参数提示

这个功能应人而异,有人觉得不需要,有人觉得管用。写 C/C++ 时函数忘了可以用上面的 YCM 补全,但很多时候是参数忘记了怎么办?YCM的参数提示很蛋疼,要打开个 Preview 窗口,实在是太影响我的视线了,我自己写过一些参数提醒功能,可以在最下面的命令行显示当前函数的参数,不过这是基于 tags 的,搭配前面的 gutentags,对其他语言很管用,但对 C/C++ 我们可以使用echodoc插件:

它可以无缝的和前面的 YCM 搭配,你用 YCM 时 tab 补全了一个函数名后,只要输入左括号,下面命令行就会里面显示出该函数的参数信息,唯一需要设置的是使用set noshowmode关闭模式提示,就是底部 —INSERT— 那个,我们一般都用 airline / lightline 之类的显示当前模式了,所以默认模式提示可以关闭,INSERT 模式下的命令行,完全留给 echodoc 显示参数使用。

更多阅读

2018年了,用点新方法,网上那些 Vim 开发 C/C++ 的文章真的都可以淘汰了。

更多参考:《Vim 中文版入门到精通》 和《Vim 中文速查表》。本文主要是针对 C/C++ 环境搭建的插件介绍,关于基本使用,欢迎参考上面这些链接。篇幅有限,这里只能谈一部分内容,对大多数人已经够了,如果你想继续深入的话,还可以慢慢折腾诸如 git 集成,帮助文档集成,调试,rtags 以及 lsp 这些东西。

]]>
0
<![CDATA[美好世界,源自不开心。]]> http://www.udpwork.com/item/16797.html http://www.udpwork.com/item/16797.html#reviews Sat, 21 Apr 2018 00:00:00 +0800 yanyiwu http://www.udpwork.com/item/16797.html Linus 对只停留在实验室阶段,迟迟走不进工业界的 Unix 操作系统忍无可忍,觉得非常不开心,于是自己写了 Linux ,成为服务端操作系统的世界主宰。

乔布斯对塞班手机下载一个日历应用都需要搜索各种论坛,才能找到一个可以安装成功的安装包,觉得非常不开心,于是开发了划时代产品iPhone ,把人类带入了移动互联网时代。

雷军对于华强北各种粗制滥造的山寨机忍无可忍,带着十几个兄弟,干了一锅小米粥,创办了可能是中国有史以来最伟大的手机厂商,小米。

胡玮炜对于ofo机械锁经常输错密码,忍无可忍,于是创办了摩拜单车,曾经一度成为共享出行业界龙头,最后为了梦想和现金,加入美团。

马云对于银行营业厅存取款,业务办理,排队十几米的等待忍无可忍,做出了支付宝,让手机支付成了中国新四大发明之一。

张小龙深夜寂寞无处排遣,在「饭否」振臂高呼出一句「明天去东莞」之后,但是从东莞回来后仍然不开心,于是创办了微信,让社交进入了语音时代。

扎克伯克在哈佛校园内追妹子,却发现连个头像照片都找不到,非常不开心,于是创建了Facebook,从此校园的爱恨情愁,无病呻吟,都走上了社交网络。

王兴对于淘宝上无法买美食,饥肠辘辘,日渐消瘦,忍无可忍,创办美团,从此接管人类的吃住行。

中本聪对于携带笨重的黄金忍无可忍,郁郁度日,于是发布了比特币白皮书,用代码创造了数字货币的共识新解决方案,开启区块链时代。

V神理解到不只是货币需要共识,这个世界上的任何事都需要共识,对于比特币无法运载智能合约,创造了以太坊,从此「代码即共识」,让共识成为了世界上永恒的主题。

BM对于目前区块链链路性能低下,比特币居然每秒钟只能转账7笔交易,忍无可忍,于是创办了币圈最大众筹项目EOS,用增发代替手续费,让区块链交易走入了免费时代。

忍无可忍,无需再忍。
不开心,才能拯救世界。
美好世界,源自不开心。

以上内容纯属虚构。

]]>
Linus 对只停留在实验室阶段,迟迟走不进工业界的 Unix 操作系统忍无可忍,觉得非常不开心,于是自己写了 Linux ,成为服务端操作系统的世界主宰。

乔布斯对塞班手机下载一个日历应用都需要搜索各种论坛,才能找到一个可以安装成功的安装包,觉得非常不开心,于是开发了划时代产品iPhone ,把人类带入了移动互联网时代。

雷军对于华强北各种粗制滥造的山寨机忍无可忍,带着十几个兄弟,干了一锅小米粥,创办了可能是中国有史以来最伟大的手机厂商,小米。

胡玮炜对于ofo机械锁经常输错密码,忍无可忍,于是创办了摩拜单车,曾经一度成为共享出行业界龙头,最后为了梦想和现金,加入美团。

马云对于银行营业厅存取款,业务办理,排队十几米的等待忍无可忍,做出了支付宝,让手机支付成了中国新四大发明之一。

张小龙深夜寂寞无处排遣,在「饭否」振臂高呼出一句「明天去东莞」之后,但是从东莞回来后仍然不开心,于是创办了微信,让社交进入了语音时代。

扎克伯克在哈佛校园内追妹子,却发现连个头像照片都找不到,非常不开心,于是创建了Facebook,从此校园的爱恨情愁,无病呻吟,都走上了社交网络。

王兴对于淘宝上无法买美食,饥肠辘辘,日渐消瘦,忍无可忍,创办美团,从此接管人类的吃住行。

中本聪对于携带笨重的黄金忍无可忍,郁郁度日,于是发布了比特币白皮书,用代码创造了数字货币的共识新解决方案,开启区块链时代。

V神理解到不只是货币需要共识,这个世界上的任何事都需要共识,对于比特币无法运载智能合约,创造了以太坊,从此「代码即共识」,让共识成为了世界上永恒的主题。

BM对于目前区块链链路性能低下,比特币居然每秒钟只能转账7笔交易,忍无可忍,于是创办了币圈最大众筹项目EOS,用增发代替手续费,让区块链交易走入了免费时代。

忍无可忍,无需再忍。
不开心,才能拯救世界。
美好世界,源自不开心。

以上内容纯属虚构。

]]>
0
<![CDATA[数据库用上了腾讯云]]> http://www.udpwork.com/item/16796.html http://www.udpwork.com/item/16796.html#reviews Thu, 19 Apr 2018 10:04:20 +0800 s5s5 http://www.udpwork.com/item/16796.html 腾讯云最近上了一个云数据库 MySQL 入门机型,只要 12 块一个月,多买还有优惠。我一听这个消息立马就把网站的数据库移到腾讯云上了,之前虽然也在腾讯云上,但也只是在服务器上自建了一个 MySQL,现在好了用上了云数据库,备份、性能优化什么的都自动完成了,只管用就可以了。

买了后,主要用以下方法导入以前的方法导入即可:

  1. 买数据库入门机型(如果是服务器在腾讯云选同地域的,不是的话后面要开启外网访问)
  2. 在数据库控制台初始化实例(记住你设置的 root 密码)
  3. 从控制台点 管理 进入 实例详情
  4. 进入 数据库管理 – 数据库列表
  5. 点 导入数据
  6. 按提示导入你之前导出的数据 (注意你导出的 SQL 有没有建库语句,没建库在右上角点 登录 进数据库管理新建库)
  7. 进入 实例详情,记下数据库内网地址(我是同地域的,不是的话要开启外网访问)
  8. 配置 WordPress 配置文件 wp-config.php 中数据库相关配置项
  9. 完成,看看效果吧

基本上配置一次,后面就没啥事了。

数据库用上了腾讯云最先出现在[米随随] s5s5

]]>
腾讯云最近上了一个云数据库 MySQL 入门机型,只要 12 块一个月,多买还有优惠。我一听这个消息立马就把网站的数据库移到腾讯云上了,之前虽然也在腾讯云上,但也只是在服务器上自建了一个 MySQL,现在好了用上了云数据库,备份、性能优化什么的都自动完成了,只管用就可以了。

买了后,主要用以下方法导入以前的方法导入即可:

  1. 买数据库入门机型(如果是服务器在腾讯云选同地域的,不是的话后面要开启外网访问)
  2. 在数据库控制台初始化实例(记住你设置的 root 密码)
  3. 从控制台点 管理 进入 实例详情
  4. 进入 数据库管理 – 数据库列表
  5. 点 导入数据
  6. 按提示导入你之前导出的数据 (注意你导出的 SQL 有没有建库语句,没建库在右上角点 登录 进数据库管理新建库)
  7. 进入 实例详情,记下数据库内网地址(我是同地域的,不是的话要开启外网访问)
  8. 配置 WordPress 配置文件 wp-config.php 中数据库相关配置项
  9. 完成,看看效果吧

基本上配置一次,后面就没啥事了。

数据库用上了腾讯云最先出现在[米随随] s5s5

]]>
0
<![CDATA[关于国内程序员肉身翻墙]]> http://www.udpwork.com/item/16795.html http://www.udpwork.com/item/16795.html#reviews Wed, 18 Apr 2018 13:48:51 +0800 四火 http://www.udpwork.com/item/16795.html Image result for 翻墙本来是没有倾向谈论这个话题的,但是最近邮件或者微信问我这个问题的国内程序员朋友很多,我在这里一并介绍一下,也算作简单的解答。同样的问题就直接参阅即可。事实上,我很乐意收到这样或者那样的问题,也包括肉身翻墙这样的话题,混熟了的话瞎扯也开心。但是也请大家注意一点礼貌,有好几次有程序员没头没脑地微信上跳出来问问题,然而话都说不清楚,或者连个招呼也不会打,更有甚者二话不说直接把log贴过来让我看问题,实在是让人觉得很不舒服。有些我回复了,有些我实在是不想回复了。另外,具体的问题我比较好解答,像有不少人问我,“你觉得美国怎么样?”,我都不知道从何说起。具体问题还是邮件沟通更合适,我答复起来也更舒服,微信更适合有一句没一句的扯淡。另外,要说明的是,因为我是14年搬到西雅图的,并不算待了很久,我也有一些其它国家的程序员朋友,但是我只谈论美国,因为我也没有其它的经历。

首先,我觉得需要问自己一个问题,为什么要出国工作?是一时脑热么?别人的饭碗里的饭,闻起来总是香的;别人的生活,看起来总是美的。但轮到自己的时候,却不一定如此。如果你想去哪个国家工作,那么至少办理旅游签证去玩一玩、看一看吧?签证有时候会很麻烦,这没错,可是连这样的事情都不做的,下了决心立了志愿又有多少可信度呢?现在旅行那么方便,旅游签证又已经是10年签了,出行应该说不能算什么问题。不同人生活上的追求千千万,找到自己最喜欢的,或许才是最合适的。而怎么才能认定喜欢,肯定是去看看最保险了。当明确了目的和原因,那么才往后思考才有足够的意义。

接着,我想泼一点冷水,谈谈我觉得在海外工作令我失去的东西。

1. 朋友和亲人。这不必细谈了。会认识新朋友,但是绝大多数的交际圈和亲人都会远去,而对于远行后父母养老的顾虑,也是很常见的。

2. 便捷的生活。我记得几年前住在北京的时候,下楼就是一条便利街,从吃饭剪头到购物遛狗,日常服务都有了,踢个球打个篮球,边上就是球场和gym,每天可以步行上班,怎一个方便了得……现在呢,不开车出门就相当于残疾一样,最近的公交车站要走很远,更何况公交系统远没有国内发达,经常一小时一班车,还得倒车才能去市区(西雅图)。

3. 职业生涯的某些可能。你可以认为是职业生涯的瓶颈。语言问题和文化问题是夹杂在一起的,本质上是一类问题,无法分开。程序员这样靠技术吃饭的职业,依然需要语言文化这样强力结合的软能力,而这一点,从我观察来看,中国人普遍有短板,基本上能够奋斗到很高职位的母文化为中国文化的程序员,凤毛麟角。

还有很多其他的方面,但主要是以上。知道这些很重要,是帮助冷静下来做trade off的。

至于好的一面,已经有太多的文字了,我只说一点:

体验。不止是生活上。能在世界软件大国中的top 2都当过工程师工作过,实在是一个非常难得的经历。

接着我才说肉身翻墙的方式。据我所知,有这样三种,难度依次增加:

1. 海外读书,现在留学不同于20年前,学校的选择余地也很大。我身边的大多数华人朋友就是在国内读的大学,然后跑出来读研究生。这种方式的好处在于来到美国在语言方面的压力会小一点,并且在学校里右足够的机会得到语言的强化和锻炼。毕业前可以实习,这也是很好的留下工作的机会,比社招面试成功率要高很多。学生签证到期可以申请18个月的opt,因此有若干次机会进行H1B的抽签,每年的抽签中,如果是美国国内的硕士毕业身份会有两次不同概率的机会,总体抽中的概率还是比较高的。

2. 在一些大型跨国企业工作,然后藉由L1签证transfer到国外去。这种方式的选择余地没有第一种大,但是适合那些已经走出学校的程序员,先要面试进入外企,然后根据这些外企的内部转岗政策,至少在国内干满一年后,获得海外职位(这很可能需要经过面试、推荐、商谈等不同的阶段)。这种方式的好处在于可以带家属,而且家属在冗长的流程申请到L2的EAD后可以工作。在L1期间如果公司支持,每年都可以申请H1B签证,但是如果没有美国本土的硕士经历,抽中的概率不大,这两年中每年抽中的概率大概不到三成。如果身份没有变化,L签证在5年后到期,必须离境。

3. 直接投海外简历。这种方式最难,并不只是美国直接招聘的公司凤毛麟角,不只是候选人考察bar高,还包括这种方式无法办理L签证,只能走H1B这一条路,这也就意味着能否抽中签证并非自己能够控制,概率见上。如果面试通过,但是H签证没抽到,有的公司会把你送到别的英语国家去等一年继续抽。对于那些拖家带口的程序员来说,这无疑增加了许多不确定性。

当然,无论是哪一种,都会面临大量的签证等等材料的准备,甚至年年如此。在获得绿卡之前,身份问题一直是一个比较烦人的问题,通常公司会联系律师代理帮助,但依然会花费很多的心思和时间,但如果对那些文件材料准备看了就头大,恨之入骨的程序员,这显然是件很不好的事情。

最后,回答两个常见的关于海外求职方面的问题。

英语有多重要?就面试而言,英语很重要,但是远没有专业能力重要。能够沟通交流这是必须,否则一定会影响能力的打分。特别是对于投海外简历有兴趣的程序员,电话面试中能够沟通交流是一个必须要做到的事情。在语言层面耽搁的时间越少,留给自己花在问题本身上的思考和沟通交流的时间就越多。现在英语可以不那么好,但是职业的发展来说,英语机会是一个必要条件。我见过不少中文说起来头头是道的程序员,讲英文却要命一样。

适应异地他乡的生活有多难?这要看怎么定义“适应”这个词。直接来工作的话,前三个月会特别困难一点。几年后绝大多数事情都没有太大问题。但是长远看,最大的困难还是在文化上,文化背景的关系,主流的文化圈子还是很难进入,当然我们自己也有自己熟悉的圈子。而这个困难,基本是终生的。这个问题要看你怎么看了,有的人在乎,有的人不在乎。

就说这些吧。

文章未经特殊标明皆为本人原创,未经许可不得用于任何商业用途,转载请保持完整性并注明来源链接《四火的唠叨》

]]>
Image result for 翻墙本来是没有倾向谈论这个话题的,但是最近邮件或者微信问我这个问题的国内程序员朋友很多,我在这里一并介绍一下,也算作简单的解答。同样的问题就直接参阅即可。事实上,我很乐意收到这样或者那样的问题,也包括肉身翻墙这样的话题,混熟了的话瞎扯也开心。但是也请大家注意一点礼貌,有好几次有程序员没头没脑地微信上跳出来问问题,然而话都说不清楚,或者连个招呼也不会打,更有甚者二话不说直接把log贴过来让我看问题,实在是让人觉得很不舒服。有些我回复了,有些我实在是不想回复了。另外,具体的问题我比较好解答,像有不少人问我,“你觉得美国怎么样?”,我都不知道从何说起。具体问题还是邮件沟通更合适,我答复起来也更舒服,微信更适合有一句没一句的扯淡。另外,要说明的是,因为我是14年搬到西雅图的,并不算待了很久,我也有一些其它国家的程序员朋友,但是我只谈论美国,因为我也没有其它的经历。

首先,我觉得需要问自己一个问题,为什么要出国工作?是一时脑热么?别人的饭碗里的饭,闻起来总是香的;别人的生活,看起来总是美的。但轮到自己的时候,却不一定如此。如果你想去哪个国家工作,那么至少办理旅游签证去玩一玩、看一看吧?签证有时候会很麻烦,这没错,可是连这样的事情都不做的,下了决心立了志愿又有多少可信度呢?现在旅行那么方便,旅游签证又已经是10年签了,出行应该说不能算什么问题。不同人生活上的追求千千万,找到自己最喜欢的,或许才是最合适的。而怎么才能认定喜欢,肯定是去看看最保险了。当明确了目的和原因,那么才往后思考才有足够的意义。

接着,我想泼一点冷水,谈谈我觉得在海外工作令我失去的东西。

1. 朋友和亲人。这不必细谈了。会认识新朋友,但是绝大多数的交际圈和亲人都会远去,而对于远行后父母养老的顾虑,也是很常见的。

2. 便捷的生活。我记得几年前住在北京的时候,下楼就是一条便利街,从吃饭剪头到购物遛狗,日常服务都有了,踢个球打个篮球,边上就是球场和gym,每天可以步行上班,怎一个方便了得……现在呢,不开车出门就相当于残疾一样,最近的公交车站要走很远,更何况公交系统远没有国内发达,经常一小时一班车,还得倒车才能去市区(西雅图)。

3. 职业生涯的某些可能。你可以认为是职业生涯的瓶颈。语言问题和文化问题是夹杂在一起的,本质上是一类问题,无法分开。程序员这样靠技术吃饭的职业,依然需要语言文化这样强力结合的软能力,而这一点,从我观察来看,中国人普遍有短板,基本上能够奋斗到很高职位的母文化为中国文化的程序员,凤毛麟角。

还有很多其他的方面,但主要是以上。知道这些很重要,是帮助冷静下来做trade off的。

至于好的一面,已经有太多的文字了,我只说一点:

体验。不止是生活上。能在世界软件大国中的top 2都当过工程师工作过,实在是一个非常难得的经历。

接着我才说肉身翻墙的方式。据我所知,有这样三种,难度依次增加:

1. 海外读书,现在留学不同于20年前,学校的选择余地也很大。我身边的大多数华人朋友就是在国内读的大学,然后跑出来读研究生。这种方式的好处在于来到美国在语言方面的压力会小一点,并且在学校里右足够的机会得到语言的强化和锻炼。毕业前可以实习,这也是很好的留下工作的机会,比社招面试成功率要高很多。学生签证到期可以申请18个月的opt,因此有若干次机会进行H1B的抽签,每年的抽签中,如果是美国国内的硕士毕业身份会有两次不同概率的机会,总体抽中的概率还是比较高的。

2. 在一些大型跨国企业工作,然后藉由L1签证transfer到国外去。这种方式的选择余地没有第一种大,但是适合那些已经走出学校的程序员,先要面试进入外企,然后根据这些外企的内部转岗政策,至少在国内干满一年后,获得海外职位(这很可能需要经过面试、推荐、商谈等不同的阶段)。这种方式的好处在于可以带家属,而且家属在冗长的流程申请到L2的EAD后可以工作。在L1期间如果公司支持,每年都可以申请H1B签证,但是如果没有美国本土的硕士经历,抽中的概率不大,这两年中每年抽中的概率大概不到三成。如果身份没有变化,L签证在5年后到期,必须离境。

3. 直接投海外简历。这种方式最难,并不只是美国直接招聘的公司凤毛麟角,不只是候选人考察bar高,还包括这种方式无法办理L签证,只能走H1B这一条路,这也就意味着能否抽中签证并非自己能够控制,概率见上。如果面试通过,但是H签证没抽到,有的公司会把你送到别的英语国家去等一年继续抽。对于那些拖家带口的程序员来说,这无疑增加了许多不确定性。

当然,无论是哪一种,都会面临大量的签证等等材料的准备,甚至年年如此。在获得绿卡之前,身份问题一直是一个比较烦人的问题,通常公司会联系律师代理帮助,但依然会花费很多的心思和时间,但如果对那些文件材料准备看了就头大,恨之入骨的程序员,这显然是件很不好的事情。

最后,回答两个常见的关于海外求职方面的问题。

英语有多重要?就面试而言,英语很重要,但是远没有专业能力重要。能够沟通交流这是必须,否则一定会影响能力的打分。特别是对于投海外简历有兴趣的程序员,电话面试中能够沟通交流是一个必须要做到的事情。在语言层面耽搁的时间越少,留给自己花在问题本身上的思考和沟通交流的时间就越多。现在英语可以不那么好,但是职业的发展来说,英语机会是一个必要条件。我见过不少中文说起来头头是道的程序员,讲英文却要命一样。

适应异地他乡的生活有多难?这要看怎么定义“适应”这个词。直接来工作的话,前三个月会特别困难一点。几年后绝大多数事情都没有太大问题。但是长远看,最大的困难还是在文化上,文化背景的关系,主流的文化圈子还是很难进入,当然我们自己也有自己熟悉的圈子。而这个困难,基本是终生的。这个问题要看你怎么看了,有的人在乎,有的人不在乎。

就说这些吧。

文章未经特殊标明皆为本人原创,未经许可不得用于任何商业用途,转载请保持完整性并注明来源链接《四火的唠叨》

]]>
0
<![CDATA[skynet cluster 模块的一点优化]]> http://www.udpwork.com/item/16794.html http://www.udpwork.com/item/16794.html#reviews Tue, 17 Apr 2018 15:21:21 +0800 云风 http://www.udpwork.com/item/16794.html 上周末,我对 skynet 的 cluster 模块做了一点优化。

cluster 模式是 skynet 的一种集群方案,用于将多台机器更为弹性的组成一个集群。我们将每台机器都赋予一个名字,然后就可以在集群间用这个名字向对方推送消息或发起请求。

集群的管理是一项非常复杂的工作,skynet 作为一个轻量化的框架,只实现了最基本的基础设施。cluster 这个基础设施已实现的部分并不复杂。在每个 skynet 进程中,我们启动了一个叫 clusterd 的服务,专门用于集群间的通讯。由 clusterd 再启动了一个 gate 服务,监听其它节点连过来的连接;同时,当前节点如果要对其它节点发送数据,也通过 clusterd 向外连接。业务要使用 cluster 的时候,都是通过 require "cluster" 这个库,然后这个库中的 api 负责和本节点的 clusterd 交换数据。

我们正在开发的一个 mmorpg 项目重度依赖了 cluster ,在过去的多次压力测试中,发现 clusterd 是测试中单位时间内消耗 CPU 最多的服务。它是整个 skynet 节点中的一个性能热点。所以我考虑了对这个 clusterd 做一些优化。

clusterd 在转发内部请求到外部的过程中,由于涉及消息转发,所以有几处地方需要拷贝/序列化消息。这个可以考虑优化为内存指针的传递。有些环节好做,有些环节不好做。我先把好做的部分改掉了。不好做的地方涉及对更底层 socket 模块的改造,为了避免优化改动涉及面太大,暂且放在一边。单单优化实现未必能获得特别的效益。

skynet 框架的目的就是为了充分发挥多核硬件的优势。在同一时间能把工作分摊到更多核心上处理,且不增加总体的工作量,才是最大的优化。从这个角度看,最容易做的优化是把 clusterd 负责对外请求的部分和接收外部请求的部分分离开。降低单个服务的 cpu 占用量就可以提高硬件对同时在线玩家的承载能力,且减少每个玩家消息处理的响应速度。

接收外部请求的部分是比较容易剥离的部分,因为它不需要了解 cluster 网络上各个节点的名字和地址的对应关系,而这个对应表可以是动态的,在 clusterd 中统一维护。接收请求只需要获得外部连接的网络包,解析出请求,转发给当前节点中的对应服务,然后把回应原路返回即可。

之前的版本中已经启用了一个 gate 来接受外部连接,只是过去把所有的请求又转回了 clusterd 。我改动成针对每个连接都启动一个新的 clusteragent 服务,然后让 gate 把数据转给它就行了。至于处理数据包的代码,简单的从 clusterd 中移到了新服务 clusteragent 中。由于每个连接都分开了,原来处理大数据包请求的部分还可以做一些简化。

周一,就这个修改,我们在已有的项目上做了压力测试。从数据看效果比较明显。由于我们的组网从功能上是对等结构,每个节点是等价的,所以在压力测试中 cluster 向外请求和接收请求数量是基本相同的。压测一个小时,发现 cluster 相关服务在处理的消息数量上是基本相同的。即过去被 clusterd 单一服务处理消息被分摊到了多个服务上。clusterd 保留了对外请求的功能,所以大致是原来 50% 的处理量。而剩下的 50% 则被分摊到了多个 clusteragent 上,数量正是节点数量减一。

由于 clusteragent 的相关消息转发环节还做了一些优化处理,减少了消息内存的拷贝,对消息转发的处理速度也比 clusterd 的转发速度快了一倍。经测试,在我们这台虚拟机上,差不多达到了 7 万条每秒。因为每个请求都要转发一个外部网络包,以及把内部的回应包转发出去,也就是可以达到每节点 3.5 万 qps 。

我们压力测试用的硬件 E5-2620 两块,有 24 核心,CPU 主频 2GHz 。这应该是 Intel 26 系列中最低档次的 CPU 。我们采购的比较早,如果是现在采购新的硬件,应该比它性能要好一些。我们的压力测试并没有完全跑满硬件的处理能力(cluster 相关服务的消息队列并未堆积过载)。我想 3.5 万 qps 应该能作为之后项目中, cluster 针对两个节点间互通的处理能力下限参考。这个处理能力和 CPU 单个核心的处理能力有关,和核心数量无关。

对于很多不对等的组集群的方式,很多节点的业务单一,处理着外部大量节点的请求,这次优化的意义可能更大。比如中心的登录及在线状态维护,信箱,等等业务都可以放在集群的一个单独节点上。cluster 的这次优化可以帮助这类节点消除之前 clusterd 是单一服务的热点问题。

]]>
上周末,我对 skynet 的 cluster 模块做了一点优化。

cluster 模式是 skynet 的一种集群方案,用于将多台机器更为弹性的组成一个集群。我们将每台机器都赋予一个名字,然后就可以在集群间用这个名字向对方推送消息或发起请求。

集群的管理是一项非常复杂的工作,skynet 作为一个轻量化的框架,只实现了最基本的基础设施。cluster 这个基础设施已实现的部分并不复杂。在每个 skynet 进程中,我们启动了一个叫 clusterd 的服务,专门用于集群间的通讯。由 clusterd 再启动了一个 gate 服务,监听其它节点连过来的连接;同时,当前节点如果要对其它节点发送数据,也通过 clusterd 向外连接。业务要使用 cluster 的时候,都是通过 require "cluster" 这个库,然后这个库中的 api 负责和本节点的 clusterd 交换数据。

我们正在开发的一个 mmorpg 项目重度依赖了 cluster ,在过去的多次压力测试中,发现 clusterd 是测试中单位时间内消耗 CPU 最多的服务。它是整个 skynet 节点中的一个性能热点。所以我考虑了对这个 clusterd 做一些优化。

clusterd 在转发内部请求到外部的过程中,由于涉及消息转发,所以有几处地方需要拷贝/序列化消息。这个可以考虑优化为内存指针的传递。有些环节好做,有些环节不好做。我先把好做的部分改掉了。不好做的地方涉及对更底层 socket 模块的改造,为了避免优化改动涉及面太大,暂且放在一边。单单优化实现未必能获得特别的效益。

skynet 框架的目的就是为了充分发挥多核硬件的优势。在同一时间能把工作分摊到更多核心上处理,且不增加总体的工作量,才是最大的优化。从这个角度看,最容易做的优化是把 clusterd 负责对外请求的部分和接收外部请求的部分分离开。降低单个服务的 cpu 占用量就可以提高硬件对同时在线玩家的承载能力,且减少每个玩家消息处理的响应速度。

接收外部请求的部分是比较容易剥离的部分,因为它不需要了解 cluster 网络上各个节点的名字和地址的对应关系,而这个对应表可以是动态的,在 clusterd 中统一维护。接收请求只需要获得外部连接的网络包,解析出请求,转发给当前节点中的对应服务,然后把回应原路返回即可。

之前的版本中已经启用了一个 gate 来接受外部连接,只是过去把所有的请求又转回了 clusterd 。我改动成针对每个连接都启动一个新的 clusteragent 服务,然后让 gate 把数据转给它就行了。至于处理数据包的代码,简单的从 clusterd 中移到了新服务 clusteragent 中。由于每个连接都分开了,原来处理大数据包请求的部分还可以做一些简化。

周一,就这个修改,我们在已有的项目上做了压力测试。从数据看效果比较明显。由于我们的组网从功能上是对等结构,每个节点是等价的,所以在压力测试中 cluster 向外请求和接收请求数量是基本相同的。压测一个小时,发现 cluster 相关服务在处理的消息数量上是基本相同的。即过去被 clusterd 单一服务处理消息被分摊到了多个服务上。clusterd 保留了对外请求的功能,所以大致是原来 50% 的处理量。而剩下的 50% 则被分摊到了多个 clusteragent 上,数量正是节点数量减一。

由于 clusteragent 的相关消息转发环节还做了一些优化处理,减少了消息内存的拷贝,对消息转发的处理速度也比 clusterd 的转发速度快了一倍。经测试,在我们这台虚拟机上,差不多达到了 7 万条每秒。因为每个请求都要转发一个外部网络包,以及把内部的回应包转发出去,也就是可以达到每节点 3.5 万 qps 。

我们压力测试用的硬件 E5-2620 两块,有 24 核心,CPU 主频 2GHz 。这应该是 Intel 26 系列中最低档次的 CPU 。我们采购的比较早,如果是现在采购新的硬件,应该比它性能要好一些。我们的压力测试并没有完全跑满硬件的处理能力(cluster 相关服务的消息队列并未堆积过载)。我想 3.5 万 qps 应该能作为之后项目中, cluster 针对两个节点间互通的处理能力下限参考。这个处理能力和 CPU 单个核心的处理能力有关,和核心数量无关。

对于很多不对等的组集群的方式,很多节点的业务单一,处理着外部大量节点的请求,这次优化的意义可能更大。比如中心的登录及在线状态维护,信箱,等等业务都可以放在集群的一个单独节点上。cluster 的这次优化可以帮助这类节点消除之前 clusterd 是单一服务的热点问题。

]]>
0
<![CDATA[一手华人人日 一手腾讯百度 梨视频喜提6亿巨资]]> http://www.udpwork.com/item/16792.html http://www.udpwork.com/item/16792.html#reviews Mon, 16 Apr 2018 15:18:42 +0800 魏武挥 http://www.udpwork.com/item/16792.html

邱兵是一个很大大咧咧的人。

吴晓波写文章《我的总编同学们》,说他很帅很邋遢,后面是实话,前面纯属恭维。

与他当年在澎湃三年三篇情怀文相对应的事是,这哥们并不像文字所展现出来的那种书卷气十足。

他很喜欢看某个内容客户端,并且会由于太过投入而坐在马桶上长达半小时之久。

有机会我一定要提示他注意健康。

但他又不太乐意让别人知道这事,所以他断言那个产品很难社交化:让吴晓波知道我喜欢看这个,还被他发现我喜欢看哪些文章,不太好吧?

 

去年他有一次神神秘秘地和我讲,梨视频正在做融资,投资方如何如何牛逼。

我表示我想到“刷屏”里吼一声:有人做了个小混改啊!

他一脸苦相地求我不要大嘴巴,因为还没有完全落实。

不过我还是在“刷屏”里吼了一声,只是语焉不详,并没有说是梨视频,也没有说都有哪些牛逼的投资方投资了这个短视频平台。

时至今日,尘埃落定。

梨视频接受了腾讯领投共四方总计6个多亿的投资。投后TOP4投资人占股比例排序:华人文化、腾讯、人民网和百度。估值大概在30亿上下。

除了阿里没有加入,真有点迷你混改的意思:国媒巨头+江湖大佬。

 

当年他离开澎湃,是从一个幼儿园公号里暗搓搓地发布了消息。他去他女儿幼儿园做了一次分享,提到了他卸去了澎湃CEO一职。在那篇分享中,还是很能看出一个父亲对女儿的疼爱的。

不过他从来不在朋友圈晒娃。

邱兵的朋友圈很单调,一般每天七八条,量多的日子会丧心病狂的多达数十条。单调就单调在,除了转发梨视频的东西,几乎没有任何其他内容——大多数男性创业者和一小部分女性创业者都这个德性,拼命给自家企业刷存在感,乏味之至。

但如此单调没有变化的朋友圈,倒也不失趣味,因为梨视频还是有不少好玩的东西,比如前两天邱兵就转发了一条狗拳的短视频:虽然毫无战斗力,但招式真的好生搞笑。

梨视频由于某条视频,是吃过亏的,然后就全面转向为生活化,但邱自己则更喜欢用“民生化”这个标签来定义这个平台的内容调性。

当下内容行业的大气候和背景,对时政类内容不利,同样对三俗类内容也不利,反倒是对梨视频这种民生化的有利。

更加上它拿到了人日系的投资,邱兵常年的一种焦虑,想必有了很有效的缓解。

我总觉得,一个坐在马桶上连刷半小时事后自己都觉得空虚但依然不晓得爬起来的人,骨子里是有焦虑的。

 

30个亿的估值,应该是内容视频领域里的一个benchmark。

这种短视频的生产,比纪录片式的长视频轻,但比抖音快手类的小视频重,国内官媒体系也是有人做的,比如新京报的我们。

一位互联网从业人士在微头条上这样评价短视频:

短视频能火,是因为人的回忆就是由短视频构成的。不是文字,不是静止的图片,也不是长视频。就是由一个个短视频构成。好莱坞牛逼动画片《头脑特工队》里,描述人大脑重要的核心记忆球,也是短视频样式。

邱兵对特斯拉的马斯克曾经转过他们的视频,很是骄傲。他最近一个心得是,其实那些看上去很严肃乃至于到有些boring的场合,一个短视频一样能带起巨大的关注。

因为短视频会提供图文无法表达的观感,孙宏斌说自己是傻逼,蓝衣女怼红衣女的白眼,的确是把那些严肃到颇有些boring的场合弄成了全民关注的议题。

由第三方(拍客)提供素材,然后经梨视频剪辑加工,再加以全网发布。为了支撑数万名拍客,梨视频还开发了一套管理系统Spider,这被邱兵称为统治级别的系统。

邱兵很希望2018年这个体系能有五万名核心活跃拍客。其中有个路径就是:一帮地方传统媒体能成为梨视频拍客,并开设在梨视频上的官方号。这符合梨视频在地化的目标。

他用跑出去给人讲媒体融合转型的方式,当做BD的手段之一。

不过,作为复旦的高材生,他也有些落寞。

一次酒喝多了的时候,他提到,跑出去讲课居然只有两千块。

我安慰他,你一个中级职称,当然只有两千块。体制内初级给一千,中级给两千,高级给三千,院士也就五千。符合规矩。

他露出一副恍然大悟的表情之后问我:那你什么职称啊?

 

邱兵执掌东方早报的时候,他的副总编们,是很出了一些风云人物的。

比如吴晓波。

吴晓波还是他复旦的同学。

吴晓波才叫一个帅(真的,说邱兵帅我实在无法接受),再加上真叫一个功成名就,于是他们的同学聚会,大家纷纷找吴晓波合影留念。

邱兵对这件事耿耿于怀,因为没啥人要和他合影。

30亿的估值,总算让邱兵在被同龄人抛弃的路上,又紧赶慢赶了几步。

30亿的估值,也使得他把当年的一位副总编给抛下了。

右边这位愁眉苦脸一脸皮笑肉不笑拼命躲闪左边邱兵灌酒的同学,一手创办的新榜,大概也就10个亿上下吧。

 

骨子里,邱兵其实很传统。

他不会用支付宝,我估计这就是为什么小混改里阿里缺席的原因吧:居然连支付宝都不会用,还想拿我们投资么?

他对互联网有很强的陌生感,以至于王兴在他朋友圈里他一直不知道这哥们到底是谁。不过幸好他除了会转发梨视频的东西,也没其它内容了。

我告诉他,如果他既想看一点事实上蛮三俗无需动脑的东西但又想保持对外的逼格,可以看即刻。

他一脸懵逼地问我,即刻是什么东西?

好了,现在不用懵逼了。你们是兄弟公司了。

在内容环境颇有些严酷的2018年,梨视频一举拿下可能是内容创业领域最大的单笔融资,真是有钱又有背景的主了。

实属可喜可贺。

不过,我想,以后邱兵再出去讲课,两千都拿不到了吧?

]]>

邱兵是一个很大大咧咧的人。

吴晓波写文章《我的总编同学们》,说他很帅很邋遢,后面是实话,前面纯属恭维。

与他当年在澎湃三年三篇情怀文相对应的事是,这哥们并不像文字所展现出来的那种书卷气十足。

他很喜欢看某个内容客户端,并且会由于太过投入而坐在马桶上长达半小时之久。

有机会我一定要提示他注意健康。

但他又不太乐意让别人知道这事,所以他断言那个产品很难社交化:让吴晓波知道我喜欢看这个,还被他发现我喜欢看哪些文章,不太好吧?

 

去年他有一次神神秘秘地和我讲,梨视频正在做融资,投资方如何如何牛逼。

我表示我想到“刷屏”里吼一声:有人做了个小混改啊!

他一脸苦相地求我不要大嘴巴,因为还没有完全落实。

不过我还是在“刷屏”里吼了一声,只是语焉不详,并没有说是梨视频,也没有说都有哪些牛逼的投资方投资了这个短视频平台。

时至今日,尘埃落定。

梨视频接受了腾讯领投共四方总计6个多亿的投资。投后TOP4投资人占股比例排序:华人文化、腾讯、人民网和百度。估值大概在30亿上下。

除了阿里没有加入,真有点迷你混改的意思:国媒巨头+江湖大佬。

 

当年他离开澎湃,是从一个幼儿园公号里暗搓搓地发布了消息。他去他女儿幼儿园做了一次分享,提到了他卸去了澎湃CEO一职。在那篇分享中,还是很能看出一个父亲对女儿的疼爱的。

不过他从来不在朋友圈晒娃。

邱兵的朋友圈很单调,一般每天七八条,量多的日子会丧心病狂的多达数十条。单调就单调在,除了转发梨视频的东西,几乎没有任何其他内容——大多数男性创业者和一小部分女性创业者都这个德性,拼命给自家企业刷存在感,乏味之至。

但如此单调没有变化的朋友圈,倒也不失趣味,因为梨视频还是有不少好玩的东西,比如前两天邱兵就转发了一条狗拳的短视频:虽然毫无战斗力,但招式真的好生搞笑。

梨视频由于某条视频,是吃过亏的,然后就全面转向为生活化,但邱自己则更喜欢用“民生化”这个标签来定义这个平台的内容调性。

当下内容行业的大气候和背景,对时政类内容不利,同样对三俗类内容也不利,反倒是对梨视频这种民生化的有利。

更加上它拿到了人日系的投资,邱兵常年的一种焦虑,想必有了很有效的缓解。

我总觉得,一个坐在马桶上连刷半小时事后自己都觉得空虚但依然不晓得爬起来的人,骨子里是有焦虑的。

 

30个亿的估值,应该是内容视频领域里的一个benchmark。

这种短视频的生产,比纪录片式的长视频轻,但比抖音快手类的小视频重,国内官媒体系也是有人做的,比如新京报的我们。

一位互联网从业人士在微头条上这样评价短视频:

短视频能火,是因为人的回忆就是由短视频构成的。不是文字,不是静止的图片,也不是长视频。就是由一个个短视频构成。好莱坞牛逼动画片《头脑特工队》里,描述人大脑重要的核心记忆球,也是短视频样式。

邱兵对特斯拉的马斯克曾经转过他们的视频,很是骄傲。他最近一个心得是,其实那些看上去很严肃乃至于到有些boring的场合,一个短视频一样能带起巨大的关注。

因为短视频会提供图文无法表达的观感,孙宏斌说自己是傻逼,蓝衣女怼红衣女的白眼,的确是把那些严肃到颇有些boring的场合弄成了全民关注的议题。

由第三方(拍客)提供素材,然后经梨视频剪辑加工,再加以全网发布。为了支撑数万名拍客,梨视频还开发了一套管理系统Spider,这被邱兵称为统治级别的系统。

邱兵很希望2018年这个体系能有五万名核心活跃拍客。其中有个路径就是:一帮地方传统媒体能成为梨视频拍客,并开设在梨视频上的官方号。这符合梨视频在地化的目标。

他用跑出去给人讲媒体融合转型的方式,当做BD的手段之一。

不过,作为复旦的高材生,他也有些落寞。

一次酒喝多了的时候,他提到,跑出去讲课居然只有两千块。

我安慰他,你一个中级职称,当然只有两千块。体制内初级给一千,中级给两千,高级给三千,院士也就五千。符合规矩。

他露出一副恍然大悟的表情之后问我:那你什么职称啊?

 

邱兵执掌东方早报的时候,他的副总编们,是很出了一些风云人物的。

比如吴晓波。

吴晓波还是他复旦的同学。

吴晓波才叫一个帅(真的,说邱兵帅我实在无法接受),再加上真叫一个功成名就,于是他们的同学聚会,大家纷纷找吴晓波合影留念。

邱兵对这件事耿耿于怀,因为没啥人要和他合影。

30亿的估值,总算让邱兵在被同龄人抛弃的路上,又紧赶慢赶了几步。

30亿的估值,也使得他把当年的一位副总编给抛下了。

右边这位愁眉苦脸一脸皮笑肉不笑拼命躲闪左边邱兵灌酒的同学,一手创办的新榜,大概也就10个亿上下吧。

 

骨子里,邱兵其实很传统。

他不会用支付宝,我估计这就是为什么小混改里阿里缺席的原因吧:居然连支付宝都不会用,还想拿我们投资么?

他对互联网有很强的陌生感,以至于王兴在他朋友圈里他一直不知道这哥们到底是谁。不过幸好他除了会转发梨视频的东西,也没其它内容了。

我告诉他,如果他既想看一点事实上蛮三俗无需动脑的东西但又想保持对外的逼格,可以看即刻。

他一脸懵逼地问我,即刻是什么东西?

好了,现在不用懵逼了。你们是兄弟公司了。

在内容环境颇有些严酷的2018年,梨视频一举拿下可能是内容创业领域最大的单笔融资,真是有钱又有背景的主了。

实属可喜可贺。

不过,我想,以后邱兵再出去讲课,两千都拿不到了吧?

]]>
0
<![CDATA[大学,难道不应该禁止师生恋么?]]> http://www.udpwork.com/item/16793.html http://www.udpwork.com/item/16793.html#reviews Mon, 16 Apr 2018 15:15:38 +0800 魏武挥 http://www.udpwork.com/item/16793.html

网上开始流传一个实名举报:现长江学者沈阳教授,20年前性侵一名女学生。

后该生在就读期间自杀。

我看到的时候,访问量才两万多,但现在已经过了十万加。

另外还有一篇文章,是女生当年两位同学所写,也应该视为一种实名举报。

有人说,这二十年的陈年旧案,现在再翻出来,举报人当年干什么去了?

我觉得还是要持平而论。

二十年前,整个大环境大气候不是这样的。举报人后面留下了当下的工作单位:1、三名在美国执教,一名定居加拿大,很可能受到了metoo的影响;2、到底是实名举报,也是押上了自己的声名的。

退一万步讲,迟到的正义,总比缺席的正义好罢!

 

在举报信的最后,举报人是这么写的:

本文提及的性侵,并非严格的法律意义上的概念,而更多的是师风、师德意义上的概念。

我对这句话的理解,大概应该是指,并不是举报沈阳强奸女学生。

一位朋友也说,按照追诉期,20年前的案子,现在也已经过了。

举报信就沈阳到底有没有和女学生发生实质性关系,写的比较隐晦和曲折。但的确是发生关系了,细读就能明白,不再赘述。

但举报人又说不是严格的法律意义上的概念,这里不太好懂。

不过,在举报人写的那句话上面还有一段:

所谓性侵,指任何未经同意的性行为。换言之,即使对方没有说“no”(不,绝对不行),只要她或他没有说“yes”(是,可以),而你却跟人家发生了性关系,就已然构成了性侵。可见,对方是否知情与许可,是界定性侵的主要标准。

我不是法律专家,也不知道这段话是不是真的就是符合法理。但根据逻辑来讲:

1、举报人知道她的同学与沈阳发生了性关系。

2、举报人说性侵是指只要不说yes,就是。

3、举报人说本文说的性侵,不是法律意义上的概念。

推论而得:女学生可能真的至少说过一次“yes”,虽然心里是不愿意的。

 

我一直听说,我所在的上海交大,是严禁师生谈恋爱的。

可能我小讲师一枚,级别不够,没有看到过相关红头文件。

但我非常支持这样的规矩,如果有的话。

我个人极度鄙视师生恋,大致有这样几个原因:

1、存在可能仗势压人,如果老师和学生的关系,还是导师和弟子的关系的话。

2、虽然大学生大部分已经是成年人,但到底涉世未深,属于欺骗无知少女/男

3、这个观念你可以说我传统:老师总是要讲师德的吧?

4、这个老师的社交圈太窄了,搞来搞去都是自己的学生,丢不丢人?

5、如果该大学地处郊区(今天中国很多大学都不太在市中心),该老师占人家便宜还不肯支付高额成本——郊区大学旁边没什么可消费的地方,这点很猥琐啊。

文科院校,师生恋其实很多年了,我从教十一年,也就鄙视了十一年。

师生恋不是两个成年人间正常的恋爱,因为它实在是瓜田李下,有太多的说不清楚。

 

我们学院最近进行了一次拆分,细心的读者可能已经发现,我底下那条小尾巴,已经从“媒体与设计学院”变成了“媒体与传播学院”:设计系独立成院了。

媒体传播学院近日喜提新办公大楼,组织上派员前来调研教工对新办公场地的装修要求。

部分同仁提出,应该每个教师都配备独立办公室一间。

这个提议我是理解的,到底东北那所职校的新闻学院,真的是人手一间。

但我用开玩笑的方式提出了反对。

教师一人一间办公室,来个学生聊正事,其实不方便的。我院男教师居多,女学生又是乌央乌央的一堆,学生跑上门来,为避嫌我还得开着个门。

两个人一间就不太需要了。虽然大学老师也不坐班,但到底你吃不准另外一个啥时候会跑进来,嫌疑会少很多。

虽然我的语气是玩笑的,但我是真心这么想的。

要独立一间办公室干啥?

文科搞研究没啥的,有时候图书馆坐着都可以弄。

 

在一个满是新传老师的大群里,我表达了师生恋是不对的观点。

有朋友表示支持。

如果是真爱,那就等毕业后再谈吧。实在是等不及了,要不学生退学,或老师辞职?

是,本来成年人之间的私事,双方你情我愿,旁人真不该说三道四。

但老师和学生并不是,因为这里的所谓你情我愿,实在是说不清道不明。

导师不签字,学生就无法开题,后面什么答辩、毕业都不用讲了,这里的学生包括本硕博三阶段。

至于有些学生想入党想做学生官(学生会那种的),都得班主任签字。

学生毕业如果是通过公务员考试去做公务员,接收单位做背景调查是要给班主任打电话的。

大学,应该禁止,完全禁止,师生恋。

管你什么真爱不真爱。

 

这个沈阳教授真的是蛮卑鄙的。

女生自杀后,一直在试图撇清此事与他有关。

按照举报信的说法,甚至说过这样的话:

有人为我自杀,这说明我有魅力!

我呸

也就是专盯懵懵懂懂的女学生下手,外边姑娘大概都瞧不上你吧?这也叫有魅力?

 

—— 首发 扯氮集 ——

作者执教于上海交通大学媒体与传播学院,天奇阿米巴创投基金管理合伙人

大学,难道不应该禁止师生恋么?最先出现在扯氮集

]]>

网上开始流传一个实名举报:现长江学者沈阳教授,20年前性侵一名女学生。

后该生在就读期间自杀。

我看到的时候,访问量才两万多,但现在已经过了十万加。

另外还有一篇文章,是女生当年两位同学所写,也应该视为一种实名举报。

有人说,这二十年的陈年旧案,现在再翻出来,举报人当年干什么去了?

我觉得还是要持平而论。

二十年前,整个大环境大气候不是这样的。举报人后面留下了当下的工作单位:1、三名在美国执教,一名定居加拿大,很可能受到了metoo的影响;2、到底是实名举报,也是押上了自己的声名的。

退一万步讲,迟到的正义,总比缺席的正义好罢!

 

在举报信的最后,举报人是这么写的:

本文提及的性侵,并非严格的法律意义上的概念,而更多的是师风、师德意义上的概念。

我对这句话的理解,大概应该是指,并不是举报沈阳强奸女学生。

一位朋友也说,按照追诉期,20年前的案子,现在也已经过了。

举报信就沈阳到底有没有和女学生发生实质性关系,写的比较隐晦和曲折。但的确是发生关系了,细读就能明白,不再赘述。

但举报人又说不是严格的法律意义上的概念,这里不太好懂。

不过,在举报人写的那句话上面还有一段:

所谓性侵,指任何未经同意的性行为。换言之,即使对方没有说“no”(不,绝对不行),只要她或他没有说“yes”(是,可以),而你却跟人家发生了性关系,就已然构成了性侵。可见,对方是否知情与许可,是界定性侵的主要标准。

我不是法律专家,也不知道这段话是不是真的就是符合法理。但根据逻辑来讲:

1、举报人知道她的同学与沈阳发生了性关系。

2、举报人说性侵是指只要不说yes,就是。

3、举报人说本文说的性侵,不是法律意义上的概念。

推论而得:女学生可能真的至少说过一次“yes”,虽然心里是不愿意的。

 

我一直听说,我所在的上海交大,是严禁师生谈恋爱的。

可能我小讲师一枚,级别不够,没有看到过相关红头文件。

但我非常支持这样的规矩,如果有的话。

我个人极度鄙视师生恋,大致有这样几个原因:

1、存在可能仗势压人,如果老师和学生的关系,还是导师和弟子的关系的话。

2、虽然大学生大部分已经是成年人,但到底涉世未深,属于欺骗无知少女/男

3、这个观念你可以说我传统:老师总是要讲师德的吧?

4、这个老师的社交圈太窄了,搞来搞去都是自己的学生,丢不丢人?

5、如果该大学地处郊区(今天中国很多大学都不太在市中心),该老师占人家便宜还不肯支付高额成本——郊区大学旁边没什么可消费的地方,这点很猥琐啊。

文科院校,师生恋其实很多年了,我从教十一年,也就鄙视了十一年。

师生恋不是两个成年人间正常的恋爱,因为它实在是瓜田李下,有太多的说不清楚。

 

我们学院最近进行了一次拆分,细心的读者可能已经发现,我底下那条小尾巴,已经从“媒体与设计学院”变成了“媒体与传播学院”:设计系独立成院了。

媒体传播学院近日喜提新办公大楼,组织上派员前来调研教工对新办公场地的装修要求。

部分同仁提出,应该每个教师都配备独立办公室一间。

这个提议我是理解的,到底东北那所职校的新闻学院,真的是人手一间。

但我用开玩笑的方式提出了反对。

教师一人一间办公室,来个学生聊正事,其实不方便的。我院男教师居多,女学生又是乌央乌央的一堆,学生跑上门来,为避嫌我还得开着个门。

两个人一间就不太需要了。虽然大学老师也不坐班,但到底你吃不准另外一个啥时候会跑进来,嫌疑会少很多。

虽然我的语气是玩笑的,但我是真心这么想的。

要独立一间办公室干啥?

文科搞研究没啥的,有时候图书馆坐着都可以弄。

 

在一个满是新传老师的大群里,我表达了师生恋是不对的观点。

有朋友表示支持。

如果是真爱,那就等毕业后再谈吧。实在是等不及了,要不学生退学,或老师辞职?

是,本来成年人之间的私事,双方你情我愿,旁人真不该说三道四。

但老师和学生并不是,因为这里的所谓你情我愿,实在是说不清道不明。

导师不签字,学生就无法开题,后面什么答辩、毕业都不用讲了,这里的学生包括本硕博三阶段。

至于有些学生想入党想做学生官(学生会那种的),都得班主任签字。

学生毕业如果是通过公务员考试去做公务员,接收单位做背景调查是要给班主任打电话的。

大学,应该禁止,完全禁止,师生恋。

管你什么真爱不真爱。

 

这个沈阳教授真的是蛮卑鄙的。

女生自杀后,一直在试图撇清此事与他有关。

按照举报信的说法,甚至说过这样的话:

有人为我自杀,这说明我有魅力!

我呸

也就是专盯懵懵懂懂的女学生下手,外边姑娘大概都瞧不上你吧?这也叫有魅力?

 

—— 首发 扯氮集 ——

作者执教于上海交通大学媒体与传播学院,天奇阿米巴创投基金管理合伙人

大学,难道不应该禁止师生恋么?最先出现在扯氮集

]]>
0
<![CDATA[移动网页的 iPhone X 适配]]> http://www.udpwork.com/item/16790.html http://www.udpwork.com/item/16790.html#reviews Mon, 16 Apr 2018 12:37:10 +0800 Cat Chen http://www.udpwork.com/item/16790.html Instagram web without iPhone X fix (portrait)

一个月前我在 iPhone X 的 Mobile Safari 中打开Instagram web,发现页面底下的导航栏跟 iPhone 的 home indicator 重叠在一起不方便使用。我想既然 Apple 为 iPhone X 专门更新的Human Interface Guidelines并为 native app 引入了 safe area 和 inset 等概念,那 Mobile Safari 应该有对应的 web 概念吧。搜索了一下,发现 Apple 确实对 Mobile Safari 增加了对应的功能。既然 Instagram 是我们公司的产品,那就动手去改吧。

改造的第一步是对页面加上这一句:

<meta name='viewport' content='initial-scale=1, viewport-fit=cover'>

因为大多数移动页面都已经有类似的声明,所以只要加上viewport-fit=cover就行了。不加的话,下面所有的 CSS inset 声明都不会生效。

第二部是把竖屏(portrait mode)时的页面底部导航栏往上挪。这时候我们可以把导航栏到屏幕底部的距离设置为env(safe-area-inset-bottom),然后浏览器自动会使用正确的数值来进行布局。(在 Safari 显示自己的工具栏时,这个值会神器地变为0,使得页面底部导航栏紧贴 Safari 工具栏。)假设我们使用padding-bottom把导航栏往上挪,那么我们可以写padding-bottom: env(safe-area-inset-bottom)。(当然 Instagram web 的实际情况比这个复杂,如果你想研究的话可以用 Safari remote debugger + iPhone X Simulator 来看。)这样竖屏的问题就修复了。

Instagram web with iPhone X fix (portrait)

如果这是个 native app 的话,问题可能到此就结束了,因为 native app 可以选择不支持横屏(landscape mode)。然后网页必须支持横屏,因为浏览器本身可以横屏。(当然你也可以很霸道地在浏览器横屏时只显示一句提示让用户把屏幕直过来,这样就可以不支持横屏了。)因为 iPhone X 屏幕顶上的那个缺口(notch),Mobile Safari 在横屏时默认会在页面两侧加白边,确保任何没对 iPhone X 做修改的页面能够正常显示。

Instagram web without iPhone X fix (landscape)

这两侧的白边很不好看,因为会让原本应该贯穿全屏的横线终止在屏幕内。在加上viewport-fit=cover后,两侧的白边会消失掉,因为 Mobile Safari 把这看作开发者愿意对 iPhone X 布局负责,之后如何处理横屏一侧缺口就是开发者的责任了。之前对 Instagram web 的竖屏调整一旦放到横屏就会发现新问题。

Instagram web with some iPhone X fix (landscape)

页面顶部标题栏两侧的按钮太靠近屏幕边缘了。因为 iPhone X 屏幕边缘有圆角,所以按钮放在那里并不好按。此外那也在 Apple 定义的 safe area 之外,本来就不应该放可点击元素。为此我们必须使用env(safe-area-inset-left)和env(safe-area-inset-right)把这两个按钮往页面中间挪。假设我们使用margin-left和margin-right来控制布局的话,我们可以这样写:

.leftButton {  margin-left: env(safe-area-inset-left);}.rightButton {  margin-right: env(safe-area-inset-right);}

这样子横屏是修复了,但又会给竖屏引入新的问题。在原本的竖屏设计中,按钮离两侧屏幕边缘16px。在我们把16px替换成env(safe-area-inset-left)和env(safe-area-inset-right)之后,竖屏时这两个按钮就贴着屏幕边缘了。为此我们要引入max()来保证按钮离屏幕边缘至少有16px。

.leftButton {  margin-left: max(16px, env(safe-area-inset-left));}.rightButton {  margin-right: max(16px, env(safe-area-inset-right));}

这时候竖屏横屏都没问题了,唯一问题是 Safari 以外的浏览器都被弄晕了,这max和env都是什么呀?我们还没支持呢,而且是否会被标准化也很难说。幸好大多数浏览器都支持@support,我们可以用它来进行筛选,把专门写给 Safari 看的 CSS 留给 Safari 看。

.leftButton {  margin-left: 16px;}.rightButton {  margin-right: 16px;}@supports (margin: max(16px)) {  .leftButton {    margin-left: max(16px, env(safe-area-inset-left));  }  .rightButton {    margin-right: max(16px, env(safe-area-inset-right));  }}

到此所有的问题都解决了,Instagram web 也能在横屏中正常显示了。王子和公主从此幸福地生活在一起。

Instagram web with all iPhone X fix (landscape)

故事当然不会到这里就结束了。首先,Instagram web 可不止这一个页面。这些页面的竖屏都不会有问题,但横屏就很难说了,有可能某些元素在使用viewport-fit=cover之后被布局到了 safe area 之外,需要把它们挪回来。这些问题我见到一个修一个,但永远也不知道是否有遗留的。当然这个问题在 native app 里面也存在,除非从零开始设计一个新的 app 并在设计原则和布局框架上对 safe area 作出考虑,否则一个 app 无论怎么改都无法证明改全了,而且开发新功能时一不小心没测 iPhone X 就可能出现不兼容的问题。

其次,Mobile Safari 在横屏模式时如果显示地址栏就会导致页面底部导航栏处于半隐藏状态,而非原来的全隐藏状态。

iPhone X Safari Apple bug (landscape)

为什么会发生这样的事情呢?因为在显示地址栏时 Safari 会把整个 viewport 往屏幕下方挪动地址栏的高度。这时候 viewport 高度是不会改变的,因此 viewport 的一部分就跑到屏幕外去了。(但 viewport 的定义不就是屏幕内可见区域么?Apple 你自己发明了这个概念,现在说改就改。)Apple 对此的解释是,显示地址栏的 animation 必须保持 60 FPS,但 viewport 高度变化过程受页面布局速度影响而无法做到 60 FPS,所以这是 feature 不是 bug。(Chrome for iOS 在显示地址栏时会调整 viewport 高度,但因为不是 60 FPS animation 所以会看到页面闪烁。)

我觉得 Apple 要把 viewport 偷偷隐藏掉一部分也不是问题,但在隐藏的时候至少应该把env(safe-area-inset-bottom)自动变会0吧?这样子底部导航栏至少可以完全隐藏掉。这个问题已经有其他人写过,并且那篇文章的作者已经给 Apple 开 bug。

最后一个问题,为什么env(safe-area-inset-top)没有被用到?因为 Mobile Safari 总会在屏幕顶部显示状态栏,所以网页永远都不需要自己想办法避让屏幕顶部的缺口。(那使用<meta name="apple-mobile-web-app-capable" content="yes">强行进入全屏模式呢?iPhone X 会很恶心地在屏幕上方留下一个黑色区域。)估计唯一的例外是你自己写一个 app 并在里面放一个全屏的 WebView,这时候 WebView 内的网页就需要使用env(safe-area-inset-top)了。我没有试过做这样的事情,但可以参考别人的文章

总的来说,iPhone X 适配不是一个很难的技术问题,尤其是只做竖屏模式的话。

]]>
Instagram web without iPhone X fix (portrait)

一个月前我在 iPhone X 的 Mobile Safari 中打开Instagram web,发现页面底下的导航栏跟 iPhone 的 home indicator 重叠在一起不方便使用。我想既然 Apple 为 iPhone X 专门更新的Human Interface Guidelines并为 native app 引入了 safe area 和 inset 等概念,那 Mobile Safari 应该有对应的 web 概念吧。搜索了一下,发现 Apple 确实对 Mobile Safari 增加了对应的功能。既然 Instagram 是我们公司的产品,那就动手去改吧。

改造的第一步是对页面加上这一句:

<meta name='viewport' content='initial-scale=1, viewport-fit=cover'>

因为大多数移动页面都已经有类似的声明,所以只要加上viewport-fit=cover就行了。不加的话,下面所有的 CSS inset 声明都不会生效。

第二部是把竖屏(portrait mode)时的页面底部导航栏往上挪。这时候我们可以把导航栏到屏幕底部的距离设置为env(safe-area-inset-bottom),然后浏览器自动会使用正确的数值来进行布局。(在 Safari 显示自己的工具栏时,这个值会神器地变为0,使得页面底部导航栏紧贴 Safari 工具栏。)假设我们使用padding-bottom把导航栏往上挪,那么我们可以写padding-bottom: env(safe-area-inset-bottom)。(当然 Instagram web 的实际情况比这个复杂,如果你想研究的话可以用 Safari remote debugger + iPhone X Simulator 来看。)这样竖屏的问题就修复了。

Instagram web with iPhone X fix (portrait)

如果这是个 native app 的话,问题可能到此就结束了,因为 native app 可以选择不支持横屏(landscape mode)。然后网页必须支持横屏,因为浏览器本身可以横屏。(当然你也可以很霸道地在浏览器横屏时只显示一句提示让用户把屏幕直过来,这样就可以不支持横屏了。)因为 iPhone X 屏幕顶上的那个缺口(notch),Mobile Safari 在横屏时默认会在页面两侧加白边,确保任何没对 iPhone X 做修改的页面能够正常显示。

Instagram web without iPhone X fix (landscape)

这两侧的白边很不好看,因为会让原本应该贯穿全屏的横线终止在屏幕内。在加上viewport-fit=cover后,两侧的白边会消失掉,因为 Mobile Safari 把这看作开发者愿意对 iPhone X 布局负责,之后如何处理横屏一侧缺口就是开发者的责任了。之前对 Instagram web 的竖屏调整一旦放到横屏就会发现新问题。

Instagram web with some iPhone X fix (landscape)

页面顶部标题栏两侧的按钮太靠近屏幕边缘了。因为 iPhone X 屏幕边缘有圆角,所以按钮放在那里并不好按。此外那也在 Apple 定义的 safe area 之外,本来就不应该放可点击元素。为此我们必须使用env(safe-area-inset-left)和env(safe-area-inset-right)把这两个按钮往页面中间挪。假设我们使用margin-left和margin-right来控制布局的话,我们可以这样写:

.leftButton {  margin-left: env(safe-area-inset-left);}.rightButton {  margin-right: env(safe-area-inset-right);}

这样子横屏是修复了,但又会给竖屏引入新的问题。在原本的竖屏设计中,按钮离两侧屏幕边缘16px。在我们把16px替换成env(safe-area-inset-left)和env(safe-area-inset-right)之后,竖屏时这两个按钮就贴着屏幕边缘了。为此我们要引入max()来保证按钮离屏幕边缘至少有16px。

.leftButton {  margin-left: max(16px, env(safe-area-inset-left));}.rightButton {  margin-right: max(16px, env(safe-area-inset-right));}

这时候竖屏横屏都没问题了,唯一问题是 Safari 以外的浏览器都被弄晕了,这max和env都是什么呀?我们还没支持呢,而且是否会被标准化也很难说。幸好大多数浏览器都支持@support,我们可以用它来进行筛选,把专门写给 Safari 看的 CSS 留给 Safari 看。

.leftButton {  margin-left: 16px;}.rightButton {  margin-right: 16px;}@supports (margin: max(16px)) {  .leftButton {    margin-left: max(16px, env(safe-area-inset-left));  }  .rightButton {    margin-right: max(16px, env(safe-area-inset-right));  }}

到此所有的问题都解决了,Instagram web 也能在横屏中正常显示了。王子和公主从此幸福地生活在一起。

Instagram web with all iPhone X fix (landscape)

故事当然不会到这里就结束了。首先,Instagram web 可不止这一个页面。这些页面的竖屏都不会有问题,但横屏就很难说了,有可能某些元素在使用viewport-fit=cover之后被布局到了 safe area 之外,需要把它们挪回来。这些问题我见到一个修一个,但永远也不知道是否有遗留的。当然这个问题在 native app 里面也存在,除非从零开始设计一个新的 app 并在设计原则和布局框架上对 safe area 作出考虑,否则一个 app 无论怎么改都无法证明改全了,而且开发新功能时一不小心没测 iPhone X 就可能出现不兼容的问题。

其次,Mobile Safari 在横屏模式时如果显示地址栏就会导致页面底部导航栏处于半隐藏状态,而非原来的全隐藏状态。

iPhone X Safari Apple bug (landscape)

为什么会发生这样的事情呢?因为在显示地址栏时 Safari 会把整个 viewport 往屏幕下方挪动地址栏的高度。这时候 viewport 高度是不会改变的,因此 viewport 的一部分就跑到屏幕外去了。(但 viewport 的定义不就是屏幕内可见区域么?Apple 你自己发明了这个概念,现在说改就改。)Apple 对此的解释是,显示地址栏的 animation 必须保持 60 FPS,但 viewport 高度变化过程受页面布局速度影响而无法做到 60 FPS,所以这是 feature 不是 bug。(Chrome for iOS 在显示地址栏时会调整 viewport 高度,但因为不是 60 FPS animation 所以会看到页面闪烁。)

我觉得 Apple 要把 viewport 偷偷隐藏掉一部分也不是问题,但在隐藏的时候至少应该把env(safe-area-inset-bottom)自动变会0吧?这样子底部导航栏至少可以完全隐藏掉。这个问题已经有其他人写过,并且那篇文章的作者已经给 Apple 开 bug。

最后一个问题,为什么env(safe-area-inset-top)没有被用到?因为 Mobile Safari 总会在屏幕顶部显示状态栏,所以网页永远都不需要自己想办法避让屏幕顶部的缺口。(那使用<meta name="apple-mobile-web-app-capable" content="yes">强行进入全屏模式呢?iPhone X 会很恶心地在屏幕上方留下一个黑色区域。)估计唯一的例外是你自己写一个 app 并在里面放一个全屏的 WebView,这时候 WebView 内的网页就需要使用env(safe-area-inset-top)了。我没有试过做这样的事情,但可以参考别人的文章

总的来说,iPhone X 适配不是一个很难的技术问题,尤其是只做竖屏模式的话。

]]>
0
<![CDATA[当我们谈重构的时候我们想谈什么? - 旁观者]]> http://www.udpwork.com/item/16791.html http://www.udpwork.com/item/16791.html#reviews Mon, 16 Apr 2018 11:51:00 +0800 旁观者 http://www.udpwork.com/item/16791.html 【摘要】你的业务已经完成了从0到1,正在从1走向10,或者从10走向100,请记住下面这些忠言。阅读全文

]]>
【摘要】你的业务已经完成了从0到1,正在从1走向10,或者从10走向100,请记住下面这些忠言。阅读全文

]]>
0
<![CDATA[使 Visual Studio Code 的打开文件始终在新 Tab]]> http://www.udpwork.com/item/16789.html http://www.udpwork.com/item/16789.html#reviews Mon, 16 Apr 2018 10:13:06 +0800 图拉鼎 http://www.udpwork.com/item/16789.html 最近会更新一系列和 Visual Studio Code 有关的文章,从小小的自定义设置到开发环境的设计都会涉及。今天这篇是「使打开文件始终在新 Tab」。

在进入这个话题之前,首先我们要了解 Visual Studio Code 有几种打开文件的方式,对我来说,常见的有两种:

  • 从侧边的资源管理器打开;
  • 使用快捷键(CMD+P)搜索文件名再打开。

无论哪种方式,Visual Studio Code 的默认行为都是一致的,那就是当你打开一个文件的时候,如果你只是看看,并不做任何修改,那么这个查看文件的 Tab 只是临时的,它会在你打开下个文件的时候被替换,也就是说,始终只会有一个「预览」功能的 Tab,直到你在这个 Tab 做了修改,那么下个预览就会在新的 Tab 打开。

但说真的,我不是特别喜欢这个「特性」,我想要我在选择一种方式打开文件时,使 Tab 可以保持住,这样我可以打开很多文件并在其中跳转。因为我平常操作快捷键比较多,所以我要把「使用快捷键」打开文件这种形式变成始终在新 Tab 打开。Visual Studio Code 提供了这样的设置,很方便,进入用户设置模式(CMD+,),写入这么一行配置即可:

{
    "workbench.editor.enablePreviewFromQuickOpen": false
}

这行配置的意思是:关闭从 QuickOpen(即快捷键 CMD+P) 打开文件时的预览功能。做了这个变更以后,以后只要你用 CMD+P 搜索文件来打开文件,就会始终在新的 Tab 打开了,而当你从侧边资源管理器打开文件时,依然保持着原有的行为。

如果你想使资源管理器的打开行为也变成这样,那么加这个设置即可:

{
    "workbench.editor.enablePreview": false
}

Visual Studio Code 的自定义性真的非常强!虽然默认情况下它基本上开箱即用,但每个人多少会有一些不同的、属于自己的更高效的习惯,那就让我们充分利用这个特性,好好打造出趁手的编辑器吧!

本站架设于Linode 东京机房

]]>
最近会更新一系列和 Visual Studio Code 有关的文章,从小小的自定义设置到开发环境的设计都会涉及。今天这篇是「使打开文件始终在新 Tab」。

在进入这个话题之前,首先我们要了解 Visual Studio Code 有几种打开文件的方式,对我来说,常见的有两种:

  • 从侧边的资源管理器打开;
  • 使用快捷键(CMD+P)搜索文件名再打开。

无论哪种方式,Visual Studio Code 的默认行为都是一致的,那就是当你打开一个文件的时候,如果你只是看看,并不做任何修改,那么这个查看文件的 Tab 只是临时的,它会在你打开下个文件的时候被替换,也就是说,始终只会有一个「预览」功能的 Tab,直到你在这个 Tab 做了修改,那么下个预览就会在新的 Tab 打开。

但说真的,我不是特别喜欢这个「特性」,我想要我在选择一种方式打开文件时,使 Tab 可以保持住,这样我可以打开很多文件并在其中跳转。因为我平常操作快捷键比较多,所以我要把「使用快捷键」打开文件这种形式变成始终在新 Tab 打开。Visual Studio Code 提供了这样的设置,很方便,进入用户设置模式(CMD+,),写入这么一行配置即可:

{
    "workbench.editor.enablePreviewFromQuickOpen": false
}

这行配置的意思是:关闭从 QuickOpen(即快捷键 CMD+P) 打开文件时的预览功能。做了这个变更以后,以后只要你用 CMD+P 搜索文件来打开文件,就会始终在新的 Tab 打开了,而当你从侧边资源管理器打开文件时,依然保持着原有的行为。

如果你想使资源管理器的打开行为也变成这样,那么加这个设置即可:

{
    "workbench.editor.enablePreview": false
}

Visual Studio Code 的自定义性真的非常强!虽然默认情况下它基本上开箱即用,但每个人多少会有一些不同的、属于自己的更高效的习惯,那就让我们充分利用这个特性,好好打造出趁手的编辑器吧!

本站架设于Linode 东京机房

]]>
0