<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title>Blog on Nekocode 的博客</title>
		<link>https://nekocode.cn/blog/</link>
		<description>Recent content in Blog on Nekocode 的博客</description>
		<generator>Hugo</generator>
		<language>zh-CN</language>
		
		
		
		
			<lastBuildDate>Mon, 31 Dec 2018 00:00:00 +0000</lastBuildDate>
		
			<atom:link href="https://nekocode.cn/blog/index.xml" rel="self" type="application/rss+xml" />
			<item>
				<title>在知乎的 2018 年</title>
				<link>https://nekocode.cn/blog/2018/12/31/%E5%9C%A8%E7%9F%A5%E4%B9%8E%E7%9A%84-2018-%E5%B9%B4/</link>
				<pubDate>Mon, 31 Dec 2018 00:00:00 +0000</pubDate>
				<guid>https://nekocode.cn/blog/2018/12/31/%E5%9C%A8%E7%9F%A5%E4%B9%8E%E7%9A%84-2018-%E5%B9%B4/</guid>
				<description>&lt;p&gt;今年是在知乎的第二年。&lt;/p&gt;&#xA;&lt;p&gt;首先得提及下我的前 Leader 佳恒（目前已去美国），他是个十分 Nice 的人，也是知乎里对我帮助最大的人。今年夏季，他把我从业务组调到了他 Lead 的「Android 基础架构组」，这个组属于中台部门，主要负责提升工程师团队的开发效率、质量，国外有个很火的词「DevOps」指的就是这个方向～&lt;/p&gt;&#xA;&lt;p&gt;实际上，在知乎里做 DevOps 十分具有挑战性。庞大的开发人员数量和 Codebase 规模都让开发效率和质量的保障变得很困难。而且作为一个有着上亿用户、千万级 DAU 的产品，开发时看似很小的问题一旦到了线上都可能会被放大而导致公司损失惨重 w(ﾟДﾟ)w。所以非常需要中台提供流程、工具、自动化来解决这些问题。&lt;/p&gt;&#xA;&lt;p&gt;接下来，就记录一下我在这个组里做过的一些有意义或有趣的事～&lt;/p&gt;&#xA;&lt;h2 id=&#34;maven-仓库&#34;&gt;Maven 仓库&lt;/h2&gt;&#xA;&lt;p&gt;随着组件化的推行，Android 组变得严重依赖于 Maven 仓库。虽然公司内部已经搭建了一个 JFrog 仓库，但是由于管理权限不在我们组，想自定义或遇到问题想解决时都十分困难，所以我们组计划自己搭建一个 Maven 仓库。&lt;/p&gt;&#xA;&lt;p&gt;由于当时组里只有我有过搭建 Maven 的经验，所以这个任务自然而然就落到了我的手上 ㄟ( ▔, ▔ )ㄏ 。于是用 Docker，配合公司内网 Dns、Nginx-proxy 快速搭了个 Nexus 仓库服务，并且代理了所有用到的第三方的远程仓库，然后把我们 Gradle 工程的 Maven 源依赖都收缩到我们自己搭建的仓库上，这样就能很方便地集中管理我们的 Maven 源和所有 Artifact 了。&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;images/img_001.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;jarfilter&#34;&gt;JarFilter&lt;/h2&gt;&#xA;&lt;p&gt;这其实是我的个人 &lt;a href=&#34;https://github.com/nekocode/JarFilterPlugin&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;开源项目&lt;/a&gt;&#xA; 但目前已经用在了知乎上，想更详细了解的话可以看这篇 &lt;a href=&#34;https://juejin.im/post/5addf731f265da0b83365df3&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;文章&lt;/a&gt;&#xA;。&lt;/p&gt;&#xA;&lt;p&gt;简单来讲，这个 Gradle 插件可以在编译时把指定 Jar 里的指定 Class 文件剔除掉。这么做主要为了能快速修改某个第三方库里类的实现：&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;images/img_002.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;无需 Fork 或 Clone 第三方库的所有源码，只需复制目标类的源码到主工程（通常在 IDE 中可以直接从 Sources.jar 中复制），然后用该插件剔除掉原 Jar 中的 Class 然后一起编译即可。&lt;/p&gt;</description>
			</item>
			<item>
				<title>Kotlin 101</title>
				<link>https://nekocode.cn/blog/2018/12/16/kotlin-101/</link>
				<pubDate>Sun, 16 Dec 2018 00:00:00 +0000</pubDate>
				<guid>https://nekocode.cn/blog/2018/12/16/kotlin-101/</guid>
				<description>&lt;h2 id=&#34;kotlin-简介&#34;&gt;Kotlin 简介&lt;/h2&gt;&#xA;&lt;p&gt;2011 年，作为全球最先进 IDE 开发商之一的 JetBrains 揭露了一项正处于开发中的编程语言 —— Kotlin。它是一门跑在 JVM 上，和 Java 间具有高互操作性的全新语言。JetBrains 通过多年来和各种编程语言打交道的经验，为 Kotlin 整合了多项现代编程语言特性。&lt;/p&gt;&#xA;&lt;p&gt;2017 年，Google 在 I/O 大会上宣布将 Kotlin 作为 Android 开发的官方支持语言。彼时，Kotlin 的开发者社区开始了爆炸性的增长，而 Netflix、Pinterest、Trello、Kickstarter 等知名公司也早已开始使用 Kotlin。&lt;/p&gt;&#xA;&lt;p&gt;2018 年，目前 Kotlin 1.3 正式版本已经发布，更多的语言特性得到了支持。而随着官方提供了更多的编译后端，也让 Kotlin 摆脱了 JVM 的束缚，使用 Kotlin 编写的代码可以编译成机器码甚至 JavaScript 而跑在不同的运行环境中。另外，根据 Google 官方的调查，目前已有 40% 的 Android 开发者选择使用 Kotlin 进行编程工作，国内抖音、网易有道词典、大众点评、知乎等大量应用也开始引入 Kotlin。&lt;/p&gt;&#xA;&lt;h2 id=&#34;使用-kotlin-有什么好处&#34;&gt;使用 Kotlin 有什么好处？&lt;/h2&gt;&#xA;&lt;p&gt;既然 Google 已经宣布 Kotlin 成为 Android 开发的官方支持语言，也说明了至少在 Android 开发上使用 Kotlin 目前已经毫无障碍了。那么作为 Android 开发者，对比 Java 而言，使用 Kotlin 语言能获得什么好处呢？&lt;/p&gt;</description>
			</item>
			<item>
				<title>被滥用的 GUI 设计模式</title>
				<link>https://nekocode.cn/blog/2018/12/02/%E8%A2%AB%E6%BB%A5%E7%94%A8%E7%9A%84-gui-%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/</link>
				<pubDate>Sun, 02 Dec 2018 00:00:00 +0000</pubDate>
				<guid>https://nekocode.cn/blog/2018/12/02/%E8%A2%AB%E6%BB%A5%E7%94%A8%E7%9A%84-gui-%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/</guid>
				<description>&lt;p&gt;随便侃些个人对 GUI 设计模式的看法。&lt;/p&gt;&#xA;&lt;p&gt;近些年来，随着 Fronted 技术的火热和推进，古老的（至少有几十年历史）用来解决 GUI 应用中代码组织问题的「GUI 设计模式」现在也成为了 Frontend 工程师的热门话题，MVC、MVP、MVVM 等设计模式在网路上被议论不绝。有很多工程师开始通过写博文来介绍它们、阐述自己对它们的理解，甚至在 Github 上开源了各种 GUI 设计模式的实现。&lt;/p&gt;&#xA;&lt;p&gt;顺着这种趋势，很多 Frontend 工程师甚至把 GUI 设计模式当成一种「规范」乃至「教条」。然而糟糕的现实是，大多数人并没有正确地、细致地理解和运用 GUI 设计模式，反而因为 Tradeoff 导致它的缺点被放大。结果就是你用了大量精力、模板代码去设计它，反而让它更复杂、更难维护了。&lt;/p&gt;&#xA;&lt;p&gt;例如，当你打开 Github 上大多数试图实现 GUI 模式的仓库时会发现，整个应用大概也就两三个页面、四五个网络接口，就可能已经创建了几十个类和接口来承载那单薄的逻辑了。举个更具体的例子，我个人曾经接触过几个用 MVP 模式设计的大型 Android 工程，在进行维护或者迭代的时候，各种带有问题的设计反而让 MVP 模式成为了累赘。&lt;/p&gt;&#xA;&lt;p&gt;首先，工程中大多数 View 都是粒度大耦合度高的 Activity 类，而且很多 View 里为了方便，会提供 &lt;code&gt;fun updateView(user: UserModel)&lt;/code&gt; 这样的方法，导致 View 和领域/业务模型直接耦合了。再者，View 和 Model 中还会包含了跳转页面、发送全局消息等各种带有「副作用」的命令，这也让面向接口编程成为了形式主义。&lt;/p&gt;&#xA;&lt;p&gt;所以与其「舍本逐末」、「知其然而不知其所以然」，倒还不如理解问题的本质。于 GUI 设计模式而言，实际上最重要的思想是「分而治之」，通过把之前都写在一处的代码按照职能分到不同的类，来让它们实现「低耦合高内聚」。所以，我们更应该把 GUI 设计模式当成一思想而不是具体的手段，更也没必要用各种所谓的模板来解决问题，只要你能把热点、关键代码设计得足够低耦合高内聚，那么你完全可以无视所有 GUI 设计模式。&lt;/p&gt;&#xA;&lt;p&gt;例如上面提到的 &lt;code&gt;fun updateView(user: UserModel)&lt;/code&gt; 问题，实际有两种方式来让 View 和业务模型 UserModel 解耦：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-kotlin&#34; data-lang=&#34;kotlin&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// 方法一&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;interface&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;ViewA&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;fun&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;updateText1&lt;/span&gt;(text: String)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;fun&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;updateText2&lt;/span&gt;(text: String)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// ...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;PresenterA&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;fun&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;onSomeEvent&lt;/span&gt;() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;val&lt;/span&gt; userModel = &lt;span style=&#34;color:#a6e22e&#34;&gt;Apis&lt;/span&gt;.requestUser()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        viewA.updateText1(userModel.name)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        viewA.updateText2(userModel.age.toString())&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// 方法二&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;interface&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;ViewA&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;data&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;ViewAttributes&lt;/span&gt;(&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        text1: String,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        text2: String,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;// ...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    )&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;fun&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;updateView&lt;/span&gt;(view: ViewAttributes)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;PresenterA&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;fun&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;onSomeEvent&lt;/span&gt;() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;val&lt;/span&gt; viewAttributes = &lt;span style=&#34;color:#a6e22e&#34;&gt;Apis&lt;/span&gt;.requestUser().mapTo ViewAttributes()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        viewA.updateView(viewAttributes)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;方法一更倾向于用「指令」来描述 View，方法二则更倾向于用「数据」。而我个人更喜欢方法二，因为数据是运行时可处理、可持久化的，甚至可以跨进程、跨语言、乃至跨机器共享的。讲个题外话，Web Fronted 里 Redux 等状态管理工具捧起了一个很火的词「时间旅行」。在我看来核心思想其实也是把指令下沉，用数据（/状态）来描述上层逻辑，这样就可以在运行时实现逻辑可记录、可回放。&lt;/p&gt;</description>
			</item>
			<item>
				<title>GraphQL 纪要（二）</title>
				<link>https://nekocode.cn/blog/2018/10/20/graphql-%E7%BA%AA%E8%A6%81%E4%BA%8C/</link>
				<pubDate>Sat, 20 Oct 2018 00:00:00 +0000</pubDate>
				<guid>https://nekocode.cn/blog/2018/10/20/graphql-%E7%BA%AA%E8%A6%81%E4%BA%8C/</guid>
				<description>&lt;h2 id=&#34;resolver-设计&#34;&gt;Resolver 设计&lt;/h2&gt;&#xA;&lt;p&gt;我们可能会在 Resolver 里做一些耗时的操作（例如操作 Database）。为了保证我们尽可能快地响应用户的查询，我们必须保证只对那些用户需要的字段进行查询。&lt;/p&gt;&#xA;&lt;p&gt;首先举个反例，我们定义了以下的 Schema：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-graphql&#34; data-lang=&#34;graphql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;type&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Query&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  getPost: &lt;span style=&#34;color:#a6e22e&#34;&gt;Post&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;type&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Post&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  title: &lt;span style=&#34;color:#a6e22e&#34;&gt;String&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  authorName: &lt;span style=&#34;color:#a6e22e&#34;&gt;String&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;对应的 Resolver Map：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-typescript&#34; data-lang=&#34;typescript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;resolverMap&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;IResolvers&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;Query&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;getPost&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#a6e22e&#34;&gt;resolve&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; () &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;post&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;queryPostDbTable&lt;/span&gt;();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;author&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;queryUserDbTable&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;post&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;authorId&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#a6e22e&#34;&gt;title&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;post.title&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#a6e22e&#34;&gt;authorName&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;author.name&lt;/span&gt;;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        };&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;可以看到，在 getPost 字段的 Resolver 里会查询 Post 和 User 表。糟糕的是，即便用户并没有查询 authorName 字段，在获取 getPost 字段的时候也会查询 User 表。这造成了冗余的数据库操作。&lt;/p&gt;&#xA;&lt;p&gt;为了解决这个问题，我们应当把 authorName 字段的获取放到另一个 Resolver 里。例如：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-typescript&#34; data-lang=&#34;typescript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;resolverMap&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;IResolvers&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;Query&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;getPost&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#a6e22e&#34;&gt;resolve&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; () &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;queryPostDbTable&lt;/span&gt;();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;Post&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;authorName&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#a6e22e&#34;&gt;resolve&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; (&lt;span style=&#34;color:#a6e22e&#34;&gt;post&lt;/span&gt;) &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;queryUserDbTable&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;post&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;authorId&lt;/span&gt;).&lt;span style=&#34;color:#a6e22e&#34;&gt;name&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这样可以只在用户查询到 authorName 字段时才去查询 User 表。&lt;/p&gt;</description>
			</item>
			<item>
				<title>GraphQL 纪要</title>
				<link>https://nekocode.cn/blog/2018/10/19/graphql-%E7%BA%AA%E8%A6%81/</link>
				<pubDate>Fri, 19 Oct 2018 00:00:00 +0000</pubDate>
				<guid>https://nekocode.cn/blog/2018/10/19/graphql-%E7%BA%AA%E8%A6%81/</guid>
				<description>&lt;h2 id=&#34;schema--graphql-语句&#34;&gt;Schema &amp;amp; GraphQL 语句&lt;/h2&gt;&#xA;&lt;p&gt;GraphQL 是一门查询语言，使用它可以描述你需要哪些数据。而 Schema 则是用于声明你能够查询什么样的数据。&lt;/p&gt;&#xA;&lt;p&gt;举个例子，下面的是 Schema：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-graphql&#34; data-lang=&#34;graphql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;type&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Query&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  hello: &lt;span style=&#34;color:#a6e22e&#34;&gt;String&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;通过以上 Schema 的声明，你可以写下这么一条 GraphQL 查询语句：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-graphql&#34; data-lang=&#34;graphql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;query&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  hello&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;schema&#34;&gt;Schema&lt;/h2&gt;&#xA;&lt;p&gt;Schema 里主要有两个核心的概念，类型（Type）和字段（Field）。举个例子：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-graphql&#34; data-lang=&#34;graphql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;type&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;User&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  name: &lt;span style=&#34;color:#a6e22e&#34;&gt;String&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;上面定义了一个名为 User 的类型，并且这个类型里包含了一个叫做 name 的字段。&#xA;注意，字段必须声明类型，可以声明为 Int、String 这类基础类型，也可以声明为自定义的类型。另外，字段是可以包含参数的，这让它看起来有点像函数：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-graphql&#34; data-lang=&#34;graphql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;type&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;User&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  name: &lt;span style=&#34;color:#a6e22e&#34;&gt;String&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  posts(count: &lt;span style=&#34;color:#a6e22e&#34;&gt;Int&lt;/span&gt;): [Post]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;type&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Post&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  title: &lt;span style=&#34;color:#a6e22e&#34;&gt;String&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;例如这里 User 类型里的 posts 字段，它接受一个名为 count 的参数并返回一个 Post 类型的列表。&lt;/p&gt;&#xA;&lt;h2 id=&#34;schema-里的-query-和-mutation-类型&#34;&gt;Schema 里的 Query 和 Mutation 类型&lt;/h2&gt;&#xA;&lt;p&gt;在 Schema 里面有两个约定的类型：&lt;/p&gt;</description>
			</item>
			<item>
				<title>Docker, Serverless, GraphQL</title>
				<link>https://nekocode.cn/blog/2018/09/10/docker-serverless-graphql/</link>
				<pubDate>Mon, 10 Sep 2018 00:00:00 +0000</pubDate>
				<guid>https://nekocode.cn/blog/2018/09/10/docker-serverless-graphql/</guid>
				<description>&lt;p&gt;最近被 Backend、DevOps 的一些新概念震撼到了。&lt;/p&gt;&#xA;&lt;h2 id=&#34;docker&#34;&gt;Docker&lt;/h2&gt;&#xA;&lt;p&gt;Docker 应该是目前 DevOps 界最火的工具了。&lt;/p&gt;&#xA;&lt;p&gt;早在前几年，我就开始使用 Docker 了。通过 Docker 为公司搭建 Maven 和 Jenkins 服务，然后构建用于编译 Android 项目的 Docker Image 提供给 Jenkins 使用。&lt;/p&gt;&#xA;&lt;p&gt;对于曾经尝试过 Deployment 地狱的人，Docker 的便捷让我对它的印象十分好。&lt;/p&gt;&#xA;&lt;p&gt;而今年，借助 Docker Compose，我更在我的服务器上成功用几句命令就搭建了一系列工具。仅仅是写写 YAML 配置，就可以快速轻松地部署到任意服务器上，这得有多爽。甚至还包括以下一些自动化的事情：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;通过 &lt;a href=&#34;https://github.com/jwilder/nginx-proxy&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;jwilder/nginx-proxy&lt;/a&gt;&#xA; 自动为其它 Docker 容器配置 Nginx 代理；&lt;/li&gt;&#xA;&lt;li&gt;通过 &lt;a href=&#34;https://github.com/JrCs/docker-letsencrypt-nginx-proxy-companion&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;jrcs/letsencrypt-nginx-proxy-companion&lt;/a&gt;&#xA; 自动创建 Let&amp;rsquo;s Encrypt 证书并配置，轻松支持 Https。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;如果是在远古时代，对一个非专业 DevOps 工程师而言，即使不考虑系统和软件之间的兼容问题，要手动完成上述的所有部署操作也是十分麻烦的。要是遇到要把所有服务迁移或复制到其他机器上这种事情，估计得抓狂。&lt;/p&gt;&#xA;&lt;p&gt;来看看我的 Docker Compose YAML 吧：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;Nginx-Proxy&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;image&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;daocloud.io/daocloud/nginx-proxy:latest&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;privileged&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;restart&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;always&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;ports&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;80&lt;/span&gt;:&lt;span style=&#34;color:#ae81ff&#34;&gt;80&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;443&lt;/span&gt;:&lt;span style=&#34;color:#ae81ff&#34;&gt;443&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;volumes&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;/root/nginx-proxy/certs:/etc/nginx/certs:ro&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;/root/nginx-proxy/vhost:/etc/nginx/vhost.d&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;/root/nginx-proxy/html:/usr/share/nginx/html&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;/var/run/docker.sock:/tmp/docker.sock:ro&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;labels&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;true&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;LetsEncrypt&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;image&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;jrcs/letsencrypt-nginx-proxy-companion&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;restart&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;always&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;volumes&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;/root/nginx-proxy/certs:/etc/nginx/certs:rw&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;/root/nginx-proxy/vhost:/etc/nginx/vhost.d&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;/root/nginx-proxy/html:/usr/share/nginx/html&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;/var/run/docker.sock:/var/run/docker.sock:ro&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;Gitlab&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;image&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;gitlab/gitlab-ce:11.2.1-ce.0&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;privileged&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;restart&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;always&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;ports&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;80&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;443&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;22&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;volumes&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;/root/gitlab/config:/etc/gitlab&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;/root/gitlab/logs:/var/log/gitlab&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;/root/gitlab/data:/var/opt/gitlab&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;environment&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;VIRTUAL_HOST&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;git.nekocode.cn&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;LETSENCRYPT_HOST&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;git.nekocode.cn&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;LETSENCRYPT_EMAIL&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;nekocode.cn@gmail.com&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;GITLAB_OMNIBUS_CONFIG&lt;/span&gt;: |&lt;span style=&#34;color:#e6db74&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;      gitlab_rails[&amp;#39;smtp_enable&amp;#39;] = true&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;      gitlab_rails[&amp;#39;smtp_address&amp;#39;] = &amp;#34;smtpdm.aliyun.com&amp;#34;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;      gitlab_rails[&amp;#39;smtp_port&amp;#39;] = 465&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;      gitlab_rails[&amp;#39;smtp_user_name&amp;#39;] = &amp;#34;git@nekocode.cn&amp;#34;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;      gitlab_rails[&amp;#39;smtp_password&amp;#39;] = &amp;#34;xxxxxx&amp;#34;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;      gitlab_rails[&amp;#39;smtp_domain&amp;#39;] = &amp;#34;smtpdm.aliyun.com&amp;#34;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;      gitlab_rails[&amp;#39;smtp_authentication&amp;#39;] = &amp;#34;login&amp;#34;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;      gitlab_rails[&amp;#39;smtp_enable_starttls_auto&amp;#39;] = true&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;      gitlab_rails[&amp;#39;smtp_tls&amp;#39;] = true&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;      gitlab_rails[&amp;#39;gitlab_email_enabled&amp;#39;] = true&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;      gitlab_rails[&amp;#39;gitlab_email_from&amp;#39;] = &amp;#39;git@nekocode.cn&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;      gitlab_rails[&amp;#39;gitlab_email_display_name&amp;#39;] = &amp;#39;noreply@nekocode.cn&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;Gitlab-Runner&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;image&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;gitlab/gitlab-runner:latest&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;container_name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;gitlab-runner&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;restart&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;always&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;volumes&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;/root/gitlab-runner/confg:/etc/gitlab-runner&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;/var/run/docker.sock:/var/run/docker.sock&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;Wiki&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;image&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;blacklabelops/confluence&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;privileged&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;restart&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;always&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;ports&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;8090&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;8091&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;environment&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;VIRTUAL_HOST&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;wiki.nekocode.cn&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;VIRTUAL_PORT&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;8090&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;CONFLUENCE_PROXY_NAME&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;wiki.nekocode.cn&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;CONFLUENCE_PROXY_PORT&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;443&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;CONFLUENCE_PROXY_SCHEME&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;https&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;LETSENCRYPT_HOST&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;wiki.nekocode.cn&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;LETSENCRYPT_EMAIL&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;nekocode.cn@gmail.com&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;PostgresDB&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;image&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;blacklabelops/postgres&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;restart&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;always&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;ports&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;5432&lt;/span&gt;:&lt;span style=&#34;color:#ae81ff&#34;&gt;5432&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;environment&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;POSTGRES_DB&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;postgresdb&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;POSTGRES_USER&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;admin&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;POSTGRES_PASSWORD&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;admin123&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;POSTGRES_ENCODING&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;UTF8&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;感谢 Docker 和社区的发展，让快速轻松地部署软件成为可能。所以请不要再去手工部署或写兼容性差的 Deploy 脚本了。你需要拥抱 Docker / 容器技术。&lt;/p&gt;</description>
			</item>
			<item>
				<title>「二零一七年」的总结</title>
				<link>https://nekocode.cn/blog/2018/02/15/%E4%BA%8C%E9%9B%B6%E4%B8%80%E4%B8%83%E5%B9%B4%E7%9A%84%E6%80%BB%E7%BB%93/</link>
				<pubDate>Thu, 15 Feb 2018 00:00:00 +0000</pubDate>
				<guid>https://nekocode.cn/blog/2018/02/15/%E4%BA%8C%E9%9B%B6%E4%B8%80%E4%B8%83%E5%B9%B4%E7%9A%84%E6%80%BB%E7%BB%93/</guid>
				<description>&lt;p&gt;为什么二月十五才写去年的总结？一，懒；二，正处农历大年三十，可以诡辩地说二零一七在农历上仍未完结。&lt;/p&gt;&#xA;&lt;p&gt;二零一七，于我而言是十分重要的一年。&lt;/p&gt;&#xA;&lt;p&gt;一五、一六年我跟着几个刚毕业的朋友一起创业，从获得千万级风投，到最终资金链断裂，总算结束了我个人的所谓「大学生创业」之路。而一七年初，我入职了知乎。这是一家已经连续创业七年多的公司，而我一直是知乎的重度用户。&lt;/p&gt;&#xA;&lt;p&gt;把之前创业的经历，和在知乎这一年的经历联系在一起，让我感触十分大。我个人的观点是，「大学生创业」、「九零、零零后创业」等，这些只是资本包装起来的词汇。风口上的标签、媒体口味的变化、可观的投资回报率让很多投资者突然对这块市场虎视眈眈。能够在一个早期创业团队上买入股份，然后对团队进行包装和宣传，就有可能再融个几轮卖出个好价钱了。这种已成套路的投资，让大学生创业市场近几年变得熙熙攘攘。&lt;/p&gt;&#xA;&lt;p&gt;但是，缺乏从业经验、市场眼光、风险控制能力、精英化管理能力的大学生团队，不管是在创业的哪一个环节上遭遇到了问题，都可能会是对团队的致命一击。如果我是投资家，我是万万不敢重仓大学生创业团队的，因为在我看来，目前以及未来仍旧是「精英创业」的时代。而那些投资大学生团队的人，他们肯扔钱其实主要出于三个原因：一，容易用很低的价格买入大量的股份，因为大多数大学生团队在面对资本的时候，根本没有任何谈资。二、大学生团队运营成本极低，只要不乱烧钱，想要活久一些太容易了。三，前面就说过了，媒体的口味决定了大学生团队更容易被包装起来，这个其实主要看 CEO，可以参考「余佳文」这类典例（但我个人并不喜欢被这类人 Lead）。&lt;/p&gt;&#xA;&lt;p&gt;而一七年，我能明显感觉到媒体的口味开始再度产生变化，之前一向喜欢鼓吹大学生创业的媒体开始倒戈相向，反而频频开始对大学生创业项目发起质疑、反讽。这让我学习到了三件事：一，资本市场都是贪婪、黑暗的。二，媒体的能力变得日益可怕，创造错误的信息差也能挣钱。三，风口是会改变的（或者说具有周期性），虽然跟着泡沫涨能吃上猪肉，但你得预测到它什么时候会爆。&lt;/p&gt;&#xA;&lt;p&gt;写到这顺带把一五、一六年的一些看法也总结了。接下来说回二零一七这一年。&lt;/p&gt;&#xA;&lt;p&gt;我前面说到了，入职知乎的这一年于我而言十分重要。一来是遇到了很多职场精英，颠覆了我很多过往的看法。他们中有极具有 Geek 精神的工程师、年投资回报过百万的工程师、极具逻辑能力的 Leader。在这个平台上，其实能明显感觉到，相对于很多其他人，自己能力还十分不足，但值得庆幸的是自己的职业生涯还早，并且自己能明显意识到自己的一些问题所在。我本身算是个 Workaholic，希望之后方向正确的话，勤能补拙。&lt;/p&gt;&#xA;&lt;p&gt;二来是由于「实际收入 / 工作时间」比的提高，让我有更多精力去学习、探讨一些技术以外的东西，譬如投资。相对于之前泡沫化的收入，其实到手的收入对于一个风险承担能力弱的穷人而言更踏实。创业的话，干个几年活，最终期权变废纸的概率太大了。当然我不是抵抗创业，我骨子里是喜欢创业的，而且我也崇拜硅谷创业精神。但所谓厚积薄发，我认为目前并不是 Allin 创业的时机，因为我根本没有多少资本去支撑高风险的持续创业（这里的资本包括经验、眼界、资金等）。不过我相信，未来我应该会重新投入其中。当然，目前在知乎也是一种创业，但我想做的其它事还多着。&lt;/p&gt;&#xA;&lt;p&gt;技术相关的事在这个博客上不想费太多笔墨，简单总结下：大多数达到了我对二零一七的心里预期，稍微提高了自己在社区的影响力（我在 Github 社区的一些成就可以在 &lt;a href=&#34;http://git-awards.com/users/nekocode&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;这里&lt;/a&gt;&#xA; 查看）。希望二零一八可以持续提高自己的能力和影响力，并且能在一些其它的领域（新技术、Web）获得新的成就。&lt;/p&gt;&#xA;&lt;p&gt;接下来我想讲下「投资」。&lt;/p&gt;&#xA;&lt;p&gt;很多人喜欢把它称作「理财」，这其实是每个人都会接触到的事情，即使是你把钱全部放在银行里，你也是在做一项投资，只不过你是把钱投给了风险和投资回报率都相对较低的银行（银行也会拿你的钱去投资其它产品、或借贷出去来获得利润）。在二零一七的下半年，我开始大量接触了投资相关的知识，一来是市场突然一片大好，以及投资热潮的突然刮起（这其实是个相当危险的讯号），二来是我创业的时候做的是新三板相关的内容，耳濡目染也开始对金融行业产生兴趣。&lt;/p&gt;&#xA;&lt;p&gt;比较狗血的是，我入场的时机几乎是最差的。二零一八初，我投资了些数字货币，没想到不到半个月比特币的价格就腰斩了。而最近美股市场也一片哀嚎，可以看出经济可能要到周期的拐点了，也就是泡沫要爆了。而我恰好在最高点入场了，。。。&lt;/p&gt;&#xA;&lt;p&gt;经历被割韭菜的洗礼后，上个月，我在知乎想法上发表了一些 &lt;a href=&#34;https://www.zhihu.com/pin/938432484480962560&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;对数字货币的看法&lt;/a&gt;&#xA;，现在可以在这里再补充一些。首先，大部分经济学家都认为数字货币是泡沫，而股神巴菲特也不看好，并坦言很乐意买入五年期的加密货币看空期权。为什么是五年期？因为即使是巴菲特也没法准确预言这个泡沫会什么时候爆，但他觉得五年后必然会爆。&lt;/p&gt;&#xA;&lt;p&gt;但是「天下熙熙皆为利来，天天攘攘皆为利往」，由于人性的贪婪，没人知道这个泡沫会怎么发展，虽然近期腰斩之后目前又开始回升了，但是说实话，我不建议再投钱进去。目前的币市由于缺乏公信机关的监管基本已沦为赌场，而目前能支撑起价格的，大部分还是黑市的需求，和一些尚未对社会产生实际价值的概念。&lt;/p&gt;&#xA;&lt;p&gt;在这次经历里，我犯的最严重的错误就是简单地认为「看好某样事物」就值得投资，然而这其实只是最基础的一个判断因素。假设市场里有十个人，你是第八个看好某件事物的，那么你可能就已经站在泡沫的顶端了。所以看涨某件事物，首先你得足够早（这其实是个信息差的问题）。其次，你得准确预判它的价值是被低估了，还是已经产生泡沫了。&lt;/p&gt;&#xA;&lt;p&gt;但这绝非易事。只能不断学习和尝试。最近春节无聊，刚好也沉迷上了玩德州扑克，这其实可以看作是一个微型的投资训练了，取胜需要你有足够的情绪和风险控制能力。其实，很多时候投资和 投机 / 赌博 是有共通点的，投资也有赚有亏，能稳住牌面最终赢钱离场，那你就是赢家。&lt;/p&gt;&#xA;&lt;p&gt;二零一七要记录的也就那么多。希望新的一年能有更多新的进步。&lt;/p&gt;</description>
			</item>
	</channel>
</rss>
