Serverless实战:打造个人阅读追踪系统 – ThoughtWorks洞见

标签: | 发表时间:2017-09-30 02:35 | 作者:
分享到:
出处:http://insights.thoughtworks.cn

阅读习惯和个人知识管理体系

进入互联网时代,知识的获取成本变得前所未有的低廉,但是无论再好的知识,若是没有对个人产生价值的话,那也只不过是一种信息噪音而已。我在《个人知识管理:知识的三种形态》这篇文章中使用“材料 -> 资料 -> 知识”这样的路径来诠释信息的流通,如何方便快捷并且有效地收集材料,再将其整理转化为有价值的个人知识体系结构,在这个信息极度碎片化的时代变得尤为重要。而在《去伪存真的知识管理之路》一文中也详细阐述了如何将网络上的碎片化文章纳入统一的稍后阅读体系,比如有时候在朋友圈看到一篇好文章,但暂时没时间直接看,或是这篇文章值得再读一遍,细读一遍,那么我就会将其存入稍后阅读工具即Instapaper当中,诸如此类的还有Pocket收趣等等。

稍后阅读中永远读不完的痛点:缺乏追踪

随着时间的推移,Instapaper里面的文章将会变得越来越多,就像我们在代码中所注释的TODO:可能就变成了Never Do,“稍后读”也是一样地被广为诟病:Read it Later=Read Never。其实我发现文章堆积的一个永恒痛点就是没有有效的方式追踪自己的阅读需求与能力,其核心原因在于阅读的速度赶不上添加的速度。从而没办法可视化的评估阅读进度、合理安排阅读计划,也就没办法给予自己适当的奖励,长此以往必然将失去阅读的动力。

在之前的一篇文章——《基于GitHub的敏捷学习方法之道与术》,其中提到使用GitHub Issue来管理自己的学习计划,于是就产生了这么一个想法——将我的稍后阅读列表跟GitHub结合起来,使用ZenHub丰富的图表功能将阅读体系进行追踪与可视化。

可视化Cumulative Flow Diagram

首先让我们直接来看一下最终的具体效果图,在这里简单介绍一下CFD(Cumulative Flow Diagram)即累积流图,这是一种能让你快速了解项目或产品工作概况的图表,关注的是价值的流动效率,价值的流动最直接的体现就是需求卡片在各个队列中的数量。

里特定律(Little’s law)告诉我们,交付时间(Delivery time)依赖于在制品数量(Work In Progress, WIP)。WIP是指所有已经初始但还未完成的工作,例如:所有在分析(Analysis)与完成(Done)之间的工作。首先需要留意的就是WIP,如果WIP增加了,交付日期就会有风险。ZenHub所提供的Release Report中最有效果的就是预测完成日期,总之就是跟敏捷方法结合起来,使用项目管理的方式来管理自己的阅读列表,虽然我还处在进一步的探索之中,但是每次看到这个走势图就能对自己的阅读列表有更多的掌控和理解,至少减少了因文章堆积而产生的焦虑感。

IFTTT与Serverless架构

那么这是怎么通过APIs来实现的呢?在真正进入正题之前我们先来简单介绍一下Serverless架构。Serverless指的是在构建Web应用程序的时候,不用担心如何配置服务器,但是这并不意味着应用程序不会在服务器上运行,而是说服务器的管理都可以尽可能地交给相应的云平台,从而最大程度地减轻开发人员的部署与配置工作。与之对应的一个名词可能就是Function As a Service(FAAS),由AWS Lambda这个命名就能想到,当我们在构建Serverless架构时,实际上我们是在写一个个的Function,即函数而已。

流程化:APIs即服务

首先让我们来介绍一下IFTTT即if this then that。通俗的来讲,IFTTT的作用就是当一件事情被触发时,能够执行设定好的另一件事。所谓的「事」,指的是各种应用、服务之间可以进行有趣的连锁反应。IFTTT的宗旨是Put the internet to work for you(让互联网为你服务)。用户可以在IFTTT里设定任何一个你需要的条件,当达成条件时,便会触发下一个指定好的动作。它就像是一座神奇的桥梁,能连接我们日常所用的各种网络服务。

而我们现在遇到的这个串联式的场景是特别合适Serverless架构的,使用IFTTT并且将它跟Instapaper账号绑定,设置文章添加、高亮、归档等行为作为trigger条件,然后将相关信息发到某一个指定API endpoint。先把操作GitHub Issue和ZenHub的各种APIs准备好,结合IFTTT的触发器与Marker工具能够非常方便地与之相集成,最后我们可以产出这样一个APIs交互流程图:

