数码荔枝
我是如何把 Klib 带到这个世界的
我是如何把 Klib 带到这个世界的
分享到:

编者按

Kilb for Mac 是一款 Kindle 标注、笔记、笔记管理软件,近日一上架便迅速获得大量好评。作者 Jason 还写了一篇文章,记录了软件从概念到实现的种种。我们决定在本期会员通讯中转载该文章,不管你是 Kindle 用户、软件爱好者还是开发者,相信看完后都能从中获得感悟或共鸣。

数码荔枝已获得原作者 Jason 的转载授权,仅作了微小的语句改动和格式更改。您也可以点此 阅读原文 或了解 Klib 是如何重塑Kindle 笔记管理的。Klib 现已上架 Mac App Store,定价¥50。

(以下为作者原文)

历时 50 天、横跨 2 年、经过 258 小时的纯手工打造,Klib 终于来到了这个世界。

这两天 Klib 刚刚发布,收到很多用户的好评。赶着手热,记录下 Klib 的诞生历程吧。

缘起

2016 年底的时候,我在思考接下来做什么项目,并没有定下来,只是有个大概的方向——「做个稍微大些的」;以及技术上的需求,「做一个有界面交互的」。因为之前做的 i 系列工具 (iPiciTimeriPasteiHosts) 都是非常垂直的,并且都是菜单栏工具——我想让自己有所突破。

正巧,当时也给自己定了读书计划,就是 要经常读书,并且读完后要在博客上写文章。主要自己是独立开发,获取信息的渠道本来就不多,就要用这种方式强迫自己不断更新。而要写文章,很重要的内容就是读书时的书摘。我习惯于用 Kindle 读电子书,于是,很直接的需求就是,把 Kindle 中的标注、笔记复制出来,用于写文章。

而我大致搜索了下当时 macOS 平台下的标注管理工具,发现并没有趁手的。于是,就开始了程序员最喜欢做的事:造轮子。

时间,正好是 2017 年元旦,详见 当天日记 。顺便说一句,我有每天写日记的习惯,已经坚持几年了 ,也是为了逼迫单打独斗的自己,能够保持思考、反省。

设计

这里借用设计这个名字,只是用以涵盖产品前期的各种思考。确实是有各种思考,如市场环境、商业模式、竞品分析、名字、Logo、做成什么样子、交互、如何发布、怎么运营、时间节点、等等。时间有些早了,这里简单回忆下几个比较重要的点。

一、定位

我一向倾向于做简洁的产品,这个工具也是如此 。我最核心的需求就是导出 Kindle 中的笔记,最直观的衍伸就是能持久保存、定期回顾这些笔记。好了,就是这些吧,再多就难做的精简、好用了。重复+小结一下:

定位:精简的、macOS 平台 Kindle 笔记管理工具。

功能集:

  • 导出 Kindle 中的笔记
  • 持久保存笔记
  • 方便回顾

二、名字、Logo

名字好定,因为我开发的工具都是 i 开头的 (iPiciTimeriPasteiHosts),这个自然也是。再加上是 Kindle 相关的,于是就叫:iKindle。当然,你知道最后不是这个名字;这个坑,以后再填。

Logo 也很容易呀,你看我之前产品的 Logo 就知道了:

iKindle 的 Logo 一定是类似下面这个样子的:

当然,你知道,后来也改了。这是后话。

交互

有了前面的铺垫,就可以考虑具体的交互。

交互一定要直观、符合直觉。开始时,大致的想法是这样的 (幸亏我还保留了当时的截图):

左侧是书列表、右上角是书中笔记列表、右下角是选中笔记的内容、方便编辑。后来当然是不断演变了。

一、先是书

我一开始就没打开按作者来区分,因为我本人并没有追作者的习惯;并且,即使追,也没必要非得按作者分类,搜索不就可以了。

