我想要什么样的房子?

A bedroom with a large bed and a ceiling fan

在少数派看到一篇沪漂七年、搬家七次的文章,介绍了作者自己的选房思路。刚好,我从毕业开始,基本上每年搬家一次,也不断的试出来了什么是我想要的,记录一下,以便于后续看房的时候了解。

布局

必须两室及以上

我自己对于书房是有追求的。日常喜欢买书,也希望有一个不错的工作环境,因此,我希望我自己的房子应该是有两室及以上的。这涉及到我是否可以在家工作。

当然,两室还有个问题,如果有了孩子,可能不够,这个问题的解决办法是等有了孩子可以把书房外移(比如在同小区租一个房子作为书房 / 健身房等可外移的家庭职能的模块)。

有个阳台(或者通风极好的房间)

我有三只猫,这三只猫需要一个阳台来放置他们的自动猫砂盆,让他们也可以有更好的装扮。

三分离或干湿分离的卫生间

干湿分离或三分离可以让多个人同时洗漱,同时也不会让干区受淋浴影响,变得太湿。

如果可以的话,最好是多个卫生间,这样早上起来不抢….

软装

置物柜

我是一个有很多杂物的人(有太多的爱好),所以需要足够的置物柜和空间,以便于放置东西。置物柜内部最好也是有一个个的篮子,方便从里面拿东西。

单人床/可睡觉的沙发

我的工作习惯是全身贯注把精力用完,然后快速休息,睡一觉起来继续干。因此,书房有一个可以睡觉,但不要太舒服(会睡很久)的单人床,是必要的。

家电

空调

所有房间必须都要有空调(卧室、空调,甚至是厨房)。有可能最终会发现中央空调是最好的选项。一定要有,极端温度和天气越来越多,还是有必要保证每个房间都有空调的。

(当然,身在北方,同样需要暖气系统,来让房间在冬天更暖和)

冰箱

500 L 以上的冰箱。自打成了山姆的会员后,我开始喜欢采购一些青菜沙拉之类的视频,山姆的食品都是大份,小的冰箱确实放不下。租房常见的 100 L / 200L 的冰箱总是太小了。

如果可以的话,选择一个带制冰功能的冰箱,这样就可以不用专门买制冰机了。

制冰机

作为一个咖啡/茶叶/各种饮品爱好者, “喝冰的”,是我的核心需求,所以家中需要有个制冰机,以对抗炎炎夏日。如果冰箱提供了制冰功能,就不用再单独买制冰机了。

饮水机

夏天要多喝水,冬天更要多喝水。作为一个饮品爱好者,饮水机是必不可少的。且,饮水机应该是同时能够制冷和制热的饮水机,这样才能适配动态和夏天的不同情况,满足喝水的需要。

多喝水,少喝饮料。

洗烘一体机

洗衣机和晾衣服是一个麻烦事,如果能够有洗烘一体机(或者两台也 OK),可以让我免去需要用阳台来挂衣服。一方面,更加体面(别人来拜访时看不到你的房子中的那些衣物);另一方面,也可以让衣服变得更柔软和舒服。

洗碗机

做饭是我喜欢的,但洗碗不是。我身边有买洗碗机的同学都给我反馈洗碗机带来的生活幸福指数很高。因此,我也一直想要购买。但洗碗机需要在装修的时候装上(对水有依赖),所以,组房不太合适,就只能期待买房可以解决了。

智能门锁

智能门锁意味着出门不再需要带钥匙,只要刷指纹、输入密码,就可以进入家门,再也不用担心钥匙丢掉了。再配合数字门禁卡,进小区也不需要门禁卡。

智能窗帘(米家窗帘伴侣)

我享受重磅窗帘的强力遮光效果,但同时,也希望能够在早晨被自然光照醒,那么能够在晚上不影响睡觉,早上又能自动打开的智能窗帘伴侣就是必备产品了。

网络环境

NAS + 路由

我自己是有不少项目数据要存储的,NAS 是我需要的,因此家里必然会有一个 NAS,相应的网络基建也是需要的(比如千兆网)。

更多约束,To Be Continue…

什么是 Hackathon 以及在 Hackathon 当中取得更好的名次的小技巧

people doing office works

这个分享是我在 2024 年 5 月份的飞书 AI 训练营的分享,我觉得这个 PPT 的内容可以完美的诠释我对于 Hackathon 的态度,所以除了视频,我将文字稿也完整的撰写出来,希望让这篇文章对 Hackathon 感兴趣的你,能够有些帮助。

视频版可以在 BilibiliYoutube 找到。


什么是 Hackathon?

5e70b9cc82dbaf59c5fbfb19c1c488ce

Hackathon 是一个起源于美国硅谷地区的创新技术活动,来自不同背景、技术各异的天才开发者们会现场组队,在 24 小时内进行代码开发、创造新的产品,以解决某一个具体的行业难题或痛点。

当然,得益于技术基建的发展,Hackathon 不再是工程师、开发者们的专属,借助于各种 Low Code、Zero Code 工具,非技术人员也可以打造出一个产品,来解决一个具体的问题。

Hackathon 的三大特点

7463ba38c49de8883d69ee00a93adb06

Hackathon 有三个非常显著的特点,也是我个人非常喜欢 Hackathon 的原因:

  1. 短时高强度:Hackathon 往往是有时间限制的,一般是 24 ~ 72 小时之间。这个是我认为 Hackathon 最重要的特性。
  2. 开放:Hackathon 会更加的开放,无论你是什么背景,都可以在这里找到合适的队伍参与到其中。即使你的 Day Job 是一个设计师,但在 Hackathon 里,你一样可以是一个产品经理。
  3. 从零到一:Hackathon 一个很大的好处是给了大家一个从 0 到 1 的机会,你可以从 0 到 1 的打造一款产品,这对于在公司里往往只能做 1~100 中的某一小部分增量价值的打工人来说,颇为难得,可以帮助你获得在企业中无法获得的经验和视角。

我进一步解释一下我为什么认为短时高强度是 Hackathon 的精髓。

如果你做过力量训练,就知道有效的力量训练是让你在短时间内做最大力量的练习,以让你的肌肉发力,直至断裂的效果,并通过休息来让肌肉组织重新生长和链接。而Hackathon就有类似的效果,让你在一个很短的时间内去做一个看似不可能的事情,通过在这个极短时间内做事,来实现锻炼的效果。当你完成 Hackathon 之后,就可以复盘自己在 Hackathon 中的所作所为,并一次优化自己的下一步动作。

而且,因为Hackathon 本身的开放性,你可以在不同的 Hackathon 当中去锻炼不同的能力,第一场可以锻炼开发能力、第二场锻炼产品能力、第三场锻炼运营能力,以此类推,逐步把自己的各项能力的短板完成补上。

短时高强度另外的一个好处,便是沉默成本可控。我每次参加 Hackathon 的时候,都抱着:大不了这两天就浪费了的心态参加 Hackathon,因为就算我这次 Hackathon 一无所获,我也不过是浪费了 24 小时,周末在家躺平刷抖音也是浪费 24 小时,又会亏到哪里呢?而实际上,当我抱着这样的心态去参加 Hackathon,再配合自己多次参加 Hackathon 的经验进行一些基础的设计,我大部分时候都是有所收获的,甚至是大有所收获。

为什么“你”应该参加 Hackathon

上面说了 Hackathon 的特点,接下来说说“你”为什么应该参加 Hackathon

为了学习新的技能

  • Hackathon 是一个很好的学习新技能的机会:因为没有人会预期你会做的特别牛逼,反而能够让你放下自己内心的戒备,以空杯心态,认真学习新的技能。同时, Hackathon 因为是从 0 到 1,你可以试一试一些新的产品、技术方案。
  • Hackathon 是一个很好锻炼自己的创新思维的机会:Hackathon 不是日常工作,会让我们跳出当下的工作,抬头看路,看看还有什么新的可能性。而且,当你做一件事的事情被限制在一个特定的时间内,为了达成目标,你可能会爆发出你自己难以想象的潜力。
  • Hackathon 是一个很好的探索自己边界的机会:Hackathon 当中的组队只有分工,没有职位,你完全可以在 Hackathon 当中,试着去换不同的岗位来做事。比如你的日常工作是工程师,那不妨在 Hackathon 当中试着去做一个产品经理,换个视角来做事。
  • Hackathon 是有奖项的,如果可能的话,赢得一个奖项,也是不错的收获。随着 Hackathon 在国内的大行其道,不少的投资团队也会参与到 Hackathon 当中,你的项目甚至有可能会被投资人看中,给你一笔钱,让你全职做这个项目。
  • Hackathon 可以帮助你建立新的友谊关系:在平日里,我们扩展朋友的机会可能不多,Hackathon 是一个很好的机会,你可以认识新的人,了解不同人的思维风格和习惯,并通过 Hackathon 共同协作,达成战斗友谊。比如我自己之前和一个伙伴合作,参加了一次 Hackathon(当然,也拿了奖),在Hackathon 结束之后,我们又合作了一次,搞出了一个新的项目,数据还非常不错。如果没有 Hackathon,我们可能从一开始就不会认识,更别提合作项目了。

如何选择 Hackathon 主题

当你确定要参加一场 Hackathon 之后,马上就会面临组队和选题的问题了。组队不多说,每个人都有自己的风格,你可以选择强强联合,也可以选择百花齐放,自己喜欢就行,也往往不会成为大家困扰的内容。

而选主题往往会成为大家最困扰的问题,毕竟日常的工作当中,我们往往是在做命题作文,很少让你去自主命题。但 Hackathon 往往是不预设主题的,你需要自己去研究、发现,找到合适的主题。

从我自己的经验而言:

  • 如果你没有主题和想法,那么首先可以选择在日常工作中困扰你的主题,这类主题很适合在 Hackathon 当中解决掉。如果你搞定了但没拿奖,至少可以提升自己的工作效率;如果你搞定了且拿到奖,那就是双喜临门!
  • 其次,是选择那些你自己特有的、细分的、具有行业 Know How 的问题,这比你去解决一些更通用的问题产生的价值会更大,且你能够做的更好。如果一个医学背景和一个计算机背景的人同样去做一个医学领域的问答工具,那么医学背景的人肯定会比计算机同学做出来的东西更有价值,因为他更懂行业中到底有什么问题。
4ede7b9387234f30a091401d39586a5d

当然,找到这些问题可能不代表你马上会选择,很多时候,我们会担心自己选择的问题很小,不值得我们去解决。这里我的观点是:问题大小并不是关键,关键在于这个问题是否有价值,以及你是否能够在 Hackathon 的时间范围内解决它。毕竟没有人预期你会在一个 Hackathon 当中解决光刻机的问题。

当你真的打算去解决这个问题的时候,如果无法判断自己的问题是否有价值,一个最简单的方法是,先想清楚自己要解决谁的问题,然后找到符合这个画像的人,去问问他,给他提供这样的解决方案,是否可以满足他的问题。

77d11b8c3e5a43447b006c763082e175

Hackathon 中的项目管理

对于没有项目管理经验的人来说,Hackathon 是一个完美锻炼自己项目管理能力的试炼场。因为这是一个资源有限(3~5个人,24~72小时,满打满算 15 人天),同时 DDL 明确、目标明确的项目。

你需要在项目的开始时,找到项目最重要的P0、P1、P2,并安排好人、事物,让大家知道自己在什么时候应该做什么事情。此外,你还需要为项目规划合理的 Milestone,以便于检查项目的执行情况,降低风险,并尽早的发现风险点位,解决风险。

当你能够做好一个 Hackathon 项目的项目管理,那么对于一些小团队内部协作的项目管理,你便有了基础的经验,下次自己去做项目的时候,也就不会那么的焦虑。

5cf6bc1ed7aeb1dab4e4d37d6d0e3c4b

Hackathon 中的项目路演

在 Hackathon 的最后,一般是项目的路演。对于路演,我只有一句忠告:“项目路演很重要,要当成一件事来规划”。

我们在 Hackathon 的前半程都是在设计和实现产品,是一个”做产品“的过程,而路演,则是”卖产品“的过程,你要让评委 Buy in,让你的目标受众 Buy in。在 Hackathon 当中,你即要能做产品,也要能卖产品。毕竟,现在是一个酒香也怕巷子深的时代

把路演当成一件事,提前规划和留出时间做你的演示文稿,可以有效降低你在路演过程中的风险,同时如果可以的话,至少演练 1~2次你的演示文稿,以确保每个视频\动图\文字都是正确且易于理解的。

在你的路演过程中,如果有一些演示,可以用录制好的动图、视频,这样可以从整个过程中“偷时间”,将真实的产品演示放在最后,这样如果你的路演还不错,评委会给你时间让你演示完,以查看实际的效果,你就有了更多的时间去表达自己的主张。

以及,提前想想,假设你是评委,你会怎么挑战自己的项目?这样提前做好准备,就能更好的去应对评委的提问。

总结

以上的这些,是我自己参加 Hackathon的一些经验分享。希望能帮到你,同时,也希望你能享受 Hackathon,感受 Hackathon 的魅力,把 Hackathon 当成一种生活方式来体验。

住院须知

empty hospital bed inside room

最近因为锁骨上的取出,住了一次院。虽然我自己在同一家医院住过,但依然还是犯了不少的错。因此把我自己认为的一些需要注意的住院须知记录下来,希望帮助到从未住院过的你。当然,如果可以,别住院。

为什么要住院?

实际上住院有很多种不同的情况,一般来说,两种:

  1. 突发意外:这种情况下你往往是通过 120 / 突发事件住院的,你的病情可能不足以支撑你再回家好好准备一下具体的东西,那么就直接看下面的 Checklist,美团外卖采购吧。
  2. 计划住院:不管是从门诊转住院还是复查转住院,意味着你都是有计划有节奏的住院,那就做好准备,带好必要的东西,再来住院吧!

两种不同的情况意味着你可能遭遇的问题和需要准备的物资不同,但有两个东西大概率是相同的:

  1. 身份证 / 社保卡:医院需要建档,所以这些东西必不可少。
  2. 钱 / 现金:医院里可能会有各种开支项目(和医保无关的),所以需要准备点钱,最好手头还有个 100~200 现金。

住院会用到哪些东西?

从我自己的经验来看,我认为住院你需要带的东西如下:

  1. 一套衣服:(入院的时候穿半天,出院的时候穿半天),当然,也可以带两套,反正不会特别占地方。办理完住院手续后,一般情况下你会有病号服,护士也会要求你穿病号服,所以你自己带的衣服大概率是穿不到的。所以,衣服不用带太多。
  2. 拖鞋:住院期间,你是会起床走动的(腿部有病的另说),你需要一个拖鞋,这样你在住院期间就无需总是频繁的穿鞋拖鞋,直接套在脚上就能走。
  3. 不锈钢饭盒:住院期间,你可能会选择吃医院的病号饭,那么你就需要一个不锈钢饭盒,以便于去打饭(因为并不是每个医院都提供一次性餐具的)。当然,现在其实外卖也非常方便,你完全可以餐餐点外卖,只是这个有个前提(你得有人能出住院区去取外卖,一般是陪护人员)。
  4. 卫生纸 & 普通手口湿巾(无酒精):卫生纸是上厕所、擦桌子可能用到,湿巾则是你擦自己的身子用的,毕竟在医院里,如果你住院了,身上有伤口,大概率是没办法洗澡的,这意味着你需要时不时用湿巾擦擦身子,以保持身体的清爽。
  5. 酒精湿巾:酒精湿巾主要的目的是消毒,比如你在吃饭前,拿酒精湿巾擦一遍你的不锈钢饭盒,可能会对于你自己的饮食安全提供一层保障。
  6. 充电器:你去医院不玩手机么?如果玩,就带上。记得把你的手机、手表、耳机之类的充电器都带上,别遗漏。
  7. 降温/保温产品:医院的空调往往都是照着大众的体感来调整的,同一间病房可能会面对有的人热有的人冷的问题。如果你怕热/怕冷,别忘了带一些降温/保温的产品,以便于无法微调时,满足自己的需要。

除了上述用品之外,根据你的病症可能还会有不同的选择,比如如果你无法下床,那么可能意味着你需要买尿壶,以及成人尿垫,以便于自己在无法起身的情况下完成排泄。但这些当你真正需要住院的时候,问一嘴医生,大概率也会告诉你。

除了上述的这些住院期间能用到的物品,还推荐你带一个文件袋,这样当你入院的时候,可以把押金条之类的东西放在这个文件袋里,方便出院的时候找。同时当你出院的时候,可以把收据、详单之类的放在这个文件袋里,后续用的时候好找。

当然,你也可以选择全程用钱开道,外卖平台上买就完了。

解决因为 SSL 导致的 WordPress 后台无限 Redirect 的问题

silver mercedes benz emblem on blue surface

在使用 CapRover 并配置域名为 HTTPs 域名时,在你访问管理后台时,可能会导致触发Chrome 自己的无限 Redirect 的问题。

之所以出现这个问题,是因为 CapRover 的架构导致的:CapRover 在最外层是一个 Nginx,SSL 证书也是在这一层完成的。而 CapRover 的默认配置,在将请求向后转发时,透传的域名会是不含 HTTPs 的协议标识的,导致 WordPress 认为发来的请求是非加密的。

d2b5ca33bd970f64a6301fa75ae2eb22 18

而 WordPress 识别到你的请求未加密,就会返回 302 让你进入 HTTPS的链接。但新的请求并不会带上 HTTPs 的标识,导致进入无限循环。

解决这个问题的一个简单处理的方式是 — 在你的 wp-config.php 中加入如下代码,来告诉 WordPress,这个请求已经是 HTTPs 保护的了,你直接处理就好。

/* for ssl in docker */

define('FORCE_SSL_LOGIN',true);

define('FORCE_SSL_ADMIN',true);

$_SERVER['HTTPS'] = 'on';
Code language: PHP (php)

给孩子用的 AI 工具

a close up of a computer screen with a purple background

