selective focus silhouette photography of man playing red-lighted DJ terminal

我喜欢的歌手

最近突然想起来,应该把我喜欢的歌手 Share 给大家,互相交换一下自己喜欢的歌手、歌曲,让那些好听的歌曲广为流传。

周杰伦

不用多解释,我们那个年龄段的人都喜欢。

赵英俊

赵英俊的歌我一致都很喜欢,他的歌曲风格独特又深入人心。

我喜欢的歌包括:

  • 《送你一朵小红花》
  • 《世界上不存在的歌》
  • 《悟空传》
  • 《万万》
  • 《不许离开我》
  • 《唐人街》
  • …几乎他的所有歌我都很喜欢

他的歌很多时候唱出了小人物的无奈,像我这样的小人物,难免会有一些「他唱出了我的感觉」,所以很习惯。

再加上他的编曲也都不错,人也很有才,所以很喜欢听他的歌。

可惜天妒英才,英年早逝。

汪苏泷

汪苏泷的情歌很多,也很值得听。

海来阿木

海来阿木坦白来讲,之前我不是特别的熟悉,因为的确小众。不过听了以后,他的声音还挺有个性的,自带嘶哑的特效,唱起来情歌,自带的撕裂感。

我喜欢的歌包括:

  • 《不过人间》
  • 《你的万水千山》
  • 《别知己》
  • 《三生三幸》
  • 《阿果吉曲》
  • 《西楼儿女》

海来阿木算是宝藏歌手了,比较小众,但歌的确很好听。独特的声线值得一听。

李宗盛

我目前已经到了能听懂李宗盛的年纪了。所以,也推荐给大家。

此外,李宗盛之前和 New Balance 拍的一系列广告片也不错,感兴趣的可以找来看看。

ea3765a81c7a26a7864efdcf7c81ef7b

为什么说投资是认知的变现?

过去一直听孟岩讲「投资是认知的变现」,没什么感觉,最近投资拼多多属实让我自己感受到了「投资是认知的变现」这句话。

投资的核心动作是低买高卖

在股票市场中,所有的盈利来源都可以归结为「低买高卖」,你在低价时购买了股票、基金,并在高价时卖出基金,获得其中的差价。

一种策略是简单的「追涨杀跌」,如果发现一个股票/基金开始出现涨势,就开始买入,并在买入后不久,进行售出。这种行为并非完全不可行,在高频交易和量化交易的过程中,基本上便是基于这样的逻辑进行,并通过机器逻辑来提升交易的频度和粒度,获取高额收益。

另一种策略便是我们所说的「投资」,找到你觉得价值和价格不匹配的股票,以低于市价的标准买入,并以高于市价的标准卖出,获得其中的价差。绝大多数的投资便是如此。

如今有了各种股票基金 App,投资动作变得越来越简单,你不再需要前往股票交易所现场购买,远程在家中,甚至坐在马桶上,都可以完成一次交易,「认知」体现在何处?

认知便是你知道这支股票的价值是多少。当你知道一个股票的价值,你便敢于在市场情绪崩溃的时刻激情买入;当你知道一个股票的价值,你便敢于在市场热捧之时,激情抛售。

我的收益不过是运气

我买入拼多多时,正值中美关系冰冻,拼多多股票跌至 70 美元。所以我买入了 20 股,把当时海外的空闲现金全部投入。后续随着中美关系解冻、拼多多的海外版 Temu 业绩不错,拼多多股票一直涨,直到最近的 145 美元。

从 70 买入开始,一直到 110 美元开始,我开始纪律性的卖出,110 美元卖一部分;120 美元卖出一部分;130 美元卖出一部分;目前手头还剩不多,定下的售出价格是 150 美元。虽然尚未达到 150 美元,但已经收回本,剩下的部分其实都是赚的。

在此刻,我深刻的感知到「投资是认知的变现」。我不知道拼多多的价值是多少,所以我会在 110 卖出、120 卖出、130 卖出。如果我始终没卖,可能到了 150 美元卖出,不仅仅是收回本,而是翻倍的收益。