但是,太多书放在一起,就有了排序的问题。按书名、最后阅读时间、还是别的?其实你会发现, 如果书多,再怎么排序都没用。那干嘛不让书少点呢?有了,如果只看最近的几本书,比如3本,还需要考虑排序吗?那些更早的书,归档起来不就好了,之后能搜索到就行。

于是,这就诞生了 iKindle 独有的创意:区分当下正在阅读的书、和之前已经阅读的书。形式上就是把已读的书放在一起,可以折叠隐藏。「嗯,挺棒的!」

二、然后是笔记列表

程序员的思考,很直观的就是把所有属性都列出来,比如笔记内容、类型 (是标注、还是笔记)、位置、添加日期。这用列表很容易实现。

可问题是,除了笔记内容,后面这些属性会占用大量屏幕内容,却又不重要,只要在我需要的时候能看到就可以了。

于是,那就把它们都隐藏起来好了,隐藏到简介里,这样笔记列表就只显示纯粹的笔记内容。「嗯,挺棒的!」

三、再然后就是阅读、编辑当前笔记

你会发现,在最原始的设计中,这部分也占据了大量屏幕、却不得已有大量空白。并且,对于我实际的笔记来看,很多都是一句话的,在列表中就几乎可以展示了,不再需要额外的这个区域。再并且,真正编辑的需求并不大 (最多的就是在标注时,前后有不需要的内容、符号),大部分时间只要看就行了。

于是,这部分也被我干掉了。那如果笔记确实很长怎么办呢?我自然想到了 Finder 的快速预览。OK,那就搬过来吧。「嗯,挺棒的!」

四、下一个就是搜索

这个并不需要特别设计,跟系统的保持一致好了,不一致反而不好。「嗯,挺棒的!」

五、最后,就是整体的交互

我一看,经过上面的改进,这不就是个系统「提醒事项」的样子吗?好吧,那就做成「提醒事项」的样子。「嗯,挺棒的!」

开发

设计差不多了,就可以码了。 我开发的顺序一般是三步走:数据结构、堆 UI、完成业务逻辑。

一、数据结构

数据结构又主要为三块:Kindle 本身数据结构、内存中数据结构、持久化数据结构。

1. Kindle 本身数据结构

好吧,先吐槽一句:Kindle 的数据结构真垃圾!至少是开放出来的数据结构真垃圾,就是一个纯文本,类似于以下的内容:

看起来还行是吗?那再来一些多语言版本的:

单单是识别其中的日期,就有种想 shi 的冲动:要获取日期文本、识别格式、确定 Locale;另外,还不知道日期所在时区。

这里我做一个小机巧: 数据结构的解析能力可以动态更新。也即,在二进制程序不变的情况下,可以从云端获取数据的最新解析方式。这样,当用户反馈给我不支持的格式时,我只要更新云端的解析能力,客户端就都可以无痛、后台式更新了。为自己这个设计点赞!

2. 内存中数据结构

这个没太多好说的,定义书、笔记的各个属性即可。一个主要的机巧在于:如何识别笔记的唯一性?前面的文本中可以看到,笔记并没有所谓唯一 ID 之类的东西。既然没有,那就把笔记整体、或整体的 Hash 值作为唯一 ID 好了,反正笔记的数据量并不大, 一个人一生的笔记,可能也没有 iPhone 拍的一张图片体积大。

3. 持久化数据结构

这一步,主要 在结构化存储、和非结构化存储中纠结。前者数据规整,适合笔记存储,但扩展性差。后者优缺点大致和前者相反。最后,我还是选择了结构化存储。具体的,就是 SQLite。 一方面笔记类数据实在是太规整了;另一方面,抱着学习的态度,反正我哪种都不熟悉,随便拉一种出来练手吧。

4. 还有一个考量就是: 数据结构的公开性。数据是用户的、宝贵的,如果使用私有的二进制数据结构,万一哪天要停止维护了,用户就没有任何办法可以解析这些数据。而使用公开的 SQLite 则不怕,任意一款 SQLite 工具都可以查看用户自己生成的数据。这样做,对用户是负责任的。