初始化Webtask项目

虽然AWS Lambda是Serverless架构的典范,但它也有一些槽点,而且我觉得已经被人说得足够多了,所以我们今天就来尝尝鲜,着重介绍和使用一下Webtask。你可能没有听说过推出该服务的这家公司——Auth0,但你一定知道大名鼎鼎的JWT即JSON Web Token,这是一种开放标准(RFC 7519),通常被运用在身份验证(Authentication)和信息交换等需要安全传输信息的场景下。

首先让我们来安装工具初始化项目以及注册账号,然后使用电子邮件进行登录:

npm install -g wt-cli
wt init <YOUR-EMAIL>

创建项目目录,添加index.js文件并添加以下内容:

module.exports = function (cb) {
  cb(null, 'Hello World');
}

然后在该目录中运行以下命令,进行应用程序部署之后,点击控制台中输出的URL就能看到编程史上最有名气、没有之一的HelloWorld!:

wt create index

Webtask的上下文绑定

Webtask有一个实用工具webtask-tools,可以将应用程序绑定到Webtask上下文,让我们将之前所export的简单函数修改为绑定到Webtask的Express app,然后就可以愉快地使用Express进行开发,一切就又回到了熟悉的轨道:

app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())

require('./routes/reading')(app)

module.exports = Webtask.fromExpress(app)

Webtask context还有一个非常重要的用途,就是在部署时传输一些敏感信息,比如安全Token,从而在应用程序当中随时使用它们。下面的部署命令中–secret后面所传入的ACCESS_TOKEN都会在后续与GitHub和ZenHub APIs交互时被用到。

wt create index --bundle --secret GITHUB_ACCESS_TOKEN=$GITHUB_ACCESS_TOKEN 
--secretZENHUB_ACCESS_TOKEN=$ZENHUB_ACCESS_TOKEN --secret
ZENHUB_ACCESS_TOKEN_V4=$ZENHUB_ACCESS_TOKEN_V4

# ./routes/reading.js
module.exports = (app) => {
  app.post('/reading', (req, res) => {
    const { GITHUB_ACCESS_TOKEN, ZENHUB_ACCESS_TOKEN, ZENHUB_ACCESS_TOKEN_V4 } = req.webtaskContext.secrets
    }
}

使用GitHub Issue追踪阅读列表

IFTTT:添加Instapaper文章后自动创建GitHub Issue

得益于IFTTT非常丰富的第三方服务,IFTTT可以直接创建Instapaper与GitHub Issue相集成的Applet:If new item saved, then create a new issue – IFTTT,就可以在当Instapaper新增文章的时候,自动在GitHub所指定的仓库Issues · JimmyLv/reading中创建一个新的Issue并添加相应的标题、链接以及描述等相关信息。

但仅仅只是添加一个Issue还不够,这时候还需要将这个Issue加入到指定的Milestone以便利用ZenHub的图表功能,使用GitHub的Webhooks功能就可以轻松帮我们把Issue更新的状态转发到我们所指定的Webtask地址:

使用GitHub Webhook 更新Issue的Milestone

所以我们的Webtask就需要处理GitHub Webhook所转发的POST请求,其中包括了Issue的类型和内容,在拿到’opened’即新建Issue类型的action之后我们可以对其进行相应的处理,即添加到Milestone当中:

if (action === 'opened') {
  fetch(`${url}?access_token=${GITHUB_ACCESS_TOKEN}`, {
    method: 'PATCH',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      milestone: 1
    })
  })

}

结合ZenHub的Milestone燃尽图我们可以清晰地看到剩余阅读量,并且能够跟理想中的阅读速度进行对比,从而判断自己什么时候能够全部读完所有的文章。可能有些小伙伴看到这里会有所疑问,这些所谓的Story Point是从哪儿来的呢?接下来就要提到我们将要集成的ZenHub API了。

集成ZenHub API:阅读可视化

更新Issue的估点和Release

GitHub Issue的任何变动都会触发Webhook,因此我们可以在Issue被加入Milestone之后再处理下一个’milestoned’ action,即:

if (action === 'milestoned') {
fetch(`https://api.zenhub.io/p1/repositories/${REPO_ID}/issues/${number}/estimate?access_token=${ZENHUB_ACCESS_TOKEN}`, {
    method: 'PUT',
    body: JSON.stringify({ estimate: 1 })
  })
    .then(() => {
      return 
fetch(`https://api.zenhub.io/v4/reports/release/591dc19e81a6781f839705b9/items/issues?access_token=${ZENHUB_ACCESS_TOKEN_V4}`,
        {
          method: 'POST',

        })
    })
}