今天参加一个线下活动,和朋友聊起来对于 AI 的恐惧和焦虑,问我该不该引导孩子去接触这一轮的 AGI 工具、接触这些 AI 工具。

我给了一些建议:首先,我认为我们应该给孩子接触 AI 工具。AI 的大趋势是不可逆的,基于这个前提,我们不应该抗拒孩子去接触 AI,甚至应该尽早的让孩子去建立 AI 的认知,知道什么是 AI 能做的,什么是 AI 不能做的,已经应该明确 AI 和 人类的价值边界。

用法

在聊天过程中,我们聊到了如何用 AI,我自己的观点是:

我们需要让孩子知道如何提问,以及区分出它是工具还是目的。工具掌握用法,并要明确我们的目的是什么。

剩下的,让他自己去玩就好啦。

工具

基于上述的认知,我认为现在可以推荐的工具如下:

ChatGPT

如果可以,当然是给孩子用最好的。但这个有门槛,以及作为家长,你可能要考虑 ChatGPT 本身是有风险的,可能会输出一些你不希望的内容(比如色情、暴力之类的)。

推荐程度: 5 🌟。

Perplexity

AI 搜索,体验很不错。如果孩子有搜索和探索的欲望,那么这个可能会比 Google 会是一个更好的体验。

推荐程度:5🌟

MetaSO

秘塔搜索的研究模式,比较适合孩子做一些方向的研究。可以让孩子在日常学习和生活过程中,有问题,提问。

推荐程度:5🌟。

Other things

在和这个家长聊的时候,发现现在缺乏一个 For 家庭教育场景下的GPT产品。这个产品的客户是家长,用户则是孩子。

和标准的大模型 、 产品之类的区别,是提供一些家长控制能力,这样会让家长们减少焦虑。

但我内心的另外一个声音告诉我:真的做出来,可能孩子也不会用,更好的办法是在现有的产品上加入家长控制模式。

鱼跃 Anytime CT 15 血糖监测仪体验 & 个人心得分享

white One Touch at 6.7 remote

本文内容仅作为个人体验分享,不作为任何医疗建议提供。如已有相关疾病,建议尽快就医咨询医生。

CGM(Continuous glucose monitor)是指持续血糖检测仪,在下文中,指我自己购买的鱼跃 AnyTime CT15 血糖监测仪。

个人使用体验

在详细介绍我和 CGM 的故事之前,我想和你聊聊个人的使用体验。

这 14 天的持续监测,对我来说是很不一样的,我经历过一开始的恐慌期(一开始因为适应的原因,导致我把自己吓了一跳)到小心翼翼期(担心胖胖的自己把设备给压坏了、担心洗澡会让设备失灵)再到无所谓期(把 CGM 当成日常来使用,不再担心会影响到 CGM 设备)心态变化还是挺大的。

在使用整个 CGM 的过程中,我自己的认知也得到了更新,比如:过去我一直以为我的血糖是稳定在一个点位上(毕竟空腹血糖也只取一个点),但实际上,血糖是在不断波动的,只不过是在安全的范围内不断波动。经过佩戴 CGM 的这 14 天,我也变得能够更加坦然地和自己的血糖和谐相处的过程(当然,我的血糖其实没啥问题hhh,倒也没有到病的阶段)。

作为一个个体,在经历过 CGM 的体验后,我认为:

  • 如果持续使用 CGM,那么他只适用于糖尿病患者:这句看似是废话,但我想表达的是,绝大多数人的血糖波动范围,完全没必要关注血糖波动。现有的 CGM 的设计基本上也是服务于糖尿病患者的保命需求的。普通人用起来可能没啥太大的感觉。糖尿病患者使用 CGM 主要也是因为扎手指太疼、有感染风险、没办法比较高频采集数据,不然其实指尖采血也挺好的。从痛感的视角来看,CGM 的痛感更轻,且只需要痛一次,更适合持续使用。
  • 如果是体验 CGM 的话,那么我推荐你可以买一个试试:血糖的监控就如同血压、体温、心率等一系列监控,可以给你提供一个不同的指标。特别是肥胖率日渐增长的中国,监控一下自己的日常饮食会给自己的身体带来的变化,对于你更好的理解自己的饮食有很大的帮助。¥299 的价格,属于可以考虑尝试一次的范围。

对于我自己而言,我这一次使用了 CGM,短时间我可能不会继续购买 CGM 设备了(如我上面所述),但如果我再需要监测我自己的血糖的时候,我想来也不会对于 CGM 有太多的恐惧,可以坦然面对使用 CGM。


过程全记录

缘起

作为一个曾经撰写《自我量化指南》的人,对于自身数据、各项指标的探索从未止步。我长期佩戴 Apple Watch,便是为了追求自身的各项指标的收集。最近在听无人知晓的 EP34 ,孟岩对话顾中一这一期时,孟岩提到了,他自己在佩戴持续血糖检测仪(CGM),让我产生了好奇心和兴趣:我是不是也可以使用这样的工具来检测自己的血糖?

d2b5ca33bd970f64a6301fa75ae2eb22 1

我并不是全无接触过血糖检测设备,实际上我过去曾购买过鱼跃的血糖检测仪,但我之前购买的是采用指尖采血的血糖仪,需要你有毅力给自己的指尖破一个小洞,采血并进行检验。从自我量化的视角来看,倒也并非不可接受 —— 我并不需要那么多的血糖数据埋点,对么?但毕竟要出血,且要带酒精棉片、采血针等一系列设备,属实麻烦。所以这个血糖仪如今也在我的医疗箱里吃灰。

CGM 作为一个可以持续佩戴的产品,让我想要试试,刚好这次听播客被勾起了兴趣。那就试试吧!

购买

既然已经决定了要购买,那说买就买。在经过一番搜索和研究之后,我最终选择了鱼跃(Yuwell)家的动态血糖仪 CT15 。虽然在这个领域,更加专业的可能是雅培,国内的也有三诺、微泰等企业,但对于我来说,最重要的是 鱼跃的 App 可以和 Apple Health 打通,将数据透传给 Apple Health。这样未来我就可以把我自己的各种数据都汇总起来进行分析和消费。

做出了选择,接下来就很简单,我在拼多多上下单了鱼跃 CT15 血糖仪,并在 4.24 日拿到了这个设备(然后在当天给自己装上了它)。

d2b5ca33bd970f64a6301fa75ae2eb22 7

安装鱼跃 CT15

收到货后,拆开快递后,我拿到了两个设备,一个是有点像 Airpods 的 蓝牙发射器 & 充电底座;另外一个则是真正插入体内的传感器及其辅助发射器。

5vvd4g
收到的设备

拆开后,大概是这样的:

d2b5ca33bd970f64a6301fa75ae2eb22 8
蓝牙发射器 & 底座
d2b5ca33bd970f64a6301fa75ae2eb22 9
传感器 & 辅助植入设备
d2b5ca33bd970f64a6301fa75ae2eb22 2
传感器底部的标签

安装不复杂:

  1. 先在手机上下载安耐糖的 App;
  2. 确认你自己要安装的部位,你可以选择手臂后方或腰部。根据自己的习惯选择即可。我最终选择的是手臂后方(主要是我有趴着睡的习惯,放在腰腹部担心压坏)。
  3. 链接 App & 蓝牙发射设备。
  4. 对植入部位使用酒精消毒。
  5. 使用辅助植入器植入设备。
  6. 将蓝牙发射器和传感器组装起来。

更加详细的安装过程,我直接把官方的视频搞下来了,你可以看这个视频快速了解安装的链路。

安装完成后,大概是这样的:

d2b5ca33bd970f64a6301fa75ae2eb22 10

数据监测 ing

设备安装好后,接下来就是持续性监测这个数据 & 指标了。

坦白来讲,设备装上的第一天我是把自己吓到了,因为监测到了我有史以来最高的血糖值 — 11.6(我差点就给自己确诊糖尿病了),在给自己上 CGM 的那个晚上,我看了不少的二型糖尿病防治指南(放在最后了hhh)。

9232b01d0fb1ad6abf7e9b947b94e4d7
第一天记录到的 11.6 的巨高数据