但另一个层面,上面的这些不过是马后炮,拼多多完全有可能从 110 美元跌回 70 美元,甚至跌回 40 美元,这一切都是有可能的。我的认知并不能告诉我拼多多的价值到底是多少,只不过是纪律性的交易让我可以赚钱,本质上是幸运,而不是能力。

一如当下纠结的我,到底该不该卖拼多多?现在是否是已经超过了拼多多的股票价值?我是否应该继续持有还是卖出?我不知道。或许止盈是一个好的选择,既然认知不到位,就应该接受自己认知不到位带来的结果。也像我年初 200+ 卖掉的 NVDA,我的认知没办法想象到 NVDA 可以卖到 400+ ,所以自然无法享受到其从 200+ 涨到 400 + 的收益。

投资不过是认知的变现。

woman eating sandwich

从童年找答案

熟悉我的人知道,我是一个胖子,不折不扣的胖子。身高 180 ,体重 110 Kg。我也试图减肥,但一直以来,并没有养成良好的饮食习惯,导致体重一直没有减下来。我也在想,到底是什么让我始终瘦不下来?

答案当然是:迈不开腿、管不住嘴。可真的这么简单嘛?

为什么迈不开腿?

因为内心有恐惧:

  1. 恐惧自己的体能不足,所以到健身房去根本做不了几个动作。
  2. 工具自己的能力不足,到健身房会被嘲笑。

但这些真的是问题么?或许是的,毕竟我还算的上是一个骄傲的人。但同时,这些想法也限制了我的发展和身体健康。

也许是因为在我看来,总有比健身更重要的事情,身体可以往后放一放。但,真的还能往后放一放么?

为什么管不住嘴?

相比于迈不开腿, 管不住嘴显然是让我持续胖下去更加重要的原因。但,为什么?为什么管不住嘴?为什么习惯性的吃多?

当我无意识的时候,我自然会继续吃多。但真的去思考为什么吃多的时候,我赫然发现,这问题原来是从童年带回来的回忆。

打小吃的就多

从小时后开始,我吃的就比较多。所以一直以来,给家里人养成的印象也是我比较能吃。从而形成恶性循环。

家里人觉得我能多吃 — 给我安排更多吃的 — 激励家里人给我安排更多吃的 — 进一步多吃。

这种恶性循环使得我被要求吃的更多,而我为了让家里人更开心,所以也在不断的吃的更,久而久之,固化了我吃的多的风格。

但,这解释不了如今我已经离开了家乡,已经开始自己做饭吃饭,为什么还是吃这么多?

内心深处对于物资匮乏的恐惧

我家里并不算富裕,甚至从小我的外食之类的都是很少的。大部分时候我都是在家吃的,对于外面的好吃的其实并没有太多的机会去吃。

这样使我养成了一个坏习惯 — 每当有的机会去吃的时候,就会多吃。因为不知道自己什么时候还能再吃到。这个坏习惯也加重了家里人对于我「吃的多」的刻板印象。

而且,这件事也影响我在其他方面的习惯。举个例子来说,如果我住高档酒店,没有用完的洗漱用品一定会带走。一方面是我觉得不带走浪费。另一方面,的确这些高档酒店的洗漱用品我拿回家依然可以用。

虽然我的收入可能完全可以支付的起一块肥皂的钱,但习惯趋势我还是会把酒店的香皂带回家日常使用。我真的缺这块肥皂钱么?显然不是的。

想要改变,需要从心改变

我其实在朋友的减肥的服务中学了不少,包括理论也都看了,也都学了,但还是减不下来。真的是服务不行么?不是的。

从技能上,我已经掌握了先吃青菜蛋白质,再吃碳水;控制自己摄入食物的比重和顺序。但,习惯性的多吃,让我即使是已经在先吃碳水的情况下,依然大量的摄入了食物。

想要改变这些问题,需要解决我自己的心病、心理问题,最终才能得到解脱。

person holding sticky note