这样我们就完成了对每个GitHub Issue的估点,以及设置了对应的Release,接下来所有的变动都将体现在ZenHub的图表当中。

归档Instapaper文章后关闭GitHub Issue

说了这么多,不要忘了整个阅读系统最最核心的部分依然还是「阅读」啊!在众多的稍后阅读工具中我无比喜爱Instapaper并迟迟没有转到Diigo的原因就在于它优秀、简洁、纯粹的阅读体验,让人可以专注在阅读本身这件事情上,在被Pinterest收购之后更是将所有的诸如全文搜索、无限高亮/笔记、速读等Premium功能都变成了免费,岂不美哉?

那么在完成阅读归档之后,最后一步就是在GitHub当中将Issue关闭掉,但是IFTTT的GitHub服务并没有提供close Issue的接口,于是乎我们就只有利用IFTTT新推出的Maker自己创建一个,即将Instapaper规划作为一个IF trigger,然后用Maker发出一个Web请求,可以是GET、PUT、POST、HEAD、DELETE、PATCH或者OPTIONS之中的任何一种,你甚至还可以制定Content Type和Body。

app.get('/reading', (req, res) => {
    const { GITHUB_ACCESS_TOKEN } = req.webtaskContext.secrets
    const title = req.query.title
    let keyword = encodeURIComponent(title.replace(/\s/g, '+'))

fetch(`https://api.github.com/search/issues?q=${keyword}%20repo:jimmylv/reading`)
    .then(data => {
          if (data.total_count > 0) {
        data.items.forEach(({ url, html_url }) =>
          fetch(`${url}?access_token=${GITHUB_ACCESS_TOKEN}`, {
              method: 'PATCH',
              headers: { 'Content-Type': 'application/json' },
              body: JSON.stringify({ state: 'closed' }),
            })
                   }
    })
}

上述代码就可以用于处理IFTTT Marker所发送的GET请求,我们从query参数中取到文章标题之后再去搜索相对应的Issues,再通过GitHub API将其关闭。

而与此同时,我们在文章的阅读过程中,有时候也会想要对文章中的亮点部分进行高亮,甚至添加自己的一些想法和总结,那我们也可以用IFTTT Marker和Webtask的套路添加至GitHub Issues的comments当中。具体的详细代码就不贴了,更多内容都已经放在我的GitHub上:JimmyLv/demo.serverless-mern,与此同时我的阅读列表也公开在GitHub上:Issues · JimmyLv/reading,欢迎围观。

总结与后续计划

随着时间的推移,日常你只需要在Instapaper添加并阅读文章即可,而背后利用Serverless所搭建的整套阅读追踪系统将会任劳任怨的帮你记录下所有的踪迹和笔记,你只需要在特定的时候定期review、分析阅读的效果与预测效果,与此同时结合自己的时间统计系统,持续不断地改进自己的阅读目标与阅读计划。

最后再来考虑一下后续计划,比如说我现在只是简单把Instapaper中高亮部分和阅读笔记作为评论放到GitHub的comments里面,但是最终我需要把它收藏到自己的个人知识库即Diigo,这也是可以通过API自动实现的,以及最终需要被刻意记忆的部分还需要与Tinycards或者QuizletAPI相集成,对抗艾宾浩斯遗忘曲线。

与此同时,还需要根据文章类型和难易程度具体划分一下估点,而不是现在简简单单的1点,比如说Instapaper也有根据字数来预测的阅读分钟数,以及根据中文或英文、技术或鸡汤等不同种类文章阅读难度进行区分,从而使整套追踪系统更具有效性与参考性。




相关 [serverless 个人 阅读] 推荐:

Serverless实战:打造个人阅读追踪系统 – ThoughtWorks洞见

- -
阅读习惯和个人知识管理体系. 进入互联网时代,知识的获取成本变得前所未有的低廉,但是无论再好的知识,若是没有对个人产生价值的话,那也只不过是一种信息噪音而已. 我在《个人知识管理:知识的三种形态》这篇文章中使用“材料 -> 资料 -> 知识”这样的路径来诠释信息的流通,如何方便快捷并且有效地收集材料,再将其整理转化为有价值的个人知识体系结构,在这个信息极度碎片化的时代变得尤为重要.

敏捷个人-阅读笔记

- Tizen - 人月神话的BLOG
周金根同学的原文档在:http://www.docin.com/p-44561337.html. 如果把经营个人成长作为一个项目来看待,那么我们每个人都是这项目的管理者和执行者. SCRUM的核心价值观是:承诺,专注,公开,敬重和勇气. 它提倡自我管理,涌现机制,可视性和评估/适应循环的根本原则. 这些价值观在个人自我管理中依然有效.

知乎个人回复整理-3个阅读问题

- - 战隼的学习探索
最近在混知乎,回答了300多个问题,定期把知乎上的回答整理一下,跟大家进行分享. 这几天的文章都是回答知乎上的问题得来的. 有一起玩的,可以关注一下: warfalcon : http://www.zhihu.com/people/warfalcon. 1、可以使用番茄工作法,看40分钟左右,休息5-10分钟.

移动阅读与阅读

- - 扯氮集--上海魏武挥的博客 - 扯氮集--上海魏武挥的博客
近日,由中国新闻出版研究院组织实施的第十次全国国民阅读调查显示,国民在数字阅读这个维度上的比例有所上升,从11年的38.6%小幅增加到12年的40.3%,而电子书阅读,更是有比较可观的增幅,从11年的人均1.42本到12年的2.35本. 另外一个消息是,搜狐移动设备上的新闻客户端,累计下载安装量已经破亿.

伪阅读

- coen - 情书
    在一次百老汇大街边的午餐交谈中,关于阅读,我和我的荷兰同事达成一个共识:学术生涯实际上是一个摧毁阅读的过程.    从道理上来说,怎么会呢. 从事学术工作,尤其是社会科学的学术工作,我们最有条件进行大量阅读了.     但事实是,学术工作从以下几方面摧毁了阅读及其乐趣:第一,为了“研究”需要,你的阅读范围一般都非常狭窄.

社会化阅读:阅读的未来

- waco - 互联网的那点事...
本文来自MTC联合创始人,社会化阅读观察员钟雄的投稿,新浪微博@钟雄这Y. 从传统阅读到数字阅读,不仅是媒介的变化,更是阅读习惯的改变,它降低了阅读门槛,提高了获取知识的效率,推动了文明的进程,更催生了网络原创文学. 但是,看到自己想看的内容,并与志同道合的朋友交流分享的需求并没有被很好的满足,因此以读者为中心,基内内容获取个性化,分享交流社区化的社会化阅读正成为阅读的未来.

未来的阅读

- xj - 左岸读书_blog
雪茉莉灵感突至,写了一篇对未来阅读的设想. 2010年年末的时候,听了一场主题为“新媒体的未来”的讲座,引发了我对未来阅读模式的思考,在我的想象中,未来的阅读体验应该是这样的:. 下班的途中,坐在车上,我从包包里拿出了我的“墨宝”,开始阅读. “墨宝”(Mobile Book Reader)是类似于Ipad的东东,但是比Ipad轻、薄、更小巧,更时尚,功能更强大,使用更方便.

《观止》阅读录

- Calvin998 - 阿朱=行业趋势+开发管理+架构
观止这本书讲的是微软在1989年-1993年这5年开发WINDOWS NT的故事.观止,是叹为观止的意思.意思是好到了极点.但事实上WINDOWS NT的产生九曲九弯、筋疲力尽、歇斯底里、极度焦虑、几乎失控,但最终还是完成. 卡特勒是NT的开发主管,是这个开发团队的领袖,是主宰一切的头. 他一直是争强好胜、斗勇好狠的角.

阅读的力量

- - 简单文本
阅读,以灵魂融合的方式阅读,或许会战栗,恐惧,喜悦,哭泣,甚至紧张,却可以让你成为阅读的人存在,你既是独立的,又陷入作品中成为你臆想和理解的另一个人. 乔治.斯坦纳(George Steiner)在《语言与沉默(Language And Silence)》的第一篇《人文素养》中如是评价阅读:. 一个人读了《伊利亚特》第十四卷(普里阿摩斯夜会阿基琉斯),读了阿廖沙.卡拉玛佐夫跪向星空那一幕,读了《蒙田随笔》的第二十章,读了哈姆雷特对这章的引用,如果他的人生没有改变,他对自己生命的领悟没有改变,他没有用一点点彻底不同的方式大量他行走其中的屋子,打量那些敲门的人,那么,他虽然是用肉眼在阅读,但他的心眼却是盲视.

有关英语阅读

- kezhuw - 云风的 BLOG
不知不觉,我最近两年居然读了许多英文读物. 书、手册、论文、blog 等等. 前段想翻一点资料原文,居然记错了,以为自己曾在中文版中读到的,后来才发现我以前读的是英文版. 昨天晚上在小店客厅的沙发里窝着,读 Dungeon Twister 2 Prison 的规则书. 然后把游戏 setup 好自娱.