二、堆 UI

这部分倒没有太多可说的。一方面就是一些核心控件的用法,如 NSOutlineView、NSTextView、NSPopover、NSSearchField。其中,Source List 模式的 NSOutlineView 是有些坑的,会出现诸如 UI 刷新不及时、图标丢失等现象。有遇到类似问题的朋友,可以找我聊聊。

另一方面就是界面的细节,如字体、字号、颜色、留白、间距、等等。这方面我倒是偷懒了,因为基本就是「复刻」系统「提醒事项」。

三、实现业务逻辑

  1. 打通数据流
    比如,选择右侧书时,右侧笔记列表能相应变化;编辑笔记时,数据能持久化;查看笔记时,能读取正常的数据;等等。是不是听起来都像是废话?恩,就是这么回事,做对就行了。关键是 代码结构要好,不要有复制代码、严重耦合之类的问题。
  2.  用户引导层面
    比如,开始时引导用户手动导入、进行过程中引导用户如何操作。这部分我基本没做太多,因为希望程序可以做到无需引导。不过,引导用户导入这一步,做的确实不好,还要再改进。
  3.  外围的一些功能
    比如,账户系统、日志及反馈系统、等等。这里就不再铺开了。

测试

一、单元测试

其实,单元测试是在开发一开始就进行的。尤其是对数据结构部分,要充分测试。如果这部分没问题,只要程序能跑起来,基本就没有大问题。如果这部分有问题,改 Bug 够喝一壶的。

并且, 要在定义数据结构、完成新功能那一刻,立即完善单元测试。因为这时候是对代码最熟悉、最清楚、也最愿意写单元测试的时候。错过这一刻,实在是太可惜了。

二、完善测试用例

和单元测试一样,测试用例不是在产品开发结果后补齐,而是在每开发完一个功能逻辑后,立即完善测试用例。道理一样,因为这个时候是对逻辑理解最透彻、清晰的时候,千万不能错过。

三、版本测试

单元测试跑一遍,心里就有底了。再加上前面完善的测试用例,版本测试无非就是照着用例跑一遍。

我并没有做自动化测试、持续集成,主要是涉及 UI 的自动化测试并不好做,而且投入很大。对于我这种小项目、独立开发者而言,手动跑跑测试用例,可能是性价比最高的。

值得介绍的一点是, 推荐使用虚拟机进行版本测试。事先建立好干净的系统、生成镜像。每次测试时,只要将虚拟机恢复到指定的镜像即可。再者,就是可以在当前系统 (如 macOS 10.12)中,测试其它版本的系统 (如 macOS 10.11)

上架

自己辛苦做出来的东西,当然是希望越多人用户越好。要触到更多的用户,最直接有效的办法就是 上架 Mac App Store (MAS)了。

一、内测、公测

在上架前,要保证自己的产品的可用、好用的,最好的办法就是,先让一部分用户用起来,也就是内测、公测 (以下统一称公测)。

特别要强调的是, 公测的目的并不是发现 Bug,这是你自己要做好的事。公测主要有以下目的:

  • 检验市场:也就是说,这个产品是不是有人需要、有多迫切需要,之前假想的市场是否存在、有多大,等等
  • 检验设计:如果有人要,那自己做出来的东西是不是他想要的?哪些地方设计的比较好,有没有致命的缺陷?
  • 检验质量:因为自己能覆盖的情况是有限的,还是要靠真实用户的实际使用来最终检验质量。

我的内测主要是在之前的用户群中、V2EX 中, 在此特别感谢参与公测的朋友!

二、Mac App Store

好吧,终于来到 Mac App Store (MAS) 这个大坑。说 MAS 是大坑,主要是以下方面:

1. 沙盒限制
沙盒会限制很多接口、系统权限的使用,对程序设计、产品交互有明显的影响。

