2025-04-13 11:15:26
这些内容在 4月2日就写好了,原计划进入新工作后一周再发出来。这是我自己对这件事情的总结。
前段时间有一个同事(老员工,被重用那种,不然也不会摆那么大的谱),在群里发表了针对我的不友善言论,让我感觉有点生气,他说的话类似于 “你写的代码很垃圾”、“以后不要再让我 review 你的代码”、“这种代码谁爱合谁合,反正我不合” 之类,与其说是在表达对我代码的不满意,更像是在撒泼式的宣泄自己内心对生活的不如意,随便找个借口找个场合发泄。
这件事情本身的前因后果我都没有动力去讨论,因为很明显不是行为规范的问题,而仅仅只是他个人的情绪问题。我对造成这件事情的深层原因,总结为团队内部的管理混乱、每个人职责不分明。但原因是什么不重要,我会用实际行动来表达对这种工作环境的不满意。
在这件事情的过程中,我感受到的是一种不尊重,也因此写了《从团队内部的混乱想到……》和《关于 Code Review 的礼节》来委婉的提及一些当时的情况。
“尊重” 重要吗?我的出身并不好,谈不上什么尊重,更没有资格要求别人尊重我什么的,毕竟别人对你怎么样,是别人的事情,我又怎么能左右呢,说到底还是我自己的能力不够强大,强大到让别人主动尊重我。那么抛开原生家庭和个人教养的问题,对于我来说,在这件事情上,“尊重” 重要吗?
很简单,如果我能找到工作,那么就很重要,这件事情已经是一个非常充足的让我换工作的理由。如果我找不到工作,那就不重要,在生存和挣钱面前,受这么点气算什么呢,我要是一旦离开这个项目就再也找不到工作了,那我也就这么点水平,受气也是活该,忍着呗,还能怎么着。
我是毫无理由去忍受这种来自同事的情绪的,所以我现在确实已经离职、并且开始新的工作了。这件情绪上的事情算是一个契机,让我有足够动力开始改好简历、进行找工作这件事情,不然可能不会这么早主动换工作,会稍微晚一点,等等看项目进一步的情况。但是因为这件事情,我就不想等了。
对于换工作的原因,除了这件情绪上的事情作为契机外,也有一些项目整体的因素在里面,总体来说,为什么现在到了一个需要换工作的时候?
从项目整体看,项目现在在往 AI 方向发展,全面转型到 AI,几乎放弃了区块链方面的叙事,老板从外部邀请了整个 AI 团队做事情,后续在区块链方面不需要有什么功能上的迭代。我也有听到说,老板提到过精简团队的事情,需要用到人再招,也确实精简掉一个人。虽然没有精简掉我,但这显然是一个不好的信号。
从内部管理看,团队内部的管理比较混乱,人员之间的协作很糟糕,工作协调起来比较困难,尤其是作息时间上的差异,偶尔会引起一些问题。人员素质层次不齐,虽然现在人数逐渐减少、没几个人了。整体工作氛围让人不是很舒服。
在工作内容上,最近一段时间开始,逐渐进入了没事找事的状态,没有什么紧急的需求需要做,尤其最近做的大都是一些不重要的事情,做也行不做也没差,纯粹只是为了工作而工作,让每个人显得在工作。一般来说工作进入到这种状态,也是一种非常不好的的信号。
从内部团队的前景看,整个团队能不能做成事情,几乎依赖于 Leader 的个人判断,能做什么事情、需要做什么事情、交付结果的上限是什么,都取决于 Leader 的个人能力,这对团队来说不是好事。曾经就出现过 Leader 一人判断失误,导致整个团队的努力都白费的情况。当然 Leader 本人的学习速度和改进自己的速度非常快,在意识到失误后能够在短时间内频繁做出调整,整体上是在往好的方向发展的,这一点上我还是佩服的。如果不是 Leader 有这种迅速调整的能力,我换工作可能比现在还得提前几个月。
总的来说,从各方面角度看,都有一些让自己换工作的理由,所以总结起来,目前到了一个需要换工作的时候。
(注意,换工作的原因里完全不包括我自己对项目和赛道的评价和看法。我在入职 3 天的情况下头脑里就对这个项目产生过怀疑,具体细节在《Restaking 项目的经济难题》,时至今日我作为项目内部的开发人员,都没有找到这个问题的答案。但我想说的是,这些丝毫不影响我愿意在这个项目上继续工作,并且希望能把项目做好。事实上,我们比外部的人更希望项目能越来越好,因为我们本身就是利益相关者。所以,我想再次强调,换工作和项目本身的好坏无关,只是工作氛围的问题)
2025-04-12 20:33:38
有点标题党,不要太介意。我想表达的是不应该过于关注使用的工具。很简单的逻辑,只有自己工程能力不如 Cursor,才会觉得 Cursor 厉害,干什么都行。当然这句话属于比较空的废话。
事实上,Cursor 的代码补全能力没有比 GitHub Copilot 好多少,底层使用的模型是一样的,不是 Claude 就是GPT。而在工程化调教方面,Cursor 和 Copilot 都是在把一些文件作为 context,继续后面的对话。
Cursor 比 Copilot 好一点的地方在于,会自己去当前工程目录下,搜索和参考其他文件的写法,这一点确实有用,你不需要告诉他具体引用那哪些文件,他自己会不断的尝试,Copilot 这种插件是不具备这种能力的,这确实是好的一面,如果项目下存在大量可复用的代码,Cursor 可以比较好的发挥出它的能力。
但有时候又会觉得 Cursor 过度智能,它甚至会自己在你的工程下面创建新文件,而不需要经过你同意,这就导致在用 Cursor 的时候需要时刻关注,他是否改变了你预期之外的代码文件。相比之下,(GoLand 下的)Copilot 只是插件的形式,只会给出代码片段,用不用是你自己的事情。VS Code 下的 Copilot 现在和 Cursor 倒是有类似的体验了,会给你一个接受或不接受更改的选项。
所以相比来说, Cursor 和 Copilot 使用了一样的大语言模型(不会有人觉得 Cursor 自己训练了个模型出来吧),然后 Cursor 拥有更大的、项目级别的控制力,而 Copilot 像他的名字一样,只是辅助级别的能力,这是它们最大的区别。
回到模型本身,o1 是迄今为止最厉害的模型,在日常工作中深有体会,我经常用 o1 来精准定位编程中遇到的 bug,而对于相同的问题,其他模型往往给出错误或者不准确的解释,包括 o3-mini-high 和 4o。
比如,在调用智能合约的时候,原本的命令是
cast call requestPrice(string) "BTC" —-rpc-url=http://eth:8545
现在需要调用另一个函数,比原本的函数多了一个入参,我就直接复制代码写成
cast call requestPrice(string) "BTC" "USD" —-rpc-url=http://eth:8545
不知道你有没有第一时间看出问题?其实 4o 倒是给出了正确的分析,只是没有特别精准,给出了 3 种有可能的错误原因,而 o1 直接就说对了。
当然大模型之间的差异不会体现在这么微小的问题上,只是正好有印象就随便提一下,我想表达的是,从日常体验来看,o1 是最好用的模型。
我严重怀疑鼓吹 Cursor 的人,都是之前没有使用过 AI、体会过 AI 强大能力的人,在用到 Cursor 之后,才明白原来现在的生成式 AI 已经这么强大了,欣喜若狂。而当需要使用生成式 AI 的时候,他们的第一反应不是打开 ChatGPT 的聊天框或者 Gotk3 的界面,而是打开了 Cursor 的代码框,开始去聊天。
所以鼓吹 Cursor 的人,实际上是把生成式 AI 的能力,误以为是 Cursor 的能力,才因此觉得 Cursor 异常强大。
我在工作中就不止一次被强烈推荐使用 Cursor ,让我别再用 GoLand,还说出 “GoLand 就是垃圾” 这种话,Cursor 最好用什么的。
首先我一直觉得喜欢用什么编辑器是个人的选择,管这个干啥。其次如果觉得使用什么编辑器会给使用者带来鄙视链和优越感,未免有点小儿科。最后就是我喜欢用 GoLand 的理由,只有两点:1.箭头非常直观的表达了接口的实现关系。2.前进后退快捷键很好用。基于这两点,我才可以比较快速的读懂和理解代码。
也因此带来一个差异是,使用 GoLand 的人,往往更加关注代码逻辑,比如在寻找代码位置的时候,喜欢通过代码之间的跳转,例如接口的实现关系等。而使用 Cursor(VS Code)的人,更加关注项目的目录结构、文件名、文件的位置,因为 Cursor 没有提供很好的代码跳转功能,所以不得不更加依赖通过项目结构来梳理代码功能。
代码的自动补全方面,GoLand+Copilot 插件能应付日常场景,需要补全的往往是打日志之类的内容,简单用用就可以,我不太敢用 AI 写侧重逻辑的代码。
给我推荐使用 Cursor 可能还有一种心理就是,觉得我不知道怎么使用 AI,或者觉得我不知道怎么使用 Cursor (?),也挺奇怪的。我在 2023 年(ChatGPT 开始大火的那段时间)就试用了 ChatGPT,还写了《不要小瞧 ChatGPT》,而现在不论是日常工作还是生活,都在高频率使用 ChatGPT。
总的来说,我的意思是,你可以喜欢 Cursor,也可以使用 Cursor,但最好不要鼓吹 Cursor。
2025-04-11 21:28:11
根据以往找工作的经历看,一般至少面试 20 次左右才会找到合适的工作,所以不用着急也没办法着急。
面试有两种情况,一种是先看过你的简历,然后约你面试,面试的过程中都不怎么 “考核” 你,就是在聊天。还有一种是流水线式的面试,面试官往往在面试开始后,才会第一次看你的简历,而且会问你各种各样具体的问题。前一种情况希望比较大,后一种情况则大多数成不了,不太靠谱。
不知道对方是什么公司,面试了十来分钟吧,说不匹配对方的职位。对方的项目是在基于 Cosmos SDK 搞一条新的链,这条链要集成 EVM,并且做一些性能上优化,因为 Evmos 在性能上存在瓶颈,听起来像是要和 Evmos 做竞争。EVM 之外还在尝试做一些 ZK Layer 2 方向上的探索。然后说我因为缺少这方面的经验,就不匹配了。
对方不愿意透漏自己是哪家交易所,钱包产品类似于币安内置的 web3 钱包,也就是自己管理自己资产那种,而不是托管钱包,所以技术上没怎么问有深度的内容,问了一些比较浅显的问题,也可能开发钱包的都是这种类型的知识面吧。
很经典的剧情,传统公司试图做联盟链并且向 web3 靠拢。
比较常规的面试,实际上需要 web2 相关的技能,关注 Go 语言、数据库的使用、数据库的迁移等。
对方在招聘的职位主要是想做 Solona 节点的 RPC 性能优化,因为目前 Solona 的 RPC 查询有 1 秒左右的延迟,一方面想在代码层面做提升,另一方面兼顾节点的运维,保证节点的高可用。
HR 面的时候才知道这家交易所是 coinstone。和面试官感觉聊的不错,然后 HR 说需要再等一段时间,还在面试其他人。
不过说实话我觉得面试官技术能力不太好,如果让这样的人当我的上级,我感觉不一定会开心,所以即使真的给我发 offer 了,我都可能得纠结一下,要是没 offer 就算了。
不找了……
2025-03-25 21:45:43
前情提要,推荐王垠的两篇博客文章:
由于过往不规范的工作经历,我之前是缺少对 Code Review 的理解的。最近因为同事对这个问题情绪化的表达,我开始关注到关于 Code Review 的问题。
谷歌公开出来的 Code Review 规范 《The Standard of Code Review》已经非常具有指导意义,内容很全面,包括我现在实际遇到的流程问题,也完全可以依照这个规范来消化解决。当然前提是所有团队成员事先对这个规范的内容已经达成一致,而不是假设公司的员工已经知道并且开始遵循这个规范。
关于规范(TSCR)中已经提到的流程问题、礼貌问题,这里是不需要赘述的。我关注到的是其中一个小章节《Label comment severity》,也就是对 Code Review 之后的 comment 进行重要程度的区分,并且加上前缀,让 author 可以明确知道哪些留言是必须要改的,哪些是无关紧要的。
除去必须要改的 comment 不加前缀,谷歌的规范中提到有三类前缀,这些都是指站在 Reviewer 的立场,如何去写 comment,本质上这三类前缀都不影响代码的 approve 和合并:
Nit
(Nitpick): 你应该改,但是不改我也能接受。Optional
:只是建议,你自由选择改还是不改。FYI
(For Your Information):这个 PR 中完全不需要因此有改动,但我觉得这是一个有意思的点,后续你可以关注下。其中第三个前缀 FYI,每当看到 For Your Information 这个短语的时候,我总是下意识的会把这个短语翻译为中国传统社会普遍流行的一句古话: “为了你好”。
相信在中国本土长大的华人,即使没有遭受过严苛古怪的家庭教育,也都能深刻理解到 “为了你好” 的威力。
为了你好,你要好好学习
为了你好,你不能打游戏
为了你好,你要考公务员
为了你好,你要早点结婚
为了你好,你必须生孩子
……
一些情况下,父母的 “为了你好” 只是他们满足自己变态控制欲望的借口,另一些情况下,有些父母发自真心的 “为了你好”,然后由于自身有限的眼光给出了不正确的建议。
总的来说,中文语境下的 “为了你好” 绝不是什么好词,如果把这种话语带到工作中,就更匪夷所思了。虽然 For Your Information 并不能直译为 “为了你好”,但是为了避免歧义,还是建议大家不要使用这样的话术。
所以,Code Review 的基本礼仪就是,不要用 FYI。
因为没有人可以在实际上了解另一个人。
父母真的了解自己的孩子吗?结婚多年的夫妻,真的知道对方的心思吗?审查犯人的警察,足够了解自己在调查的罪犯了吗?心理学的专家,能猜到自己女朋友早上为什么生气吗?对于每一个人,你真的了解自己吗?
所以其实可以得到这样一个和技术无关的结论,出于礼貌,我们应该尽量避免对别人说 “为了你好”。
最近的工作中,我提交的代码包含一个简单的事件总线(Event bus)的实现,其中事件的 Publish 和 Subcribe 都用了 RW 锁来保证 map 读写的线程安全:
func (eb *EventBus) Publish(event Event) { eb.mu.RLock() defer eb.mu.RUnlock() if ch, exists := eb.channels[event]; exists { ch <- event }}
而我得到的 CR 建议是用 Sync map 改写为:
func (eb *EventBus) Publish(event Event) { if ch, ok := eb.channels.Load(event); ok { // 注:这里需要类型断言 ch.(chan Event) <- event }}
这实际上最多是一个 Nit 级别的 comment,我是不太在意的,这个事情的处理起来也非常简单。
而事实上问题在于,我听到了类似于 “为了你好” 的话,大致意思是,为了你好,你要了解清楚 RW 锁、互斥锁、Sync map 的区别,然后选择在 Event bus 场景下最正确的实现方式,并且能够条理清晰地去说服别人。
如果说我从自身技术发展的角度,是不太在乎这种问题的。这个问题本质上是我们平时面试时候说的八股文,随着最近几年面试风向的转变,也越来越多的人开始逐渐达成一致、反感八股文一类的东西了。
当然追求这一类底层问题到极致的人,肯定是有技术追求的人,这并不是什么坏事,我们应该尊重任何努力以及对技术较真的人。只是技术也分很多种方面。
我算不算有技术追求的人呢?也许有时候算吧,不然也不会从 Fusionist 裸辞,放弃了比现在算上币权还要高的工资。或者说,无论是技术还是别的东西,其实我们所有人都愿意追求有趣的东西。
从过往经历来看,我关心的技术话题并且乐于出自兴趣去学习、思考的,比如:
PoW 和 PoS 的本质区别是什么,PoW 好还是 PoS 好
以太坊的 PoS 和 Cardano 的 PoS 有什么区别
PBFT 的优缺点是什么,PBFT 有哪些优化的空间
不同类型的区块链是如何处理分叉的
区块链可能有哪些有趣的应用场景
知道这些东西有用吗?没什么用,面试的时候几乎不会有人问,工作中更是用不到,就仅仅只是出于兴趣爱好去探索这些技术问题。这些问题的答案,从来也都不是现成的,网络上是搜索不到的,ChatGPT 也是没办法精准回答的,只有经过一段时间的学习,加上查阅论文资料,结合自己的亲身经历和理解,才可以形成技术观点,无论观点本身是对还是错。
因此可能出于某种思维上的惯性,我很少关心太过基础的编程类问题。这种事情因人而异,不能强求,自然也不能强迫别人因为 FYI 就去关心某些问题。
(刚说完不要 FYI,我这里就在 FYI)
《Rework》 这本书里有一个章节印象挺深,标题是 “Hire great writers”,书中的观点是,不是因为工作中需要发表什么文章、写什么报告,而是好的 writer 往往具备逻辑清晰表达问题的能力,可以帮助到工作。
回到技术问题上,现在各种形式的技术文章也都非常普遍,比如对锁的使用场景比较有心得的话,完全可以落实到文字上,输出成果形成一篇文章,分门别类的介绍锁的种类、最佳的使用场景,然后发表到各种平台上,获得成千上万人的关注,再然后如果对其他技术细节也有心得,内容逐渐丰富,直到写出了一本书,甚至有出版社看上,或者公开到网络上作为电子书开源……FYI……何必跟我较真呢。
2025-03-22 20:23:47
首先推荐两篇王垠的博客文章:
今天回看了一遍王垠的这两篇文章,比较庆幸的是,自己在平日的工作中,很少在无意间触犯到王垠提到的这些礼节问题。
会突然想起这个话题是因为工作中的一点小事,也挺有意思。起因是我擅自 merge 了没有经过 review 的代码,我的同事就开始在群里批判我的代码,也许是他觉得不经过他 review 就合并代码的行为,伤到了他在团队中的尊严和地位。
我现在在一个 web3 项目的开发团队工作,团队总共也就四五个人,内部管理却非常混乱,这是我在之前的工作中没有遇到过的。不过说实话我之前的工作经历不太够看,没有什么参考价值,所以我总结不出什么有用的结论。
要我对比的话,现在的工作和以前的工作,工作方式上最大的区别,在于分配任务的粒度不同,或者说分配到个人头上,负责的事情大小不同。
比如我在 Onchain 工作的时候,需要开发 Solidity 合约,来支持我们的分布式文件系统对 EVM 链的兼容,那么这件事情就是我在做,有人 review,但实际上整个 合约仓库 的代码只有我一个人提交(这里不是在强调提交人数的问题),在这样的模式下,自然也就不存在现在遇到的什么代码质量之类的问题。
(Onchain 这家公司已经解散了,当时项目的代码并没有开源,现在的代码仓库是我私自备份下来的,两年过去了,应该不会有什么风险吧)
再比如我在 Fusionist 工作的时候,整个 Endurance Network 的网络是我一个人启动并维护的,没出过什么问题。主网上线的时候有一个专业的运维同事帮忙开服务器、配置 Docker 之类。
(我已经离职了说出来应该没事吧)
包括更早先的工作经历,不管是我自己还是同事,直观感受上就是每个人都会负责某一块的业务,对整体业务负责而不是对某个具体的开发任务负责,个人的职责相对明确,在负责事情的时间长度上,都是几周到几个月为单位的,所以倒是没有出现过管理混乱的情况。
现在的工作模式是不太完整的 Scrum 风格,每个任务都是两到三天的开发周期,也就是小的开发任务,这些开发任务一定程度上是不区分业务线(代码仓库)的,开发人员会随机参与到不同的事情上。每个人都是在对自己的开发任务(PR)负责,而不是整个仓库负责。这种模式下,每一个开发任务都会有不同的负责人,造成感官上是比较混乱的。
侧面来对比的话,我之前的工作,如果某个人离职,是需要做很长时间工作交接的,因为需要一段时间来让别人接手。现在的工作,如果某个人离职,其实也没啥需要交接的,最多也就两三天的任务内容。不知道是不是远程工作的缘故,让公司被迫选择这样的管理方式。
我的大老板曾经把这种工作模式上的差异,总结为中国式的管理风格和欧美式的管理风格之间的差异。
我只是个普普通通的开发人员,没有管理经验,也不懂这些管理模式什么的,并不想也没什么机会需要我去思考这些问题。只是现在有点能感受到,其实管理本身是一门学问,挺大的学问……
2025-01-28 23:26:40
OIIA OIIA(Spining Cat)是最近很火的一只鬼畜旋转猫,对比 PoW 链上的 DOGE,OIIA 将是 PoS 链上的猫主题 memecoin。
OIIA 与 pump.fun 发行的 memecoin,以及 $Trump 之类不同的地方在于,所有代币的发行量都将通过 PoS 挖矿新增,没有任何预分配(可以验证 genesis 文件),未通过挖矿产生的代币,花钱都买不到。
如果参与者没有相关经验,作为学习者,可以:
作为以太坊网络的学习者,为什么不直接用 Sepolia 这样的测试网去用,而是选择 Oiia Network?
因为 Oiia Network 的定位是 memecoin。
使用以太坊客户端 Geth + Lighthouse 作为初始节点。只修改启动配置和 genesis 文件,不修改代码。
十进制:
20220915
十六进制:
0x1348BF3
128 个,这个是网络启动的最小规模,会直接写入到 genesis.ssz 文件中。
由于一开始网络的参与人数会比较少,会预留 128*32 = 4096 OIIA 作为水龙头余额,放到水龙头地址中。
水龙头使用 PoW Faucet(网页挖矿)的形式来分配。
水龙头的目的是提供少量的流通金额用于网络的测试使用,以及早期愿意参与到网络中的 Validator(虽然靠水龙头很难领到 32 个 OIIA)。预留额度上,如果有 128 个 solo-staker,这个网络就算是巨大的成功了,所以认为预留 4096 个 OIIA 够用。
为了避免类似以太坊基金会抛售的问题,OIIA 不会预分配任何金额给开发人员或 DAO,几乎所有网络都会因为预分配受到怀疑。
以太坊的 PoS 共识没有发行量上限,所以网络的初始发行量就是 4096 个 OIIA。网络启动后的流通量全部依靠挖矿奖励来产出,就像比特币一样。
也就是说,从 Oiia Network 的 genesis 文件来看,除了 4096 个 OIIA 预留用于的空投外(创世节点的 128 个 Validator 不体现在 genesis 文件上,价值 4096 OIIA),不会再预分配任何金额给任何地址。
由于网络初始代币发行量特别少,Faucet 上又领不到足够多的 OIIA,所以可以在社区中申请成为 Validator,社区直接从 Faceut 地址转账 32 OIIA 到申请地址。
由于没有任何商业目的,网络的启动进度会比较随心所欲。