FastAPI 在使用 pytest 加载不同的配置文件,以实现测试环境单独运行某些配置项目

引言

Fast API 作为一个新兴的 Python Web 框架,不少的开发者都在使用 FastAPI 来开发应用。我最近也在试着使用它。

在开发应用时,我习惯使用 TDD 的方式进行开发,特别是开发飞书机器人时,由于飞书给我提供的请求是可预测的,特别适合以 TDD 的方式来定义行为并实现。

同时,我在使用其他语言开发的时候,也会用到使用 .env.env.testing 这样的配置文件来在不同的环境下加载不同的配置文件,达到在不同环境使用不同的变量来完成任务。

内容大纲

  1. 实现读取 .env 文件
  2. 实现在测试环境读取 .env.testing 文件

模块详细内容

实现读取 .env 文件

想要实现在 FastAPI 中读取 .env 文件,首先,你需要引入 pydantic_settings 包,来完成基本的配置文件的读取。

from pydantic_settings import BaseSettings

class Settings(BaseSettings):
    app_name: str = "Awesome API"

settings = Settings()
print(settings.app_name)

接下来你可以为这个 Settings 类新增 Config 配置,以实现读取本地的 .env 文件

from pydantic_settings import BaseSettings

class Settings(BaseSettings):
    app_name: str = "Awesome API"

    class Config:
        env_file = ".env"

settings = Settings()
print(settings.app_name)

通过上述代码,你的配置项目就会自动读取 .env 文件来加载环境变量,从而实现更加简单的环境变量管理。

实现在测试环境读取 .env.testing 文件

在测试时,为了避免使用线上的数据,你可以在测试时加载不同的环境变量文件。

如果你只有一个测试环境,可以有一个非常简单的方式来实现:在配置 env file 时,传入一个元组,会自动加载多个文件。

from pydantic_settings import BaseSettings

class Settings(BaseSettings):
    app_name: str = "Awesome API"

    class Config:
        env_file = (".env",".env.testing")

settings = Settings()
print(settings.app_name)

需要注意,这里实现的实际上是使用 pydantic-settings 自己的加载顺序来实现。默认情况下,靠后的文件优先级会更高(覆盖了前面的内容)。这样的好处是如果你有些配置测试环生产是一样的,可以在 .env.testing 中加入不同的部分,相同的部分直接复用生产环境的配置项目即可。

但由于使用的是顺序加载多个问题,如果你发现表现和你配置的不一致时,就要看看是不是有优先级更高的环境变量文件覆盖了默认的 .env 文件。

结论

借助 pydantic-settings 的一些配置,你可以快速实现 .env.env.testing 的加载,相比与判断环境变量,这样会比较简单,且可以实现在 .env.testing 中只维护变量,和线上保持一致的部分可以直接继承。


附加部分

black flat screen computer monitor

JSON to Pydantic

使用 FastAPI 后,你需要写完整的请求体和返回体,以便于生成 API 文档,对于完全从 0 开始构建的项目来说,是不难的,但如果你需要做的是一个项目的迁移,那么写这些类型定义可能需要耗费你大量的时间。

不过,JSON to Pydantic 可以帮助你解决这些问题:

d2b5ca33bd970f64a6301fa75ae2eb22 6

这个网站支持使用一个 JSON 作为 Input,并生成对应的 Pydantic 的代码,对于一些老旧项目迁移的工作来说,可以说是节省了大量的时间。

Go All In signage in middle of camera and banknotes

大力出奇迹,但不是 All in

不少人对于大力出奇迹有一个错误的认知 —— 认为大力出奇迹便是 ALL In。但其实并不是,大力出奇迹更像共产主义的一个特色 —— 集中力量办大事

实际上,我并不鼓励任何形式的 ALL IN,如果你开始思考要不要 ALL IN 的时候,说明你的路子大概率已经走错了。正确的事情需要投入去做,但不需要 ALL In 的去做。

ALL In 是指你将所有事情都押宝在一件事上,这意味着你不成功便成仁。但当你走到这一步的时候,可能你已经没得选了,大概率面临的是失败,不然为何成功成了千古佳话。