比如,除非用户手动操作 (即用操作本身来授权) 沙盒不允许产品访问用户的文件系统。这就使用 iKindle 无法在一开始时直接自动导入当前连接的 Kindle 设备,而必需由用户手动操作。这就需要很恰当的引导。而一旦使用过一次,后续就不再需要用户手动操作。这也是为什么 iKindle 后续可以自动导入。

还有一个很关键的: 即使在开发过程中打开了沙盒限制,苹果在审核时还是可能以沙盒为理由拒绝。虽说苹果准备了齐全的文档来说明这些限制,但一般开发者明显不能完全领会。就像你不可能读完所有法律以后再迈出家门第一步,一定碰到问题再解决问题更实际。好在,这次我没碰到这个问题。

2. 名字
好吧,来说前文的坑。也许你会奇怪,为什么直到「沙盒限制」用的还是「iKindle」这个名字?是不是打错了?没错,确实是叫 iKindle。

但是, 苹果不允许在 App 名字中出现 Kindle 这个字样。于是,只能改名了。这真是个痛苦的过程。一方面,想出一个好名字并不容易,我纠结了 N 久 (具体可见我的博客),最终写了 Klib – Kindle library 这个名字。

另一方面,所有的东西都是跟名字相关的,比如代码、App 名称、文案、截图、等等。一旦名字改了,所有这些都要改。这是极其繁琐的事,我再也不想做第二次。

比如 Logo,变成了下面的样子:

发布、推广

终于,在被拒了两次后,Klib 终于顽强上架 Mac App Store。接下来的问题就是, 怎么让更多人知道 Klib,也即,如何发布、推广?

一、Product Hunt

在这一环节,我最没有办法的,就是 如何在海外推广。毕竟咱们是中国人,很难打入敌人内部,更别说在外国产生影响力。

怎么办呢?我目前找到最直接有效的方法,就是在 Product Hunt 中有个成功的发布。这样国外的媒体也会在 Product Hunt 中找较好的产品进行报道。所以, Product Hunt 成了 Klib 走出国门、走向世界的关键。

Product Hunt 的发布有很多可说的,这里挑几点重要的来说:

1. 发布时间:

  • 从星期几的角度, 每周二是最合适的。因为周二 Product Hunt 的用户量最多,也有充足的时间进入 Product Hunt 的 Weekly Report. 不过,考虑到 Klib 是小众产品,不太可能进入当天的 Top 1。根据「鸡头与凤尾」的逻辑,我选择美国的周一来发布。
  • 从几点的角度,一种做法是在凌晨 00:00 发布,这样可以充分利用 24 小时进行传播;另一种做法是在早上的时间发布,因为这里媒体人、评测者刚刚起床,可以给他们更多爆光。考虑到我并没认识国外的媒体人,还是 00:00 发布吧。 因为时区的原因,Product Hunt 会在北京时间下午 4 点切换昨天、与今天的产品列表。

2. 名字、标语:

名字就是 Klib 了,重要的是标语。要简洁、要突出产品特色、要抓住用户眼球。

3. 截图:

  • 如果有必要,可以制作动图,虽然我挺讨厌一旦有多个产品都使用动图,会让界面闪啊闪,显得很 Low;但没办法,这确实是能抓用户眼球。并且,Product Hunt 的 Twitter 账户也有专门转发动力的。
  • 基本上,我把 Mac App Store 的截图重用了。

4. 发布后,立即在首条评论中添加更多信息。如产品的进一步介绍、未来的规划、联系方式、等等。

5. 转发、扩散。也就是让更多的人点进来看,投票、讨论。尤其是大咖的转发会很有效。我最大的成绩是 Ben Tossell (Community Lead of Product Hunt) 参与了讨论。可惜,他并没有转发。不过,不要一味的拉票,Product Hunt 有自己的排名算法。

6. 及时回复留言。用户的留言,要立即回复 (嗯,晚上基本可以不睡了,盯着)。并且,可以将用户的回复转发到 Twitter 上,并表示感谢。