不过,经过一天的适应,在第二天,我的血糖进入了常规的阶段,慢慢的,我的心态也没有那么慌了(所以提醒大家,即使 CT15 这样不需要额外校准的设备,也有可能会存在初期数据不准的问题,如果看到了一个非常夸张的数字,不要慌让他再抓一些数据看看。

d2b5ca33bd970f64a6301fa75ae2eb22 12
第一天的血糖
d2b5ca33bd970f64a6301fa75ae2eb22 14
第二天的血糖

接下来的每天的日常就是让他自己跑数据,监测一下自己的血糖变化。安耐糖的 App 提供了血糖变化数据,方便你看到你的数据变化范围,是否在你预设的血糖范围内等一细节数据,方便你快速了解自己的血糖情况。

b555bc2dba39cab693734ece65408b1e 1
安耐糖的主界面

取出设备

当时间走到 5 月份时,我佩戴 CGM 也满 14 天了,就必须要取下设备(设备的设计监测周期是 14 天),取下的过程非常简单,先按下传感器的卡扣,取下蓝牙发射器,然后去除传感器周围的胶布拔下传感器即可。

在没有取下来之前,我对于 CGM 的体内植入深度没啥感觉(虽然说明书上已经说了 5~10 mm),但当你真的看到这个探针,并意识到这个探针已经在你体内 14 天时,还是有点惊悚的…

d2b5ca33bd970f64a6301fa75ae2eb22 15

数据分析

数据采集只是手段,归根结底,我们是希望用数据指引我们做决策。血糖分析也是如此。一方面, 你可以直接查看安耐糖上的一些数据来观测自身的指标,另一方面,安耐糖也提供了官方的报告解读的服务。

当你的设备取下后,官方会拉个微信群给你做一下基本的报告解读,简单分析一下你的情况,会得到如下的报告内容。

nafg1c

一些你可能关注的问题

误差?

CGM 的原理是基于组织液的数据采集 + 算法的方式来计算出你的实时血糖。这个原理决定了它的数据注定不是真正意义上的精确值。刚好在最后几天,我参加了中关村的四高共管项目,基于指尖采血血糖仪的数据,和 CGM 的数据做了对比。在实际测试过程中发现,CGM 和指尖血糖仪的数据大概有 0.5 左右的误差。

但,作为一个可以持续监测的设备,0.5 的误差在我看来是可接受的范围。毕竟可以帮助我们监控自己的血糖,了解不同食物带来的影响,还是有其价值的。

洗澡?

从我自己的体验来看,洗澡(淋浴)是完全不影响 CGM 的,你可以放心的购买 & 使用。也合理,毕竟要在身上放 14 天,厂商也需要考虑这个问题。

按压?

安装上之后,基本上不会有什么问题,直接用即可。我自己体验下来看,只要不是硬破坏,其实没那么容易出问题。

感染?

坦白来讲,CGM 是存在感染的风险的。毕竟是有创的,我们能做的是尽可能降低感染的风险,比如在植入前用酒精棉擦拭植入区域;比如擦拭完就赶快植入,别等着。

创口?

CGM 的探针比较细,所以创口和痛感也都不强烈。从我自己的个人体感而言的话,比指尖采血的疼痛度还要小一点。

d2b5ca33bd970f64a6301fa75ae2eb22 17

医用胶布使用指南

你可能会担心,传感器容易掉怎么办?从我自己的体验来看,不太会容易掉,此外,安耐糖会送一个加固胶布,你配合上加固胶布,基本上没有掉下来的可能性。

持续使用成本

在上面提到,CGM 智能连续使用 14 天,对于一个日常监测的人来说,必然是每两周要更换一次的,所以就需要持续购买耗材,传感器作为一次性用品,每个买下来大概是在 250 元,一年持续监测下来的话,成本还是比较高的,一年需要 250 * (52/2) = 6500 元左右,批量购买可能可以控制在 6000 以内,成本不低。但考虑到这玩意是用来保命的,倒也合理。

d2b5ca33bd970f64a6301fa75ae2eb22

二型糖尿病防治指南

延展阅读

https://sspai.com/post/77324

https://sspai.com/post/77348

Chinese-Calendar: 一个帮助你判断今天是不是工作日的 Pypi 包

person holding sticky note

在开发过程中,你可能会需要实现某些和工作日相关的特性(比如,工作日才发某些通知 /推送),这个时候,你可以借助于 chinese_calendar 这个包,来查看当前是否是工作日,你可以引入 chinese_calendar 这个包,来实现判断今天是否是工作日。

可以参考如下代码,is_workday_today 返回 True 时,就是工作日,就需要执行某些特定的逻辑。

from datetime import datetime
from chinese_calendar import  is_workday

# https://github.com/LKI/chinese-calendar
def is_workday_today():
    today = datetime.now();
    return is_workday(today)
Code language: Python (python)

介绍一下 Read it!

pile of assorted-title books

每年我都会给自己开一些新的坑,用于探索新的技术方向、新的领域。2024 年,我的新项目是 —— Read it!

Read it! 是一个用于分享我自己觉得不错的文章、网站的地方, 你可以在这里看到我日常浏览网页过程中发现的不错的网站、文章。

我会在分享链接的过程中,加上一些我自己的看法、总结。

如何使用 Read it!

  • 网页浏览: Read it! 是一个网站,所以你只需要打开浏览器,访问 readit.ixiqin.com,就可以看到我分享的网站。
  • RSS 订阅:作为一个古早 RSS 爱好者, 你可以直接在你的 RSS 里订阅 Read it! ,将 https://readit.ixiqin.com/rss/bookmarks/ 贴在你的 RSS 阅读器里,就可以查看到它。

为什么会有 Read it!

我是湾区日报的读者,也很喜欢湾区日报的形式。包括过去也尝试过用 WordPress 之类的系统来搭建类似的形态。但,繁琐的操作会消磨我分享的耐心。

最近又在整理书签,加上也开始进行一些大模型应用的开发,所以决定借助大模型来帮助我自己完成一些工作,就重新搞起了 Read it! 这个项目。

Read it! 目前的工作模式挺简单的,我找到觉得不错的文章,直接在 IM 里发给他,他会自动解析我的意图,并将解析出来的结果录入到系统当中,给大家看。想来这样的交互可以让这个项目活得更久一些~

d2b5ca33bd970f64a6301fa75ae2eb22 15
流程说明

Read it! 会分享什么?

Read it! 可以理解为是我自己再看的各种文章,所以并不会局限领域、方向,只要是我自己看的觉得有收获的,我都会分享。后续会考虑提供分标签的订阅方式,这样你可以选择只订阅自己喜欢的文章。

CapRover 如何停止服务,并进行硬盘扩容/维护

34456427bc43e44f517b4eece861c6f5

在一开始使用 CapRover 时,我使用的是一个 10 GB 的数据盘,但在部署了诸多应用后,10GB 的数据盘已经无法满足我的需求,于是我就对其进行了扩容,扩容至 20GB。在完成扩容 & 重启后,仍需要执行 Linux 的扩容命令 resize2fs 来扩容硬盘。

但由于 CapRover 中运行的服务跑在这个数据盘上,并没有办法直接在这个数据盘上进行扩容(进程会持续读取文件),因此,需要先将 CapRover 上的服务暂停,暂停后进行扩容,并重新启动服务。

CapRover 底层是使用 Docker Swarm + Nginx 来进行的,因此,我们只需要使用 Docker Swarm 的命令,来停止服务运行即可。

1. 获取服务名称

首先,你需要先获取到当前所有在跑的服务,以便于稍后去暂停。执行 docker service ls 来获取到具体的服务名称。

d2b5ca33bd970f64a6301fa75ae2eb22 13

2. 拼接所需的命令

在 Docker Swarm 当中,并没有直接的 Start or Stop 概念,而是通过将 Replica 设置为 0 来实现关闭的能力。这个命令可以通过 docker service scale 服务名=服务数 来实现。因此,你需要将对应的服务设置为 0 来解决这个问题。你可以先行把开启和停止的命令拼接好,从而实现快速的启动和关闭,尽可能的减少宕机时间。

如果是有多个服务,可以直接拼接在后面,从而实现一次关闭 / 开启多个服务。

# docker service scale service_name=1 service_name_2=0
# 停止命令
docker service scale srv-captain--blog-ixiqin-com=0 srv-captain--mysql-8-production-db=0 srv-captain--pgsql-16-production=0 srv-captain--redis-server-production=0
# 启动命令
docker service scale srv-captain--blog-ixiqin-com=1 srv-captain--mysql-8-production-db=1 srv-captain--pgsql-16-production=1 srv-captain--redis-server-production=1
Code language: Bash (bash)

3. 执行命令,扩容硬盘

你可以先执行停止命令,然后执行扩容命令。完成扩容后,重新启动,即可完成整体的扩容。

使用 CapRover WebHook 获得类 Vercel 部署体验

34456427bc43e44f517b4eece861c6f5

我在开发前端应用的时候,基本上使用的都是 Vercel ,究其原因,主要是以下几个点:

  1. Vercel 可以方便的与 Github 整合,提供简单易用的部署方式:写完代码,测试完成后推送到 Github ,就会自动部署到线上。对于小型项目来说,可以简化部署的流程。
  2. Vercel 提供了自定义域名和自动配置的 SSL,提供了简单的配置方式:在现在 SSL 成为标配的模式下,在 Vercel 你只需要把域名解析到 Vercel ,并在你的 Project 当中绑定域名,就会自动完成域名绑定和 SSL 申请和续期。
  3. Vercel 提供了 FaaS 环境:写应用的时候,很多时候不只有前端的需求,这个时候, Vercel 自身的提供的 FaaS 环境可以帮助你完成基本逻辑的编写。

但 Vercel 毕竟是以前端为主,且函数运行时长也有限制,对于一些比较重的场景下,Vercel 还是不太够用。刚好最近我把服务部署从传统的 LAMP 换成了 Docker Based PaaS,我使用的 CapRover 提供了类似的体验。

使用 Cap Rover 你能获得的体验:

  • 上传代码后,自动部署到 Production
  • 绑定域名后,自动配置 SSL 证书,且可以配置其他域名转发到主域名

具体操作步骤见下:

安装 CapRover

CapRover 的安装我就不再赘述,跟随官方的说明安装即可。

绑定根域名

当你登录 CapRover 时,CapRover 会让你绑定一个泛域名解析,你可以根据自己的需要,绑定一个二级或者三级域名,然后在 DNS 解析一个 * 到这个服务器上。这样后续部署的服务就会自动解析一个 服务名.你的域名 ,用于服务的初步访问(类似于 xxx.vercel.app)。

d2b5ca33bd970f64a6301fa75ae2eb22 6

上传代码至 GitHub

在 Github 上创建一个代码仓库,并把你自己的项目部署上去。如果你有已经写好的 Dockerfile,可以一并上传上去。如果没有的话,则可以选择参考 CapRover 提供的 Sample App ,里面提供了常见语言的部署参考。

创建容器并配置环境

完成代码上传后,你可以进入到 CapRover 后台,创建一个新的 App。这里可以输入你喜欢的名字,方便后续查找即可。

d2b5ca33bd970f64a6301fa75ae2eb22 7

创建完成后,点击下方列表中的应用名称,进入应用的配置页面,并切换至 Deployment 页面。

d2b5ca33bd970f64a6301fa75ae2eb22 8

在这个页面,可以找到 Method 3 : Deploy From GitHub/ Bitbucket/Gitlab,填写你的仓库信息、分支名、用户名。密码你可以选择直接使用你的密码,也可以选择创建一个 Personal Access Token ,或者是在仓库里配置一个 Deploy SSH key 均可。

d2b5ca33bd970f64a6301fa75ae2eb22 9

配置完成后,会自动给你生成一个 Webhook 地址,复制这个 Webhook 地址。

d2b5ca33bd970f64a6301fa75ae2eb22 10

配置 Github 上的 WebHook

复制上方的 Webhook 地址,并进入到 Github 你的仓库 – Settings – webhooks 页面,新增一个 Webhook。

d2b5ca33bd970f64a6301fa75ae2eb22 11

粘贴你刚刚复制的 URL,Content Type 选择 application JSON,并在下方选择触发部署的时机。

d2b5ca33bd970f64a6301fa75ae2eb22 12

点击报错。

等待自动部署

接下来你就可以通过提交代码,来让其自动完成部署,从而享受类似于 Vercel 的推送即部署的体验~。

在你的 Github Actions 中添加一个 PostgreSQL 用于测试

black and white penguin toy

在开发应用的时候,我们会选择使用 PostgreSQL 作为数据库进行开发,但在 Github Actions 环境下,默认是没有 PostgreSQL 作为数据库后端的,这个时候如果你想要测试一些和数据库相关的逻辑,就不得不面临两个选择:

  1. 使用一个和生产环境无关的数据库,比如 SQLite。
  2. 在 Github Actions 当中添加一个 PostgreSQL。

前者是大多数常规的做法,大概率也不会出现什么问题(毕竟作为 CURD 仔,我们用的大部分时候都是一些 ORM,很少裸写 SQL),不过依然存在一些概率是你写了一些 PostgreSQL Only 的 Query 无法覆盖到测试。

另外就是本文的核心了:在你的 Github Actions 当中添加一个 PostgreSQL

Github Actions Service

想要实现这个效果,我们依赖了 Github Actions Service Containers 这个能力。

服务容器是 Docker 容器,以简便、可携带的方式托管您可能需要在工作流程中测试或操作应用程序的服务。 例如,您的工作流程可能必须运行需要访问数据库和内存缓存的集成测试。

您可以为工作流程中的每个作业配置服务容器。 GitHub 为工作流中配置的每个服务创建一个新的 Docker 容器,并在作业完成后销毁该服务容器。 作业中的步骤可与属于同一作业的所有服务容器通信。 但是,你不能在组合操作中创建和使用服务容器。

GitHub

你可以选择你需要运行测试的环境中,找到对应的 Job,并在 Job 下新增一个 services ,即可为你的 job 设定一个依赖的服务容器,它可能是数据库 、 缓存之类的。比如我这里用的就是 PostgreSQL。

我的 Github Actions 完整参考:

  • services 是我运行的服务容器。
  • steps 是我的真正的测试流程。
name: Django CI

on:
  push:
    branches: [ "main" ]
  pull_request:
    branches: [ "main" ]

env:
  DEBUG: true
  SECRET_KEY: django-insecure-github-actions
  DB_NAME: postgres
  DB_USER: postgres
  DB_PASSWORD: postgres
  DB_HOST: localhost
  DB_PORT: 5432

jobs:
  build:
    runs-on: ubuntu-latest
    services:
      postgres:
        image: postgres
        env:
          POSTGRES_PASSWORD: postgres
        # Set health checks to wait until postgres has started
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
        ports:
          - 5432:5432

    strategy:
      max-parallel: 4
      matrix:
        python-version: [3.12]

    steps:
    - uses: actions/checkout@v3
    - name: Set up Python ${{ matrix.python-version }}
      uses: actions/setup-python@v3
      with:
        python-version: ${{ matrix.python-version }}
    - name: Install Dependencies
      run: |
        python -m pip install --upgrade pip
        pip install -r requirements.txt
    - name: Run Tests
      run: |
        python manage.py test
Code language: PHP (php)

Thinking in Component Tree

blue red and green letters illustration

在开发前端应用的时候,我比较推荐在真正开始写代码之前试着画一画组件树 / 状态树。

在很多时候,可能你的设计师已经帮你做好了组件树,但在某些场景下,你的设计时并不会帮你拆解组件树,或者是你是直接和产品经理对接,他不会帮你拆解组件树。

这个时候,相比于写代码,我更推荐你先拆解组件树,在完成组件树之后,再开始你的 Coding。

d2b5ca33bd970f64a6301fa75ae2eb22 5

Figma / Sketch 之类的软件提供的分组能力、图层的能力,可以帮助你将组件合理的拆解、分组、归类。当你完成树的建设之后,可以试试看将不同的模块拆解,每个模块是否可以独立正常的运转。如果不可以,则说明你的状态拆解的可能是有问题的。

当你完成拆解之后,只需要按照你拆解出来的树组织你的 Component 即可。

在 WordPress 的 Docker 镜像上加装 Redis 拓展,以支持 Redis 缓存

docker

从 LAMP 到 Docker based PaaS 工具 当中,我提到我现在使用的是 Docker Based PaaS 产品来托管站点。本站目前其实就是跑在 Docker 上的。

使用默认的 WordPress 镜像时,我发现一个问题:没有支持 Redis 拓展!我使用 Redis 来缓存 Query,提升访问的性能。如果缺失了 Redis 拓展,就会减少一部分缓存的能力。于是开始研究如何在官方的 WordPress 镜像上加入 Redis 拓展。

根据 WordPress 镜像的官方说明,我们可以 docker-php-ext-* 命令来配置镜像,安装必要的拓展,来满足我们日常使用的需求,并给出了官方的参考。

不过,我在验证 Redis 拓展时,使用 docker-php-ext-* 命令没有配置成功,好在可以使用 pecl 来安装。于是,我便将 Dockerfile 修改成如下内容,来完成对于 Redis 拓展的安装。

FROM wordpress:latest
RUN pecl install -o -f redis && rm -rf /tmp/pear && docker-php-ext-enable redis

修改好 Dockerfile ,然后重新启动,一切都好了~

d2b5ca33bd970f64a6301fa75ae2eb22 4

使用 idb-kayval 作为前端数据存储

text

在前端留存一些状态,是在前端场景下提升性能的常规操作。最近我有一个场景需要在前端留存一个状态,借着这个机会,试了试 IndexedDB 来作为数据存储,拓展一下新的方向。

关于 Indexed DB

Chrome 在中提供了多种不同的存储,按下 F12 ,打开 DevTools ,找到应用 – 存储,你就会看到目前 Chrome 支持的多种存储方式。常用的主要就是本次存储空间(Local Storage)、会话存储空间(Session Storage)和 Indexed DB。这次我用的便是 Indexed DB。

d2b5ca33bd970f64a6301fa75ae2eb22 1

开发使用建议

由于 Indexed DB 提供的 API 整体比较裸,在实际应用开发时,可能并不好用,你可以根据自己的需要,选择使用不同的第三方开发库来开发你的应用。在这篇文章中,我使用了 idb-keyval 来作为我的开发库。

d2b5ca33bd970f64a6301fa75ae2eb22 3

用法

首先,使用 yarn add idb-keyval 来安装依赖,安装完成后,可以参考如下代码来在你的项目中引入 indexedDB.

import { set,get,keys } from 'idb-keyval';


// 下面演示了一个 get_books 函数,会将内容存储在 IndexedDB 的 your-keys 当中。
// 如果存在缓存,则直接使用缓存,不存在,则进行数据获取
function get_books(){
   // 使用 keys 获取当前 IndexedDB 当中的所有 Key,用于判断当前是否有缓存结果。
   const exists_keys = await keys();
   if(exists_keys.indexOf('your-keys') !== -1){
    console.log("use cached glossary")
    return await get('your-keys');
   }

   // fetch data
   let data = fetch_data();
   
   await set('your-keys',data)
   return data;
}
Code language: PHP (php)

使用前后的效果

在性能上,使用 Indexed DB 之后,根据你的数据获取的难度,会有不同的性能提升。比如这里我不使用缓存,单次数据获取需要花费 800ms,借助于 Indexed DB,时间可以被控制在 10ms 以内,从而得到一个不错性能。

d2b5ca33bd970f64a6301fa75ae2eb22 2

从 LAMP 到 Docker based PaaS 工具

docker

白宦成简史 当中,我写到过,我从 2013 年就开始写博客,至今已经 11 年有余。而我和互联网、编程的缘分,也从 2013 年开始。

在 2013 年的时候,我主要是使用 WordPress 建站(现在也还在用,比如本站)。所以,从哪个时候开始,我开始接触 LAMP、LNMP 这些个概念,并在过去的若干年里,使用了不少「一键安装包」来部署我的网站。

我用的一键安装包 / 控制面板不算少:LNMP.orgOneInStack(从它还是 LinuxEye 的时候开始用),LAMP.sh等一键配置包,AMHWDCPAppNodeWebminBTVestaCPVirtualmin等等一系列控制面板。

如果说这些工具有什么相同点,那便是都提供了十分方便的 LAMP / LNMP 的配置方式,让彼时不够专业的我、主要是用别人开发好的应用的我能够快速部署一个基于 MySQL + PHP 的应用,让它 Run 起来。

而随着时间的流逝,我已经不再是曾经的我了。我不再局限于使用别人写好的程序,我开始自己写;我不再局限于使用 PHP 来编写程序,我同样会使用 Python、Ruby、Golang 、Node.js 来编写应用程序;所有的这些,都告诉我,我需要在现有的框架和程序上去做很多额外的配置,比如,我需要在 LNMP 的基础之上,配置 NPM,以完成 Node.js 的构建;我需要在系统上配置 Docker ,以便于去运行某些需要复杂配置的环境。

曾经那些可以帮到我的程序已经不再能帮到我了,如今的他们,成了我的累赘。我开始需要为了他们去多做一些事情了。

如今的我,更需要的是一个能够基于 Docker 来运行的管理工具,能够帮助我完成不同环境的配置、管理的能力。我需要的是一个类似于 Heroku 的管理工具,能够让我把更多的精力放在把事做好上。

我试用了

最终,选择了 CapRover ,主要原因有几个:

  1. 支持基础的 Docker 管理功能:这样意味着我其实可以在网页端管理这些资源。
  2. 使用 Nginx ,并集成了 Let’s Encrypt:我的应用都希望有 HTTPs 的能力,所以默认集成了 Let’s Encrypt 可以帮助我解决不少的问题。我也不需要自己去维护一个 Traefik 来解决请求转发的问题(我没有使用 Rancher / Kubesphere 之类的容器管理平台也是这个原因)
  3. 提供了一些一键配置的 Sample:这意味着我把一些我常用的应用迁移过去的时候,可以抄袭一下其官方推荐的配置,可以降低我的使用门槛。
  4. 足够久远:CapRover 作为一个从 2017 年就开始运作的工具,代表着有足够多的 issue 可以供我参考 / 使用,可以减少我踩坑的概率。
  5. 提供了 CLI 来进行部署:对于一个经常需要部署的人来说,提供 CLI / Github Action 可以帮助我快速实现多种不同需求下的部署,帮助我来提升效率。

种种的这些,让我最终从过去的 LNMP,跳船到了 Docker Base PaaS 工具上。

《奔跑吧程序员:从零开始打造产品技术和团队》

d2b5ca33bd970f64a6301fa75ae2eb22

评价

值得所有工程师来读一遍。

书摘

  • 因为在写代码的时候,结果都是非常确定性的,编译成就是成,不成就是报警。而现实的创业生活中,有太多的灰色地带,你分不清楚对错,这时候就特别需要有人能告诉你,他当时遇到这样的问题,是怎么做的。
  • 创业公司就是在极度不确定的条件下创造新产品或服务的人类组织。
  • 创业公司的目标在于快速增长。一家公司成立的时间短并不能让其本身成为创业公司,创业公司也未必要从事科技领域的工作,未必要接受风险投资基金或有某种“退出”的机制。创业公司唯一必不可少的东西就是增长,其他和创业相关的所有东西都是伴随着增长而来的。
  • 创业公司是一个暂时性的组织,目的在于寻找一种可重复、可扩展的商业模型。根据这一定义,创业公司既可以是一家新的企业,也可以是现有公司中的一个新部门或业务单元。
  • 科技创业公司”是具有下述特征的组织。
  • · 产品:技术。 · 环境:极度不确定。 · 目标:大幅增长。 · 运作模式:探索。
  • 要在科技创业公司中工作,甚至自己创立这样一家公司,我们应该考虑三个主要因素:更多的机会、更多的所有权以及更多的乐趣。
  • 我在大学毕业正决定去哪儿的时候得到了一条建议:你应该把硅谷当作一家大公司,其中有Facebook部门、Google部门和一大堆小型创业部门。有时候部门会发生重组而不再独立存在,但所有的人只要加入其他的团队就可以了。我觉得这是一个非常好的比喻,在这里人们会相当频繁地在不同的公司间流动。
  • 真正的风险并不是因加入了小型创业公司而失业——毕竟我们在大公司工作也没办法保证不失业——而是失去机会的风险。如果选择了在一家公司工作,实际上也就是选择不在其他许多的公司工作。在这个意义上,缺乏工作稳定性也许并不是一件坏事。如果同一份工作已经干了很久,我们很可能正在错失其他一些更好的机会。
  • 大部分的Web创业公司能否成功,几乎都完全取决于执行、有针对性的推广、销售、产品和技术。
  • 那是因为创造力的产生可以归结为三个阶段,这三个阶段都不过是不同形式的重新合成: (1)模仿; (2)转换; (3)合并。
  • 既是通才(在许多有价值的方面高度熟练——T的横),也是专才(在某个特定的学科中属于领域内最出色的——T的竖)。
  • 只有培养了足够的专业技能,才能进入所选学科的前沿领域。在这一不断探索的过程中,你会想出一些创业点子,例如Larry Page在图形理论、文献计量学和Web方面拥有足够的专业技能,从而推动了搜索技术的发展。Reid Hoffman之所以打造了LinkedIn,是因为他作为创业者和投资者,必须要成为建立人际关系网的专家,而在这一过程中,他认识到存在着通过互联网为专业人士建立人际关系网的机会。
  • 要成为一名通才,你必须定期搜寻新点子。有些人天生就对所有东西都有好奇心,会觉得这很容易做到。如果你不是这样的人,也许需要刻意努力跳出自己的舒适区,体验各种各样的文学著作、电影、旅行和活动。有一种实现的途径,就是写出一些“top 5”清单。例如,你可以做一张所有文学体裁的清单(如历史、心理学、科幻小说、数学、计算机科学、生物学,等等),试着阅读每一种体裁中最出名的5本书;或者列出学校所有科目(例如数学、物理、历史、生物、英语,等等),每一门科目都去上五门主题课程,如果没有时间的话,可以阅读这些主题最好的教科书。 这是一种让自己大范围接触新点子的有趣方法。每当我这么做时,都会震惊于人类知识看似不相关的领域竟有这么多重叠的地方。我发现《写作法宝》中的写作建议竟然和《代码大全》中编写整洁代码的建议有那么明显的相似之处。我从心理学图书《思考,快与慢》中学到了产品定价的宝贵知识,这些知识和我阅读所有商业或经济类图书所得到的收获一样多。我甚至发现将我女朋友关于20世纪40年代东欧共产主义崛起的论文研究用在解释当前硅谷的创业发展方式上也能有所洞察。
  • 什么样的环境可以激励人们产生新的点子呢?因人而异,但最常见的要素有这么一些: · 给自己充足的时间; · 记录点子日记; · 解决问题; · 放下工作; · 添加约束; · 寻找痛点; · 与他人交谈。
  • 要养成习惯,每天至少花20分钟做一些可以自我放松的事情,倾听自己的想法。可以是走路、洗个时间长点的澡、冥想、在吊床上躺一会儿、写写日记、画画、雕刻、做做木工或者放放音乐。不管怎么样,把点子日记放在边上,随时准备记下笔记。
  • 重要的是把问题写下来,即便你还不知道要如何解决。如果你一次次地看到问题出现,也许出现的场合略有差异,但每一次都可以简单地把想法记下来,然后你对这个问题的理解就会慢慢加深。
  • 学会鉴别和解决特别难解决的问题是一种宝贵的技能。Paul Graham在他的一篇文章中说道:“我们的周围存在着各种难办之事(schlep)”。“
  • Howard H. Aiken说过:“别担心人们偷走你的点子,如果你觉得自己的点子非常棒,还得让人们接受才行。”如果你不相信,不妨去http://www.hello-startup.net/resources/startup-ideas看看,了解一下别人的创业点子,看看有多少是你想“偷”去做成公司的。
  • 实际上,真正吸引竞争者的并不是点子,而是点子受到广泛关注。只有在你发布了产品,并且已经开始显露峥嵘的时候,别人才会想着去抄袭你,所以不用担心在早期讨论你的点子。另外,如果你担心有人偷听你的点子而想把它偷走并打败你,这样的点子很可能没有防御性,无法实施。虽然这里用了防御性这个词,但我想表达的是,一个出色的商业点子应该具备某种差异性,可以让你和竞争对手之间产生巨大的差距(阅读3.2.2节了解更多信息)。
  • 仅仅有点子还成不了业务,理解这一点同样重要。业务是由点子和执行力构成的。也许有人可以偷走你的点子,但偷走你的执行力就要困难得多。我们来更深入地看看点子和执行力之间的关系。
  • 这就是TripAdvisor的准则,Kaufer在那天午餐的时候解释了这个准则,后来也多次在公司的全体大会上做过解释。创业成功,无论在哪个层面上,归根到底都取决于速度。你必须更快地实现产品、更快地编写代码、更快地招聘,最重要的是,必须更快地学习。
  • 我喜欢用速度制胜这个词,因为它又短又好记,但是用频率制胜可能更为精确。这并不是说要像变魔术一样只用一半的时间去完成相同的工作量,而是说要安排好工作,尽快得到反馈。这是因为反馈回路短的系统通常总是胜过回路长的系统。
  • 在空战中,双方飞行员通常都是按照所谓的OOPA(observe, orient, plan, act,即观察、确定方向、制订计划、行动)的顺序进行操作,而液压助力能够让它的飞行员以稍微快一小点的速度完成OOPA的过程。
  • 博伊德确定赢得空战的主要决定因素并不是更好的OOPA,而是更快的OOPA。博伊德提出,迭代的速度会打败迭代的质量。 ——Roger Session
  • 对某些产品而言,即便最小的尝试方法也需要有相当优美的体验;对于其他一些产品,只要有骨架就足够了。某些情况下,你根本不需要实现产品,3.2节谈论这个问题。一般的规则是要遵循“完成比完美更好”原则。否则,就像Reid Hoffman所说的:“如果你第一次发布的时候没有感到尴尬,就是产品推出的时间太晚了。”即便如此,有少数领域并不是依靠速度制胜的。
  • 如何找到客户并与之对话呢?可以分解为以下三个连续的阶段。 第一步:验证问题 确保找出客户实际面临并且痛苦到愿意掏腰包去解决的问题。 第二步:验证MVP 实现潜在解决方案的最简可行产品(minimum viable product,MVP),让少量客户购买该产品进行验证。 第三步:验证产品 把MVP完善为完整的产品,让更多客户去购买,对可扩大化的商业模式进行验证。
  • 在思考问题的大小时,有三个方面需要考虑:频率、密度和痛苦程度。 · 频率:你所解决的问题经常发生吗? · 密度:有很多人都会面临这个问题吗? · 痛苦程度:该问题只是让人讨厌,还是绝对必须解决?
  • 考虑市场规模有一个好方法,就是考虑建立一家赚得10亿美元收入的公司的几种方法。 · 以1美元的价格销售10亿件产品:可口可乐(罐装汽水); · 以10美元的价格销售1亿件产品:强生(家用产品); · 以100美元的价格销售1000万件产品:暴雪(《魔兽争霸》); · 以1000美元的价格销售100万件产品:联想(笔记本电脑); · 以1万美元的价格销售10万件产品:丰田(汽车); · 以10万美元的价格销售1万件产品:Oracle(企业级软件); · 以100万美元的价格销售1000件产品:Countrywide(高端金融抵押公司)。 ——Balaji S. Srinivasan,斯坦福创业项目工程课程
  • 下面,我会列出评估市场规模的几种方法。 广告 许多广告公司都会提供一些广告目标分析工具,我们可以在不需要购买任何广告的情况下对市场进行研究(虽然购买广告是测试MVP的好方法,3.2节将详细讨论)。例如,我们可以用Google的AdWords Keyword Planner研究每个月有多少人搜索某些特定术语。我在对hello-startup.net做研究的时候,查阅了大概50组相关关键字(例如“创业点子”“代码评审工具”“净值计算器”),发现平均每月每个关键字都有超过1200万次的搜索。这给了我信心,“如何创业”确实是一个真正的问题。而其中的资源页面也可以帮助我雕琢语言,例如我发现人们也经常使用“商业点子”来代替“创业点子”。我还使用过其他几家公司的广告工具,发现Facebook上大约有1600万人对创业感兴趣,Twitter上有200万人对创业感兴趣,LinkedIn上则有1300万人把他们所在的行业列为创业领域。 竞争 如果已经有公司在解决你发现的问题,其实未必是坏事。甚至可以说,“你的想法并不唯一”才说明你发现了真正的问题。要寻找你都有哪些竞争者,可以使用前面介绍的广告工具,找到合适的关键词,试着在Google和一些移动应用商店中搜一搜(应该不难找到,否则他们的客户也就无法找到他们了,如果真的找不到的话你也就不用担心竞争了)。如要想了解某个特定的竞争者正在做什么,你可以试试用网站分析工具(例如comScore、Quantcast)和移动分析工具(例如App Annie、Xyo)去估算他们的流量。你也可以使用CruchBase或AngelList这样的网站,看看竞争者获得了多少投资以及背后是哪些投资者。
  • 社区 验证问题还有另一种好方法,就是看看社区中是不是已经有人在讨论这些问题了。你可以在聚会、会议、用户组和在线论坛等网站上搜索,估算一下这个问题影响了多少人。例如,在研究hello-startup.net的时候,我在meetup网站上看到有15 000个创业小组(400万成员)、3000个科技创业小组(100万成员)和2200个精益创业小组(650 000成员)。在lanyrd网站上,我发现有119个创业会议,并向其中的几个会议提交了申请,得以和这些社区中的人进行实际的交流。我也在subreddit上寻找有关创业的内容(大概涉及74 000名会员),在LinkedIn上寻找创业和创业者小组(大概涉及150 000名会员),在Quora上查找有关创业的主题(大概涉及800 000名关注者)。当然,我也在Hacker News上搜索(每天至少有120 000名独立用户阅读了有关创业的内容)。
  • 市场研究和报告 某些传统的研究方法也是值得尝试的。我们可以试着在网上搜索探讨你所关注主题的报纸、图书、期刊、课程、广播和博客。如果有必要,你也可以查阅美国证券交易委员会的备案文件或政府报告(例如查阅美国小企业管理局的相关报告)。我在研究hello-startup.net的时候,发现了数以百计的博客都在关注创业(例如Paul Graham的随笔、TechCrunch和OnStartups),还有几十本书(例如《创业者》《精益创业》和《创业者手册》)以及好几门课程
  • 例如斯坦福的“How to Start a Startup”以及Coursera的“Startup Engineering”)。 目前也有一些公司专门针对特定的行业收集相关数据并发布报告。其中有些数据是免费的,比如世界银行数据。另外,也可以花钱请Nielsen Media Research这样的公司为你进行市场研究,或者找AYTM那样的公司代表你向目标客户发送调查问卷。 产品数据 如果产品已经面世,我们可以收集到许多数据并进行分析,对产品新特性的影响进行评估。这方面内容将在第4章详细介绍。
  • 我们和客户交谈,目的是要尽可能地了解他们的日常生活,对下列问题做个决定。 · 对该客户而言,那是一个真正的问题吗? · 针对该问题,有什么可能的解决方案? · 该客户愿意支付多少钱去解决这个问题? 要回答这些问题,我们需要走出去和真正的客户交谈。但这样也有一个问题:直接询问客户需要什么,得到的答案一般都不太让人满意。有些客户根本就不知道他们自己想要什么。
  • 是否能够解决一个问题存在两个因素。 · 问题可以被解决。 · 问题可以被你解决。 第一个问题和市场实际情况有关。我们既要考虑前面所提到的市场规模、问题验证,也要核实解决该问题的技术是否已经存在,还要看解决方案从经济上是否足以建立起可盈利的商业模式。红杉资本是当今世上最成功的风险投资公司之一,它的合伙人会询问创始人们一个问题:“为什么是现在?”世界发生了什么变化,使得现在成为建立这家公司的最佳时间?你知道什么其他人所不知道的?为什么没有人在两年前建立这样的公司?为什么两年以后再建立这样的公司就太迟了?
  • 对于点子来说也是类似的:没有能预测哪些知识可以让你产生有用的点子,哪些知识不能的方法。最好的做法就是尽可能多学习一些东西,特别是你觉得有意思的主题。换句话说,“获得创业点子的方法就是不要去想创业点子”,而是把自己变成一个有创业点子的人。找到吸引你的主题,花大量的时间去思索,在点子日记上写下自己的想法并与他人分享。学会利用约束条件,寻找痛点,多出去走走,为你的潜意识提供大量时间处理所学到的东西。最终,便会萌发点子。 在此阶段,点子仍然是不成熟的。所以要注意,不要因为太快对这个点子下结论而扼杀了它,就像你无法预料哪些数学上的概念是重要的,你也同样无法预测哪些点子在未来会有更大的发展。回到1997年,Larry Page也不知道Google会是多么大的一个点子,那时他还想把公司以160万美元卖给Excite(今天Google的价值大约是4000亿美元)。我在这本书中采访的每一个程序员,都没有想过他们的创业公司会发展得那么大。Jessica Livingston在《创业者》一书中采访过的所有创始人都是如此,包括Max Levchin(Paypal)、Caterina Fake(Flickr)、Craig Newmark(Craigstlist)和Steve Wozniak(Apple)。
  • 在顾客看来,界面就是产品。 ——Jeff Raskin,《人本界面》
  • 从根本上说,设计就是如何去呈现信息,让他人可以理解并使用这些信息。人生中的许多次成功其实都取决于我们能够在多大程度上良好地交流,如果在大多数人的教育中加入一点设计方面的训练,结果将大为不同。
  • 其中有三个原则可以应用到设计中。 · 设计是一种可以学会的技能。 · 我们必须训练自己的眼睛有意识地识别出为什么有些设计能发挥作用,有些则不行。 · 设计的目的是把一些东西传递给用户。
  • 第三点,即设计的目标是为了与用户沟通,这意味着虽然“看起来漂亮”是设计的一个很有价值的因素,但是更为重要
  • 所有计算机用户的第一目标就是不要让自己觉得自己愚蠢。 ——Alan Cooper,The Inmates Are Running The Asylum
  • 解决的办法就是要认识到我们不能在工程或产品完工之后,才把“设计”加上去。设计就是产品,从产品开发的第一天起,它就应该是其中的一部分。以用户为中心的设计应该纳入我们的产品开发过程中,下面是它的五个基本原则: · 用户故事; · 人物角色; · 情感设计; · 简单; · 可用性测试。
  • 1. 用户故事 提前考虑设计并不意味着需要做出一份300页的详细规格说明书,而是在一心投入代码开发之前,先定义出用户故事。所谓用户故事,就是从用户的角度简短地描述你所做的东西。它应该回答下面三个问题。 · 用户是谁? · 他们要实现什么? · 他们为什么需要? 第一个问题“用户是谁”要求你要理解人,这可是出奇困难的事。
  • 作为程序员,当你在设计软件的时候,你的大脑其实一直都在“听着歌曲”。然而,你的用户却什么都没有听到,他们必须通过你所设计的用户界面(user interface,UI)去使用软件。你不能期待用户知道你所知道的,你也不能指望用户通过文档或教程来填补这一鸿沟。(正如Steve Krug所说的:“关于说明书你必须知道的最主要的一件事就是,没有人想读说明书。”)所以,想要做出成功产品的唯一选择就是做出出色的设计。
  • 最常见的设计错误就是把用户的目标(他们要实现的是什么)和任务(他们可以如何实现)混淆了。
  • 这里有另一种可以显著提升设计技能的快捷方法:不要再为“平均的人”设计产品。人平均下来就是不洋不土、不男不女,如果你为平均的每个人做设计,那么谁都不会喜欢你设计出的东西。 真正的平均用户被保存在日内瓦国际标准局的密不透气的地下室中。 ——Steve Krug,《点石成金》
  • 每个人都应该有名字、年龄、简历、工作经历和相关技能、信仰和目标,以及其他一些与你的业务相关的细节。为了让虚拟角色看起来更像真人,可以为每个角色添加一张照片(最好是在图片网站上找来的照片,而不是生活中某个熟人的照片)。为产品定义好人物角色之后,无论在用户故事中,还是在谈话中,都不用再去关注“平均用户”了。团队不用再去争论“平均用户”是更喜欢X功能还是Y功能,因为每个人对于什么是“平均”都会有不同的理解。相反,我们只需要讨论我们的人物角色是喜欢X还是Y就可以了。例如,hello-startup的“平均用户”想要一个计算程序来帮助自己对股票期权进行估值吗?这我也不知道。但麦克、莫妮卡或马赫什需要这样一个计算程序吗?我可以有根据地推测麦克和马赫什会觉得这样的工具是有用的。
  • 你关注的目标越广泛,错失靶心的必然性就越大。想让大量人口中50%的人满意你的产品,从而实现50%产品满意度的目标,这种做法是行不通的。我们只能挑选出50%的人,想方设法让他们100%满意,才能实现我们的目标。我们甚至可以瞄准市场中10%的人,让他们100%地心醉神迷,从而取得更大的成功。这听起来可能有点违背我们的直观感觉,但为单个用户进行设计是满足广大人群需求最有效的方式。 ——Alan Cooper,The Inmates Are Running The Asylum
  • 只要有可能,我们就应该把软件设计得像把你记在心上、考虑周到的人一样。要记住用户的参数设置,记住他们上次使用你的软件做了什么事情,记住他们过去搜索了什么东西,要尝试使用这些信息预测用户在以后会做什么事情。例如,大多数网页浏览器都会记住你过去输入的网址。Google的Chrome浏览器甚至更进一步,只要你一输入www.goo,它不仅会替你把网址补充为Google首页,而且如果该网址是你之前已经多次输入的,它还会在你点击回车之前就开始抓取网页,让网页加载得更快。Google对于密码的考虑也很周到,如果你最近修改过密码,而不小心还用老密码去登录,Google会提醒说“你的密码已经在12天前修改过”,而不是给你标准的“密码无效”的错误消息。
  • 要积极响应 好的设计会响应用户的需求。例如,Apple的笔记本电脑会检测房间中的光线强度,自动调整屏幕亮度和键盘背光。
  • “对错误的发生要宽容”这一点真的太重要了,我们不妨再多讨论一番。
  • 以下是一些经验法则,可以避免这种错误的发生。 · 提供帮助和指引,而不是错误消息。例如避免使用“错误”“失败”“问题”“无效”和“异常”这样的词,而是向用户解释程序希望获得的输入与用户的输入之间有什么差异。 · 在用户输入的同时进行检查(而不是在页面提交之后再进行),并分别给出肯定和否定两种反馈,给出的反馈应该在用户视线附近(而不是页面的顶部)。 · 永远不要把用户做好的东西弄丢。
  • 这种说法乍一看似乎很拗口。我们通常认为“简单”就是精简而没有多余的东西。如果从空白状态开始,只是随处添加几样东西,不就可以得到简单的设计吗?如果你写过文章或者复杂的代码,或者尝试设计过产品,就知道一开始的草稿往往都过于杂乱。我们要花大量的工作才能把这种杂乱削减成为简单的东西。
  • 简单其实就是一件我必须完成的事。我的产品必须完成的一件事是什么?我的设计必须向用户传达的一件事是什么?定期问问自己这几个问题,得到答案后亦可再次发问。我所设计的产品是否做了这样一件事?抑或我迷失在了细节的实现当中,产品最终做的是其他的事情。
  • 设计需要简单并不是因为简单更优美,而是因为人的记忆在同一时间只能处理少数几件事。如果设计中塞入太多东西,很快就会超出人的记忆局限,用户会觉得产品功能过多而无法使用。
  • 不要把可用性测试与焦点小组(focus groups)混为一谈。焦点小组的目标是了解人们如何看待某个点子或某种产品,而可用性测试的目标则是了解人们如何使用你的实际产品去完成特定的任务。虽然有一些公司可以帮助你开展正式的可用性研究,但一般都昂贵且费时,大多数创业公司都可以用更简单的方法去实现。下面列出了大概的步骤(读者可阅读《点石成金》一书了解更完整的介绍)。 (1)把少数用户(3~5个)带到你的办公室。 (2)准备好录像设备(例如安装在三脚架上的iPhone)。 (3)记录下用户使用你的产品执行一系列任务的过程。 (4)让团队成员观看录像。 (5)根据你们认识到的情况决定采取什么行动。 (6)每3~4周重复一次。 如果之前从未进行过可用性测试,你很快就知道第一次观察公司以外的人使用你的产品会是一种发人深省的体验。
  • 伟大的界面是写出来的。如果你认为每一个像素、每一个图标和每一种字体都很重要,那么你也要相信,每一个字母都很重要。
  • 你的大标题必须能够和目标人群的角色产生共鸣,不仅告诉他们你要做什么(“我们的软件可以实现XXX”),还要告诉用户为什么应该关注它(“我们的软件可以实现XXX,所以你可以成功地YYY”)。知道如何提炼出清晰的信息去介绍你的动因、你的使命,是各种事情成功的关键因素之一(
  • 如果你不想立马跳到代码中,可以先使用线框图或原型工具,比如Balsamiq、UXPin或者Justinmind。利用这样的工具,可以从UI元素库拖拽出一些元素进行摆放,组合成一份设计。
  • 创业时面临的第一个设计上的挑战,就是要实现产品最初的版本。即便你已经想出了出色的点子,也对真实的客户进行了验证,你也要耐住性子,把自己锁在房间里,花上一年时间去设计,才可能做出完美的产品。但是请记住,产品并不仅仅是一个点子,而是新的问题、新的想法和执行的不断循环。执行是昂贵的,所以你需要尽可能低成本、快速地向客户验证你遇到的每一个新问题和想法。最好的方法就是实现所谓的最简可行产品(minimum viable product),或者叫MVP。
  • MVP是“新产品的某一个版本,团队可以利用它以最小的付出去最大程度上、验证性地了解客户”。MVP的关键就是从中学习,其目的就是找到成本最低的方式去验证对真实客户的假设。
  • MVP的实现并不是一次性的行为。对某种东西而言,在找到可行的产品方案之前,极有可能需要实现多个MVP。但更为重要的是,MVP的构建不仅仅是在产品生命周期的早期所要做的一件事,它更多的是一种思考方式。不妨把它想成在玩纸牌游戏,每次都下一小点赌注,而不是一次就把房子全压上。不论你是在试验从未有人用过的新产品的点子,还是为已有大量用户的产品添加新的功能,都应该有使用MVP的习惯,我们可以把MVP的实现归纳为以下几点: (1)找出风险最大、最重要的设想; (2)把这种设想以一种可测试的假设描述出来; (3)构建一个最小的实验(一个MVP)去测试你的假设; (4)分析结果; (5)用新发现去重复第一个步骤。 不管对一个点子有多么自信,一定要努力找到最小、成本最低的测试方法,而且要随时保持项目规模小、可改进。Standish集团通过对50 000多个IT项目进行研究,发现有3/4的小项目(少于100万美元)可以成功地完成,只有1/10的大项目(大于1000万美元)能够按时且在预算内完成,而超过1/3的大项目是彻底失败的。
  • 不管对一个点子有多么自信,一定要努力找到最小、成本最低的测试方法,而且要随时保持项目规模小、可改进。Standish集团通过对50 000多个IT项目进行研究,发现有3/4的小项目(少于100万美元)可以成功地完成,只有1/10的大项目(大于1000万美元)能够按时且在预算内完成,而超过1/3的大项目是彻底失败的。
  • 展示页面 有一种比较容易实现、成本低、效果又出众的MVP,那就是做个简单网页,描述产品情况并在用户感兴趣的时候让他们提交某些信息,比如让用户提供email地址以便获得更多信息,或者让用户进行预订。总的思路就是向用户描述产品最理想的景象,看看它对用户有多大吸引力,哪怕产品尚不存在。如果你以最理想化的方式向用户描述了你的点子都无法说服一小部分人在你的邮件列表上注册,也许就需要再重新想想。例如,社交媒体管理应用Buffer开始时就用一个页面展示了有关产品的理念和价格细节,并提供了注册邮件获取更多信息的功能,如图3-36所示。他们获得了足够多的注册量,更重要的是,他们在价格选项上也获得了足够点击,令他们足以信心满满地去实现真正的产品。
  • 在Drew Houston开始构建DropBox之前,他想确认自己不会花多年心血却做出无人问津的产品。但即便实现一个用户可以在自己电脑上试用的简单原型,也要花很长的时间,因为想要存储所有的数据,就需要搭建起一个可靠的、高性能的在线服务系统。Houston选择的替代方法是建构一个简单得多的MVP:一个具有注册表单,还带有4分钟讲解视频的展示页面,如图3-37所示。
  • 无论最终要实现哪种类型的MVP,关键是确保自己实现的是简化但仍然可用的东西,而最好的方法就是关注自己产品的差异性。
  • 同样的道理也可以用在制作MVP上。对你的产品而言,什么是重要的问题?你在MVP中实际实现的又是什么?为什么会不一致?产品最重要的一点就是差异性:让产品和其他替代品区分开来的特性。人们通常把差异性称为“竞争优势”,但这个词听起来就像其他优势一样,不管超过多少,只要具备就足够了。
  • 因此,很重要的一点就是要问自己:我的产品有哪两三个地方是做得特别出色的?只要你找出了这样几个核心特性,就可以以此做出你的MVP,先忽略其他东西。
  • 让客户爱上你的产品,而不只是喜欢它,这是一个巨大的优势。让一个已经有少量用户爱上的产品变得有更多的用户爱上,比起让大量的用户从喜欢一个产品变成爱上一个产品,前者要容易得多。让一个用户从“喜欢”到“爱”,你要让他们大为心动才行。你需要让他们能大叫一声由衷地赞叹,想想最后一次有东西让你发出赞叹的感觉,很可能是有人超出你的预期,让你高兴不已,也可能是一些超乎寻常的东西。因为做出不同一般的东西本身就要花大量的时间,所以,如果你想让用户能够爱上你,比起让许多事情都差强人意,你应该让少数事情无与伦比。
  • 那么,我们怎么知道要把关注点放在哪些特性上呢?有一种方法,就是在做出产品之前,先写一篇宣布产品发布的博客,看看文章中有哪两到三个关键特性是你会重点宣传的,你会在插图中展示哪些特性,博客的标题会是什么。好的博客文章都是简短的,所以这样的训练可以帮助我们梳理出哪些特性真正能让产品充满诱惑力。这样的特性就是MVP必不可少的,其余的一切都是可选的。事实上,其余的一切不仅仅是可选的,大多数时候,甚至对产品是有害的。每一个额外的特性都会带来显著的成本(阅读3.1.2节了解更多信息),所以,除非该特性对取悦客户或者验证假设是绝对不可或缺的,否则就不应该放到MVP中。
  • 我们要对MVP确定一个目标,即便在很早的阶段,也要让客户购买你的解决方案。注意,这里强调了“购买”一词。许多人会告诉你他们“喜欢”一个点子,甚至也许想得到它。但是,喜欢某种东西和承诺会购买某种东西是大不相同的。购买一种新产品不仅仅要花费金钱,还要花费时间——他需要花时间去说服家人(如果是消费产品的话)或者同事(如果是企业产品的话),让他们相信产品是值得的;而且,还要花时间去安装和部署,花时间培训自己和别人去使用它,将来还得花时间去维护和更新。即便你的产品对某些用户是免费的(例如靠广告支持的网站或者免费增值服务),他还是要付出自己的时间,而时间因素也会让他们考虑一番。所以,不管你考虑采用什么样的定价策略,目标就是要让客户牢牢承诺会购买你的产品。
  • 也许影响创始人意识到能够在多大程度上关心用户的最大障碍,就是他们自己从来没有体验过这样的关心。他们对待客户服务的标准是依据他们自己作为客户的那些公司的标准来设定的,而那些通常都是些大公司。蒂姆·库克不会在你买了笔记本电脑之后给你寄一张手写的卡片——他做不到,但你可以。这就是小公司的好处:你可以提供大公司实现不了的服务。
  • 当你还是一家小型创业公司,仍然还在验证自己的点子时,做一些无法规模化的事情去获得早期的客户是你可以承担的方式。如果点子可行,后续可以通过自动化的方式,让这一过程变得更具扩展性;但如果点子不可行(大多数点子都是这样的结果),那么你也节省了大量的时间,因为你不需要为了错误的事情而做一大堆自动化工作。另外,这种方式可以让你直接接触业务的烦琐细节,你会成为领域的专家,而这一点在前面已经说过,它对于想出伟大的点子是至关重要的。
  • 另外,这种方式可以让你直接接触业务的烦琐细节,你会成为领域的专家,而这一点在前面已经说过,它对于想出伟大的点子是至关重要的。
  • 设计是一项重要的技能,因为用户界面就是产品。好在设计过程是迭代的:任何设计都可以递增式地改进,任何人也都可以递增式地提高自己的设计技能。而最好的做法就是去重用现有的设计、编写用户故事并为人物角色而设计。
  • 只要你手中拿着的是一件精雕细琢的产品,你就要记住,其实我们看到的是无数次试验和错误的迭代之后形成的结果。这其中包含了许多失误、原地打转、重新设计和妥协折中。这一路上,制造它的公司可能要为生存而苦苦挣扎,希望能够在倒闭之前找对路子。
  • 这就是创业公司总是处于“搜索模式”的含义所在。这是一场和时间的疯狂比赛,你要尽快找到值得解决的问题,找到值得实现的方案。而实现这一切的最佳方式并不是寄希望于尤里卡时刻,而是要利用迭代、试验的方法去实现。
  • 产品经理的工作就是要把两件简单的事情说清楚: · 我们正在进行什么比赛? · 我们怎么得分? 把这两件事情做对,就可以不经意间聚集一批在技术、运维、质量、设计和市场推广上具备天赋的杰出人才,在同一个方向上聚力前行。没有这两点,无论做多少优化和执行管理,都拯救不了你。
  • 并不是所有东西都可以测量,或者都应该被测量。对于每一种数据X,我们要问自己两个问题。 (1)如果我可以测量X,它至少会影响一个具体的决定吗? (2)该决定的价值超过测量X的成本吗? 如果这两个问题都无法回答“是的”,那么就不值得去测量X。话虽这么说,大部分人并不清楚能够以最小成本、付出最少努力去测量什么东西。《数据化决策》一书介绍了如何对各种各样的概念进行量化,包括一些看似模糊和不可测量的概念,比如产品质量、品牌认知、安全以及风险。
  • Andrew Chen在Quora上发表了一篇关于如何找出公司神奇数字的优秀教程,其中的第一步就是找出衡量公司成功的指标是什么。当成功指标增长的时候,你的业务也会取得成功;当指标下降的时候,你的业务会随之失败。这个指标对于每个公司而言有很大差别,但应该是相当明显的。比如Facebook和Twitter的大部分收益来自于广告,所以它们的成功指标和用户参与度结合得非常紧密(例如用户在过去28天的周期内会回到网站多少次);Slack是一个订购产品,所以它的成功可能和有百分之多少的用户会成为付费用户有紧密关系;Etsy是一家电商公司,所以它的成功指标可能和网站的交易数有紧密关系。
  • 一旦找到衡量成功的指标,第二个步骤就是判断用户的哪些行为与成功指标的增长是有关联的。抓取一部分有代表性的用户,把他们的全部数据(例如获取指标、激活指标等)放入一张巨大的表格中。如果幸运的话,把用户的活动指标和公司的成功指标放在一起绘制出图表之后,会发现它们之间有非常明显的相关性。例如,如果把Twitter用户的关注人数和他们连续登录的天数放在一起对比做图,可以得到图4-1所示的图表,临界点大概就在y轴的30~40。有时的结果并不会很明显,这就需要进行回归分析,找到理想的相关性。
  • 许多人,特别是专家,都相信自己只需要深入思考,就可以解决几乎所有问题。他们可以在纸上画出周密的产品点子、聪明的工程设计又或者是精美的图表和等式,然后等待成功的到来。只可惜,在大多数情况下,成功永远不会到来。那是因为我们所生活的世界无比复杂,通常我们面对的系统已经超出了任何个体的理解能力,比如自由市场经济、人的思想或者分布式计算机系统,影响这些系统的问题太过复杂,从单一原因入手无法得到解决。
  • 我们需要的是进化,而不是聪明的设计。这意味着不要有上帝情结,要承认自己并不知道正确答案是什么。
  • 应用迭代的方法论,而不是一开始就投入精力把整个产品做出来。 (1)做一个MVP。 (2)对其进行A/B测试。 (3)分析结果并做出下面三个决定中的一个。 a. 改善:测试得出的数字不错,足以证明我们能够进一步完善MVP,回到步骤1。 b. 发布:测试得出的数字非常好,并且产品已经完成,可以向所有人发布。 c. 放弃:测试得出的数字并不好,不足以证明应该继续工作,可以转到下一个点子上。
  • “开发设计的时候要坚定你在做正确的事,阅读数据的时候要提醒自己可能会出错。”
  • 如果我们生活在一个可以获得完美信息的世界里,那么最好的产品总能胜出,但我们生活的世界并非如此。
  • 我们以前讨论过,在公司成立的早期,做一些无法规模化的事情是最好不过的。让每个人都参与到客户服务中,对公司的扩大发展确有惊人的作用,因为这么做不仅可以让忠诚的客户传播你的产品,还可以让这些写代码的人也感受到使用产品的客户的痛苦,帮助你做出更好的产品。
  • 要计算病毒系数(K),需要用每N天的用户发送邀请数(I)去乘以这些邀请的平均转化率(C)。对于I而言,就是当前一个用户执行了多少次才吸引来新用户的某个动作,这种动作就好比在社交网络上发送一个邀请;对于C而言,就是邀请被接受的百分比是多少。 K=IxC 例如,假设你今天发布产品,有1000个人注册,通过查看指标发现,这1000个用户在注册后不久即发送了5000个邀请,或者平均下来每个用户会邀请5个新用户,即I=5。这些邀请在最开始的几天会获得许多点击,在大概一周左右就会降到0,所以你的循环时间就是N=7天。
  • 尽管调查和促销代码都不像在线跟踪一样精确,但我们的目标并不是为了得到完美的数据,仅仅是降低一些不确定性,只要能够测量出用户的来源以及是什么样的用户就行了。因为我们不仅仅要确定广告已经到达了受众,还要确定它到达的是不是正确的受众,这一点在电视和广告牌这样的广播式媒介上,通常需要一定的技巧去处理。
  • 集客式营销背后的关键理念就是不要尝试把东西卖给客户,而是尝试去教育他们。 教导客户,就可以和客户建立起传统市场营销策略所无法获得的纽带。通过杂志或网上横幅广告去购买人们的关注力是一方面,如果教育他们,赢得他们的忠诚,建立起完全不同的关系,他们就会更加信任你、更加尊重你。即便他们不用你的产品,仍然会成为你的粉丝。
  • 我之前提过,并不是最出色的产品胜出,而是客户认为最出色的产品胜出。客户如何看待你的公司——如果他们想到的是你的品牌,那么尝试对这种感知进行影响的行为就称为品牌化。
  • 只用了“think different”两个词,就能够让你准确地知道Apple是做什么的,以及你为什么应该关注它。精心制作出这样一条清晰、引人注目的广告词并不容易,但正所谓文案是产品设计最重要的因素(阅读3.1.3节了解更多信息),广告词也是市场推广的核心。产品的宣传口号就是一个很好的例子,它必须能够一下子抓住人们的注意力,让别人知道你的产品有什么不同,而且必须简洁明了。例如,我们看看最初iPod的口号。
  • Y Combinator的座右铭就是“做人们想要的东西”(make something people want)。这四个简单的单词可以表达出创立成功的创业公司必须了解的几乎一切。
  • 技术栈就是工具,它是实现产品的手段,不是产品的终结,也不是产品本身。不要因为某项技术听起来很酷或者很有趣就选择它,我们选择一种技术是因为它可以为我们所用。为此,应该在把选择技术栈的黄金法则记在心中。
  • 好的技术栈的扩展要快于需要进行的维护。
  • 我们先从需要在很早就做出的一个决定开始:如何为创业公司选择初始的技术栈?我可以只用一句话来回答:熟悉什么就用什么。
  • 当你违背了技术栈的黄金法则——当你发现人数的扩展快于技术的扩展——就是时候重新进行评估了。
  • 暂停所有的发展、在全新的技术栈上重写代码要冒巨大的风险。这种情况被称作“所有软件公司都可能犯的单一的、最糟糕的战略性错误”和“创业自杀”。如果你抛开旧代码,就等于抛开了多年的学习和修复的bug。
  • 一个残忍的事实是:当你的关键业务过程运行在内部情况不清楚(更别提修改)的不透明代码上时,你就失去了对业务的控制。你对供应商的需要超过了供应商对你的需要——因为这一巨大的不平衡,你只能付钱、付钱、再付钱。
  • 任何库复杂到一定的程度之后,都会包含一个临时的、不合规范的、充满程序错误的、运行速度很慢的、只有一半功能的全栈Web框架,这是向格林斯潘的编程第十定律致敬。该定律告诉我们,任何C或Fortran程序复杂到一定程度之后,都会包含一个临时开发的、不合规范的、充满程序错误的、运行速度很慢的、只有一半功能的Common Lisp实现。
  • 如果你正在使用Web框架去实现对业务至关重要的东西——不仅仅只是原型,最好的选择通常就是模块化的全栈框架。那样的话,你可以获得两个方面的好处:一是得到了一个文档完善、有社区支持的开源框架,默认功能就可以出色地处理用户的大部分需求;二是对于小部分特定的情况,也可以通过插入定制库的方法去满足要求。
  • Web框架很少成为应用程序可扩展性方面的瓶颈(阅读第7章了解更多信息)。所以通常来说,我们最好选择开发效率比较高,而不是处理请求比较快的框架。也就是说,如果你担心性能问题,就需要弄清楚你的应用程序是否有I/O或CPU、内存方面的限制。
  • 安全的实现是非常困难的。它是5.3.4节所列清单中的一项。
  • 我们应该使用内置了安全特性、开源且经过实际检验的框架。因为这不可能是后期再加入的功能,所以框架必须是默认安全的,使我们做不安全的事情也变得困难或不可能。我们要花时间去熟悉常见的Web安全实践方法——开源的Web应用安全项目(Open Web Application Security Project,OWASP)就是一个很好的开始。
  • 我们要花时间去熟悉常见的Web安全实践方法——开源的Web应用安全项目(Open Web Application Security Project,OWASP)就是一个很好的开始。
  • 即便是一个简单的类,从关系型数据库映射到内存中的表示也是很复杂的,这就是所谓的阻抗失配。许多对象关系映射(Object Relational Mapping,ORM)工具都是为了尝试解决这一问题而诞生的,比如ActiveRecord和Hibernate,但通常都会引起争论——有人责备这些工具会暴露抽象泄露(leaky abstractions)问题,还会引发一些性能问题。这并非个别ORM工具存在的问题,而是由于映射本身就是一个难题。所有你能想出的解决方案都会包含一些严重、痛苦的取舍。
  • 一个分布式系统不可能同时满足以下三点: · 一致性(所有节点能够同时访问同一份数据); · 可用性(保证每一个请求都会接收到成功或失败的响应); · 分区容忍性(系统一部分出现任意信息丢失或故障时,系统仍能继续工作)。 在一致性(Consistency)、可用性(Availability)和分区容忍性(Partition Tolerance)中,只能择其二。
  • 在一致性(Consistency)、可用性(Availability)和分区容忍性(Partition Tolerance)中,只能择其二。
  • 如果使用关系型数据库遇到了障碍,极有可能是因为我们的数据量和可用性方面的需求已经超出了单台服务器的能力范围。此时,我们要优先考虑找出可以扩展的最简单的解决方案。按照复杂程度,以下列出了最常见的一些选择: · 对数据存储格式和现有数据库的查询进行优化; · 在数据库之前设置缓存(例如内存缓存); · 建立主-从复制; · 对无关联的表进行垂直分区; · 对单张表进行水平分区; · 建立多主复制。 一般而言,我们要尽可能避免对数据进行分区,并坚持使用单点写入。
  • 所谓整洁的代码,是指代码专为人的理解而优化。记住,创业和人是密不可分的,所以对代码来说,最重要的并不是运行得多快或者使用什么样的算法,而是它对使用它的人有什么样的影响。编写整洁的代码并不是为了理想主义,也不是因为有些书上说你必须这么做(即便不是本书),更不是因为空格比制表符更优美,而是因为作为程序员,你要把大部分时间花在理解和维护代码上,这只是为了让自己方便。
  • 语法工具存在这么多个世纪并不是偶然,它们满足了读者的需求和潜意识的要求。 ——William Zinsser,《写作法宝》
  • 变量、函数或类的名称应该回答所有重要的问题。它应该告诉你它存在的原因、它是干什么的,以及如何使用。 ——Robert C. Martin,《整洁代码之道》
  • 我们一定要明智地选择用词,肯定有比temp、num和data这样不明确的术语更好的选择。而且相对数字符号,我们更应该选择单词,即不要用subtotal1 和subtotal2 这样的名称,而是选用能够清楚表示值的含义的词,比如subtotalWithShipping和subtotalWithShippingAndTax。一定要想出一个好的词,哪怕查词典也可以。
  • 好的命名应该能够揭示意图。计算机只会关心代码是干什么的,而人却会关心代码为什么要这么做。
  • 如果我在看一个由10名工程师写的文件,应该让我几乎无法区分哪部分是哪个人写的才对。对我来说,这就是整洁的代码,而达到这一目标的方法就是通过代码评审以及发布你的风格指南、模式和语言惯用语。只要你做到这一点,每个人都会变得更有生产效率,因为所有人都知道如何以相同的方式去编写代码。到了那个阶段,你们主要关注的就是在写什么,而不是怎么写的问题了。 ——Nick Dellamaggiore,LinkedIn和Coursera软件工程师
  • 清晰的错误消息是整洁代码的主要特征。我们可以抛出异常、把错误消息作为返回值的一部分,或者将错误记录在日志中——只要不是静静地发生失败就行了。由于BookParser是对业务数据进行处理,我们通常要让数据尽可能保持原样,所以如果遇到了任何类型的错误,就应该让整个转换过程明显地抛出失败信息。为此,我们可以把所有无用的try/catch块去掉,让异常可以向上传导给调用者:
  • 注意该函数的签名中并没有返回值(它是void函数),这是有副作用的函数的典型特征。没有了返回值,我们就很难把这个函数和其他函数组合起来,这些函数将不得不通过文件系统或共享的可变变量进行通信,这两种方式都会比使用参数和返回值更加复杂,也更容易出错。
  • 不可变数据要求你要在脑海中弄清楚多条时间轴,副作用函数则要求你要在脑海中弄清楚多条时间轴和多个可能的全局状态。把几个有副作用的函数组合起来可能会引起所有时间轴和状态相互间进行交互,导致复杂度呈现指数式增长。 我认为可重用性的缺乏存在于面向对象语言,而不是函数式语言,因为面向对象语言的问题是它们离不开各种隐性的环境。你要一根香蕉,但得到的却是一只拿着香蕉的大猩猩和整个丛林。
  • 在软件领域,两个模块相互之间的依赖程度称为耦合。如果无论什么时候更新一个模块,都不得不频繁地更新另一个模块,这些模块就是紧耦合的,这通常表明代码是脆弱而且难以维护的。
  • 整洁的代码应该遵循依赖反转原则: · 高级的模块不应该依赖于低级的模块,二者都应该依赖于抽象; · 抽象不应该依赖于细节,细节应该依赖于抽象。
  • 根据经验,我们更应该对一些有如下特征的库的具体实现进行注入抽象。 · 具有副作用。 · 在不同的环境中有不同的表现。
  • 整洁的代码应该有高内聚:所有的变量和方法都应该是有关联的,一切都应该在同一抽象层次上操作,每一部分都应该很好地相互配合。
  • 不要为糟糕的代码注释——重新写吧。 ——Brian W. Kernighan、P. J. Plauger,《编程格调》
  • 我有意把介绍注释的内容放到比较靠后的位置,因为代码本身应该告诉你需要知道的几乎一切。如果代码没有做到,在你费劲地编写任何注释之前,应该先对代码进行改进。
  • 构是改变代码结构而没有改变其外部行为的过程,这是一种只影响软件“非功能”方面的编码任务:从外部看,代码实现的功能并没有变化;但从内部看,我们已经改进了它的设计。 合理的重构是必不可少的,因为我们不可能一开始就能正确地设计。和论文的初稿一样,代码的初稿也会是凌乱、不完整、需要重写的。虽然我有意把BookParser的例子写得很难看,但任何代码实现的第一个版本总是存在问题的。随着继续编写代码,我们会更好地理解问题,而重构的本质就是回到代码中,根据这种新的理解去改进它。
  • 编程在很大程度上就是一门手艺。你会因为选择了正确的工具、努力工作并制作出精美的东西而获得深深的成就感。它的美不仅源于对用户而言漂亮的外观,还源于其精工细作的内部运作方式。优雅的解决方案会让程序员愉悦,丑陋的拼凑则会让程序员悲伤不已。而悲伤的程序员生产效率更低、表现欠佳,最终将会离开公司。
  • 在创业公司中,一切都在不断变化。如果你已经到了害怕修改代码的地步,就意味着你需要在编码实践上进行扩展,以适应增长的需要。应对不断增长的代码库和开发团队的最重要的四个编码实践是: · 自动化测试; · 代码分离; · 代码评审; · 文档。
  • 要为代码编写测试,我们要先回过头来问自己几个重要的问题:我要如何组织代码的结构才能对它进行测试?我的代码有什么依赖项?常见的使用场景是什么?会遇到什么特殊的情况?
  • 最为重要的是,TDD可以迫使我们从最终结果反过头来考虑问题,帮助我们确认自己正在编写正确的代码,而不是直接跳入编码工作中,迷失在实现的细节里。我们要关注自己正在做什么,而不是怎么去做,如果我们能通过快速反馈循环的方式去做,就可以得到更高质量的设计。正所谓速度制胜。
  • 保持小规模的评审。10行代码的修改是很容易评审的,但是1000行代码的评审几乎是不可能的。这就意味着我们应该鼓励开发人员进行小修改,增量式地提交,而这恰好也是减少bug、合并冲突和后期集成问题出现概率的好方法。
  • 注释的正确用法是弥补代码本身表达上的失败。注意我用的是“失败”一词,这也就意味着,使用注释总是面临着失败。但我们又必须使用注释,因为不可能一直在没有注释的情况下解决自我表达的问题,但是使用它们并不值得称赞。
  • 程序员容易痴迷于性能、大O符号和可扩展性,会赞美一些“网络级”和处理“大数据”的公司。但现实却是,对于大多数创业公司而言,这些都不是特别重要的问题。我们的时间更应该花在能提高开发团队效率的工具和实践上,而不是让服务器跑得更快。事实上,做一些不能扩展的事情是早期创业成功的一个重要因素(
  • 一般来说,考虑性能或软件开发的基本过程就是让它工作,让它正确、让它快速。这是几个连续的步骤,我们必须按顺序去实现。实现错误功能的软件,即便它非常有效率也没有什么价值,所以我们在担心性能问题之前,必须先担心正确性的问题。只有得到整洁、可靠的代码之后,性能调优才是我们应该开始考虑的事情。
  • 当你开始尝试在软件公司中引入过程方法的时候,总会听到这样的声音:“我只能在不赶时间的时候去使用好的方法。如果时间很赶,我就管不了那么多了”。我总喜欢把这个故事拿出来举例子,想告诉大家一个真正好的方法无论在什么尺度上都应该能够加快你的速度。一个好方法可以缩短你一小时、一天或一年的时间。
  • 敏捷需要安全。 ——Jay Kreps,Confluent联合创始人
  • 使命宣言清楚地表达了公司的目的。它应该解释公司为什么存在,公司是做什么的、为谁而做。我们应当把使命当作公司的指南——它是一个梦想、一个目标,它是你、你的员工和客户所向往的。
  • 不要把你的使命宣言和当前的战略或产品混淆起来。战略和产品是如何做和做什么的问题,而使命宣言则是为什么的问题。“
  • 客户不会愿意在使命陈述中看到关于股东价值、收益和利润这样的东西,因为这些只会让人们觉得公司是贪婪且不值得信赖的。同样也不会有员工愿意为了提高2.3%的利润率而将心血投入到项目中。当然,每家公司都是要赚钱的,但金钱并不是公司的目标,它只是让公司达成真正目标的资源。金钱就像氧气,它是维持生活所必不可少的,但并不是生活的目的。事实上,忽略金钱是想出一个好的使命陈述的最佳方式。
  • 这里隐含着一个出人意料的道理:有时,一个大胆、宏大的使命实现起来并不会比一个小一点的使命容易。任何创业都是艰难的,但如果这一事情的回报是完成一个宏大而重要的目标,可能更容易说服出色的人参与进来。为出色的人提供一个宏伟的挑战才能够让他们在职业中尽其所能。
  • 核心价值是你在组织中用来做出每一个决定的信条。核心价值并不需要去选择,因为它们在你的团队中即可发现。它们是你已赖以为生的主要价值,你对其深信不疑,它们对你至关重要,不管你加入什么公司或者做什么产品,都会坚持这些价值。
  • 设定目标 经理应当决定一些目标、为了实现这些目标需要完成什么工作,以及如何将这些目标传递给团队。 组织 经理应当对工作进行划分,并挑选人员从事这些工作。 激励和沟通 通过在薪水、人员安排和晋升方面的决定以及经常性的沟通,经理应当将人员凝聚成一个高效的团队。 评估 经理应当为每个人建立目标并评估他们迈向这些目标的进度,形成一种绩效评估方式。 助人成长
  • 经理应当帮助团队中的每一个人提升自己的能力。
  • Douglas McGregor在1960年《企业的人性面》一书中,讨论了一种普遍的观念,即一般的工人并不喜欢他们的工作,并极可能去避开它。对某些工作来说也许是这样,比如一些无聊的、重复的手工劳动。那种情况可能需要一直有管理人员的存在,用报酬(薪水、奖金)促使工人们工作,或者用惩罚(解雇、蒙羞)威胁他们。然而,这种方式在许多需要创造性的工作中并不适用,比如编程。许多人喜欢使用自己的创造力去制作东西,所以他们实际上是喜欢自己的工作的,而且会积极主动地寻找要解决的问题。而我们要做的就是为他们提供合适的环境,他们内在的驱动力将促使他们努力工作。
  • 这种方式在许多需要创造性的工作中并不适用,比如编程。许多人喜欢使用自己的创造力去制作东西,所以他们实际上是喜欢自己的工作的,而且会积极主动地寻找要解决的问题。而我们要做的就是为他们提供合适的环境,他们内在的驱动力将促使他们努力工作。
  • 那么要怎么办呢?答案就是内在激励因素——我们都具有的内部驱动力,能够让我们因为任务本身的利益而喜欢上一个任务。人天生就是爱玩而好奇的,我们经常会在一些困难的任务上投入大量的时间,即便没有人为此买单。如果你是程序员,你已经有所体验了。你是否曾经花了一个周末的时间去改动一个工作之外的项目?你是否曾在工作之余学习过一门新的编程语言或技术?你是否曾为解开朋友告诉你的一个逻辑谜题而无法入眠?你是否曾经向开源项目做过贡献?这些活动大部分都是受内在激励因素驱动的。
  • 如何才能促进内在激励呢?由于它是很自然的,我们无法从外部去驱动内在激励。我们能做的只是提供一种环境,有利于将人们已经具备的内在激励带动出来。为此,我们需要营造一种能最大程度放大自主权、专业能力和目标的环境。
  • 每个公司都想招聘到最出色的程序员,但是最好的公司都会紧紧抓住他们的程序员并在他们身上投入,让他们变得更加出色,这就形成了一种良性循环。这些员工会因为他们正在提升自己的技能和市场价值而高兴,公司也因为得到更出色、技术更精湛的员工而高兴。专业能力上的投入有许多方法,比如鼓励员工定期加入新的项目和团队,参加会议和演讲(能够在会议和演讲中有所表现则更好),组织公开论文、博客和图书阅读小组(能够自己写论文、博客和图书则更好),向开源项目做贡献(阅读第12章了解更多信息)。
  • 通过这种方法,我们得以用更加透明的方式代替模糊、不确定的员工评估过程。而且它也不仅仅提供外在的奖励(例如薪水),还提供了内在的奖励(比如公司投资你的专业技能),这是一种明显的交互。LinkedIn的全局方案高级副总裁Mike Gamson写过一篇博客,提到了一个很好的例子,这篇博客名为“My Promise to You(Our Employees)” 我们先从坏消息讲起。坏消息就是有一天你会离开LinkedIn。我知道你才进入公司就要考虑离开是很奇怪的,但我要让你关注这件事,这样我们才能最充分地利用我们一起在公司的时间,携手前行。我不清楚你打算在这里度过2年、5年、10年还是更长的时间,但我要确保无论你和我们一起在这段旅途上待多长时间,当你在20、30、40年后回首整个职业生涯的时候,你会觉得待在这儿的岁月是职业生涯中变化最大的。你在这里的这些年学到的最多、成长最快、接触到最多不可思议的人和最具创新性的想法。我希望你在这里的这些年能成为真正改变你职业轨迹的岁月。我希望你在Linkedln比在你们本可能选择的其他地方,获得生命中更多的成就。我向你承诺,我将致力于营造和培育能够让你改变职业轨迹的环境,为你提供接触各种思想、各种人员、各种体验的机会,满足你在生命中实现这一切所需的因素。当你在某天离开LinkedIn,我希望你能够真正地转变。我所期望得到的回报是你能允诺全身心投入到这个自我转变的机会中,投入到我们的公司和这个世界中,并用你的勇气和坚持去追寻这些机会。
  • 开发人员的理想办公室需要满足4个条件: (1)一个可以和他人一起工作的地方; (2)一个可以独处专注工作的地方; (3)一个可以放下工作的地方; (4)一种可以根据个人需要定制办公室的方法。 注意,前三项从本质上不应该属于同一个地方——这是现代办公室设计最经常被完全忽略的原则,这一点将在下一节介绍。
  • 仅仅因为存在会被打断的可能性,就会让这些开发人员不敢开始困难的项目。这也是为什么他们喜欢在深夜工作的原因,也是他们几乎不可能在隔间里写出出色软件的原因(除非在深夜)。 ——Paul Graham,Y Combinator联合创始人,硅谷创业教父,《黑客与画家》作者
  • 健康的公司文化鼓励员工去分享坏的消息。可以自由、公开讨论其问题的公司也可以快速地解决这些问题,而掩盖问题的公司则会打击员工参与的积极性。所以CEO的做法应当是:营造一种文化,奖励(而非惩罚)人们将问题公开,使得问题得以解决。
  • Twilio是一家API公司。我们有一个传统,要求每一名员工必须实现并演示一个应用,这个应用必须是用Twilio API实现的,为此可以得到有公司logo的外套和Kindle(这是一项不受限制的公司福利),适用于所有部门,包括技术、销售、财务和市场。 我们每个周三都有一次公司宴会,新员工会在宴会上演示他们的应用,而我们的CEO则会把外套给他们穿上,为他们“授爵”。当新员工展示他们所做的东西时,看到整个公司都为他们喝彩是很美妙的,不管他们做出来的东西多简单或多复杂。
  • 第一规则:在所有情况下采用你的出色判断
  • 这并不意味着完全不采取任何过程,但是“采用出色的判断”应该是默认的过程。对于特定的情况,只有在“出色的判断”被证明不够时,才有必要在此之上实施一些额外的步骤。
  • 这是一个有趣的证明。但在这次个名为“Optimizing for Happiness”的演讲中,有一个严肃的观点:公司应该是让人快乐的,而不是获得利润。换句话说,创业是与人密不可分的。为快乐而优化的创业公司可以产生一种良性循环:当员工感到快乐时,他们会让公司变得更加强大;当公司强大时,它又使员工更快乐。
  • 机会并不会像浮云一样飘走,它们会牢牢地与个人联系在一起。如果你在寻找一个机会,实际上是在寻找人;如果你在评估一个机会,实际上是在评估人;如果你尝试统筹资源去追逐一个机会,实际上是尝试得到他人的支持并参与其中。并不是公司给你提供工作,工作是人提供的。 ——Reid Hoffman、Ben Scanocha,《至关重要的关系》
  • 除了编程问题之外,大多数面试官还会问一些关于你自己的问题。 · 谈谈你自己。 · 你以前做过什么项目? · 你为什么要找一份新的工作? · 你为什么想来这里工作? · 你理想的工作是什么样的? · 你想在5年内做什么,10年内呢? · 你最大的优势是什么,最大的劣势呢? · 你最大的成就是什么? · 你曾经解决的最难处理的bug是什么? · 我应该再问些别的什么问题吗? 有些问题听起来可能很俗气,但是却经常出现。请加以练习!
  • 不要在面试完成之后还不了解以下问题的答案。 · 该角色的期望是什么? · 该职位能够取得什么样的成功? · 谁是我的经理? · 我将从事什么项目? · 技术栈是什么? · 工作时间怎么样?他们花多少时间在编程上,又花多少时间来开会? · 如何构建和发布代码? · 公司的使命和价值是什么? · 办公室怎么样? · 在这里工作,你最喜欢和最不喜欢什么? 几乎每一名面试官都会给你咨询的机会。
  • 工作机会最重要的就是其背后的人。你准备好每周花40个小时以上的时间和他们在一起吗?你能否从他们身上学到东西?他们对于你的职业成长是否有帮助?和他们在一起有趣吗?他们是否投入足够的精力并具有足够的才能让公司取得成功?你是不是觉得仅从几个小时的面试就要得出这样的判断是很困难的?
  • 现在你明白了股票的基本知识,那么是不是多点股权少点薪水也无妨?这个问题可以从三个角度去考虑。第一个角度是把你的股权和所在地区类似的开发人员和公司进行比较。有一种方法可以做到这一点,就是使用Wealthfront的在线薪水和股权计算器。另一种方法是查阅http://www.hello-startup.net/resources/equity/,上面有一张表格,根据工作角色、资历和员工数量,列出了在创业公司工作通常可以获得的股权数量。 第二个角度是把较低的薪水看作是对公司和你的职业的投资,看作是为了以后得到大回报的机会。这样的回报能有多大?谁都不知道。这其中有太多需要考虑的因素,所以你能做的只是进行大量的猜测和假设,得出很多种可能性。下面是一个评估风险和回报的公式(但是要牢牢记住,这只是一个简化的计算,不完全准确;另外,还要注意这个公式假设股票一兑现就被立即行使权利,而没有考虑纳税的因素)。 A = 工作薪水和公平市场薪水之间的差异 B = 你希望在该创业公司工作的年限 C = 行使股权的成本 D = 你拥有该公司的百分比数 E = 投资者的投入 F = 公司在成功退出时的价值   投入 = (AB)+C 回报 = D(F-E)
  • 假设公司提供给你的薪水是每年5万美元,这一职位的公平市场薪水是6.5万美元。意味着你每年“投资”A=6.5万美元–5万美元=1.5万美元,用于换取未来从股权中可能获得的回报。你预期在公司工作B=4年,这个年限通常足以兑现你所有的股票。提供给你的工作中,你以每股0.1美元的履约价格获得了10万股股票,所以要行使所有股份,必须花费C=10万股×每股0.1美元=1万美元。这意味着你在这家创业公司中的投入如下: A = 6.5万美元 –5万美元 = 1.5万美元 B = 4年 C = 10万股 × 每股0.1美元 = 1万美元   投入 = (1.5万美元 ×4) + 1万美元 = 7万美元 在你获得股票时,股票的总发行量是110万股,所以你行使的10万股代表了公司的0.9%。然而到你达到退出条件时,你的股份可能已经被稀释了,因为公司会建立新的期权池,引入新的员工或投资者。我们假设4年之后你的股票被稀释了50%,那么10万股最终代表了公司的0.45%,也就是D=0.0045。
  • 开始的时候,你可以对投资者做个大概的评估: E = 募集资金 × 优先系数 × 经验参数 当你获得工作机会时,需要了解公司过去从投资者那里筹集了多少资金、在未来计划筹集多少资金,以及涉及的优先权(现在通常是1倍)。
  • 我总是建议人们这样想问题:如果你打算为一家公司工作,你断定1万美元的薪水比起所获股票的上涨更值钱,那你就是在把宝贵的时间和精力压在错误的公司上——完全就是把赌注押在错误的地方。这是一种通常都可行的考虑公司的思维模式。
  • 提供给实习生和应届生的职位,特别是大公司提供的职位,通常都是标准化的。如果你刚刚进入这一行业,影响力很小,就不要期望在薪水和签约奖金方面有多少提高的余地。如果你已经在该行业工作了好几年,通常会有10%~20%的浮动空间。如果你是首席开发人员或者高级总经理,30%或更多的空间也是有可能的。注意,如果你希望在薪水上提高10%,你就应该要求提高15%。也许你会立马得到更大的数字,这当然很好,或者公司可能会向下还价为10%,这就是你在开始时想要得到的水平。
  • 我几乎没有听说过仅仅因为谈判就丢失了工作机会,如果这种情况真的发生了,无论如何也不要在这样的环境中工作。
  • 在面试的早期,即还远远未到确定录用的时候,许多招聘人员都会询问你之前的薪水。如果你告诉他们,他们就会把它当作录用你所需要付出的最少薪水,从而拉低了你的谈判能力。你应当礼貌地回绝,告诉招聘人员你更希望在正式讨论录用的时候再谈薪水的问题。
  • 招聘人员可能会声称他们需要了解你之前的薪水,这样才不会因为薪水的问题浪费你的时间。在面试的早期确定你的薪水在一个合适的范围是没什么问题的,但这不需要暴露你自己的薪水。反之,你应该反过来问招聘人员,他们为这份工作提供的薪水范围是多少,告诉他们你会愉快地告知这是否在你可接受的范围内。如果招聘人员继续追问,就要提醒他们你的薪水属于私人秘密信息——可没有法律要求你泄漏。
  • 有些招聘人员会让你原样接受当前的工作条件,因为你会在以后得到大量的加薪和奖金。他们并不是完全在说谎,但是你应该假设所有没有明确写在合同内的东西都不会发生,承诺一年后有可能发奖金还不如提前给你加薪的保障。一般而言,你最可能在加入公司之前提高薪水。一旦你进入公司一两年,获得更高薪水或更多股份的难度就要大很多。
  • 假设总是会有职位放开,假设他们已经投入数周或数月的时间来寻找你、对你进行面试并给你工作的机会,他们当然可以提供几个星期的时间让你考虑。如果你需要更多的时间,不妨告诉公司你不能匆忙做出这样一个重要的人生决定。
  • 大多数公司都不会根据你吸引人的个性和才智的估价来为你提供工作机会,他们会根据你的技能等级的平均水平给你提供工作机会。如果想获得更好的工作条件,你的目标就是让他们相信你比他们所想的水平更高。可以使用两种谈判策略。 第一种策略是把你能够摆上台面的技能、具备的经验拿出来讨论,并使用一些市场数据,让公司确信你不止值这么多。遗憾的是,除非你在行业中大名鼎鼎,否则这样的谈判战术是不会有多少效果的,因为它仅仅是你针对雇主观点的意见。这里你唯一的谈判优势就是说不,公司已经投入了许多时间和金钱去寻找你、联系你,对你进行电话面试,让你来到现场,对你进行面试和背景调查,决定雇用你并提供给你一个工作条件,所以你可以让大多数公司在薪水或奖金上给你一小点提升,仅仅因为他们不想让全部努力白白浪费。
  • 第二种,也是更有效的策略,是通过获得竞争性的职位,向公司证明你不止值这么多。 5. 竞争性职位 作为职位的候选人,你最大的谈判影响力是竞争性的工作机会。另一家公司的工作机会是你在市场上价值多少的硬数据的象征,无须让你的意见和雇主的意见去一决高下。如果多家公司争相要你,你看起来就更有价值,你也许会让他们进入争夺大战中。我最喜欢的谈判策略之一就是像这样交谈:“嗨,A公司,谢谢你提供了这个工作机会,我想在你们和B公司、C公司之间做出选择,B公司给我多提供了X的薪水,C公司则给我多提供了Y的股权。我对你们的工作更感兴趣,也喜欢和你们在一起工作,但是却很难牺牲那么大的收入,你们能让这一决定对我变得更容易些吗?”
  • 当你有多种选择的时候,你会发现使用一种最强大的手段会让谈判变得更加容易,那就是离开。这就是为什么我们总是应该同时面试多家公司。也是为什么面试工作的最好时机是你不需要工作的时候。如果你不顾一切地想要得到一份工作,就更可能接受任何正好能提供给你的工作。
  • 现在,在本章的结尾,你应该能够反过来,把自己放在创业公司创始人的角色里,写下你想要招聘到的人员的品质。下面列出了几个你可能会写下来的例子。
  • 人是公司最重要的部分。选择正确的人比选择正确的产品、市场推广策略、技术栈或者编程方法论更加重要。这意味着招聘是你要做的最重要的事情,同时也是最难的一件事情。你需要找到与公司文化相契合的人,他要具备合适的技能,对你从事的工作感兴趣,并且在合适的时间点可供你使用,愿意接受创业公司的薪水。而且你还需要不断重复地去找符合这些条件的人。
  • 对于创业公司招聘,最好的一条建议就是:别做这件事,或者至少先别做这件事。招聘更多的人意味着
  • 对于创业公司招聘,最好的一条建议就是:别做这件事,或者至少先别做这件事。招聘更多的人意味着资金消耗更快,企业经营更复杂,决策更缓慢,要花更多的时间去搜索、面试和培训。最好的创业公司就是用较少的资源做较多的事。创业公司应当以小规模为荣,通过小团队去完成尽可能多的事。这能教你学会如何保持专注、更好地权衡取舍,并培养追求高影响力和高效率的热情。事实上,招聘更多的人并不一定意味着你可以完成更多的事情。9.2节讨论过,沟通的开销会随团队规模平方增长,这也解释了为什么较大的公司不能像较小的公司那样快速转变。你应当尽可能保持小规模。
  • 那怎么才能知道何时开始招聘呢?我们要问的关键问题不是“如果我们招了人可以做什么”,而是“我们不招人的话无法做什么”。如果对业务至关重要的事在没有新员工的情况下无法完成,不管你们多么有创造性,都是时候开始招聘了。
  • 我们应当在创业伙伴身上寻找四种品质。第一,要找“敏思笃行”的人。要寻找你认识的那些不管有什么障碍都能克服的人。第二,要寻找具有互补技能的人。例如,如果你是程序员并善于开发产品,就要寻找能够处理好销售和市场推广,并善于发现客户的创业伙伴。第三,创业伙伴通常在年龄、经济状况和动机上应该是类似的。如果一个创始人寄希望于赚快钱,而另一个则对改变世界有长期的愿景,这是很难成功的。第四,也是最为重要的,就是你要找到能够信任的人。要建立信任,你必须了解合伙人的经历,所以也再次说明了为什么同事、同学和朋友是最合适的创业伙伴。
  • Chesky还问了应聘者“如果你剩下一年的生命,还会选择这份工作吗”,而且他只会录用回答“是”的应聘者。这是一个极端的例子,你可能不应该完全照搬(即便是Chesky,后来也把问题改成了十年),但是这个问题真正的意义才是我们要放在心上的:尽你所能,确保自己找到正确的早期员工。
  • 这里有一个重要的提醒:专才的反面并非是通才。不是任何方面的专家并不意味着你就擅长各个方面。真正的通才是那些多面手的人,你把一些新东西放在他们面前,他们就会把它带走并弄清楚它是如何工作的。他们拥有永不满足的好奇心,愿意对所有东西都稍做尝试。但你要是看看他们的简历,就会看到大量行业的经历(例如旅游、医药、社交网络、消费者、部署自动化、编程语言设计)以及职业角色(例如开发人员、技术主管、产品经理、设计师)。
  • 如果一个程序员解决这个问题所花的工作量要少一个数量级,那么这样的一个程序员可能胜过一个团队。通过做出更好的决定和提出更有创造性的解决方案,10倍能力的程序员也许可以避免埋头苦干好几个月。换句话说,我们并不是要编写更多的代码,而是要编写正确的代码。10倍能力的程序员实际上是10倍能力的决策制定者。
  • 这一切表明,超级明星程序员,就像超级明星运动员,是格外稀少的。如果你尝试根据只招聘“摇滚明星”的原则去制订自己的招聘策略,或者更糟的情况是,如果你的公司招摇过市,好像已经是一群“摇滚明星”,你就永远无法发展你的团队。开发人员在能力上也许会有巨大的差异,但是这一点不能掩盖下面这三个关键的事实: (1)开发人员的表现会根据不同的任务而有所不同; (2)开发人员可以逐步变得更好; (3)大多数软件都是由团队而不是由个人开发的。 第一个事实意味一个公司中10倍能力的开发人员在另一家公司中可能只是1倍能力甚至0.1倍能力的开发人员。文化、激情和使命才是至关重要的(阅读第9章了解更多信息)。第二个事实意味着建立成功创业公司的最好方法就是招聘到出色的开发人员,并为他们提供一个环境,使他们可以变得更好。有些人知道了10倍能力的开发人员的概念会觉得沮丧,因为他们认为自己永远不会做得那么出色,似乎伟大的开发人员是天生的,而不是后天的。但是在阅读了第12章之后,你就会发现许多证据表明,将精英和一般人区分开来的并不是天赋。而是实践练习。
  • 我们要在所有应聘者身上寻找的重要品质就是,他们应该是聪明并能把事情做好、能够很好地适应文化、有出色的沟通技能、能够友好相处的。
  • 当你考虑一个应聘者的时候,你是否能够和他愉快地交谈呢?如果公司中的某个子系统是他们负责的,他们能不能向新来的员工解释清楚系统是如何运转的?他们有没有维护博客?如果有的话,写出来的东西你能不能看得懂?他们能不能在会议上演讲?你能不能理解他们的代码?如果你们的角色调换过来,那名应聘者在面试你,他们会是公司的出色代表吗?
  • 你所制作的大部分内容不应该明显和招聘人员有关。例如,不要用招聘视频去打扰别人,大家应该知道我指的是什么:在一个快速平移的镜头下,出现了一个站在白板旁边或者打着乒乓球的人;在一首快节奏的背景轻音乐的伴奏下,出现了一个面试的场景,一名行政人员坐在中央,看着摄像头一侧的人,告诉他们所做的工作是多么有意义,接下来就是渐渐出现的公司logo。实际上,没有公司之外的任何人会喜欢看这种片子。
  • 特别是这则招聘公告并没有为潜在应聘者回答最为重要的问题:我究竟一开始为什么要申请这份工作?
  • 如果你打算使用求职榜,就要做一份出色的招聘公告,需要把它当作一则广告去考虑。你不仅要解释这份工作是什么,更重要的是解释为什么应聘者要申请这份工作。
  • 所以我的建议是要反过来采用寻找闪光点的方法。这些闪光点可能是从好学校获得的出色的GPA,可能是工作之余做过的很酷的项目,可能只是工作之余做过的很多小项目,也可能是他们在现在的雇主那里获得的奖励——我们应该只去看这些闪光点。 ——Gayle Laakmann Mcdowell,Careercup创始人、CEO
  • 所以,除非你绝对有把握,否则在招聘的时候请说“不”。
  • 每一名面试官从面试出来时要么得说“可以”,要么得说“不可以”,不允许说“也许吧”。只有一个“可以”而没有其他团队成员的同意,照样不行。只有获得所有面试官的“可以”的应聘者才会被录用。录用一个有问题的应聘者比错过一个出色的应聘者更糟糕,所以即便只有一个“不可以”通常也足以拒绝一个人。唯一的例外是如果有人过去曾经和那位应聘者亲密共事过,并强烈为他打包票。现实的工作经历当然比在人为的面试中得到的一个“不可以”更有说服力。
  • 不要把面试等同于质问。许多面试官会直接跳入到技术问题中,直接用智力题和编程难题去狂轰滥炸,甚至连招呼也不打。你在那儿不是要拷问应聘者知道多少,也不是要让应聘者承认自己是个糟糕的码农。他们不是你的敌人,面试本身就是有压力的,所以请善待他们。
  • 我们要把面试当作两个人之间有礼貌的交谈,介绍你自己,简短地谈谈你是做什么的以及想要填补的职位类型。询问应聘者他们是做什么的,是否需要水或者休息一下。之后,和任何愉快的对话一样,把话题转移到应聘者身上,尝试去了解他们。让他们告诉你一些与自己有关的事情,谈谈他们过去从事过的项目,描述他们希望在以后能从事的项目,了解他们为什么对你的公司感兴趣。
  • 每一名面试官都是公司的大使,所以我们要选择聪明的人。
  • 这种方法能测试我希望在数据科学家身上看到的四种关键品质:技术水平、数据创造力、沟通技能以及是否是结果驱动型的人”,她说。
  • 假设你考虑提供一个工作机会给Anna,下面是可以问Anna的证明人的一些问题。 · 你怎么认识Anna的?你们在一起工作过吗?有多长时间了? · 告诉我Anna的职业。她最出色的成就是什么? · Anna最大的优势是什么?她正致力于改进的是什么? · Anna在这份工作相关的技能方面有些什么样的经验? · 和Anna一起工作感觉如何?你想再次和她一起工作吗? · 为什么Anna要离开她当前的工作?她希望得到什么? · Anna是和你共事过的最出色的1%吗?最出色的10%呢? 如果证明人的核实通过了,就要尽可能快地给应聘者提供录用。不要超过一两天,才能让应聘者知道你对他们是感兴趣的,那时他们也还清晰记得你的公司。
  • 我和别人第一次交谈时会问:“你在寻求什么?你想要什么?”这不是我在推销Tindie,我只是在倾听他们。在交谈中谈得越多的人一般都越觉得这是一次更好的谈话,所以我会倾听——我是真正地倾听。在尝试销售之前,我会问“你想要什么”,因为如果你先去销售,然后再问,人们通常只会说一些你想听到的东西。
  • 机会是一个工作机会中最重要的部分。我们提供的职位应该是一个参与更大的使命的机会,是和了不起的人一起工作的机会,也是对事业有所发展、有更大的影响力、从头开始做一些东西的机会(阅读第9章,了解有关使命及文化的内容)。
  • 有一种工作只是工作,有一种工作却是你终生的追求。
  • 这种工作草木皆情,由你全情打造。这种工作会让你从来不妥协。这种工作也会让你甘愿牺牲周末。你可以在Apple找到这样的工作。在这里的人们不会闲庭信步,他们到这里击水三千。 他们希望自己的工作能有一些不同的东西。 一些重要的东西,一些不可能在其他地方得到的东西。 欢迎来到Apple。
  • 下面列出了一些可以提供的福利的思路: · 保险(健康、牙齿、视力和生命); · 假期(度假、节假日、病假); · 食物(免费早餐、午餐、晚餐、点心和饮料); · 薪酬(报销安家费,401K缴存比例,奖金); · 工作现场福利(日托、干洗、按摩、汽车修理); · 健康(报销健身会员费用、运动课程、运动队); · 日程(支持灵活的工作时间和在家办公); · 活动(提供远足团队、阅读小组和志愿者小组的资金); · 学习(提供图书、课程、举办演讲及参加会议的资金); · 通勤(列车月票、地铁月票、停车月票、班车); · 自主权(黑客马拉松、20%时间、孵化器); · 硬件(强大的笔记本电脑和台式机、大屏幕、平板电脑); · 工作环境(私人办公室、舒服的椅子、可带宠物)。
  • 生命中大多数事情的关键点是,平均质量和最佳质量之间的动态范围,最大也就是二比一。举个例子,如果你在纽约,最好的出租车也许能比普通的出租车快20%;在计算机领域,最好的PC也许比一般的PC好30%。从量级上看并没有那么大的差异,你很少能找到二比一的差距,无论选什么做比较。 但在我关注的领域——最初就是硬件设计——我注意到普通人实现的东西和最出色的人实现的东西之间的动态范围是50∶1或100∶1。还要考虑到,后者都是知道要追求精益求精的人。这就是我们的情况。你可以打造一支由追求A+的队员组成的团队,一小队A+的队员就可以远远超过由B和C的队员组成的庞大团队。这就是我们所要努力去实现的。
  • 这就是为什么世界上最出色的软件开发者和软件公司都有一个共同点:都在孜孜不倦地学习。Erlang编程语言之父Joe Armstrong说过,成为更出色的程序员的最佳方法就是“花20%的时间去学习——这是一种复利”。《
  • 人们会想出各种借口解释自己为什么不学习新的东西,最常见的借口是他们太忙了,但实际上忙只是一个结论——做事情的时间不是找出来的,而是创造出来的。每当你听到自己说“我没有时间学习”的时候,就要意识到你其实是在说“我宁可把其他事情放在学习前面”。错过太多的学习机会是一种短视的行为,特别是在快速变化的软件行业。在这样的行业中,打造成功职业或成功公司的唯一方法就是不断让自己变得更加出色。
  • 安迪·格鲁夫,《格鲁夫给经理人的第一课》
  • 在《优秀到不能被忽视》一书中,Cal Newport提出成功职业的秘密并不在于一直困扰你的“内心之所向”或者“激情”,而是精通“罕见而有价值的技能”。通过提供专门在公司学习的时间,你既可以让公司成为对潜在员工更有吸引力的工作场所,也可以提升每一个已经在这里工作的人的表现。
  • 根据《人件》一书的说法,一般的软件开发者连一本关于他工作主题的书都没有。作为一名程序员和作者,我发现这种情况是很让人害怕的。但是在某种意义上,这也意味着存在大量的机会。如果你是程序员,你可以定期花时间去阅读和研究,走在你的同事之前。 · 阅读文章、博客和图书。(阅读本书就是一个好的开始!) · 阅读学术论文。paperswelove是一个非常好的计算机科学学术论文知识库。 · 参加课程。Coursera和Khan学院都提供了许多免费、线上课程,涵盖了各种各样的主题,包括编程和创业。 · 参加演讲、聚会小组或者会议。请访问Meetup网站和Lanyrd网站。 · 阅读代码,特别是开源项目的代码。The Architecture of Open Source Applications提供了许多流行项目代码的指导讲解,包括Berkley DB、Eclipse、Git和nginx。 我已经发现了三种让我的研究时间变得更有效率的方法。第一,设立具体的、可测量的目标。例如,我为2015年设定的目标是阅读30本书(我用Goodreads来记录我的进度)。差不多每两周就要读一本书以上,所以如果两周过去了,还没有读完一本书,我就知道自己落后了。我还有一个目标,就是每年至少学一种主要的新技术,比如一种新的编程语言或数据库,我发现“七周七种”系列图书,比如《七周七语言》《七周七数据库》和《七周七并发模型》,都是实现这一目标很好的方法,因为这些书会向你介绍各种各样的技术,还会重点强调不同的编程范式,比如Ruby中的面向对象编程和Prolog中的声明式编程的对比,或者用MongoDB实现面向文档存储和HBase实现面向列的存储对比。 第二,记笔记。举例来说,我会对读过的每一本书进行总结,并把喜欢的文字保存在Goodreads。我会简单记下一些新的点子、问题,以及在阅读点子日记过程中产生的想法(阅读2.1.3节了解更多信息)。偶尔,我会把这些新想法发表到博客上。但是即便我把这些想法写在纸上立即丢掉,记笔记这样一个动作也可让我的学习成为更加主动的过程,帮助我更好地记住和理解这些新点子。 最后,也就是第三点,是要让你的朋友和同事也一起参与到学习过程中。在LinkedIn,我们成立了一个阅读小组,每几周就阅读一篇新的计算机科学论文,然后聚在一起讨论。在开始使用Scala的时候,我们也成立了一个学习小组,人员就是在Coursera上参加了“用Scala进行函数式编程”课程的那些人。有了别人的推动、可以在一起讨论问题和想法,你就更能坚持做一件事。
  • 最好的学习方法就是教。向别人解释一个话题,你自己就必须更深入地去理解它。每次我准备演讲、准备写博客或者像现在这样,写一本书的时候,我都会去了解比最初掌握的还要多的知识。花时间去分享知识是提升水平的一种最简单也是最有效率的方式。事实上,具有“资深”标记的工程师都是那些使周围的人更加出色的人,要达到这一目的唯一的方法就是教。
  • 我会给所有人的一条建议是,总是要考虑团队以及你可以做什么让周围的人更有效率。
  • 如果可以回到过去,我会告诉自己一件事,我会尝试进入到18岁、还在为成绩而困扰、茫无目标而被动的自己的身体里,告诉他学习编程也许是你今天可以学到的最伟大的技能之一了。编程的核心就是解决问题,毫不夸张地说,它能够在一定程度上改变世界。计算机科学的抽象理论是伟大的,但是超越理论的是几乎无限的理论实践应用领域,赶紧开始吧。
  • 我想告诉自己,即便认为自己已经实现了一些伟大的东西,也仍然要保持求知若渴。因为正是在我最饥渴的时候,才能克服最大的困难,实际学到和贡献出最多的东西。一旦认为自己都知道了,就会变得被动和缺少活力。 好多次去上班的时候,我都在想:“他们今天也许会把我解雇了。他们会发现我并没有那么出色。”如果那天过去了,我做了一些意想不到的漂亮东西,我就会想:“哇,真是个好日子,他们没有炒掉我,我做了这个很棒的东西,还行啊!” 所以,这就是我想告诉自己的。要保持求知若渴,永远不要自我满足。
  • 我真正认清楚的一件事情就是,你不能准备去创业,它是自然而然发生的,跟着它走就是了,然后一路去解决各种问题。读书仍然是很重要的(比如这一本),从经历中学习也很重要。但是最后,你还是得以你的方式去应对遇到的事情。
  • 巴顿将军说过一句非常好的话:“一个可以立即强力执行的计划,好过一个下星期才能出炉的完美计划。”
  • 不要低估创造力的威力。创造力比技术上的知识更加强大。谈论技术的人是很重要的,但你能够理解技术并不一定意味着你可以把它们用好。你可以不断学习技术,但只有当你具有了创造力,你才能够做出东西。创造力是一种需要彰显出来的能力,请练习、练习、再练习。
  • 我给大学时的我的建议是,要充分利用大学的环境,最大程度网罗各种机会,加入计算机俱乐部,参加实习,挑选一些兼职项目,学到课堂上学不到的知识。尽早关注如何建立自己的个人品牌,并在工作之后继续打造好这一品牌。噢,
  • 相信你内心的感觉,快速做出对人的决定。建立团队时,你有时会招聘到某些人,但你就是感觉这个人不合适。请尽快改掉这样的错误做法。短期来看,这样做会有些紧张,但长期来看,你会做得更好,你的生活也会更轻松一些。

Hexo 构建过程中报错 FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed – JavaScript heap out of memory 如何处理?

green and black digital device

最近在处理 Linux 中国的静态站点,在技术选项上,为了方便修改,选择了 Hexo 来建设。

数据从 Discuz 转换到 Markdown 已经处理好了,但在构建过程中遇到了一些问题,会报如下错误

☁  linux [main] ⚡  hexo g
INFO  Validating config
INFO  Start processing
INFO  Files loaded in 2.37 min

<--- Last few GCs --->

[4685:0x118008000]   188193 ms: Scavenge (reduce) 3974.1 (4131.6) -> 3974.1 (4131.6) MB, 1.96 / 0.00 ms  (average mu = 0.143, current mu = 0.117) allocation failure;
[4685:0x118008000]   188198 ms: Scavenge (reduce) 3977.5 (4135.0) -> 3977.5 (4135.0) MB, 1.88 / 0.00 ms  (average mu = 0.143, current mu = 0.117) allocation failure;
[4685:0x118008000]   188202 ms: Scavenge (reduce) 3981.0 (4138.5) -> 3981.0 (4138.5) MB, 1.79 / 0.00 ms  (average mu = 0.143, current mu = 0.117) allocation failure;


<--- JS stacktrace --->

FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory
----- Native stack trace -----

 1: 0x104762660 node::OOMErrorHandler(char const*, v8::OOMDetails const&) [/opt/homebrew/Cellar/node/21.5.0/bin/node]
 2: 0x1048dcc84 v8::Utils::ReportOOMFailure(v8::internal::Isolate*, char const*, v8::OOMDetails const&) [/opt/homebrew/Cellar/node/21.5.0/bin/node]
 3: 0x1048dcc34 v8::internal::V8::FatalProcessOutOfMemory(v8::internal::Isolate*, char const*, v8::OOMDetails const&) [/opt/homebrew/Cellar/node/21.5.0/bin/node]
 4: 0x104a82410 v8::internal::Heap::CallGCPrologueCallbacks(v8::GCType, v8::GCCallbackFlags, v8::internal::GCTracer::Scope::ScopeId) [/opt/homebrew/Cellar/node/21.5.0/bin/node]
 5: 0x104a84e98 v8::internal::Heap::ComputeMutatorUtilization(char const*, double, double) [/opt/homebrew/Cellar/node/21.5.0/bin/node]
 6: 0x104a84b80 v8::internal::Heap::RecomputeLimits(v8::internal::GarbageCollector) [/opt/homebrew/Cellar/node/21.5.0/bin/node]
 7: 0x104a83f08 v8::internal::Heap::PerformGarbageCollection(v8::internal::GarbageCollector, v8::internal::GarbageCollectionReason, char const*) [/opt/homebrew/Cellar/node/21.5.0/bin/node]
 8: 0x104a829a4 v8::internal::Heap::CollectGarbage(v8::internal::AllocationSpace, v8::internal::GarbageCollectionReason, v8::GCCallbackFlags)::$_6::operator()() const [/opt/homebrew/Cellar/node/21.5.0/bin/node]
 9: 0x104a8277c void heap::base::Stack::SetMarkerAndCallbackImpl<v8::internal::Heap::CollectGarbage(v8::internal::AllocationSpace, v8::internal::GarbageCollectionReason, v8::GCCallbackFlags)::$_6>(heap::base::Stack*, void*, void const*) [/opt/homebrew/Cellar/node/21.5.0/bin/node]
10: 0x104680028 PushAllRegistersAndIterateStack [/opt/homebrew/Cellar/node/21.5.0/bin/node]
11: 0x104a8122c v8::internal::Heap::CollectGarbage(v8::internal::AllocationSpace, v8::internal::GarbageCollectionReason, v8::GCCallbackFlags) [/opt/homebrew/Cellar/node/21.5.0/bin/node]
12: 0x104a7977c v8::internal::HeapAllocator::AllocateRawWithLightRetrySlowPath(int, v8::internal::AllocationType, v8::internal::AllocationOrigin, v8::internal::AllocationAlignment) [/opt/homebrew/Cellar/node/21.5.0/bin/node]
13: 0x104a79f20 v8::internal::HeapAllocator::AllocateRawWithRetryOrFailSlowPath(int, v8::internal::AllocationType, v8::internal::AllocationOrigin, v8::internal::AllocationAlignment) [/opt/homebrew/Cellar/node/21.5.0/bin/node]
14: 0x104a61988 v8::internal::Factory::AllocateRaw(int, v8::internal::AllocationType, v8::internal::AllocationAlignment) [/opt/homebrew/Cellar/node/21.5.0/bin/node]
15: 0x104a58874 v8::internal::MaybeHandle<v8::internal::SeqTwoByteString> v8::internal::FactoryBase<v8::internal::Factory>::NewRawStringWithMap<v8::internal::SeqTwoByteString>(int, v8::internal::Tagged<v8::internal::Map>, v8::internal::AllocationType) [/opt/homebrew/Cellar/node/21.5.0/bin/node]
16: 0x104d74a6c v8::internal::Runtime_StringBuilderConcat(int, unsigned long*, v8::internal::Isolate*) [/opt/homebrew/Cellar/node/21.5.0/bin/node]
17: 0x104573954 Builtins_CEntry_Return1_ArgvOnStack_NoBuiltinExit [/opt/homebrew/Cellar/node/21.5.0/bin/node]
18: 0x1045e94c4 Builtins_RegExpReplace [/opt/homebrew/Cellar/node/21.5.0/bin/node]
19: 0x1045625ac Builtins_StringPrototypeReplace [/opt/homebrew/Cellar/node/21.5.0/bin/node]
20: 0x1044e8b84 Builtins_InterpreterEntryTrampoline [/opt/homebrew/Cellar/node/21.5.0/bin/node]
21: 0x1289db514
22: 0x1289dbae4
23: 0x128def07c
24: 0x1289db514
25: 0x128d2de58
26: 0x1289db514
27: 0x1289d9e20
28: 0x1288da1d8
29: 0x128de4df4
30: 0x1288ce2bc
31: 0x1288c99d8
32: 0x1288de57c
33: 0x1288de6d8
34: 0x1288d0654
35: 0x1044e68ac Builtins_JSEntryTrampoline [/opt/homebrew/Cellar/node/21.5.0/bin/node]
36: 0x1044e6594 Builtins_JSEntry [/opt/homebrew/Cellar/node/21.5.0/bin/node]
37: 0x1049fca88 v8::internal::(anonymous namespace)::Invoke(v8::internal::Isolate*, v8::internal::(anonymous namespace)::InvokeParams const&) [/opt/homebrew/Cellar/node/21.5.0/bin/node]
38: 0x1049fc480 v8::internal::Execution::Call(v8::internal::Isolate*, v8::internal::Handle<v8::internal::Object>, v8::internal::Handle<v8::internal::Object>, int, v8::internal::Handle<v8::internal::Object>*) [/opt/homebrew/Cellar/node/21.5.0/bin/node]
39: 0x1048f093c v8::Function::Call(v8::Local<v8::Context>, v8::Local<v8::Value>, int, v8::Local<v8::Value>*) [/opt/homebrew/Cellar/node/21.5.0/bin/node]
40: 0x104681110 node::InternalMakeCallback(node::Environment*, v8::Local<v8::Object>, v8::Local<v8::Object>, v8::Local<v8::Function>, int, v8::Local<v8::Value>*, node::async_context) [/opt/homebrew/Cellar/node/21.5.0/bin/node]
41: 0x104681508 node::MakeCallback(v8::Isolate*, v8::Local<v8::Object>, v8::Local<v8::Function>, int, v8::Local<v8::Value>*, node::async_context) [/opt/homebrew/Cellar/node/21.5.0/bin/node]
42: 0x1047001fc node::Environment::CheckImmediate(uv_check_s*) [/opt/homebrew/Cellar/node/21.5.0/bin/node]
43: 0x107d57ec8 uv__run_check [/opt/homebrew/Cellar/libuv/1.47.0/lib/libuv.1.dylib]
44: 0x107d52cc4 uv_run [/opt/homebrew/Cellar/libuv/1.47.0/lib/libuv.1.dylib]
45: 0x1046819dc node::SpinEventLoopInternal(node::Environment*) [/opt/homebrew/Cellar/node/21.5.0/bin/node]
46: 0x1047a9ad4 node::NodeMainInstance::Run(node::ExitCode*, node::Environment*) [/opt/homebrew/Cellar/node/21.5.0/bin/node]
47: 0x1047a983c node::NodeMainInstance::Run() [/opt/homebrew/Cellar/node/21.5.0/bin/node]
48: 0x104722e80 node::Start(int, char**) [/opt/homebrew/Cellar/node/21.5.0/bin/node]
49: 0x187fb10e0 start [/usr/lib/dyld]
[1]    4685 abort      hexo g
Code language: HTML, XML (xml)

这个报错中,最有价值的便是 FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed – JavaScript heap out of memory

这个报错的意思是目前 JavaScript 使用的内存已经超出了可用范围,导致程序挂掉,而如果想要解决这个问题,只需要分配更多的内存给 Hexo 即可。

只需要在构建的命令前加入NODE_OPTIONS=--max-old-space-size=24576,就可以分配更多的内存给 Node.js 。这里的 24576 是 24GB 内存的含义,你可以根据你的需要来选择。

PS. Linux 中国的数据太多,以至于我用 Hexo 分配了 24GB 都不行。。我决定换 Hugo 了。。希望 Hugo 可以。。。