大力出奇迹则是对看重的事情大力投入,而不是停留在推演、思考,主动投入资源去推进一件事的落成,才能帮助你把想要达成的目标给达成。

这两者是不同的,可别乱用。

d2b5ca33bd970f64a6301fa75ae2eb22

小公司大多死在优先级不清晰

引言

最近在和朋友在做一些项目的时候,很深刻的感受到了创业公司的一些问题。而其中让我印象最为深刻的是 —— 优先级分不清。

这也引发了我的思考,大公司为什么能成为大公司?小公司为什么总是小公司?是不是有什么是小公司一直没做好的?

思考后我的答案是:小公司往往死于优先级不清晰

作为一个小公司来说,资源不多是正常的,但不是致命的,有多少钱就办多少事就好。但如果你没有钱,却选择做一个不适合自己的事情,或不把有限的资源投放在最重要的事情上,可能最终一定会面临一事无成,最终无法达成自己的预期。

背景信息

我们当时的目标是开发一个项目。一个项目中存在主流程和辅流程。我的观点是优先关注项目的主流程,而不是辅流程。而朋友则会关注一些偏表面的体验、颜色、或一些直线流程的产品功能。这里我们存在了优先级的冲突。当然,最终还是按照我的优先级来做事。

我的观点

在绝大多数的时候,大公司是那个资源更加充沛的角色,这使得大公司可以拥有更多的资源、更多的试错可能机会。对于大公司来说,一个方向的试错,并不会导致大公司彻底死亡。同时,大公司的各种流程的积累,可以帮助大公司尽可能的做出最正确的决策(虽然这个「最」其实是在企业内的最,未必是产品的最)。

但对于小公司来说,由于资源的有限,可能一次失败面临的就是全盘皆输。因此,对于小公司来说,优先级的决策就变得弥足珍贵。对于小公司来说,如果领导者是一个聪明、经验丰富的人,还可以很好的评估项目和工作的优先级,带领大家穿越周期,最终取得预期的结果。但如果领导者不够聪明,或者精力不在做决策上,则大概率走向不好的结果。

分析和评论

不过,这个事情上来讲,也有一点悖论。对于小公司来说,决策会更加重要,但对于小公司来说,招募到一个可用之材也是更困难的事情 —— 因为人才会选择去一些胜率更高的大公司从业,获取更加明确的收益。小公司得到的人才可能往往不是那么的优秀,使的小公司的决策行为更加雪上加霜。

对于小公司来说,需要用更高的赔率去招募合适的人才,才能招到真正优秀的人来一起做事。

结论

大公司因为有标准的流程,即使决策者水平不高,依然可以借助流程提升决策的水平。但对于小公司来说,如果决策者水平不高,大概率会死在路上。好的决策,影响一切企业。


作为一个个人,如果你刚刚走进社会,有机会进入到大公司去感受到大公司的决策流程,那对于你整个从业经验来说都是会有很大帮助的。但如果你没有办法进入到大公司,那么一定要仔细遴选小公司,特别是与小公司的领导者沟通,了解小公司的人领导者是什么样的人,确认小公司的领导者是否是你认可的人。避免浪费自己的时间。

创业公司/小公司可能是每个人必经的道路。但是,我希望你能在这个路上少踩一些坑,走的更稳。

grayscale photo of concrete houses

我们是不是在三战的前奏?

一战的导火索是萨拉热窝事件,斐迪南大公夫妇被枪杀,引发了奥匈帝国向塞尔维亚宣战,成为了第一次世界大战的导火索。

二战的导火索则是德国入侵波兰,引发世界大战。而二战前局部也发生了意大利入侵埃塞俄比亚、西班牙内战、日本侵华战争。

如今,我们面临着俄乌冲突、巴以冲突,感觉仿佛三战的前奏。印巴边境也开火了。

希望我的猜测是错误的。

APILetter

聊聊 APILetter 的新计划

APILetter 从创刊号,到 S1E6,经历了一年的时间。