最终, Klib 在 Product Hunt 上获取200+点赞,10几位国际用户参与讨论,并入选当日 Top 10,基本满意。

二、用户群

Mac App Store 上的好评、留言,自然是非常重要的。而 最有可能给你好评的,就是你之前产品的用户。我一开始没有经营自己的用户群,现在回想起来深觉可惜。好在,现在慢慢有了 微信群Telegram 群, 也有了一些非常友善的用户,感谢你们!

三、媒体

媒体的爆光自然必不可少,他们的影响力是个人无法比拟的。最好是:

  • 平时就与媒体朋友保持联系,不要临时抱佛脚;
  • 上线前发体验版本,给他们预留时间准备文案;
  • 上线时及时通知,方便他们安排发布时间;也可以提供兑换码,方便对方做活动。
  • 发布会,也要帮忙转发,并表示感谢。

四、其他影响力

动用所有可以动用的影响力,让 Klib 触达更多的人。比如让朋友帮忙转发及好评,微博转发抽奖,朋友圈,等等。

其他

一、定价

定价是门玄学,太高没人买、太低自己不划算。目前Klib 采用的是免费 + 内购 (一次性买断) 的方式。免费是为了方便更多的人使用 Klib、降低门槛。虽然我很想继续尝试订阅模式,无奈用户对订阅始终接受程度不高,且 Klib 本身的属性也不太适合订阅模式,于是采取买断式。

趁这个机会,表达下个人观点: 买断对开发者并不友好,订阅才符合实际。毕竟通常开发者需要对产品进行持续改进 (这并不是说当初发布的产品有问题,而是产品本身有改进),却不能从改进中获得收益,这并不健康。伤害的最终可能还是用户自己的利益,因为开发者一旦坚持不下去而不更新,用户只能使用有待改进的版本。

二、首发的意义

目前,Klib 是 macOS 平台、首款上架 Mac App Store 的 Kindle 笔记管理工具。这种唯一性是很有意义的。因为没有直接竞品,甚至有一定的定价权。

对用户而言,首发更容易使产品在这一品类中形成定位,后来者要想抢走在用户心智中的定位,就不容易了。

三、单日销量的意义

如果单日销量可以使 App 出现在排行榜的前面,会带来一些附加的流量,因为别的用户可能因为榜单的原因多看两眼。

首发第2天 (第1天 App Store 更新太慢,没有数据), Klib 在中国区、Utilities 这一品类中,Free 排名 22、Grossing 排名 14,算是不错的成绩了。

目前,Klib 算是成功上架 Mac App Store,也收到了很多用户的反馈。接下来,我会继续改进 Klib,如增加多看支持、与 Amazon 中的笔记同步、与 Kindle 其他平台的笔记同步、导出至 Evernote、等等。当然,我会非常谨慎地加功能,保持 Klib 的精简。

致谢

真的有很多人需要感谢…

  • 感谢家人对我做独立开发者的支持 (主要是接受不赚钱…)
  • 感谢用户对我的信任;
  • 感谢朋友的帮助,比如 Kindle Mate 作者 提供多语言支持、Allen 帮助制作 Logo、61 帮忙搞定微博短链;
  • 感谢媒体的报道(点名最先报道的 少数派);
  • 感谢所有点赞与批评的朋友;
  • 感谢苹果 (虽然 MAS 有坑);
  • 感谢 Kindle;
  • 当然,感谢 CCTV。

最后

希望 Klib 能让大家多读点书、记点笔记,哪怕只是一点点改变,也是 Klib 的莫大荣幸。

看完本文如果您也对 Klib 有了兴趣,可以到 Mac App Store 试用并购买。

感谢阅读,祝读书愉快,enjoy~

文章评论

发表评论

您忘了输入昵称
为了更好地彼此沟通,评论字数不得少于5个

关注有礼

关注公众号,每月领取大额券,最先了解软件上新与促销信息
公众号:shumalizhi