虽然在定更新节奏时,我就考虑到自己拖更的可能性,但确实没想到我拖更这么严重,在 2022 年,一口气更新了 3 篇,然后就是长达半年的拖更。不过,总算是把第六篇写完,算是给 Season 1 做个了结。

过去

APILetter 的出现,是源自我在研究 RESTFul 架构时发现的问题:国内有太多解释什么是 RESTFul 规范的文章,但你点进去看,篇篇都是复制粘贴。

而 API 是开发者生态中非常重要的一环,它不应该被草率的对待,开发者们值得用上更好的 API。既然没有人写关于 API 的严肃内容,那就从我开始吧。刚好我在研究相关的内容,那就写一些 API 到底应该是什么样的。

也正是抱着这个想法,我开始了一篇篇的创作,从 为什么是 RESTful API,到如何设计一个符合 RESTFul 风格规范的批量操作 OpenAPI;有务实的内容,也有务虚的内容。但不变的是希望让大家明白如何设计一个更好的面向开发者的 API。

但,Season 1 的内容也是杂乱无章的,聊过 RESTFul、聊过 API 文档、聊过 API 指标、聊过 API 报错,这样杂乱且没有主线的内容,作为博客来说,还算可以接受,但作为 Newsletter,可能就显得过于随意。因此,在 Season 2 开始,内容也会开始面向主题,我也会更早的设计不同的 Season 要讨论的话题,以便于让你可以有更好的阅读体验。

未来

在写第一篇邮件通讯时,我就注册了域名 APILetter.com,因为我知道这件事我应该会做很久,所以搞一个独立的站点是必然的事情,也是符合我习惯的事情 —— 每搞一个事情,就要给它一个独立的品牌。

而在刚开始写第一封邮件时,我是没有勇气使用独立的站点的,我总担心自己写完第一封就写不下去了。那搞一个独立的站点不过是浪费时间。所以我选择从竹白开始我的写作之旅。一年过去了,获得了还算不错的效果(至少比我想象中的要好一些)。

image
迁移到 Ghost 之前的数据

不论过程是否艰辛,总归我是完成了自己对自己的承诺,至少写完了一个 Season 的内容。

而 APILetter 完成了第一阶段的产出后,下一个阶段,我希望用更加品牌化的方式来运行这个项目,便启用了 APILetter.com 的域名),并搭建了 Ghost 来托管这个项目。

换到 Ghost,除了域名独立、程序独立、数据独立,相应的,自然也有一些好处 —— 比如可以 RSS 订阅了。如果你希望通过 RSS 的方式来订阅 APIletter, 也可以直接访问 https://www.apiletter.com/rss/ 来订阅。

Season 2:指标

在 Season 1 中,我花费了不少的篇幅来讲 OpenAPI 的设计问题。在 Season 2 ,我想专注于 OpenAPI、开发者体验中的指标问题,从企业和个人制定目标开始,到具体到某一个具体的 OpenAPI 指标评定。

目前预计会包含的内容:API 自身的指标定义、API 相关业务的指标定义、开发者体验中的一些指标定义。

除了这些指标,你还关注哪些指标?欢迎回复邮件告诉我。

总结

总之,APILetter 在新的一季里,我会尽量以更好的内容组织方式、更高的频率(但暂时承诺还是每月一封哈),来给大家分享我自己关于 API、关于开发者体验,以及一切与开发者有关的内容,希望可以帮到你。

如果你身边有对于开发者关系感兴趣或从事相关内容的朋友,欢迎你将 APILetter 介绍给他,帮助我获得更多的读者,以及,持续的写下去🥰。

APILetter

为什么 OpenAPI 的设计如此重要?

在 APILetter 的 S1E6,我想和你聊聊 OpenAPI 设计的重要性。

在整个 S1 的文章中,我用了接近 4 篇的篇幅来介绍 OpenAPI 的设计,从一开始介绍为什么要使用 RESTFul ,到 API 的错误码设计理念,辅以批量接口设计的实例,再加上最后这篇重要性的强调,三分之二的比重,意在让你深刻认识到,OpenAPI 的设计至关重要。

为什么 OpenAPI 的设计如此重要?

在企业内部工作时,常常需要找到平衡质量和速度之间的折衷方案。当项目时间非常紧迫时,往往会牺牲一些质量。但如果项目有足够的时间,就有更高的概率能够设计出一个质量更好、开发者体验更佳的 OpenAPI。

然而,OpenAPI 是一项非常重要的任务,不能马马虎虎。一个坏的设计会让团队持续在 OpenAPI 开发上投入更多的精力。

沟通难度高带来的维护成本增高问题

和企业团队内部使用的 API 不同,OpenAPI 的用户是内部团队,用户的差异决定了沟通的难度的。

在内部API中,若需要对某个API进行不兼容变更,我们可以通过比较简单的沟通完成变更的通知,并通过企业内部的优先级对齐方式来明确变更的时间和行为。

但对于OpenAPI的用户来说,不兼容的变更意味着需要通知所有的外部开发者,并确保他们完成相应的更新。然而,这个时间节点和周期并不容易控制,跨企业的优先级对齐、时间节点对齐、以及出现问题时的技术支持,都可能会导致OpenAPI变更周期变得非常长,让维护人员感到疲惫不堪。

以平稳迁移为例,通常需要1-2年的时间才能下线OpenAPI。如果没有平缓过渡,那基本上就无法下线API了。

无法下线的 OpenAPI 最终将会指向不断增加的维护成本。毕竟,即使我们可以不在旧版的 OpenAPI 中去提供新的 Feature ,但依然要针对旧版本的 OpenAPI 提供安全更新,这会导致团队的研发成本越来越高。

风格/设计不统一带来的开发者评价问题

OpenAPI并不一定非要选择 RESTFul 风格,但一定要统一设计风格。

好的设计风格一方面是开发者对于美和好的追求,另一方面也会是开发者对于你的能力和团队水平的评估纬度。开发者可以通过对于接口风格、文档质量等多个角度的评估来评价你的产品的质量和结果。

虽然开发者并非企业的绝对决策者,但对于那些高度依赖开放性和集成性的业务而言,开发者的评价尤为重要。出色的开发者评价,将会使企业在进行集成相关的决策时,更加放心地进行选择。

当然,风格/设计不统一带来的也不仅仅是开发者评价问题,还涉及到更多的维护成本问题:

  • 因为风格不统一,导致开发者对于不同的接口没有一个明确的范式,需要理解成本带来的学习成本高的问题。
  • 因为风格不统一,导致开发者需要针对不同的接口做不同的适配层,重复建设。

美与好不是一个 OpenAPI 在发布时必须要追求的,但又是你大规模获客时一个重要的对比项目。所以,在 OpenAPI 的设计早期,定义接口设计规范是一个值得投入时间和精力去思考的事情。

如果我的设计已经不好了,又该如何处理?

绝大多数人没有机会从头设计一个全新的 OpenAPI 系统,大多是需要一边跑一边换轮子的。

在这种情况下,可以考虑为你的 OpenAPI 设计一个明确的下线策略,以及,做好你需要花费一年的时间来做好这件事的准备。先定下统一的 OpenAPI 规范,并通过大版本迭代的方式,将旧版中的设计不好的 OpenAPI 重新梳理、设计、整合,并开放出新版的 OpenAPI 出去。

再将存量中设计不好的 OpenAPI 标记为 deprecated,引导增量开发者升级使用新版的 API,卡住存量的 API 的新增使用用户。

随后,只需要不断在新版的 API 中提供新的 Feature,使用自然的产品策略方式诱导开发者来升级,从而实现存量 API 的自然退役即可。

总结

和企业内部使用的 API 不同,OpenAPI 的开放属性决定了 OpenAPI 是很难退役的,因此,从一开始就朝着最好的方式来演进,可能才是最正确的做法。快速迭代,快速试错的路子,并不适合 OpenAPI 的产品形态。