我认识的最好的程序员
我在生活中遇到过很多开发人员。最近,我问自己 “怎样才能成为最优秀的开发者之一?他们都有哪些共同点?
我写下了我观察到的最杰出的开发人员身上的特质,希望能对大家有所启发。我真希望在我刚起步的时候就有这份清单。如果我沿着这条路走下去,就会节省很多时间。
阅读参考资料
如果有一件事是我作为年轻程序员应该做的,那就是阅读我正在使用的东西的参考资料。例如,阅读 Apache 网络服务器文档、Python 标准库或 TOML 规范。
不要去 Stack Overflow,不要问大语言模型(LLM),不要猜测,直接去找源代码。很多时候,源代码会出人意料地易于理解,而且写得很好。
真正了解你的工具
优秀的开发人员从根本上了解他们所使用的技术。
会使用工具是一回事,而真正掌握(理解)它又是另一回事。普通用户会四处摸索,容易混淆,拿错工具,无法优化配置。
专家在阅读参考资料后,会坐下来为工具编写配置文件,他们对每一行都了如指掌,还能向同事解释。这样就不会有任何疑问了!
要充分了解一个工具,您必须知道:
- 它的历史:谁创建了它?为什么创造?
- 它的现在:谁在维护它?他们在哪里工作?
- 它的局限性:什么时候不适合使用?什么时候会损坏?
- 它的生态系统:有哪些库?谁在使用?有哪些插件?
例如,如果你是一名后端工程师,并且大量使用 Kafka,我希望你对 Kafka 有很多了解–而不仅仅是你在 Reddit 上读到的东西。如果你想成为最优秀的工程师之一,至少这是我的期望。
阅读错误信息
如真正阅读错误信息,并试着理解其中所写的内容。事实证明,如果你坐下来静心阅读错误信息,它就会开始与你对话。最好的工程师可以从很少的上下文中推断出大量的信息。只需阅读错误信息,你就能自己解决大部分问题。
如果你能帮助不具备这种技能的人,也会感觉自己拥有超能力。就像 “杯中阅读 ”一样。
分解问题
每个人都会有陷入困境的时候。最优秀的人知道如何摆脱困境。他们会把问题简单化,直到变得可以消化。这是一项很难学会的技能,需要大量的经验。或者,你只是拥有超强的解决问题的能力,比如,你很聪明。如果没有,你可以训练它,但破解难题是没有办法的事。这个世界上有些问题对任何人来说都是难以一次性解决的。
如果你是一名专业开发人员,这就是你的主要工作:破解难题。如果你做对了,就会感觉像是在作弊:你只是在解决简单的问题,直到完成为止。
不要害怕弄脏你的手
我认识的最好的开发人员会阅读大量代码,而且他们不害怕接触代码。他们从不说 “这不适合我 ”或 “我帮不了你”。相反,他们只是开始学习。代码就是代码。只要肯花时间和精力,他们就能掌握所需的任何技能。不知不觉中,他们就成了团队中的得力助手。这主要是因为他们是唯一一个一开始就不怕接触的人。
经常帮助他人
与此相关的一点是。优秀的工程师需求量大,总是很忙,但他们总是尽力帮助他人。这是因为他们天生充满好奇心,而他们的助人为乐精神正是他们成为伟大工程师的根本原因。他们是问题的解决者,有他们在你的团队中,纯粹是一种快乐。
写作
大多数出色的工程师都能言善辩,乐于分享知识。
最优秀的工程师都有自己的思想出口:博客、演讲、开放源代码,或者这些方式的结合。
我认为写作技巧与编程之间有着密切的联系。我认识的所有优秀工程师都至少精通一门人类语言,而且往往不止一门。掌握了写作方法,也就掌握了思维方式,反之亦然。一个人的写作风格在很大程度上反映了他的思维方式。如果写作风格混乱、缺乏条理,那么他们的编码风格也会如此。如果一个人的写作风格简明扼要、富有教育性、结构合理,有时还很诙谐,那么他的代码也会如此。
优秀的程序员会在文字游戏中找到乐趣。
永不停止学习
我认识的一些最优秀的开发人员已经 60 多岁了。他们可以围着我转。部分原因是他们一直在学习。如果有新的工具他们还没有尝试过,或者有他们喜欢的语言,他们就会去学习。这样,他们总是不费吹灰之力就能掌握一切。
这并不是理所当然的:很多人在大学毕业或开始第一份工作后,很快就停止了学习。他们固步自封,认为学校教的就是 “正确 ”的做事方法。一切新的东西都是不好的,不值得他们花时间去学习。因此,有 25 岁的人 “精神退休”,也有 68 岁的人记忆犹新。我希望有一天自己也能成为后者。
与此有关的是,最优秀的工程师不会跟风,但他们总是会仔细评估新技术的好处。如果他们否定了新技术,他们会告诉你确切的原因,什么时候这项技术会是一个不错的选择,以及有哪些替代方案。
地位并不重要
最优秀的开发人员会与首席工程师和初级开发人员进行交流。他们没有等级之分。他们努力向每个人学习,无论老少。新人往往还没有在办公室政治中根深蒂固,他们的头脑还很新鲜。他们不知道事情困难的原因,因此会提出创造性的解决方案。也许过去的障碍已经不复存在,这让他们成为灵感的源泉。
建立声誉
如果你工作出色,你可以成为一名出色的工程师,但只有当你的出色工作为人所知时,你才能成为最出色的工程师之一;至少在一个(较大的)组织内是这样。
有很多方法可以为自己建立声誉:
- 你为一个(较大的)组织建立并提供了一项关键服务。
- 你编写了一个著名的工具
- 你为一个流行的开源工具做出了贡献
- 你写了一本经常被提及的书
为什么我认为因自己的工作而闻名很重要?以上都是扩大你在社区中影响半径的方法。知名开发者比非知名开发者影响的人要多得多。你能写的代码有限。如果你想 “扩大 ”自己的影响力,就必须成为思想领袖。
建立声誉是一个长期目标。它不会一蹴而就,也不必一蹴而就。它也不会偶然发生。你每天都要现身说法,做工作。随着时间的推移,你的工作将不言自明。更多的人会信任你和你的工作,他们会愿意与你合作。你会参与更多有声望的项目,这个圈子也会越来越大。
我曾经听说过这样一个观点:你的最新作品应该盖过你之前的所有作品。这是一个很好的信号,说明你走在正确的道路上。
要有耐心
对电脑和人类都需要耐心。尤其是对你自己。并不是所有东西都能马上发挥作用,人们需要时间来学习。你周围的人并不愚蠢,他们只是掌握的信息不完整。如果没有耐心,就会觉得全世界都在和你作对,周围的人都是无能之辈。这种感觉很糟糕。你太聪明了。
要成为最优秀的人之一,你需要极大的耐心、专注和奉献精神。要想解决难题,就不能轻易分心。你必须回到键盘前,克服它。你必须付出努力,将项目推向终点。如果你能做到不自大,那就更好了。这就是高手与高手之间的差距。
永远不要责怪计算机
大多数开发人员都会把一些看似 “随机 ”的错误归咎于软件、其他人、他们的狗或天气。
最好的开发人员不会这样做。
无论计算机的行为看起来多么反复无常或调皮捣蛋,总会有一个合乎逻辑的解释:只是你还没有发现而已!
优秀的开发人员会不断挖掘,直到找到原因。他们可能不会立即找到原因,也可能永远找不到原因,但他们从不将原因归咎于外部环境。
有了这种态度,他们才能取得惊人的进步,学到别人学不到的东西。当你把虫子误认为是难以理解的魔法时,魔法就永远是魔法。
不要害怕说 “我不知道”
在求职面试中,我极力要求应聘者至少说一次 “我不知道”。原因并不是我想显得高人一等(虽然有些人肯定会有这种印象)。不,我想触及他们的知识边界。我想和他们一起站在他们自以为知道的边缘。很多时候,我自己也不知道答案。老实说,我并不关心答案。我关心的是,面试时他们会不会胡说八道。
最好的应聘者会说:”嗯,我不知道,但这是个有趣的问题!如果让我猜的话,我会说……”,然后他们就开始推理答案。这说明你有成为优秀工程师的潜质。
如果你不敢说 “我不知道”,那你就是自大或自卫。我不喜欢我的团队里有胡说八道的人。最好承认你不可能什么都知道。一旦你接受了这一点,你就会允许自己去学习。“爱因斯坦说:”重要的是你不要停止提问。
不要猜测
“面对模棱两可,拒绝猜测的诱惑”,这是我最喜欢的《PEP 20 – Python 禅》中的一条规则。
猜测是如此如此诱人!
我曾多次这样做,但都以失败告终。
当你猜测时,可能会发生两种情况:
- 最好的情况是你错了,你的错误假设导致了一个 bug。
- 最坏的情况是,你是对的……而且你永远不会停下来重新猜测自己。你会根据错误的假设建立自己的心智模型。这会困扰你很长时间。
再次强调,抵制猜测的冲动。多问问题,阅读参考资料,使用调试器,深入研究。想尽一切办法找出答案。
保持简单
聪明的工程师写出聪明的代码。杰出的工程师则编写简单的代码。
这是因为大多数时候,简单就足够了。而且简单比复杂更容易维护。有时,把事情做对确实很重要,但知道其中的区别才是最好的区别。
保持简单,你就能实现很多目标。专注于正确的事情。
最后的想法
上述内容不是一份清单,也不是一场竞赛;伟大的工程学也不是一场竞赛。
只是不要欺骗自己,以为可以跳过艰苦的工作。没有捷径可走。祝你一路顺风。
本文文字及图片出自 The Best Programmers I Know
你也许感兴趣的:
- Git 20 年,依然怪异,依然精彩
- chroot 技术–Linux 系统的瑞士军刀
- 最近人工智能模型的进步感觉就像胡说八道
- 为什么 curl 用 c 语言开发
- 软件工程师的疯狂
- 没有大象:图像生成方面的突破
- 公司为何不修复漏洞
- 几乎不使用 CSS 的暗色模式
- 我测试了用于 SQL 查询生成的最佳语言模型。谷歌以绝对优势胜出
- 人工智能作弊: 为什么你没有注意到你的队友在作弊?
不猜测也许是企业最重要的事情。
我在半导体制造领域积累了很多解决问题的技能,在那里,错误假设的代价往往是天文数字。在那里,错误假设的代价往往是天文数字。你必须能够在 100% 的时间内准确地确定根本原因是什么,否则一切都会变得非常糟糕。如果没有办法找出根本原因,你现在就有两张单子要解决。
一旦我确定某个设备积累了一些不透明因素,导致无法进行根本原因分析,我就会扔掉整个设备。这就是我坚决避免使用非虚拟技术堆栈的原因。当然,你也可以在第三方的 GitHub repo 中 “守株待兔”,但我发现当你在千差万别的项目风格、动机和范围之间转换时,这种体验会变得相当迷幻。
几乎在所有时间里都能做到完全正确,这可能是建立声誉的最快方法。随着时间的推移,曲线可能会呈指数增长,其范围取决于你所负责问题的价值。
我总是因为避免使用框架和库而遭到很多人的反对,因为大多数事情都是手工完成的。
但是,大多数框架和库并不是为审计级的健壮性而构建的,没有企业级的兼容性承诺,不能保证任意用例不会对性能产生意外影响,等等。
有时,第三方库(如 sql-lite)也能满足要求。但是,能达到 “这比避免依赖带来的麻烦更少 ”这一标准的框架和库却少之又少。
如果你供职的公司确实需要这种级别的健壮性,那么这就是明智之举。问题是,大多数公司都不需要,而且很多为这些公司工作的人都希望自己的工作 “更好”/“更重要”,所以他们假装自己确实需要这种级别的性能。
在尖端公司的关键任务团队中,像你这样的人是天赐良机,是项目/公司成功的重要原因。想为自己无名公司的 CRUD 应用程序构建自己的 ORM 的人是在浪费大家的时间。
> 想要为无名公司的 CRUD 应用程序构建自己的 ORM 的人是在浪费大家的时间。
我曾经不幸加入过一个项目,当时选择了一个现成的 ORM,但当开发进入深入阶段时,边缘案例开始暴露出 ORM 库的严重设计缺陷。一个人想(也许不是高兴,更多的是没有其他选择)构建自己的 ORM,而且大部分 API 都兼容,这才挽救了这个项目。
这是很久以前的事了。如今,ORM 库的状况可能要好得多。但是,即使对于简单的 CRUD ORM,在使用之前确保库是 SQLite 级的建议也是正确的。或许尤其如此。
问题在于,每一个像你这样遇到非常特殊的 ORM 边缘情况的例子似乎都是完全合理的,但却有大约 95 个像这样的故事被用作花费数月时间构建某些东西的理由,而实际上一个库只需数周或数天就能很好地实现。而遇到这些边缘情况时,人们就会说 “把 ORM 扔掉”,而不是 “不要在这一类查询中使用 ORM”。
在我的.NET时代,我最喜欢 Entity Framework 的功能之一就是,即使是在 EF 特有的函数中,也可以非常容易地脱离 ORM 功能,或者以略有不同的配置拥有多个实例(我从未做过最后一点,但我知道十年前是可以做到的)。
在这种情况下,更多的是 ORM 由于基本设计问题,在某些条件下悄无声息地破坏数据什么的。为了解决这些问题,需要对 ORM 进行大修,而在当时,重写而不偏离 API 太远似乎是最简单、最快捷的方法。就像最初的评论所说的那样: 不要害怕使用库,但要明智选择。
但在你的例子中,即使 ORM 不提供原生的突破功能,你也应该清楚地知道,在 ORM 不适合的情况下,你可以保留一条通往数据库的定制路径。如果有人不清楚这一点,也许 “创建自己的 ORM ”并不像你说的那样浪费时间,而是一种必要的教育?
如果你是一家无名的 CRUD 公司,你可能不会雇用那些年薪百万的开发人员来学习所有的课程。你不得不接受这样一个事实:你正在与预算有限的工人一起工作,因此需要在工作中学习,即使你希望这不是你所面临的现实。
任何年收入低于 100 万美元的人都有预算。我特别强调的是从 ORM 本身就可以(轻松地)做到这一点,所以我认为暗示我不知道可以直接调用数据库有点草菅人命。
冒昧说一句,开发人员的年薪中位数大约是 10-15 万美元。因此,全国有一半开发人员的收入低于这个数字。Gergely Orosz 对此有很好的论述。这里有一些 FAANG 级别的科技公司,但除此之外,几乎全是 IB、HFT、对冲基金之类的公司。如果任何年薪接近 100 万美元的 TC 在日常工作中接触过 ORM,我会感到非常震惊。
[0] https://newsletter.pragmaticengineer.com/p/trimodal-nature-o…
> 我特别强调的是,可以从 ORM 本身(很容易)做到这一点
但正如我所说,即使不是内置的,也没有什么区别,不是吗?无论如何,我们都没有理由因为 ORM 在某些情况下并不是最合适的工具,就把它扔到窗外。你肯定同意吧?这是我对您之前评论意图的理解。
虽然现在的 ORM 可能确实都是 SQLite 质量,但原评论者的观点仍然成立: 您需要确保情况确实如此,否则您很快就会后悔自己编写了它。
> 因此,全国有一半开发人员的收入低于这个数字。
你可能把事情想得太简单了,但如果你想走这条路,你真的相信有一半的开发人员已经学到了软件方面的所有课程吗?我对此持怀疑态度。0.01% 的比例可能更高了。
这不是 100 万美元的 TC,而是 100 万美元的公司成本,全部算下来,还是很高,但不是最高的 0.01%
我最活跃的产品的最初设计者选择了 EntityFramework。用了大约 1.5 年之后,才发现它产生的 SQL 语句。它是一个过度 UNION 的烂摊子。本应简单的事情却复杂了 10 倍。
慢慢地,我用 Dapper 和手写 SQL、一个简单的迁移版本系统以及带验证的数据库种子取代了它。这样做之后,启动时间在标准固态硬盘上缩短了 10 多秒,在 CFast 上缩短了约 30 秒。即使最后用 SQLite 标准库替换数据库连接,也缩短了 2 秒钟。
EntityFramework 也许有用,但当开始使用软件的时间非常重要时,它的性能就显得不足了。
Entity Framework 与几乎所有的 ORM 都完全不同,只有少数例外。与之相比,即使是 Rails 中的 ActiveRecord 也不过是个玩具。
即使在 EF 推出之初,它也远远领先于当今大多数成熟的 ORM,我相信你所说的 95% 这个数字。但除了 EF 和其他一些成熟的 ORM 之外,95% 这个数字看起来更像是 50%。
我甚至认为,新的ORM对于任何非CRUD的东西都几乎毫无用处,而CRUD部分可以100%地被PostgREST/Supabase或Hasura之类的东西无缝替代,不会有太大损失。
我总体上并不反对这种看法,但我觉得我们对现代 ORM 甚至是库抱有如此大的信心是在犯错误。很少有东西能达到 Entity Framework、ASP.NET、Rails、Postgres 或 SQLite 的 1%。
我还没有发现一个简单到中等复杂的 CRUD 用例是 Supabase 无法处理的,而且几乎不需要手动配置。虽然它们隐藏了一些postgres的东西,但总的来说,它是一款很棒的产品,尤其是如果你愿意完全锁定供应商,并使用它们进行身份验证、blob存储等的话。
我有一个副项目使用 Clerk 进行身份验证,但基本上所有其他超级数据库产品都使用 Clerk,它确实非常适合小型用例。不过,我不知道一旦你开始需要真正微调的数据库权限或功能时,它的表现会如何。
是的,这也是我的经验,我现在的工作在某些产品中使用了它。
我发现,如果你接受 Supabase 的现状,它能帮你走得更远,节省大量时间和金钱。
至于边缘情况,就像你上面说的 ORM,我们不必把它扔掉,我们只需单独处理这些情况。
我不想离题太远,但 ORM 存在很多设计缺陷。它们是定义上的技术债务,从概念验证开始就存在,但一旦达到目标规模,就需要重新修改。
关系型数据和对象型数据之间存在大量基本的阻抗失配。任何 ORM 都可以解决其中的一些问题,但代价是忽略另一些问题。
这就是为什么 ORM 的人在浪费大家的时间–他的问题几乎肯定不会对所有这些权衡都有独特甚至有价值的观点。
但在现实实践中,这是无法逃避的。即使您在应用程序的大部分内容中都维护了关系,但几乎可以肯定的是,您仍然需要调用某种需要在关系和对象之间进行映射的第三方 API 或网络服务。尤其是在涉及网络服务的情况下,因为这些服务几乎总是避开关系而使用对象,以避免典型的 n+1 问题。
您的应用程序是否应该映射对象和关系通常不是您要问的问题,除非它做得不多或生活在自己的私人小岛上。您是应该自己做,还是依赖工具包的帮助,这才是您必须面对的问题。
没有 ORM 的数据库查询实际上是一种服务。这将关系隐藏在数据库层中,使得在面向对象代码中为这些关系建模的必要性变得毫无意义。因此,摒弃 ORM 完全解决了是否映射对象和关系的问题。我认为,如果你还在问这个问题,那你已经完蛋了。
查询和 ORM 是完全不同的概念。对象-关系映射关注的是关系(或者在实践中更可能是表–但就本讨论而言它们足够相似)和对象之间的映射,正如它字面上所断言的那样。也许你把 ORM 与活动记录模式(由 ActiveRecord 库推广)混淆了,后者将查询构建和 ORM 结合成了某种统一的概念?ActiveRecord 库在发布时自称为 ORM,这可能是造成混淆的原因。
我也曾对此(ORM 和 Active Records)感到困惑,但我花了一些时间学习 DDD,这让我进入了企业架构,也正是从那时起,我了解了与数据交互的设计模式。大多数 Web 框架只有查询生成器和 Active Records。
首先,关于定义,我建议使用维基百科上的 ORM [1] 和 Active Record Pattern [2]。
我认为 Active Record 是类似 ORM 的一种更具体的实现。我们可以不再谈论 Active Record,因为我的观点适用于更通用的 ORM,因此也适用于 Active Record。
为了澄清我的观点,数据的对象映射与数据的关系数据库映射之间存在着根本性的阻抗失配。这意味着不能将数据库用作服务。与数据库的交互必须通过 ORM 进行控制,ORM 控制数据库交互。
我要指出的是,数据库作为一种服务非常强大。例如,当有一个 API 合同公开了一个由原始 SQL 提供支持的值时,当数据库发生变化时,使用 API 的任何内容都无需更改。只有 SQL 会发生变化。相比之下,当 ORM 公开一个对象时,一个属性有时会被加载,有时不会。加载或不加载该属性的变化会波及使用该对象的所有内容。在 ORM 领域,这种类型的更改会导致 N+1 问题或 Null-Pointers 问题。
退一步说,让我再重申一下阻抗失配的问题。维基百科提到了这一点[1]: “相比之下,关系数据库(如 SQL)将标量分组为元组,然后在表中进行枚举。元组和对象有一些相似之处… 不过,它们也有很多不同之处”
将重点放在这里–换句话说,在对象世界中,你无法做到在数据库中 1:1 所能做到的一切。这就导致 ORM 要求应用程序将数据库视为持久层(又名:数据存储,又名:对象存储,又名:持久层)。ORM 控制着与数据库的交互,而不能仅仅将数据库用作数据服务。
我认为这一点从查询中最容易得到说明。
为了说明这一点,让我们从 Java 的 Hibernate(ORM 的原型)中提取一些查询代码 [3]。
“`
public Movie getMovie(Long movieId) {
}
“`
So, getting a release year might look like this:
“`
int movieId = 123;
Movie m = orm.getMovie(movieId);
return m.getReleaseYear();
“`
In contrast, if we put some raw-dogged SQL behind a method, we get this code:
“`
int movieId = 123;
return movieDao.getMovieReleaseYearByMovieId(movieId);
“`
Now, let’s illustrate. To do this, let us look at the example of finding the release year of the highest grossing movie. As a service, that looks like this:
“`
return dao.findReleaseYearOfHighestGrossingMovie();
“`
相比之下,作为 ORM,您可能需要加载所有影片,然后进行迭代。不过,ORM 可能会有一些神奇的糖来获得 “最小/最大 ”值。不过我们还可以继续,比方说,我们想获得最卖座的 10 部电影的导演。ORM 几乎肯定会要求您加载所有电影,然后进行迭代,或者开始创建一些专门用于表示这些数据的对象。在所有情况下,ORM 都是以对象而不是 API 调用(又称服务)的形式来呈现合约的。
对于更新情况,ORM 通常做得很好。当 ORM 尝试更新连接的实体时,可能会遇到阻抗失配的问题。例如,“更新电影 X 中的所有演员”。此外,ORM(和对象)还会产生呆滞/热缓存、无效性、可变性、性能等问题…… 更糟糕的是,所有这些问题都是内在的,关系数据和对象本质上是不同的。
[1] https://en.wikipedia.org/wiki/Object%E2%80%93relational_mapp…
[2] https://en.wikipedia.org/wiki/Active_record_pattern
[3] https://www.baeldung.com/hibernate-entitymanager
> 为了说明问题,让我们从 Java 的 Hibernate(一个典型的 ORM)中提取一些查询代码 [3]。
Hibernate是一个ORM和实体管理器(entity manager),而ORM和实体管理器又是一个结合了其他一些功能的查询生成器。你的代码主要集中在后者。虽然实体管理器方法与 Active Record 不同,但我认为查询构建和 ORM 之间的界限更加清晰。事实上,你的代码已经很明确地将两者区分开来了。我至少可以理解在活动记录下,ORM 和查询构建是如何被混淆的。
> 我们可以不再谈论 Active Record
虽然我在理论上同意,但由于我们谈论的只是 ORM,如果我们按照维基百科的说法,我们就不能把 Active Record 和 ORM 混为一谈。这是一个错误。但正如我的老师(估计你们的老师也一样)在学校里告诉我的那样: 不要相信维基百科上的所有内容。
但无论如何,我们不需要去维基百科。令人耳目一新的是,ORM 在其名称中就直截了当地说明了它是什么。你需要做的就是拼写出来: Object-Relation Mapping(对象关系映射)。
当然,它们填补了大多数数据库和大多数编程语言之间巨大而一致的空白。问题在于,它们从根本上说是一种折衷方案。这意味着,在规模和复杂性方面出现问题并不可怕。从最初的原则出发,做出一套略有不同的折衷方案,也很少有实际意义。
> 问题在于,它们从根本上说就是一种妥协。
毫无疑问,这就是为什么我最近看到的大多数新应用程序都倾向于尽可能地使用关系,只在绝对必要的情况下才使用对象映射。
> 我想这也是将映射延迟到必要时进行的另一个好处。需要映射的内容范围会更有限,而且可以被确定下来。你不必建立一个庞大的框架来处理所有可能出现的情况。您可以将其缩小到您所需要的范围(通常不会太大),并确定最适合的折衷方案。老实说,在这种情况下,使用 ORM 库可能会更浪费时间。
> 关系型数据和基于对象的数据之间存在大量基本的阻抗失配
我的经验告诉我,这些阻抗失配中最大的是 OOP 语言无法在不诉诸杂乱的黑客手段的情况下表达循环依赖关系。开发人员往往在需要开始序列化对象图时,才意识到自己已经深入虎穴。
https://github.com/dotnet/runtime/issues/29900
我认为两者都有道理,不同的时间/环境需要不同的解决方案。也许在项目开始时,想法的定义还很松散,因此能够快速更改大部件比理想的性能更受青睐。
但随着想法和项目的不断完善,你开始发现最大的缺陷究竟在哪里,你可能会得出这样的结论:很多问题都可以在 ORM 层得到解决,所以你会选择在这一层下功夫。
也许从一开始就很明显,但很有可能的是,与项目后期相比,最初负责代码库的人员对理想设计的理解大相径庭。
> ORM 库的现状如今可能要好得多
我认为并非如此。当然,旧的 ORM 仍有其特性,但较新的 ORM,尤其是较新语言的 ORM,其特性只有 ActiveRecord 或 Entity Framework 的一小部分。
我敢说,很少有开源项目是 “SQLite 级 “的。门槛很高。
在我工作过的每家公司中,我都能看到 “这样一个人”,他希望或确实在构建自己的 ORM。
我已经对 ORM 产生了深深的不信任感。我发现,大多数简单的 CRUD 项目都更适合使用带有明确编写(或生成)方法的 DAL。
> 只需使用明确编写(或生成)方法的 DAL 即可。
这有点自相矛盾。即使你使用的是 ORM 库,如果不把它放在 DAL 后面,那也是不应该的。但是,如果你从你的 DAL 发射/接受你自己转换的对象: 恭喜你,你刚刚发明了一个 ORM。你可以发射/接受关系,这是很合理的,但即便如此,你还是必须在某些时候将其映射到对象上,例如,与需要对象的第三方接口。在任何相当复杂的实际应用中,ORM 都是不可避免的。
“对象 “意味着比简单的数据承载容器更多的属性:虽然在特定语言中可以使用类/对象来表达,但除了可以包含属性之外,你真的不关心任何类似 “对象 “的特性。
一般来说,你可以使用简单的组合类型,这种类型除了语法(.attr 与 [“attr”] 的对比)之外,更接近于映射/哈希/判定,而不是 “对象”。
实际上,这也是我的首选:将查询生成器(某些 ORM 也有很好的)与代表从数据库读取的数据的本地类型相结合。
> “对象 “意味着比简单的数据承载容器多了一些属性:
同意。当然,严格来说,关系就是一组元组。但如果你使用的是 SQL 数据库(这一点已被暗示),那么你早已不是这个概念的使用者了,所以我们可以理解为,我们所说的这个概念更宽泛一些。就我而言,一个类的实例与一个数组中的一组基本属性,仍然可以被合理地视为与本讨论相关的关系,似乎你也是这样认为的。可以说,你并没有真正改变其中的数据语义。
但这并不意味着你不需要映射到对象。在一个相当复杂的应用程序中,即使只是为了与第三方接口,你几乎肯定会在某些时候需要这样做。
ORM 有一个问题,那就是它们只适用于有一定复杂性但不是太复杂的项目。
对于小型项目来说,它是矫枉过正,而如果要做非常复杂的事情,它的表现力就不够了。即使你有一个很好的 ORM 用例,但随着需求的增加,你也很难再黑进去你需要的东西了。
我认为,许多工程师都会从为期 1-2 年的安全关键型嵌入式软件工作中获益匪浅,因为这些软件对正确性有很高的要求,一旦出错或粗心大意,就会造成生命损失。这也许不是每个人都能接受的,但至少能让你接触到这个世界的另一面,你也许能从中学到一些东西。也许,如果每个人都做过这样的工作,就会有所感悟,在 “正常 ”的软件世界里,就不会有那么多随随便便的粗心大意了。
说来也巧,在我还是初级开发人员的时候,我曾在任务关键型始终在线系统中工作,这对我养成编写代码的良好习惯很有影响。在我看来,我在职业生涯早期就从这种接触中受益匪浅。
很多事情都很基本:检查每一个返回代码、测试每一个分支、验证外部环境是否在做它声称或应该做的事情。现在,所有这些都成为了我的肌肉记忆,我发现如果不这样做,就很难写出一个可有可无的 python 脚本。与其他更喜欢 “YOLO ”的开发人员相比,我也不觉得自己在脚本编写上的细致程度会明显拖慢开发进度;我花更多时间编写脚本,他们花更多时间在测试中调试脚本。而在产品开发中,前者的缺陷率更低。
嵌入式软件不一定非得是安全关键型的,它也有一些特殊的问题。即使是相当高级的数据基础架构,也面临着许多同样的挑战。
Go 等语言似乎天生就能促进这种开发。我对它比较陌生,但发现它有很多有趣的地方。
我并不排斥在真空中从事安全关键型的工作,但如果他们希望我以从事非安全关键型工作的速度从事安全关键型工作,我就会期望得到相当高的薪水,可能比我目前的薪水至少高出 1.5 倍。如果我要对生命损失负直接责任,我就需要收取更多的费用,因为我迟早会为此失眠。
另一方面,我希望粗心大意的开发人员在这些行业工作吗?
根据我在该行业的经验,如果普通的后端开发人员去该行业工作,平均能力水平就会提高(比较一下平均工资就知道了)。这些流程都是为了让人很难把事情搞砸,而不是为了淘汰 “粗心大意 ”的开发人员,只是为了限制他们可能造成的损害。
我不认为 “粗心 “是开发人员的永久固有属性。这是他们学来的,也是可以改变的。
我们会对激励做出反应。如果开发人员的唯一动力是 “我们奖励尽可能快地发货”,那么他们就会漫不经心地以最快的速度发货。如果取消这种激励机制,他们就能学到更好的方法……
我完全同意–尽管在有些地方,我相信像众所周知的算法这样的东西的实现。
不过,更重要的是,我一直对 “自己开发 ”的便宜程度感到震惊。几年后,我们对系统进行了一些审查,发现基于软件包的代码的错误和安全漏洞数量要高得多。因为修复这些问题的时间成本是不固定的,所以很难用数字来表示,但其数量是相当可观的。此外,让我感到惊讶的是,对于看起来专业性很强的东西来说,自己构建比使用第三方供应商更便宜–当然,机会成本确实是个问题。
现代图书馆的低质量让我非常震惊。
图书馆领域已变得竞争激烈,人们把图书馆当作生意来经营。目标不是正确,甚至不是好,而是成为 “先行者”,销售教程、书籍、Github 赞助、Patreon 订阅……
这不仅对安全性不利,对开发者的体验也不利。
我经常惊讶于这些东西的文档如此之少,它们没有涵盖多少基本情况(更不用说边缘情况了),这些库有多少安全漏洞,而且依赖关系的数量还在不断增加。
另一个问题是,较新的开发人员所学到的只是新奇的库,而对基础库却毫无经验。有多少 React 开发人员不知道如何在没有库的情况下使用 HTML 表单,这简直是疯了。
> 现代库的低质量让我非常震惊。
你怎么会感到震惊?在医疗/DoD 之外的软件行业中发生的一切,都是为了尽可能快地提供功能,质量才是最重要的。
我感到震惊是因为现实并非总是如此。
我已经用 “现代 ”来修饰了我的说法。
不过,自己 “滚动 ”确实需要多敲几下钉子……并希望施工人员知道该把这些支撑物放在哪里。如果有人能预见未来,知道几年后可能会出现什么问题,那就比依赖框架便宜多了。如果没有,那么你就只能使用一些别人无法修复的笨软件。我认为,这就是为什么规模越大的公司越倾向于依赖框架的原因,因为框架本身虽然笨拙,但至少很好理解。
与流行的 lib 相比,有多少人能潜在地发现你的代码中的安全漏洞?
这与具体情况密切相关。如果我正在为一家处于早期阶段的初创公司构建一个网络应用程序,它基本上就是一堆漂亮的 CRUD 视图,那么我绝对会使用一个框架来实现它。如果它对安全至关重要,或者软件更新会成为一个问题,我可能最终会更多地使用手工滚动,而减少对框架的依赖,因为我需要了解故障模式是什么,以及它将如何处理这些故障。
框架只是别人的架构。
如果你和其他公司有同样的问题,它们会很有帮助,但我担心那些使用框架的软件,因为程序员没有信心构建自己的框架。这意味着,当需要超越现成的架构时,程序员会继续向前推进,而此时他们本应增加另一层抽象和封装。
另一方面,我也看到有人在应用程序中固执地避免使用现成的架构,但也不花时间构建自己的架构。最终,一个表的引用会散落在整个代码库中的所有手工编译的 SQL 中。
比起一团糟的面条,我更愿意接受一个过时的框架。
我想你是对的,但某些库已经足够普及,所以这样做是明智的。特别是 S3、SQLite(如前所述)、Postgres 和 Redis,它们通常提供了很好的抽象。
除此之外,时间和密码这两件事我也不会自己编写代码,因为这两件事都太容易出错了。
你使用的是什么编程语言?编译器和解释器相当复杂,更不用说操作系统和计算机硬件了。
这个问题很难回答,因为我们都是在堆栈上构建的。当我们相信 Math.Abs() 能在某种语言中正常工作,或者相信某个套接字库会按照它的说明去做时,我们就站在了巨人的肩膀上。我也尽可能避免使用框架,但我所说的框架是指任何我宁愿自己用脚本语言编写的东西,尤其是在学习和跟上框架的步伐似乎更麻烦的时候。但是,对于我编写 REST 调用和异步函数背后的层层底层软件和硬件来说,这又是什么问题呢?
此外,有时一些更高级别的库也很不错,因为为什么要在每次制作时都重新发明轮子呢?我经常使用 Pixijs。还有 Chart.js。Jquery。Moment.js。Bootstrap 4 alpha 的 CSS 可以处理大量的用例,而且我再也不需要考虑它了。在这些库中,很少有我自己没有使用过的,但拥有一个你熟悉的、不会经常改变的工具包可以节省很多时间。危险更多的是涉足那些尚未死亡、仍在积极开发中的库。)
Moment.js 是需要避免的库之一;其臃肿….。
我仍然喜欢 Moment,因为与内置的日期 API 相比,它能更好地控制非浏览器时区的时区。
在这种情况下,你有替代 Moment 的建议吗?
我对 JavaScript Temporal 的未来充满希望。
moment.js的一位维护者已经使用名为luxon.js的不可变重写程序。强烈推荐。
https://github.com/moment/luxon/blob/master/docs/why.md
dayjs 是一个类似的库,我已经用它替换了 Moment,而且事半功倍。
哦,我以前也从事过半导体制造!作为一名初级离子注入工程师,我正在研究产量问题。一些测试结果不稳定,我把问题追溯到其中一个晶体管没有提供足够的电流。很好,我们知道如何解决这个问题!更多的砷!我提出了一个小规模实验,这些晶片的测试结果很好,于是我们开始推出工艺变更。这些晶片的测试结果也很好。
直到我们从封装后测试中得到消息。每个晶片都因电流过大而失效。价值几十万美元的废品。我的判断是正确的,但并不完全正确。
现在回想起来,让我感到惊讶的是,每个人都签字同意了。我们并不是没有流程,只是不知怎么的,我说服了一群本该更清楚的人去做了。
> 这就是我坚决避免使用非虚拟技术栈的原因
在这句话之前,我一直支持你。我从未见过有哪个代码库因为 “非此处发明综合症 ”而导致堆栈以任何方式 “妨碍根本原因分析”。我曾在一家 C++ 公司工作过,该公司在 NIH 中编辑了一个所谓线程安全的字符串类,结果并不理想。
现在有很多成熟稳健的技术,不管你的编程技巧如何,你自己的发明与那些经过实战检验的框架/库/数据库一样没有怪癖和边缘情况的可能性在我看来都不大。
我想你可能看错了,他们是说他们会尽量在一些普通和无聊的东西上停留,而不是 NIH。
你最终拥有所有的依赖关系,即使你从未查看过它们。在上世纪 90 年代和本世纪初,当开始一个新项目时,我会做几件事。
1)寻找我们需要解决的所有问题,并寻找能解决这些问题的第三方库
2)我将只使用第三方库做一组 PoC,看看开发体验如何。我从源代码开始构建,阅读代码,查看代码卫生状况等。
3)所有内容都将作为源代码签入我们的 repo,“完全构建 ”将构建第三方库,您将获得所有内容的源代码级调试。你可以在开发过程中对库进行侵入式修改,等等。
每个依赖库都必须有自己的位置,不能因为需要一个功能就把一堆东西都拉进来。
当你需要这种功能的时候,你的构建和开发流程正好无法承担这项工作。人们惊慌失措,系统崩溃,没人知道发生了什么。如果一切都准备就绪,你仍然可以使用科学方法进行扎实的工程设计,解决问题并继续前进。
说得好,写得好。
> 阅读参考文献
> 不要猜测
我发现,在处理一个新 “事物 “时,我经常喜欢猜测一个小时左右,然后才真正深入研究参考文献。或者,我会先看一两个 stackoverflow 的答案,玩一玩,然后再去看参考文献。
为什么呢?
通常情况下,参考文献中有很多上下文,只有当我亲身实践过参考文献所描述的内容后,才能理解其中的含义。
学习一门新语言或应用程序接口时尤其如此: 我会通过教程/快速入门;“猜测 ”进行更改;然后在更好地理解上下文的情况下再回头阅读参考文献。
顺便说一句:这就是我喜欢支持 intellisense 等功能的语言和集成开发环境的原因。能在集成开发环境中看到一点一点的文档,帮助我在 “猜测 ”阶段进行学习,这真是太棒了。
>> 阅读参考文献
>> 不要猜测
> 我发现,在使用一种新的 “东西 “时,我经常喜欢猜测一个小时左右,然后再深入研究参考文献。或者,我会先看一两个 stackoverflow 的答案,玩一玩,然后再去看参考文献。
我觉得这很公平。我见过一些 “不优秀 ”的程序员,他们只会猜测,只会阅读 stackoverflow,一遍又一遍,直到永远,却从不阅读参考文献。他们根本不知道发生了什么,只是不停地胡编乱造,直到有什么东西粘住为止。我把这一条看成是对这种人的回应。
问题在于,能否设计出好的界面与能否编写出好的文档之间存在着很大的关联。也就是说,如果猜测失败,那么参考资料也一定会因为不准确或未能传达你需要知道的信息而失败。这也是有道理的,因为两者都需要关注用户如何看待产品。这本身就是一种技能。
在实践中,我曾多次陷入困境,以为自己只是不理解参考文献,结果却发现有一个错误或修改导致参考文献失效。如今,如果我必须与一个不了解用户的人所制造的产品进行交互,如果猜测失败,我会直接查看源代码,如果没有代码,我就会对系统进行探测。这样不仅速度更快,而且你能更好地理解发生了什么,而不是磕磕绊绊地试图用自然语言来描述。
随你怎么说 Windows 开发,但在 90 年代,微软为 Win32 和 MFC 提供的 MSDN 参考文档相当不错。几乎达到了黄金标准。再加上 Petzold 和 Prosise,你几乎不用上网就能回答任何 API 问题。
然而,我们的工程师们仍然会胡乱猜测,直到不小心找到了答案,或者向更资深的工程师求助(他们总是会先问一句:你看过文档了吗?Win32 是否存在不为人知的黑暗角落?当然有,但 99% 的开发人员根本不需要接近它们。
它很好,但并不完美。我记得自己曾留下过这样的评论:“MSDN 说 X,但实际行为是 Y,因此代码中存在 Z ”
,我记得这些事实就是证明,文档总体上不错,但这并不是每天都会发生的事。
> 问题在于,能否设计出好的界面与能否编写出好的文档之间有着密切的联系。也就是说,如果猜测失败,那么参考资料也一定会因为不准确或没有传达你需要知道的信息而失败。这也是有道理的,因为两者都需要关注用户对产品的感知。
我认为我们谈论的是不同类型的猜测。我说的不是有技巧、有根据的猜测,而是愚蠢、无知的猜测。就像 “我什么都不知道,所以我只是想试试我在网上找到的’东西’,而不是真的了解。即使有最漂亮的界面和最好的文档,那些人也会这么做。
但即使是设计最好的界面,也不是所有东西都能被发现(例如,在同一个库中,另一个设计奇妙但正交的界面就能解决你的问题)。
> 就像 “我什么都不知道,所以我只是想试试我在网上找到的’东西’,但并没有真正理解。
这是一个合理的起点。但公平的是,如果不奏效,就不能止步于此。在我看来,下一步是更仔细地查看界面,看看它是否提供了任何提示。如果界面设计得好,大多数时候都会提供提示。
> 但即使是设计最好的界面,也不是所有东西都能被发现的
当然。这就是测试套件的作用: 为用户记录完整的意图和用法。你还是不会去找参考资料。另外,测试套件还能自我验证,因此不会出现 “是我的问题还是参考文献有误?”这样的问题。
>> 就像 “我什么都不知道,所以我只是想试试我在网上找到的’东西’,但并没有真正理解。
>> 一个合理的起点。但公平的是,如果没有效果,你不能就此止步。
这不是一个合理的起点。你说的基本上是复制粘贴编码。谷歌搜索,stack overflow,粘贴第一个答案。然后,问开发人员是否知道他们做了什么以及为什么能成功,他们不会回答,因为他们不知道。
> 在我看来,下一步是更仔细地查看界面,看看它是否提供了任何提示。如果设计得好,大多数时候都会提供提示。
我说的这些人不能也不会这么做。
> 这就是测试套件的目的: 为用户记录完整的意图和用法。你还是不会去找参考资料。另外,测试套件还能自我验证,不会出现 “是我的问题,还是参考资料有误?”这样的麻烦。
我在这里感受到了一种 “我不需要注释,因为代码是自文档化的 ”氛围。我不同意这种说法。与代码本身甚至代码测试相比,散文能更好地表达与代码相关的很多很多东西。
当然,代码是查找代码实现的最权威的地方,但它并不是查找代码背后的原因、概念和思想的最佳途径。
> 这不是一个合理的起点。
为什么不是?如果行得通,那就行得通。不是每个人都想获得最佳程序员奖。
> 他们无法回答,因为他们不知道。
我知道你在这里想到的是某个具体的人,但从广义上讲,你或多或少会知道它是如何工作的,因为如果你不得不这样做,你已经知道自己会如何实现。但既然别人的代码已经做到了,就没必要再想下去了。这仍然是一个合理的起点。
> 但不是为什么
如果你没有在测试中捕捉 “为什么”,那你到底在测试什么?是什么 “已经在实现中体现了。你不需要写两次。更糟糕的是,如果你最终测试的是 “什么”,那么每当你需要做出改变时,你就不得不处理被破坏的测试。这种情况是很可怕的。
我同意,编写有用的测试确实很难,至少和编写好的参考资料一样难,因此超出了大多数人的能力范围。但是,如果你不得不使用那些不熟练的人编写的东西,那么无论你从哪个角度看,所有的赌注都将落空。
>> 这不是一个合理的起点。
> 为什么不呢?能用就用。不是每个人都想获得最佳程序员奖。
好吧,我明白了:避免阅读文档进行猜测,或遵循 “谷歌搜索、stack overflow、粘贴第一个答案 ”循环的程序员都是平庸的程序员。如果他们不想成为优秀的程序员(这也是文章的意思),他们可以继续做他们正在做的事情。
> 如果你没有在测试中捕捉 “为什么”,那你到底在测试什么?
你无法在代码中捕捉 “为什么”。你的测试是对 “是什么 ”的展示。
> ……是平庸的程序员。
这取决于观察者。
– 一个程序员如果用自己所做的事情来决定谁是 “最好的 ”程序员,而自己又不去猜测,那么他很可能会排除任何这样做的人。
– 而商业人士则会认为,使用别人的代码快速成功交付产品的人是 “最好的”。
> 你无法用代码捕捉原因。
那么你也无法用自然语言来捕捉它,这整件事就没有意义了。但我不同意这种观点。
> 你的测试展示了 “是什么”。
你说得有道理,有些测试框架会为 “示例 ”测试特别声明,这些测试会被标记为包含在生成的 API 文档中。这种文档可能会有用武之地,但我想说的并不是这种测试。这并不代表你要编写的绝大多数测试。如果是这样,那你就做错了–或者至少对那些以后会使用你的测试的人不公平。
在我的洗衣清单中,“最好 ”的程序员与平庸的程序员之间的区别就在于关心下一个人。但我理解为什么你的洗衣清单有所不同。
同意。先做一个猜测,然后用运行的代码验证这个猜测,然后重复。
我很惊讶这一点会引起争议;工程学表面上遵循科学方法。没有假设和测试,就没有科学方法。除非我们想对猜测和假设之间的区别吹毛求疵,否则进行猜测是编程的关键部分。
我总是回想起彼得-瑙尔(Peter Naur)的文章《编程即理论构建》。这篇文章已经发表了 40 年,但仍能抓住编程的精髓。编程产生的价值在于系统的共享工作理论,而不是源代码本身。我不明白,如果不先形成假设,如何能发展出充分的理论。
在运行代码并进行检查之前提出假设,可以避免在事后将偶然观察到的行为合理化。无效的预测有助于加深理解和学习。
这就是为什么我倾向于用 Google 而不是 chatgpt 来处理所有事情。我最终总能在 SO
的评论/主题中找到这些有趣的小插曲。我认为我现在更喜欢的大语言模型(LLM)使用方式是自己尝试一些东西,然后让大语言模型(LLM)来批评我的做法。我认为这样做既有利于学习(就像学习自然语言一样,犯错并被纠正比每次都去查找正确答案更有利于学习),而且我认为这样做的风险更低,因为你不需要依赖大语言模型(LLM) 来避免产生幻觉。你还可以了解一些新的线索,以便自己进行调查等
如果我在用一种不熟悉的语言或使用一个不熟悉的库进行写作,我通常会打开几个浏览器标签。这是因为文档中通常会有注意事项和其他提示,而这些都是法律硕士所不具备的。而一本书可以为巩固基础创造奇迹。
有道理。我最近以大语言模型(LLM) 为起点学习了 swift,基本上就是 “我知道 java 和 python,请解释一下 swift 的语法”。这很好。
一旦进入架构,我就有了一个大致的方向,然后依靠谷歌搜索(例如,我是否应该使用 swiftData/coreData/sqlite 等的很多细微差别都是在对话线程中找到的)
中出式学习是处理全新事物的好方法。先做一些概述,看看其他人是怎么做的,怎么看待这件事的,然后在对其有了世界观之后再深入研究手册。
我认为人们会以一种完全不切实际的方式来理解 “不要猜测”,而这并不是最好的程序员所做的事情。
作为消费者,你应该对工具或库向你展示的模型有强烈的感觉。你应该使用该模型来 “猜测 ”工具的行为。你应该选择连贯一致的工具,这样你的猜测才会更加准确,并避免使用有很多特殊情况的库/工具,因为这些特殊情况会让你很难 “猜测 ”它们在做什么。
最好的程序员不会仔细检查他们调用的每个函数的文档或实现。他们善于编写测试,一次性检查大量假设,善于选择能让他们可靠猜测的工具,避免使用会导致他们错误猜测的工具。
编程中的杠杆作用来自于为了实现目标而无需理解的东西和无需阅读的代码。
我也发现几乎不可能专注于参考资料。我知道这听起来很幼稚,但我有时就是做不到。我就是这么玩代码玩到现在的。
说实话,有些参考文献非常令人困惑。有时它们 “什么都说了”,但却没有提供足够的上下文,让人无法真正理解。
这就是为什么例子也很重要。
一样。要写出好的文档非常困难,尤其是当作者同时也是设计者的时候。有很多上下文很容易被想当然地忽略掉。
我不认为你的方法不好,也不与文章中的建议相冲突,至少在精神上是这样。我认为,你所描述的情况并不是你未经测试的猜测最终被应用到已发布的产品中,或者被应用到给同事的毫无根据的建议中。(形成并测试假设是有价值的,而建立在毫无根据的假设之上则是完全不同的事情。
有意思的是,我在学习哲学时也有类似的方法。比起阅读,我更喜欢思考和写作,所以我经常先思考一个哲学问题,然后再阅读关于这个主题的其他文章。我发现这种顺序有助于我很好地掌握一个主题。
我不知道我在编程时是否也是这样做的。
我同意这一点。在有效使用文档(入门之外)之前,我必须对新工具有很多了解。如果是我已经很熟悉的领域,那么有时我可以很轻松地上手;但摸索往往是关键的一步。
事实上,根据研究,你的方法 “先测试自己,然后再学习 ”比先学习更好。
> “不要去 Stack Overflow,不要去问大语言模型(LLM),不要去猜,直接去找源头。很多时候,它出人意料地通俗易懂、文笔优美”。
这有点像数学书。我在读工科时最怕读正式的数学书,总是读通俗易懂的文字。到了硕士阶段,情况稍微好了一些,我可以读一些快速切入主题的章节。至少现在我能理解为什么人们要写简洁的参考文献,甚至是 Tutte 的书。
有些参考文献使用起来很愉快。对于 rust 板条箱,我总是去 docs.rs 搜索。我在大学选修函数式编程课程时,Haskell 的 hoogle 也很不错。Cpp 参考也很不错 — 感谢你添加了示例。
今天我在阅读 boto3 python 库的文档时,立刻错过了 docs.rs!
>> “不要去 Stack Overflow,不要去问大语言模型(LLM),不要去猜,直接去找源代码。很多时候,它出乎意料地通俗易懂、文笔优美”。
> 这有点像数学书。我在读工科的时候最怕读正式的数学书 — 总是读通俗易懂的文字。到了硕士阶段,情况稍微好了一些,我可以读一些快速切入主题的章节。至少现在我能理解为什么人们要写简洁的参考文献,甚至是 Tutte 的书。
我不认为他的建议是这个意思。我认为这更多的是系统知识与零散知识的对比。通过大语言模型(LLM) 或 Stack Overflow 来 “学习 ”的人,并不具备全面的工具知识,无法对可用的工具进行推理,因此会倾向于以非常刻板的方式使用工具,用更难的方法做事,因为他们不知道有哪些可能。你仍然可以通过无障碍文本获得系统的知识。
我已经很多年没用过 Haskell 了,但我仍然发现,无论我使用什么工具,我都希望能有 Hoogle。我知道我需要一个 X 类型的值,那么有哪些函数返回 X 类型的值呢?我想,Scala 可能是我用过的唯一一种在文档中能让你像这样按类型特征进行搜索的语言了。
我最近经常玩 Zig,他们的文档系统也很不错。我特别喜欢他们会嵌入你正在查看的内容是如何实现的源代码,通常还会提供一个预期使用方法的示例。能够在文档中看到语言的实际应用,这让我更容易上手。不过,如果能像 Hoogle 一样基于类型签名进行搜索,那就真的是杀手锏了。
我认为这也与使用有助于简化工作流程的工具有关。
如果能跳转到库代码的定义,你就能真正快速地从你的代码转到你想弄明白的函数。有了代码编辑器的支持,这将是一种无缝体验,无需进行真正的上下文切换。
如果没有这个功能,你可能会离开代码编辑器,在 Google 上搜索与之相关的项目,然后在 GitHub 上找到它,打开 GitHub 的 “开发 ”版本(登录到 repo 主页后点击 .)以便探索该项目,然后对该功能进行项目搜索,在一堆结果中寻找,直到找到为止。
或者在本地找到代码,你的软件包管理器可能已经保存了代码,但如果你的应用是在 Docker 中,这可能会是个问题,因为它可能没有被卷挂载,所以你无法在本地代码编辑器中进行探索。
> 很多时候,它出人意料地易于使用,而且写得很好
我很高兴这个人使用优质软件。我并不总是那么幸运。
Literate Programming的有力论据:
http://literateprogramming.com/
与我共事的两位最优秀的程序员都有一本拇指大的Knuth的TAoCP….。
当你不知道问题的名称时,去查找源代码可能有点困难。
大多数项目都应该遵循 diataxis,这样我们就不会那么痛苦了
天哪,boto3 python 文档简直是_insanity_。缺少类型提示,只有一种获取客户端的方法,却可以用于 100 种不同的服务……
对于新手来说,boto3 是 AWS 的官方 python 库。要获取 S3 等服务的客户端,需要使用 `boto3.client(‘s3’)` 而不是正常的 `boto3.s3.S3Client()`
> 最好的开发人员会与首席工程师和初级开发人员交流。他们没有等级之分。他们努力向每个人学习,无论老少。新人往往还没有在办公室政治中根深蒂固,他们的头脑还很新鲜。他们不知道事情困难的原因,因此会提出创造性的解决方案。也许过去的障碍已经不复存在,这让这些人成为灵感的源泉。
这就是你如何反对偏差正常化的方法。永远不要无缘无故地否定新人对你可能做错的事情的评论。是的,你一直在用不寻常的方式做 X,而且仍然没有发生意外;但你不应该这样做是有原因的,而且通过亲身经历重新学习可能要付出很大代价。
同样的道理也适用于那些没有人知道为什么存在却仍然被遵守的旧规则。任何规则的存在都应该有一个解释,并定期检查其相关性。
就我个人而言,我认为新来的人提出的问题更好,更有好奇心。经验丰富的人知道什么时候不应该遵循惯例。
事情变化真的很快,人工智能工具更是如此,所以让人们质疑我们为什么要以某种方式来做是很重要的。
在这篇文章中找不到任何错误。除了一点之外,几乎都同意:
“不要去 Stack Overflow,不要问大语言模型(LLM),不要猜测,直接去找源代码。很多时候,它出乎意料地通俗易懂、文笔优美”。
我想,我已经有将近 15 年多没有从事过专业的编码工作了。我一直在学习。刚开始工作时,我花了很多时间在 Stack Overflow 上回答问题,而不是提出问题。这对我帮助很大,因为我觉得解决别人的问题是一种 “现实世界的挑战”。因此,这完全取决于你如何使用 Stack Overflow。
对于法学硕士,我不会像现在的孩子们那样用它来 “寓教于乐”。在我看来,这是使用 LLM 的错误方式。LLMs 非常适合集成到您正在构建的软件中,在这种软件中,LLMs 必须分析实时事件并生成摘要,甚至可以自动处理一些琐碎的事情。但它绝对不能取代程序员。至少目前的版本还不能。使用 LLM 的方法是要求它为您想要了解/探索的主题提供一个万丈高楼平地起的视角。为什么?因为有时候,你甚至不知道某样东西是如何工作的,因为你不知道它叫什么(技术术语/行话)。这就是法学硕士的帮助所在。一旦你知道了这些术语/专业术语,你就可以参考官方文件/论文,而不是依赖于大语言模型(LLM)。在我看来,这是法律硕士被低估的超能力。
除此之外,我也同意其中的大部分内容。实际上,我认为这些建议来自于人们不同的学习方式。如果你的学习方式与作者不同,那么这些建议就会让你感到错误和刺耳。
我的学习方式是做,而不是读。如果我读了一些东西,但没有实际使用,就很容易忘记。我的大脑似乎会把它归类为 “不实用,不需要”。但是,如果我真的用到了,我就会很快学会。
因此,对我来说,文档是非常糟糕的,阅读某样东西是如何工作的并没有帮助,我需要看到例子。当我看到实际操作时,我才能真正学会。即使是复制/粘贴,我也会在复制的代码上做文章,修改变量、使用参数、添加/删除注释等。没有代码是简单复制的,它总是经过处理、清理,去除不必要的杂质。
现在有很多文档都没有示例,或者示例很差,与你想要使用的方式无关。
对我来说,如果 API 没有 “意义”,我就很难记住它。就像 SQL Server 的 “OVER ”子句,多年来我一直断断续续地使用它,但每次要使用它时,我都要重新学习一遍。我觉得这种 API 真的很让人沮丧。
人们学习的方式不同,创造的方式也不同。其他创意领域也有这种二分法,但我想我们更接近数学,总是试图找到 “正确的方法 ”来做事情,而我们的领域实际上非常灵活,允许大量的自我表达。
这就是我喜欢 LLMS 的原因。我把 200 份 100 多页的 13F 申报报告放入双子座,10 分钟后,它就能帮我找到异常情况。这在以前是不可能的,因为这些报告根本没有标准化。
即使只是日志,我也会这样做,因为我懒得逐字段进行适当的格式化。
他们不是有一些复杂的 XML 架构吗?还是你发送的是 html 版本的报告渲染文本?
不,这些文档没有超级一致的标准。对 13F 文件的内容有要求,但对格式没有太多要求。而且这些文件是 PDF 格式,很难使用传统脚本进行解析。
喜欢这个,我也有同样的看法。我用它们来搜索那些我不得不绕圈子又说不清楚我的意思的情况(我找到了一本旧书,但我只能用这种方法非常模糊地大致记住它的内容,而当时没有搜索引擎能做到这一点),以及 “框架 ”问题,例如这是关于什么的,各部分之间有什么关系,我甚至可以说这是另一种类型的搜索问题(这是我从零开始的搜索)。我仍然需要慎重对待,但就你的观点而言,这足以让我熟悉信息空间中的 “地标”,然后在此基础上开始建立更牢固的理解。
> 当我开始我的职业生涯时,我花了相当多的时间在 Stack Overflow 上回答问题,而不是提出问题。
我认为你不能再把回答 SO 问题作为业余爱好了。我曾经在早上喝咖啡的时候回答问题,但不知从什么时候开始,Stack Overflow 上出现了很多专业的声誉增长者,他们在问题发布前 30 秒就回答了所有问题。当你发现一个未回答的问题时,版主就会跳出来指责你 “授人以鱼不如授人以渔”,而不是随时复制/粘贴代码。
这正是我目前使用 LLM 的方式。它就像是进入任何可以想象的学科的起点,而且在这种使用水平上,它们似乎基本上没有错误。
我最近开始画画(我自己的小小中年危机),我太不深入了,甚至还不了解什么是可能的,互联网上充斥着太多垃圾教程,有时大语言模型(LLM)能够解析我的意图并引导我找到关键词和名称,这真是天赐良机,当然,问一个懂这些东西的人可能会更好,但并不总是很方便。在我的使用案例中,LLM 的最佳部分是软输入,而软输出并不是问题。
对于绘图,通常最好买一本书或一门课程(从新大师学院这样的好平台),然后(大量)练习
这不是大语言模型(LLM)的特点,而是传统搜索引擎的失败。
对于那些由于所有者网站受到 Cloudflare 限制而无法打开链接的人,这里有一个网络档案链接 – https://web.archive.org/web/20250409082704/https://endler.de…
当你创建了一个编程博客,却在获得大量网络流量时完全垮掉时,你自以为能够识别出 “最好的程序员”,这是不是有些讽刺?
作者在此。网站瘫痪是因为我使用的是 Cloudflare 的免费计划,每天有 10 万次请求。老实说,我根本不在乎网站是否为 HN 正常运行,因为流量会让我花钱,而且缓存也能正常工作。顺便说一句,网站之前在 Github Pages 上,它能很好地处理以前的前台流量。所以我想,如果这里面有什么讽刺意味的话,那就是要改变以前运行得很好的系统。我的目标是玩一下 Worker 并添加一些服务器端功能,当然,这从未实现。我可能会迁移回 GH,因为我的另一个博客 corrode.dev 就在那里,我不需要更多了。
我认为,根据完全不切实际的运行条件(如多个数量级的额外流量)来设计系统,是糟糕程序员的一个相当普遍的特征。
既然他们已经抱得美人归,下次可能就会做好准备了。
他们有多少方法可以建立一个没有这些缺陷和风险的网站?
好的工程师在建站时会消除故障模式,而不是只考虑 “合理流量”。除了 DDoS,一个简单的博客不应该因为达到速率限制而死亡。但鉴于网站已经死亡,我无法判断,也许它不仅仅是一个博客。
> 优秀的工程师制造的产品能消除故障模式,
是的,但不是所有的故障模式,只是系统目标范围内的故障模式。从外面看,你无法知道目标是什么。
不存在消除所有失效模式的说法,这正是我在上面的帖子中提出的观点。你能做的最好的事情就是明确定义你的目标,并设计一个系统来满足该目标所定义的限制条件。如果目标发生变化,就必须重新设计。
这就是工程学的核心。
> 是的,但不是所有的故障模式,只是系统目标范围内的故障模式。从外部看,你无法判断目标是什么。
基本可用性不是博客的目标吗?
换一种说法:给定两个系统,一个系统会在理论上可能发生但在其他方面 “不可预测 ”的请求数量到达时发生故障。一个没有这种故障模式。哪个更好?
> 从外面看,你无法判断目标是什么。
我要么不同意,哪怕是一点点也不同意,要么就是不理解。你能换个说法吗?
> 这就是工程学的核心。
我认为工程学的核心是制造出能发挥作用的东西。如果你没有预料到一些大多数工程师都会说是可以预料的事情,而这些可以预料的事情不但没有降低服务质量,反而让整个系统瘫痪,无法工作……这就是问题所在,不是吗?
> 自以为能找出 “最优秀的程序员”
他是在找出他认识的最优秀的程序员(这一点从标题上就能看出来)。我认为,即使是一个半技术人员,能做到这一点也不是没有道理的。
另外,作者很有可能从未想过自己的文章会获得大量的网络流量,并以此为前提分配资源。这并不能说明他们的技术能力有多高。你可能是世界上最好的程序员,却做出了这样一个错误的假设。
我可以识别狮子,却无法追赶并杀死马蹄上的羚羊
这不是一个好的比喻。任何人都能识别 “程序员”。而识别 “最好的程序员 ”或 “最好的狮子”(在某些方面)则完全是两码事。
那就改为 “我可以识别出一个好面包师,但自己却做不出野生发酵面包”。无论如何,这就是 “布丁在吃 ”的证明:好的程序员是指能做出好软件的程序员,而好软件是指能取悦用户并提供他们想要的功能的软件。你不需要成为一名程序员,就能知道你所使用的软件在整个生命周期内是否始终如一地优秀。如果它一开始就不好,那它一开始就不好;如果它的构建不具有可维护性和可扩展性,那它在整个生命周期中都会变得不好。
据推测,作者并没有说他们就是其中之一:)
> 有些讽刺意味,是不是
没有。
最优秀的程序员都知道,使用互联网档案馆的免费资源是对自己的努力和成本最有利的方法,而不是让自己的网站为临时负载而扩展?(开玩笑……我觉得)
大多数开发人员在系统管理方面都很糟糕,这一点相当令人失望,也是作者使用 Clownflare 的原因之一。能够维护系统和编写代码一样重要
这种说法有点荒谬。
我不想替作者说话,但我们中的一些人只想在空闲时间写一篇博文并发表。我们并不是为了好玩而 “维护系统”。
有些文章的浏览量为零,而有些文章最终登上了《黑客新闻》的头版。
在博文的底部有一个 “提交到 HN “的按钮。
此外,作者似乎不只是个业余博主,而是个严肃的人:
https://web.archive.org/web/20250405193600/https://endler.de…
> 我的兴趣是可扩展性、性能和分布式系统
> 以下是我的公开演讲活动列表。
> 本博客上的某些链接是联盟链接,如果您最终在合作网站
上购买了某些东西,我将赚取少量佣金 > 维护本博客和我的项目是一项繁重的工作,我希望能把生命中更多的时间用于写作和维护开源项目。如果你愿意支持我实现这个目标,最好的办法就是成为我的赞助商
我说的不仅仅是一个博客。当你在编写一个大型程序时,它会让你从不同的角度看待问题。例如,你的任务是创建一个自定义 auth。是使用过 authentik 或 kanidm 这样的软件,还是完全没有使用经验,你会感觉更得心应手?
题外话:费率限制是因为他们托管在 Cloudflare 计算服务上吗?我问这个问题是因为我想知道,如果只使用域名托管,是否可以使用这一功能。
在使用 CF Worker 或他们自己的计算设备之外,cloudflare 上还存在这一功能。这是他们 WAF 功能集的一部分。
我认为这与 WAF 无关,上面写得很清楚:
> 如果您是该网站的所有者,请在 Cloudflare Workers 面板上升级您的计划,以防止再次发生这种情况。
经过调查,我的假设是,所有者页面使用了 Cloudflare Workers 的 SSRd,并且达到了每日限制。
查看 archive.org 镜像,内容为 2000 字和几张图片。在 50K 的 HTML 中提供 10K 的文本似乎需要多少 “计算”,这一直让我感到震惊。
如果你的业务是销售服务器端计算,以便在后端渲染前端网络应用程序,那么你就要努力说服整整一代人相信这是需要的。
有几家公司在这方面做得非常成功。
注意,这里说的是 “最优秀的程序员”,而不是 “最擅长通过制作软件来影响业务的人”。
我经常在想这个问题: 如果你想产生影响/解决问题/赚钱,而不仅仅是优化你的 JIRA 单子,那么你应该投入一个小时来了解框架 X 的最底层代码,还是与业务领域的人交谈?阅读有关嵌入式系统可访问性的文档或书籍?是选择另一种技术堆栈,还是更快地掌握 “足够好 ”的技术?
答案并不容易回答,但值得牢记的是,编程不仅仅是编程。
> 请注意,这里说的是 “最优秀的程序员”,而不是 “最擅长通过制作软件来影响业务的人”。
我们可以将软件开发人员视为工匠,欣赏他们的技能和手艺,也可以将他们视为商业资产,这是两码事。
两者都有各自的优点,但这篇文章显然侧重于手艺人的一面,这就足够了。我们不需要把一切都与商业和金钱挂钩,我们也绝对不需要把编写代码的美感和技巧简化为 Jira 票据。
如今我已经退休,每天大部分时间都在编写软件。
我把它当作一门手艺,是为了个人成就感和学习。我喜欢学习和解决问题。我还喜欢创造一些我觉得美观的东西。
例如,我编写 iOS 应用程序,我正在开发一个计时器应用程序的新版本,这个应用程序已经在 App Store 上架十多年了。我为它添加了一个 Watch 应用程序,已经到了可以在 App Store 上架的程度,但却一直遇到同步问题。虽然这不是什么 “大问题”,但从美学角度看却很不雅观。
我认为这个问题可以通过改进应用程序的基本设计来解决,而这个设计多年来基本上都是不变的。
因此,我彻底重写了它。
这并不具有 “商业 ”意义,但这是我想要做的。我还将借此机会重新设计基本的用户界面。
我很享受这种自由。
我还喜欢写自己的作品。我知道很少有人有兴趣读我的文章,但我还是写了,因为这有助于我学习(最好的学习方法就是教),也有助于我集中思想。
谢谢你的分享。我喜欢听这类 “软件花园 ”的故事。我祝愿你多年来一直快乐地照料你的花园。
人生目标!如果我退休了,我也想这样做。
一般来说,我们的业务专长是没有报酬的。事实上,大多数企业都不愿意让开发人员承担深层次的领域责任。
这体现在管理方法上:开发人员在很大程度上是电子表格中可以互换的单元格。我并不是说这是件好事。
造成这种情况的原因很复杂,但一般来说,企业人员希望我们解决他们自己无法解决的技术问题,他们不希望我们 “解除 ”他们的产品管理、客户关系和行业知识。他们为什么要这样做?这会贬低他们的价值。
没错。具有 “业务影响力 ”的开发人员可能会被视为一种负担。
一个方面可能是,从事 “业务 ”的开发人员实际上不再是 “下属”。管理决策需要在不同层面上进行论证,以保持合法性。
这个话题有点疯狂,是我在技术领域从未听说过的。在我工作过的每个地方,如果开发人员真正具有商业或产品意识,并且无需与 “产品人 ”保持共生关系,那么他们的价值至少会提高 5 倍。在一家我们都听说过的大科技公司,我们部门甚至没有产品人员。工程主管需要处理所有的产品职责,如果他们不认为你至少能成长为产品主管,他们是不会聘用你的。
这也是我回去攻读商学学位,然后重新进入科技行业的原因之一。不,在硅谷当然没有人在乎 “MBA ”头衔(HN 认为它是负面的),但在我面试/工作过的地方,他们都很欣赏我们能谈论软件对经济和商业的影响,而不仅仅是算法和数据结构。
这听起来很不错,我建议你好好珍惜。大多数科技公司都没有这种前瞻性思维(往往对自己不利)
这种自上而下的管理方式导致的结果就是代码漏洞百出、期限过期、安全漏洞,以及我所见过的最慢的软件开发速度。
我发现,只要找到那些对这些问题感到沮丧的高管,对他们说:“我有一个想法,我看到了帮助。”然后把团队召集起来,说:”嘿,原来高管希望我们把软件写好。我们应该先尝试什么呢?
产品部门还有很多工作要做:他们应该处理战略、优先级排序、分析、商业智能、质量保证、促进、设计和合同等他们拥有技能的子集。但是,这需要工程师真正以同行的身份与他们合作,而不是参与权力斗争,这就需要团队中的每个人都了解我们在做什么、为谁做、为什么做。
> 一般来说,我们的业务专长是没有报酬的。事实上,大多数企业都不愿意让开发人员承担深层次的领域责任。
我认为这是鸡生蛋蛋生鸡。
我有些不解,为什么这么多开发人员坚持认为,成为一名优秀的开发人员意味着你需要成为一名优秀的项目管理人员。
这些角色需要的技能和知识大相径庭。
通常情况下,如果将两个擅长各自工作的人结合起来,效果会更好,而不是希望一个人包揽所有工作。
优秀的工程技能可以转化为优秀的项目管理技能:你需要分解问题,根据特定的时间分配来确定问题的范围,估计对用户体验的影响(统计、跟踪、什么是好的信号,什么不是),并具有敏捷的反应能力,以便在构建过程中应对不断变化的需求。
为什么只需要一个人?通常情况下,“不断变化的需求 ”实际上来自于工程师对新事物的学习(这个框架不提供这个功能,这个外部部署会迟到,我需要学习两个新东西,所以需要更多时间……),而实际上,工程师是第一个知道一些挑战和可行性的人!
现在,工程师要想成为一名优秀的项目管理人员,需要掌握的技能是良好的沟通能力、正确记录事情的能力,以及对客户和业务人员的高度同理心(这样他们才能 “站在客户和业务人员的角度 ”思考问题)。可以说,所有这些都会让一名优秀的工程师变得更加出色。
我所在的团队曾有一位非常资深、经验丰富的项目经理告诉我们,他正在寻找公司的另一个职位,因为我们的团队不需要他们:我们已经完成了他们受雇要做的事情。这是一个优秀项目经理的标志,当团队进展顺利时,他不会主动从我们手中夺走控制权。
分解问题(垂直切片)本质上并不是一种开发技能。就分解问题的可迁移技能而言,它更像是一种生活技能。
确定工作单的范围更像是一种项目管理技能。同样,这也不属于开发技能。
估计对用户体验的影响–需要换位思考,这同样不是开发技能。
如果你把开发工作重新定义为包括项目管理技能,那么当然,项目管理技能就是开发技能。
但它们不是。
>为什么说他们是一个人?很多时候,”需求变化 “其实是工程师在学习新东西
所以呢?我也遇到过这种情况。我可以把学到的东西告诉项目经理。这比管理所有利益相关者的互动、换位思考和平衡他们的需求要容易得多。
只有在项目本质上非常简单、可以节省薪水,而且担任两种角色的人都有足够资格胜任两种角色的情况下,将两种角色结合起来才真正有意义。
对于任何给定的单子,除非你消除工程师的所有创造力,否则他们必须平衡他们的深度和广度、重构的程度和跳过的程度,这样才能有效,并且不会最终得到一个审查和推出到生产中风险极高的装置:所有这些都是范围界定。
如果你没有做到这一点,你就是被微观管理了,我很同情你的工程工作。
相信我,非技术性的项目管理人员没有能力找出一条通往你想要交付的北极星产品或功能的增量路径–如何拆分分支并增量交付价值只有优秀的工程师才能做到(做得好)。
如果你不考虑实现过程会对用户产生什么影响,那么你可能只能以糟糕的体验来满足需求(但任务单上从未说过需要在 30 秒内加载,并且没有可见的重绘和跳转元素):一个好的工程师会隐含地考虑所有这些,即使任务中没有指定(还有更多,我只是用了一个离谱的例子来说明问题)。
分解问题当然是一种生活技能,但工程师天生就擅长分解问题:这是工程师的定义,没有分解问题就无法成为工程师。不过,我也见过一些项目经理,他们主要是将客户的经验和利益相关者的要求进行归纳和汇总,却不善于考虑(分解、逐步、渐进)的完成路径。
如果你擅长所有这些,你很可能也是一名优秀的工程师:这并不意味着不是工程师就不能做好项目管理,只是说一名优秀的工程师也非常接近于一名优秀的项目管理。
我并不反对分工,也不反对每个人投入时间的动机不同,但如果我们谈论的是优秀的项目经理或工程师,那么他们的思维方式基本相同,都专注于需要完成的工作的不同部分–90/10 对 10/90(以及介于两者之间的任何部分)。
最后,无论你是工程(或项目管理)方面的能工巧匠,都与出色的工程师略有不同。
后者是晋升为高级职员以上的人,或者更有可能成为总监/副总裁。
如果你纯粹专注于编程,职业发展的上限很低。
所以是的,如果你想攀登公司阶梯或经营自己的企业,编程只是所需技能的一小部分。
不过,我认为只专注于编程也是可以的。这很有趣,也是我们很多人进入这个行业的原因。不是每个人都喜欢业务方面的东西,这也没关系。
我不知道。抛开职业规划不谈,对我来说,制作软件只是达到目的的一种手段。
生产软件并没有内在价值,就像生产汽车轮胎或香蕉一样。最好的软件就是没有软件。
那么谁才是更好的程序员,是更懂得如何制作软件的程序员,还是更懂得制作什么软件的程序员?
软件是一门手艺。
编程有其内在价值,就像园艺、木工、艺术创作或乐器演奏一样。
价值在于活动带来的快乐。(请注意,这往往是一种不同于商业价值的价值。)
对我来说,汽车只是达到目的的一种手段。我可以想象一个没有汽车的世界,而不是一个没有软件的世界。
你是认为我们会以某种方式进化出超越它的能力呢?
其实并非如此。
如果我雇你为我制作软件,我并不是真的想要软件;我想要的是问题得到解决、资金流得到建立、客户感到满意。当然,这可能需要你制作软件,除非你发明了一根魔杖。但如果你有魔法棒,我每次都会选择魔法棒而不是软件。
而食品、家具或高级酒店就不一样了,我真的很想要这些东西。
如果我有一根魔法棒能让你吃饱,你就不需要食物了。如果你是为了味觉,我会用魔法棒让你嘴里有一些味道。如果我有一根魔杖,能给你一个屋顶、保护和一张床,你就不需要旅馆了。
魔杖的说法没有道理。那你还可以得到其他一切。
>最好的软件就是没有软件。
我不同意。我喜欢我正在使用的很多软件。用 Ableton 制作音乐、用 Final Cut Pro 剪辑视频,或者只是玩玩超级马里奥娱乐一下,都有其内在价值。这些软件都比没有软件好。
你可以说 GenAI 音乐创作是 “无软件”。你说你想要什么,它就会神奇地出现。
> 值得牢记的是,编程不仅仅是编程。
顺便提一句,当人们谈论由 LLM 生成的代码时,我一直在指出这一点。作为一项活动,这只是程序员做的一件事。
我认为你的问题(确实是个好问题)的答案是 “两者都要”,或者说要平衡两种能力的发展。如何花时间的决定不会是一个单一的决定,而是多年来经常重复的决定。与我共事的 Staff+ 工程师大多在这两方面都很出色,还有一小部分是技术专家。我还没有遇到过领域知识深厚但技术深度有限的人。
(编辑:格式化)
不是我尖酸刻薄,但我对最佳程序员的定义会兼顾这些。我确实比大多数人花更多时间了解技术栈的深度和潜在有用技术栈的广度。与此同时,我还努力制作能完成工作的软件,只使用能在中短期内见效的抽象概念。
要避免的陷阱是那些对业务有影响的人,他们不愿意在实际编程方面做得更好,而这恰恰会增加他们的影响力。
编辑:例如,在不了解问题原因的情况下解决问题。
> 你应该投入一个小时来了解框架 X 的最底层代码,还是与业务领域的人员交谈?
我认为与业务领域的人交谈是你在 SWE 或一般 IT 领域能做的最重要的事情。业务是你编写每一行代码的全部原因,你了解得越多,你的工作就做得越好。
我认为深入研究软件栈的下层很有帮助,可以让你成为更好的程序员,但方式要具体得多。
> 是再学一门技术,还是更快地掌握 “足够好 ”的技术?
在我看来,这两者都是编程技能,并不那么重要。趋势和技术来来去去;如果它们足够有用/实用,那么无论如何,你最终都必须在工作中学习它们。如果技术很好/很实用,你自然会经常接触到(例如 react),并在工作中不断学习。
不过,对事物的核心有扎实的了解肯定是有好处的。因此,对于 react 来说,要真正理解 useState、useEffect 的工作原理。至于 Java,那就是其他东西了。
> 业务是你编写每一行代码的全部原因
事实上,这并不是我编写或已经编写每一行代码的全部原因。
对于本网站上的一些创业者来说,这可能会让他们感到惊讶,但事实上,有些人喜欢为了写代码而写代码。
Ikigai 也适用于编写代码。
与家长的评论相比,你的观点最让我感兴趣的是,你说的是 “静态地,在所有的时间里,在你所有的选择中,最有价值的事情是理解业务”,而家长说的是 “动态地,在这一刻,在我的行动的这一次迭代中,最有价值的事情是什么?”
我认为,你的问题从长期技能组合或 “技能组合”(又称职业观点)的角度来看最有意思,而家长的问题则更有意思,因为你每天都要在完成一个项目的状态空间中穿梭。在某一天,了解业务可能不是最有价值的事情,但在你的工作或职业生涯中,这可能是最有价值的事情。
(例如,我可以说我已经有足够的业务背景来完成明天的编程任务。询问更多有关业务的问题会造成浪费: 我需要去更新批处理工作,以实现业务成果)。
编辑:我可以更进一步说,最有价值的技能不是了解业务,而是了解如何根据业务匹配和调整技术(假设你想成为一名程序员)。归根结底,收入是由业务驱动的,但你之所以有工作,大概是因为他们的业务需要技术。因此,最有价值的技能就是尽可能高效地让技术满足业务需求。与 “了解业务 ”相比,这更像是两者之间的平衡/契合。
我非常有兴趣阅读关于 “最擅长通过制作软件来影响业务的人 “的文章,到目前为止,我只发现了 kalzumeus (patio11), indiehackers, microconf, business of software forum(非常老的)等资源。
阅读 DHH 写的所有文章,他对此有很多见解。向下滚动到他的书: https://dhh.dk
我发现精益创业也非常好。
在家里/互联网上,你可以是 “最好的 ”程序员,而在工作中,你可能只是一名普通员工。
我认识的最好的程序员和最好的 Linux 向导完全没有计算机科学背景,他在 20 世纪 20 年代偶然进入编程行业,因为他必须为完全不相关的领域(农业)的硕士论文开发一个工具。之后,他很快自学了 Java、Python、C++、JavaScript、PHP 和 PostgreSQL 脚本。30 岁出头时,他已经是我当时工作的公司的资深开发人员。他在非算法编程任务方面能力很强,速度也很快,但我也经常惊叹于他在处理算法任务时的天真:他会在谷歌上搜索一天,然后发现一些标准的本科计算机科学算法,然后会对它们感到非常兴奋,并很快实现自己的版本。
有时候,你需要的只是激情。
我觉得大学教授数据结构和算法的方式并不能很好地灌输解决问题的乐趣。
话虽如此,但并不是每个人都有这种激情。而且你随时都可能失去它。
https://web.archive.org/web/20250409082704/https://endler.de…
否则会限制速率
我认识的最好的程序员都不会使用限制静态博客速率的廉价主机。
这就是我看到的 devops 在某些地方的实际应用–只是用 dev 代替 ops。这样的事情每天都在发生。
我一点也不责怪作者–我们应该多做 “大部分时间都能正常工作 ”的项目,不要再那么在意 SLA。但是,在一篇以 “真正了解你的工具 ”为主题的文章中出现这样的宕机时间,就很搞笑地说明了开发和运维是完全不同的技能组合。
具有讽刺意味的是,Cloudflare 实际上提供无限流量的免费静态主机服务,而这似乎只是出于某种原因在 Cloudflare 计算服务上运行?也许是服务器渲染的问题。
他们使用的是 Zola(Rust SSG),但我认为他们的服务来自 Worker + KV:https://github.com/mre/endler.dev/blob/32016d0f204911bc9a8a4…
他们有使用静态主机(GH Pages)的历史,但在转用 CF 后可能觉得没必要了。使用计算创建自己的小方案更有趣,而且还能将请求镜像到他们的分析服务。
我不怪他们: 我已经习惯了无限的免费层级,尤其是 CF 的层级,如果不是看到我的博客达到了工作者上限,我是不会考虑的。
你需要 “工作者 “和计算来提供 10KB 的字数……
HN 的思维模式:
– 当我做某件事情时,我明白那是我有限的时间/注意力所做的事情,你应该给我宽限,尤其是当我在周六下午玩弄我的个人博客时。
– 当其他人做某件事情时,他们设计了他们认为必要+完美的解决方案,他们在对所有选项进行评估后选择了这个确切的植入方案,我将据此批评他们。
我当然会这样做。因为一篇有见地的文章而获得大量流量是一种边缘情况,围绕这种情况进行设计没有任何意义,而且我也不希望我的个人博客成为时间和金钱的沉淀池,而我本可以把时间和金钱花在我更喜欢的事情上。因此,我打算使用免费的、能提供基本保护和可用性的东西,如果我真的被一些内容聚合器或其他东西 “抱死 ”了,他们使用回溯机器而不是直接访问我的页面,对我来说也没什么损失,因为我没有盈利。
至少我的免费 Cloudflare 托管博客还能抵挡住一次 HN 首页的冲击。我认为他们过度设计了 “静态 ”网站托管,以至于在大流量下也会出现问题。
我认识的最优秀的程序员总能发现编程的挑战无处不在,速率限制功能可能就是其中之一。
想知道静态博客如何能被限制速率 😐
Cloudflare 声称 Pages 允许无限流量 [0]。看来作者使用的是 Workers,可能是免费计划。
[0]: https://www.cloudflare.com/plans/developer-platform/
为什么要在 Workers 上运行网站而不是静态内容托管?难道 Worker 不是用来处理请求的计算工作、连接数据库、做一些工作等吗?
我对此也很好奇,发现作者在 2020 年[0]确实写过一篇文章。我对 Workers 不是很了解,但听起来好像分析需要它?
[0]: https://web.archive.org/web/20250328111057/https://endler.de…
作者在此。这就是答案。
至少在我还关心分析的时候,这曾经是答案。现在,朋友们在社交媒体上发现我的东西时会给我发信息,但我早已不再关心因果报应积分了。这不是我自谦,而是年纪大了。
更长的答案是,当 Cloudflare Worker 发布时,我对它产生了好奇。我想在边缘运行一些 Rust!结果,我从来没有用它做过任何有用的事情,后来又忙着把网站搬回 GH 页面。此外,Cloudflare Workers 对 10 万个请求是免费的,这给了我一些余地(虽然我最近在 “非前台页面 ”的好日子里会接近这个上限,因为所有额外的机器人流量和我的 RSS 订阅……)。
当然,HN 的人只是看到网站瘫痪了,就认为我无能。) 我把这条评论埋在这里,是希望只有那些想了解真实情况的人才能找到它。你是其中之一,因为你自己做了调查。这已经让你与众不同了。
现在 Cloudflare 默认推荐使用 Workers,用 “静态资产 “来托管网站的所有静态内容。据我所知,Pages 已经建立在 Workers 平台上,所以这只是简化了 Cloudflare 平台的 DX,并提供了更多选项,让您可以选择网站的渲染策略。
有时,人们会将它们用作反向代理或从云 KV 加载内容。如果你愿意,或许可以在上面构建一个网络堆栈。但我认为,像这样的静态博客在 Pages 或常规 CDN 后面就足够简单了。
这就是在 cloudflare 工作站上运行博客的后果–他们希望你使用 Pages,或者永远每月支付 5 美元,以防你被 slashdotted。
说实话,这是有道理的。静态博客内容完全可以缓存。把这些内容放到 nginx 中!
流量。巨大的流量。
我不确定 “巨大的流量 “在这里是什么意思。
还记得 2002 年为解决 C10K 问题而编写的 nginx 吗?
什么意思?什么对你来说是巨大的?对我来说,在小型 vps 上运行一个静态博客,每秒大约有 30 到 150 个请求,就会开始崩溃。这个数字很宽泛,因为即使在这个范围内也有很多移动部件。这将导致每天 250 万到近 1300 万的页面浏览量。要达到这样的数字,你需要获得非常高的人气。只要稍加规划,一个静态网站在网络堆栈达到饱和之前,每天可以提供数十亿次服务。
所以,你在说什么?
你的静态文本博客如何在 CDN 上产生 “巨大负载”?
廉价托管服务就是这样做的,不是吗?
Cloudflare 更像是 IaaS。有些服务可以用于托管(Pages)或缓存(CDN),而 Workers 则可以用于或滥用于各种用例。不知道作者的理由是什么。
二级来源:https://archive.is/0GcBe
> 真正阅读错误信息,并尝试理解其中所写的内容
这是很多开发人员遇到问题时的一个令人惊讶的绊脚石。大多数时候,解决方案就隐藏在众目睽睽之下(尽管有时至少低了一个抽象层次),阅读错误信息有助于快速解决问题。
轶事证据: 我们使用 `asdf` 管理主要项目的 Python、Go 和 NodeJS 版本。在新安装的 Fedora/Ubuntu 上,运行 `asfd install` 会导致 Python 编译失败,因为缺少 Python 标准库所需的几个依赖项。如果你愿意阅读,`asdf` 命令失败时的输出结果不言自明。
说实话,有了 LLM,这个问题变得简单多了。
就像今天,我在编译一个旧的 cpp 包时出了个乱七八糟的错误,把它扔进 4o 后,几秒钟内我就得到了一个深入的分析报告和一行更正,结果整个问题都解决了。简直省了好几个小时呢。
我读过一些非常糟糕和/或非常复杂的文档(在某些情况下没有读过)。
一些行业标准工具,如 Jackson,甚至都没有文档,而是将你引向他人撰写的各种教程,告诉你如何使用它:https://github.com/FasterXML/jackson-docs
LLM 所做的一件好事,就是将那些缺失/糟糕/繁杂/琐碎的文档中的一些乱七八糟的东西,提炼成一些足够易懂的东西,让你要么得到有用的答案,要么得到一个有用的方向,告诉你如何缩小搜索答案的范围。
我认为 “阅读文档 ”是个不错的建议;但即使是文章本身,也不能说**所有的文档都是好的。
这是一个很好的建议。不幸的是,所有这些人工智能工具让初学者很容易就不遵循这些建议。我不确定所有这些建议是否会变得无关紧要,也不确定那些在 2020 年代接受培训的程序员是否不会成为那些 “最优秀 “的程序员。
我认为任何事情都是有周期的。会有一波人工智能生成的东西,但随后人们/公司会受到错误和问题的严重打击,并重新发明质量保证的轮子。
我想知道人工智能生成的东西是否能通过我们现有的检查,如衬垫、测试覆盖率、声纳等。
> 我不确定所有这些建议是否会变得无关紧要,也不确定那些在 2020 年代接受培训的程序员是否不会成为那些 “最好的”……
这取决于他们如何使用人工智能。如果他们把人工智能看成是一个美化了的 StackOverflow,你可以粘贴一大段代码,然后问 “为什么它不能工作”,那么他们就会遇到麻烦。如果他们能将问题缩小到特定的环境中,表达清楚,并慎重对待人工智能的输出结果,那么与 2000 年代的我们相比,他们将成为 10 倍于我们的程序员。
可以说,Stack Overflow 的一个 “特点 “就是它的文化。他们建立的是一个参考资料,而不是一个帮助台,因此他们希望问题是原创的、经过研究的。一旦你身处企业环境,如果你没有提出好问题的经验,你就会显得很无能。
我不知道,他们真的会让问题变得那么简单吗?在我看来,他们会给你一些示例代码,而且通常都能用,但如果不能用,你就需要知道自己在做什么来修复它。
修复别人的代码是一项很好的练习,所以也许他们真的在无意中学到了有用的技能?)
我对你不应该使用人工智能有点矛盾。
结合使用 Cursor、NotebookLM、闪存卡(我用的是 RemNote)和练习,可以大大加快学习速度。
没有什么能阻止你阅读规范和文档,并让人工智能协助你完成这些工作。
你的工作流程听起来很有趣。
我了解闪存卡和 SRS 的强大功能。但我想知道,在学习新知识时,你是如何决定何时将某些内容放入 SRS 的。尤其是在技术/编程方面。
我一般会添加一些我好奇的、想长期学习的或在特定时间内很重要的内容。
这有点随意,随着时间的推移,我会忽略一些主题。
我同意他的所有论断,但有一条除外。
>Don’t Guess
如果你正在开发关键软件,比如在火箭或医疗设备中运行的代码,当然,绝不猜测是必须的。
但是,我和其他很多人都可能很匆忙。我们必须或希望在关键时刻快速行动。我没有时间研究每一个细节,也没有兴趣了解每一个细节。
我最感兴趣的是构建一个东西或解决一个问题,我不太关心实施细节。当然,有些时候细节确实很重要,但工作的一部分就是要了解哪些细节更重要,哪些不那么重要。
所以,我并不是因为懒惰才去猜测,而是因为我有更重要、更有趣的事情要做,而时间是有限的资源。
如果将来证明是错的,很多决定都可以挽回,而且损失很小。错误可以轻松解决。
我并不是说要快马加鞭,但学会如何做正确的权衡和做出有根据的猜测是很有价值的工具。
因此,我还想再加上一个论断:
学会珍惜时间,不要拖延,避免分析瘫痪。
我明白他们说 “不要猜测 “的意思,我也同意你的看法。我的措辞更像是 “明确承认你在猜测”。猜测是可以的,但你要明白,如果你运气不好,以后可能不得不走回头路。不好的是在猜测之上再堆砌猜测,最终被放逐到 “也许之地”。“可能是 A,然后可能是 B,然后可能是 C……所以一定是 D”。不,由于这个原因,D 的概率是 P(A) * P(B|A) * P(C|B)… ~= 0。~= 0.
在容易测试的情况下也不要猜测。“也许除数值为零”,那就用 printf() 试试看是否为零!通常情况下,你不需要猜测。我曾见过有的讨论绕着圈子问 “如果是 X 怎么办”,但只需两分钟就能知道是不是 X。
我非常同意。这只是一个滑块,一端是 “没有时间、没有知识、纯粹猜测”,另一端是 “无限时间、透彻分析、完美理解”。
显然,左端是危险的,但由于机会成本,右端也可能是危险的。判断每项决策/改变的滑块应该在哪里,是这项技术的关键技能。
我还发现,我的 “上下文窗口 ”只能容纳这么多内容。我无法一下子理解所有内容。因此,如果我做得很深入,我往往会(暂时)忘记问题/堆栈/任务/其他方面的其他部分。对我来说,解决办法就是尽可能地创建独立的可测试单元。虽然并不总是可行,但还是要努力做到。
我发现,这种组织技能是我能构建的大型/复杂系统在变得无法维护之前的极限。值得庆幸的是,随着时间的推移,这个极限越来越大。
我想这就是作者所说的把复杂问题分成更容易解决的子问题。
这一点。事实上,我做的很多事情都是猜测。然后再检查是否可行。我认为,如果你不这样做,你就会完全瘫痪,无法取得任何成就。
同意;我也经常这样做。我不认为这本身是 “猜测”,我认为这是在我对问题的现有知识和任何新观察[1]的交叉基础上形成一个假设,然后对其进行测试,以确定假设是否正确。如果证明不正确,这个过程会帮助我重新提出一个新的假设,如此循环往复,直到问题变得足够清晰,可以直接解决为止。
[1] 通过阅读更多代码、RTFM、观察日志、使用调试器跟踪、改变输入等。
对于其他人:如果公司大部分成员都是开发人员,或者是管理层,那就尽快运行,永不回头。
有时,你也会遇到一些你不理解的文档,或者可能只是写得不好,在这种情况下,我认为猜测继续前进是公平的。之后,你也许应该停下来想一想:“为什么这个东西能用/不能用?”并建立起自己的理解。
我一直不愿意学习前端开发,而我们选择的框架显然有相当完善的文档,但我甚至不理解大部分术语,不知道为什么某些解决方案有效,或者为什么有些解决方案更正确。因此,我只能猜测,然后学习,但这需要不断迭代才能奏效。
如果你只是猜测,或者问一个大语言模型(LLM),而事后并不质疑你的猜测,那么我可以理解为根本不推荐猜测。但我认为,直接建议不要猜测,忽略了我们中很大一部分人的学习方式。
阅读错误信息是个好主意。我试图让错误信息的片段具有唯一性,这样在出现类似 “foo the bar: get bar: lookup bar source: i/o timeout ”这样的错误时,你就可以搜索 “lookup bar source”,从而找到错误实际发生的代码点。(在 go 中,这涉及到错误包装和在每一级添加最小必要上下文)。这可以避免小的重构(而行号则不能)和跨子系统或跨子系统错误(下一次的错误是 “foo the bar: get bar from remote bar repository https://bar.example.com/: get bar: lookup bar source: i/o timeout”)。显然,我也会让我的团队这样做;) 在我的上一份工作中,在我加入团队之前,有人说堆栈跟踪可以消除错误包装的必要性。他们试了一下。事实并非如此。客户(和技术支持人员)永远也搞不清楚到底发生了什么。但是在每一层添加一些精心挑选的词语呢?一下子就简单多了。
阅读源代码也是一个好主意。你总能从别人的代码中获得一些好的想法。在谷歌,我们有时会有很好的文档。最后我意识到这些文档往往已经过时,于是我养成了阅读与我交互的服务器代码的习惯。突然间,一切都变得清晰多了。为什么在这种情况下会返回错误?有一个条件就是针对这种情况的。设置这个无用的标志,就可以跳过该代码块。你永远不会在文档中看到这一点,某些东西为什么会这样工作,背后的确切细节只存在于某个人某个时间点的脑海中,而代码是唯一能记住这些细节的东西。所以,问问代码吧。
在这两种情况下,一些易于使用的文本搜索工具都会有所帮助。我经常使用 rg(和 emacs 中的 deadgrep),但还有很多。
我认为这种 “优秀的开发人员不会抱怨 “的心态有可能导致真正的问题被忽视和得不到解决。
全文如下:
> 大多数开发人员都会把一些看似 “随机 ”的错误归咎于软件、其他人、他们的狗或天气。> 最好的开发人员不会这样做。> 无论计算机的行为看起来多么反复无常或调皮捣蛋,总会有一个合乎逻辑的解释:只是你还没有发现而已!
我不明白你怎么能由此得出真正的问题会被忽视的结论?我的理解恰恰相反。
我同意。作者并不是说最好的开发人员从不抱怨什么。他的意思是说,只要问题仍然存在,他们就不会听之任之、束手无策,而是深入研究,直到找到行为的根本原因,或者找到绕过它的方法。
如果你不能让 COBOL 栈正常工作,那就意味着你是一个糟糕的开发人员。不要抱怨,让它运转起来!
这是毫无讽刺意味的真理。想要使用更适合任务的不同工具并没有错。试图说服人们 “这个工具不适合这项工作,我们换一个吧 ”也没有错。但是,如果决定坚持使用 COBOL(不管是出于什么原因),好的专业人员就会尽其所能。如果你不能忍气吞声地用 COBOL 写东西,那你就不是一个好的开发人员。
我不知道,很多流行的语言/工具就是很烂,解决问题被更有经验的开发人员理解为哭诉。在我的职业生涯中就经常遇到这种情况。所以我认为最初的评论是公平的。
如果一个经验丰富的开发人员看到有人试图解决工具/语言糟糕的问题,然后将这种行为定性为哭诉,那么这个经验丰富的开发人员也参与了糟糕的问题。
是的,我同意,可悲的是,在开发社区中,考虑到开发人员在 Stackoverflow 上的行为,有很多人把关不严。
……相信我……
这次真的是宇宙射线位移
你说的是 “永远不要责怪电脑 “部分吗?
我认为这并不是针对抱怨,而是将责任转嫁到无人能控制的东西上,而不是深究问题并找到根本原因
当然。我认为这是不全面的:优秀的开发人员从不抱怨……他们只是提前两周通知,然后找一个更好的地方。
或者换一种说法,他们对自己的问题拥有自主权和责任感,并具有解决问题的思维方式。如果问题不是他们自己能解决的,而是他们的工作造成/加剧/阻碍了问题的解决,他们可以另谋高就。
或者可以,无论如何,在经历了奇异的招聘热潮后,市场似乎又安静下来了。
没错,与其认为一个组件就是这样,不如把重点放在理解解决根本问题上。当那些拥有多年经验的人任由那些狗屁问题发展下去,并一味指责平台/设备/用户/库时,我真是热血沸腾。
尤其是在当前的就业市场环境下。
我经常和招聘人员的朋友聊天,发现似乎出现了一种双峰分布的情况,一些开发人员直接找到了工作,而一些倒霉的开发人员则连续失业数月。
我最近帮了几个开发人员,他们在 2023 年被裁员,至今仍未找到其他工作。
来自 Cloudflare Worker 的巨大 “死亡拥抱 “超过了限制……真可惜,我们不能像以前那样轻松托管静态文本网站来发布这样的文章了。
存档地址: https://archive.ph/0GcBe
奇怪。我从来没有用 Cloudflare 托管过任何东西,但我通过它们运行一些网站以减少 dDos。如果我真的花钱让他们托管了什么东西,却在访问 HN 主页的那天被他们的限制搞得一团糟,我会非常郁闷的。
阅读文档–如果您是初级用户,请花时间深入了解/解决您遇到的问题。然后再阅读与之相邻的内容。
试图像阅读一本书那样从头到尾阅读某些文档将是浪费时间。
有时,我只是打开 NumPy 或 Python 文档浏览一下(或其他库,如 PyTorch)。即使我已经有了 20 年的 Python 经验,我还是经常能在 “基本 ”页面上发现一些我不知道的新东西。阅读发行说明也很有用。
许多人似乎对阅读文档和手册有一种非理性的反感。他们宁可猜测、猜想、说假话,也不愿意打开文档去了解它是如何工作的。
我想说的是,如果你多年来每天都在使用这个工具,那么投入精力去真正阅读文档是有意义的。
当然。LLM 为你提供了触手可及的压缩文档。你可以直接向大语言模型(LLM)提出这样的问题,它将给你一个相当不错的结果,而不是通过滚动手册页面和函数参考文献来查找你对手头问题感兴趣的特定标志或参数。
LLM 有助于解决的另一个问题是确定要查找的正确关键词或术语。特别是在使用手册时,我曾多次遇到这样的情况:我大致知道自己要找什么,但面对数以百计的标志和选项,我甚至无法通过 grep 找到正确的地方,因为我不知道自己需要的确切术语。因此,我有时会把 LLMs 用作支持语义同义词的 glorified grep。
我认为 GP 提出的是一种有机的知识扩展方式。阅读相邻的文档可以扩展你的知识面。大语言模型(LLM) 会告诉你如何做一件具体的事情,但你需要知道这样的事情是可能的,然后才能有效地询问它。
这样,法律硕士可能会通过提供直接、具体的答案来被动地阻止探索。有时,旅程也是有价值的。
对于经常使用的工具,从头到尾阅读文档在我看来是非常值得的投资。不管是不是初级开发人员。
通常情况下,总有比从头到尾阅读文档更好的资料来源。
不存在 “只有 SO 和大语言模型(LLM)才是捷径 ”与 “总是阅读完整文档 ”的对比–总是有更多像博文、走马观花这样的来源,会是更好的时间投资。
有时,在文档枯燥乏味的情况下,你需要有人以与文档描述大相径庭的方式来解释工具的架构。有时,你需要更好的例子,更好地与你要做的事情保持一致。你需要不同的方法来掌握事物。
我想再补充一条,处理情绪的能力(提到过,但主要是指耐心)和保持专注的能力。
两个程序员一开始在 OP 所列方面的水平差不多,但一个能够保持专注和高效,而另一个却整天在 YouTube 和 HN 上跳来跳去(是的,很多时候我就是这样),那么随着时间的推移,他们会产生不同的影响和进步。
这句话对我的描述真是不可思议。我一直在尝试各种方法,如网站屏蔽、超时、休息等,但都没有成功。
关键在于 “进入状态”。一旦我进入状态,一切都会飞起来,但编辑三行文字,然后用 alt-tab 到 youtube 上 20 分钟,这让我的进度非常缓慢。
这很奇怪,我明明知道要做什么,或者要研究什么,但就是 “不想做”。
我注意到一点,那就是晚上是我的黄金时间。我试图在正常工作时间内完成所有的购物、家务等工作,然后在下午 5 点到上午 10 点之间工作。也许这能解决这个问题。
你认为有办法训练专注力吗?
对我有帮助的是认识到让我分心的诱因,这也是我强调情绪部分的原因。
例如,当我意识到这一点时,我就会重新开始工作,抵制分心的冲动。
随着时间的推移,你会变得更好,你需要训练它,直到它开始变得更加自然。
如果不使用集中注意力的技能,你就会失去这种技能。我认为反之亦然。
不,强迫自己集中注意力毫无意义。如果不自然,那就不值得。做事情是为了好玩,不要把自己看得太重
我在学术界工作多年后,为了恢复工作效率,我做了很多年的 pomodoros。
现在,我是办公室里最专注的人。但这花了非常非常长的时间。
不知道你是不是在讽刺我,不过当然有。
我想我遇到过几个。40 多年来就见过两三个。至少从高层来看,他们能把整件事情搞清楚。他们往往还能弄清最细微的细节。我需要仔细阅读蓝图、文档和一些示例代码。然后我就可以开始编码了
我是 “阅读参考资料 “的忠实粉丝,但文档往往不再适合这种情况。我不用捧着权威书籍(如 Perl、Python、C 或 C++ 书籍、dtrace 书籍、O’Reilly X11 或 BSD 参考手册),好一点的情况是点击一个 1000 页的网站,差一点的情况是观看 50 个涵盖 10%功能的视频。
我认识的最好的程序员都有一些特点,告诉我他们可能是我认识的最好的程序员。他们真的很在乎,他们是专业人士,想要做到最好。
> 在求职面试中,我极力要求应聘者至少说一次 “我不知道”。
是的,没错!虽然在面试中,并不总能轻易地把那些在日常工作中不能说 “我不知道 ”的人和能说 “我不知道 ”的人区分开来。但这就是区别。在我的同事和一般人身上,强烈地需要隐藏缺乏全知全能的事实是非常令人恼火的。它会带来很多问题!
哈。在工作中,”我不知道 “可能是我最常回答的问题,紧接着往往是 “你试过什么 “或 “有什么变化 “
所有这些都指向如何掌握成为一名开发人员,这很好,我认为是一个很好的指南。但并不是每个人都在追求精通。
对于 SRE 或其他部门的主管来说,这当然是你想要的。但我认为,尤其是对于创始人来说,即使不能完美地调试每一个边缘案例,通常也最好能达到足够好的效果。
对于那些无法访问网站的人,我发现 GitHub 上也有这篇文章:https://github.com/mre/endler.dev/blob/master/content/2025/b…
我想我已经到了可以接受自己不是、也永远不会成为最优秀的程序员之一的人生阶段了
是啊,我年纪越大,就越发现自己在几乎所有事情上都很一般,很多事情我都不知道。
也许这篇文章可以通过添加 “领域/业务知识 ”以及了解业务和产品的实际用途来加以改进。如果因为缺乏领域知识而无法提供解决方案,那么即使你是一名优秀的开发人员也无济于事。根据不同的领域,要成为一名参考
我不知道,我会说这是工程师的素质,而不是程序员的素质。
这可能是两码事,就像一个副主厨可能更擅长烹饪/准备几道菜,但却不具备在一家成功的餐厅/酒店里创建菜单和成功经营菜肴的技能一样。
你可以与掌握领域知识的人员密切合作,他们会与程序员密切合作来完成这项工作。我曾经做过一份工作,其中的主要工作(以及创建规格等)就是做这个。
当然,开发人员仍然需要一些领域知识,但要少得多。
>不要害怕弄脏你的手。代码就是代码
所有其他主题都蕴含着巨大的智慧,但 “去接触代码 ”已不再是高级开发人员的责任。初级开发人员当然可以做一些小事。但是,高级开发人员应该严格遵守 “弄脏手 ”的流程。当高级开发人员在修补业务关键或生命攸关的代码时,他们通常不会意识到,软件所做的每一件事都是他们的责任。这就是流程存在的原因。
https://en.wikipedia.org/wiki/Software_safety#Process_adhere…
我想你可能把 “不要害怕弄脏自己的手 “误读成了 “不遵循任何适当的流程,出于琐碎的原因去捣鼓东西”,而不是 “不要因为害怕而把自己的部分工作推给其他人”。
我猜想,如果 Pacemaker Incorporated 公司的工程师接到一项任务,而这项任务又涉及到他们不擅长的领域,那么作者会建议说,“对不起,请和爱丽丝谈谈 ”不是好态度,而 “好吧,但我需要接受一些培训,你介意我向爱丽丝寻求指导吗?”才是好态度。
这句话模棱两可,以至于 “快去工作吧 ”可以被看作是高效的高级开发人员所采取的行动:
他们不怕触碰它。
他们从不说 “那不适合我”
相反,他们只是开始并学习。
最近,我花了几天时间跟踪一个问题,而我的一位同事,也就是潜伏错误的子系统的构建者,可能最多一两个小时就能找出问题所在。
我为什么不把它交给别人呢?因为我需要知道这个子系统是如何工作的。它很重要,也相当复杂,这不会是我们遇到的最后一个错误,也不会是它需要的最后一次修改。这是我工作的一部分,所以我应该了解它。我的收获不仅仅是修复了错误,而是学到了足够的知识,知道了如何去修复它。
好吧。看来我们遇到了流量限制:
““ 您无法访问这个网站,因为所有者已经达到了他们的计划限制。流量下降后,请稍后再查看。
如果您是该网站的所有者,请在 Cloudflare Workers 面板上升级您的计划,以防止再次发生这种情况。“`
https://web.archive.org/web/20250409082704/https://endler.de…
“大多数开发人员都会将片状的、看似 “随机 “的错误归咎于软件、其他人、他们的狗或天气。”
这个列表中省略了 “语言”,作者是 “Rust 顾问”。
这可能只是巧合。
> 阅读参考文献
> 不要问大语言模型(LLM)
公平地说,你可以使用大语言模型(LLM)来获取参考文献。比如,你可以问 Gemini 如何在 Python 中做这样那样的事情,并提供指向官方文档的链接。
写作的重要性怎么强调都不为过。
如果你想解决棘手的海森虫问题,你就需要写作。提出问题,写下答案。追踪线索。
有时你需要更正式一些。学习如何书写数学是非常有价值的。分布式系统、安全性、大规模性能……所有这些都得益于对一些非常简单的数学知识的扎实理解。
写作就是思考!挑战自我,审视自己的想法,学习如何写好文章。这将带来巨大的回报。
> 阅读错误信息
100% !!.!当工程师收到错误信息后,只是在 Slack 中复制/粘贴说 “我遇到了这样的错误:xyz”,而没有其他任何内容时,我感到非常恼火…… 没有检查错误,没有阅读文档或至少把它放到搜索引擎中。没有 “这是我目前尝试过的……”。只是死板地复制/粘贴,然后塞到别人的盘子里执行所有这些步骤。
> 如果有一件事是我作为一个年轻的程序员应该做的,那就是阅读我正在使用的东西的参考文献。
我很想这么做,但(请允许我扮演一下受害者的角色),我在阅读长篇文章时遇到了很大的困难;读了几段后,我就会瞪大眼睛,或者直接睡着。我不觉得这是引人入胜的阅读,尤其是当我意识到绝大多数内容都与我无关的时候。
我不知道这是因为在网上度过了 25 年而导致注意力不集中,还是仅仅因为经验–有很多工具我在一个项目中用过,但再也没有用过,或者有很多问题我只遇到过一次,“学习 ”感觉很浪费。
这要追溯到我在大学二年级学习 Java 的时候;我们有一本书,我想我只学了前两页,但之后我就放手去做了,如果需要的话就上网搜索。(这可能是当时软件开发领域的另一个巨大变化,谷歌和很容易搜索/找到的在线文档)
> 要很好地了解一个工具,你必须知道: > 它的历史:谁创造了它?
> 它的历史:谁创造了它?为什么创造?为了解决什么问题?
> 它的现在:谁在维护它?他们在哪里工作?为了什么?
我不太清楚。人为什么重要?这样你就可以查看他们的政治观点是否与你的部落一致,还是什么?
不过,我从来不看我回复的 HN 评论上的用户名,我猜文章作者会看。也许还保存着他们的档案……
创作者很重要,因为他们是了解创作初衷和创作环境的关键。你可以了解到他们的其他工作,这些工作可能也与你有关,根据所要解决的问题设计的工具的局限性,以及创建时更广泛的生态系统。例如,如果你是一名前端开发员,了解布兰登-艾奇(Brendan Eich)是谁、他发明 JavaScript 时在哪里工作以及网景公司希望通过 JavaScript 实现什么目标,都会对你有所帮助。你甚至还可以了解一下这种语言的名称。
同样,了解谁在维护你所依赖的代码也很有帮助。是否有维护者?项目路线图是什么?该工具是否有公司支持或其他资助?公司的使命是什么?如果没有这些细节,就会存在供应链风险,这可能会导致潜在的漏洞或未来的技术债务。
> 了解布兰登-艾希(Brendan Eich)是谁,他发明 JavaScript 时在哪里工作,以及网景公司想通过 JavaScript 实现什么目标
这在 15 年前可能还很有意义,但无论艾希想用 JS 做什么,这都已经脱离他的掌控很久了。
你也可以反其道而行之,根据 JS 对他形成看法:) 可能不太讨人喜欢。
确实,他已经不再领导这个项目,但他的第一个版本塑造了我们今天使用的互联网。至少,我们可以知道类似想法的现代版本会是什么样子。从那时起有什么变化?哪些问题需要修正?你最终可能会使用 Deno,也可能会使用 WebAssembly 或其他完全不同的东西,但了解我们每天都在使用的工具背后的人肯定会有所帮助。
> 你为一个(较大的)组织构建并发布了一项关键服务。> 你写了一个著名的工具 > 你为一个流行的开源工具做出了贡献 > 你写了一本经常被提及的书
所有这些都会给你打上 “超级书呆子 ”的烙印,并限制你的职业收入潜力,除非你打算成为谷歌的首席工程师。
谷歌的首席工程师生活舒适。如果你不想涉足商业领域,你还能做什么?
大多数人在谷歌担任首席工程师的机会几乎为零。但是,对于大多数人来说,担任平庸的纸上谈兵的管理工作是可以实现的。
> 不要去 Stack Overflow,不要问大语言模型(LLM),不要猜测,直接查找源代码。很多时候,源代码会出人意料地易于访问,而且写得很好
在 LLM 被广泛使用之前,这就是个问题,但它们使问题复杂化了 100 倍。
归根结底,我认为还是要回归到 RTFM。但这是一条艰难的道路,而用户已经习惯于将互联网视为一种工具,可以让他们跳到这条道路的尽头,立即前往 Stackoverflow、Reddit、Quora 等。诚然,与花时间了解问题所在、应用所学知识并排除故障相比,让别人告诉你如何解决问题几乎总是更容易些。但这会让你停滞不前,难以成长为一名开发人员,无法发挥创造力,并表现出缺乏理解力。
我是个糟糕的程序员。我知道我是。但每当我在自己的怪异小项目中艰难地解决一个问题,解决的方式让我的程序员朋友们 “呃……嗯,确实可行…… ”时,我就学到了一些东西。我学到了一些东西,不仅仅是解决那个具体问题的方法,还有我所工作的系统是如何运作的。
当年的 RTFM 文化是正确的,尽管它让年轻的我苦恼不已。小时候,我会跳上当地的 BBS,开始向那些灰头土脸的人请教有关计算机的问题,但很少能得到直接的回答,通常都会被指到手册上,而我显然没有读过手册。过了一段时间,我开始听他们说话了。很高兴我这么做了。在提出问题之前阅读文档的价值远远超出了代码甚至计算机的范畴。你的汽车、家用电器、商业模式,甚至你的法律体系和政府都可以这样做。重点是,RTFM 是建立 “理解之屋 ”的基础。它能促进自给自足,让你更加熟悉所处的系统,以及日后解决更复杂、更有创意的问题所需的亲密关系。最重要的是,它能促进成长。
现在,这一切的前提是文档要好……这完全是另外一回事了。
抛开具体的工具不谈,“授人以鱼 ”和 “授人以渔 ”是有内在联系的。如果你问了一个问题并得到了回答,你今天的问题就解决了,但明天你还得再去问那个人。这样一来,那个人就成了瓶颈,效率低下。
快速扫描后,没有发现我努力牢记的两条规则:
– 知道你不知道什么。
– 不做混蛋。
如果你为人所知,并被认为是团队中你想要的人,生活就会变得更轻松。如果我重复别人的话,请原谅,但生活往往是一项团队运动,你应该玩得很好。
我想在 “寻找源头 “的基础上再加上 “提交错误”。我曾与许多开发人员共事过,他们在向同事寻求帮助之前,会花几个小时尝试各种按键组合,更不用说在项目中提交 bug 了。
> 阅读错误信息 对大多数事情来说都是这样,除非是你心爱的 GNU C++ 编译器。你可能只是在模板方法中忘记了一个 const,它就会为此给你五页纸的地狱。
除了让思想领袖的数量保持在最低水平之外,我同意所有这些观点。
这篇文章太棒了–你让我在昨天的面试中承认自己不知道某些事情时感觉好多了!
写得很好,很有见地。
我不明白这个问题:
> 不要猜测
如果你处理的不是一个非常简单的程序,你往往必须猜测问题的原因,以便知道从哪里查找。经验越丰富,猜测就越准确。
日志、测试、调试、提问、建立心理模型、测试心理模型。经验越多,猜测越少。
对,我误解了这里 “猜测 “的意思。
是的。你没有错。要想不猜,就得先猜:)
我认为 “探索并排除可能的原因 “是一种系统的方法,而不是猜测。
我与太多的人共事过,他们除了不 “阅读错误信息 “之外,还只是猜测如何摆脱错误信息。就像在黑暗中摸索,如果我把这个改了,然后重新运行呢?
虽然这些都是优秀开发人员的特质,但也是很多中等开发人员的特质。阅读文档和了解工具并不罕见。
虽然我想说 “状态并不重要 ”只是一个症状,而不是原因。如果毫无疑问你是最优秀的开发人员之一,那么地位就不重要了–人们知道你是最优秀的,没必要提醒他们。那些极力争取地位的人都是缺乏安全感的人,他们认为自己需要提醒别人,否则就会失去自己的地位。通常情况下,那些只差几步就能成为佼佼者的人–可以说是银牌得主–才需要花大量时间提醒别人他们几乎是佼佼者。
有意思的是,我以前从未见过 Cloudflare 的速率限制。他们是否使用未缓存的工作器动态处理每个分页?页面或常规 CDN 不能工作?
因为 CloudFlare 的限制,我无法访问它。我甚至都不知道 CloudFlare 会成为瓶颈,或者在你付费之前将你的网站作为人质。
这里面有很多好东西,我完全同意。最简单的一条就是 “阅读参考资料”。如果能养成习惯,这就是一种超级能力。
我猜你的网站被黑客新闻 “死亡之抱 ”了。出现以下错误:
Please check back later Error 1027 This website has been temporarily rate limited
You cannot access this site because the owner has reached their plan limits. 流量下降后,请稍后再查看。
如果您是该网站的所有者,请在 Cloudflare Workers 面板上升级您的计划,以防止再次发生这种情况。
Rate limited。看起来 cloudflare 还不够用,这太疯狂了,因为它有 10 万个请求
假设您正在使用常规软件,可以不计成本地单独运行,我不同意 “不要猜测 “的说法。
猜测可能是您测试有关您不了解的错误的理论的最佳机会。如果你是某个领域的新手,而文档是为具有不同经验的人编写的,那就更是如此。
一系列的猜测和测试可以缩小问题的范围,最终帮助你按照自己的方式修复错误,有点像曳光弹。
我更喜欢建立一个心智模型,并将错误视为对该模型的偏离。没有指导的猜测可能是你失败的标志。但猜测也可以是建立模型的一种策略。
在我看来,这不是猜测,而是假设,这的确是缩小问题空间的好方法。我的意思是要避免盲目猜测,希望能碰上好运气,这在大多数时候都会给我们带来麻烦。
我需要做更多这样的事情
这篇文章写得很好,我很有共鸣。
> 阅读参考文献
> 如果有一件事是我作为一个年轻的程序员应该做的,那就是阅读我正在使用的东西的参考文献。例如,阅读 Apache 网络服务器文档、Python 标准库或 TOML 规范。
> 不要去 Stack Overflow,不要问大语言模型(LLM),不要猜测,直接查找源代码。很多时候,源代码出乎意料地易于访问,而且写得很好。
这一点被低估了。在我还是编程初学者的时候,我读过一些书,比如《Sams Teach Yourself Java in 21 Days》和各种 O’Reilly 的书,比如《CSS》。但随着时间的推移,我逐渐转向阅读在线文档,而且主要是阅读语言自带的文档等原始资料。例如,我阅读 Sun/Oracle 的 Javadoc 网页和 Python 标准库网页,而不是任何第三方的摘要;我阅读 Java 语言规范以及 JSR/JEP 网页中的新改进;我阅读 MDN 网页,而不是书籍(我知道 W3C 规范网页,但它们过于密集,不适合日常使用;我只在罕见的边缘情况和模棱两可的情况下才查阅它们)。我从第一方教程( https://doc.rust-lang.org/book/ )而不是别人的翻版中学到了 Rust;第一方材料非常出色,难以超越。
但这并不适用于一切。我不认为 C 和 C++ 有很好的第一方教程或参考资料。我还不知道最好的教程是什么,但我最喜欢的参考资料是 https://en.cppreference.com/w/,它显然是第三方的。
此外,随着经验的积累,我逐渐开始阅读我所使用的应用程序和库的源代码,有时还会阅读邮件列表/问题/拉取请求,以了解或参与软件开发过程。
> 专家在阅读参考文献后,会坐下来为工具编写配置,他们对每一行都了如指掌,并能向同事解释。这样就不会有任何疑问了!
我就是在这种理念下工作的,但这可能非常困难。我至今仍很难理解 Maven XML 文件(Java 构建工具)的每一行是做什么的。Ant(Java)也同样不透明。我见过太多这样的教程:”只需复制这个示例代码并修改其中的几个部分,而无需质疑其余部分,相信我们就可以了。
> 阅读错误信息
自古以来,用户不会阅读计算机错误信息就是 IT 笑话的源头。
> 大多数出色的工程师都能言善辩,乐于分享知识。最优秀的工程师都有自己的思想出口:博客、演讲、开放源代码,或者这些方式的结合。
看看。我有自己的网站和开源代码库。
> 永不停止学习;建立声誉;不要害怕说 “我不知道”
全部选中。
> 聪明的工程师写出聪明的代码。杰出的工程师编写简单的代码。
这也是我一直努力做到的一点–在解决问题(如功能和性能要求)的同时,使代码尽可能简单。有时,我发现自己会对代码进行去优化,以牺牲一点速度来换取更短的代码和更好的人类理解能力。
我想知道这些品质在不同学科中的普遍实用性有多大。在完全不同的领域中考虑每个类别可能会很有趣。以舞蹈为例。我非常喜欢阿根廷探戈舞,我将尝试从探戈舞的角度来思考这篇文章。
## 阅读参考
根据书面指导来跳舞是非常困难的,但我认为有一个被严重低估的资源,那就是非常专注地观看优秀教练跳基本动作。我早期就是这样做的,因为当你欣赏这种舞蹈时,这是一种非常愉快的娱乐,我认为这也是我进步相当快的一个重要原因。
关于这一点,我还可以继续说下去,但我认为,人类和我们的镜像神经元在观看别人做某事时,与我们如何习得口语以及最近的基于输入的语言学习运动浪潮有着类似之处。
解读这一点的另一种方法可能是了解舞蹈的历史、阿根廷的历史、世界各地更广泛的舞蹈社区和运动的历史以及总体文化。我认为,这样做的主要好处是可以将所学到的很多东西与上下文联系起来,使舞者更加沉浸于舞蹈活动之中。
## 了解你的工具
跳舞涉及舞者的一些外部工具,如衣服和鞋子,当然还有舞池,也许还有减少摩擦的爽身粉,最重要的是音乐。
穿着适合跳舞的服装固然有很多好处,但对这些东西了解得越多,对舞蹈的提高就越快。地板表面等也是如此。
但在这些 “工具 ”中,我认为最大的收获是熟悉音乐。既能获得对歌曲结构、旋律和节奏的直觉,又能获得更深刻的洞察力,更能体会其中的情感。舞蹈是诠释歌曲所有这些方面的一个机会,而熟悉音乐–连接人与舞伴的媒介,以及你试图通过动作表现的事物–与能够完全执行舞蹈动作是相辅相成的。
这篇文章的所有观点在这里都适用:音乐的历史告诉你探戈是怎么回事,告诉你今天我们所能听到的不同声音和动作;现在,是指目前流行的音乐和现场演奏的音乐;局限性,是指探戈音乐的不同风格与什么样的动作和感觉相匹配;最后,生态系统就像是对上述所有内容的总结,是人们在每场米隆加舞中都会详细讨论的内容,比如他们喜欢哪个乐团,或者他们喜欢哪个现代团体。
不过,我认为有一样东西可以作为工具,虽然有点微妙,那就是舞者自己的身体。我还没有深入研究过这一途径,但我很高兴地意识到,这确实是我应该做的事情。多年前接受过力量训练后,我对人体解剖略知一二。至于我自己的身体,也许瑜伽、普拉提或健身操之类的东西会很有价值。
## 阅读错误信息/分解问题
虽然舞蹈中没有错误信息,但你肯定能感觉到有什么地方不尽如人意。如果你在课堂上正在努力学习一个舞步,关键是要能够对自己的表现进行批判,寻找错误或不一致的地方。
也许某个舞步感觉有点不对,就像你和舞伴之间有些尴尬。
我注意到的一件事是,如果你正在尝试复习 A-B-C-D 的一连串步骤,而在这一连串步骤的 C 点出现了问题,那么错误的根源通常就在 B 点的某个地方,或者可能已经在 A 点了。
这可能会让人联想到查看错误的堆栈跟踪,并试图找出问题出在了哪个转折点上。问题往往并不完全位于错误实际发生的位置。
## 不要害怕弄脏你的手
对于任何学习者来说,危险之一就是在学习的早期阶段养成坏习惯。为了摆脱这些坏习惯,你必须愿意放弃旧的准则,重新适应,并重新学习一些东西。这可能类似于重构某种残缺的遗留代码。
成长也可以通过实验来实现,放弃旧的模式,寻找新的、可能有趣的东西。这也需要勇气,感觉就像把自己的手弄脏一样,适用于编程和舞蹈,可能还有很多其他事情。
## 总是帮助他人/写作/地位并不重要/建立声誉
由于舞蹈是一项集体活动,所以为了让别人听到自己的声音,写作并不是那么重要。但我仍然认为,在这个领域进行交流非常有价值。
在我看来,任何一个健康的舞蹈社区都有经验丰富的舞者和经验不足的舞者之间的良好交流。不健康的社区通常被称为势利社区,而另一种社区,即从上到下存在着强烈的隔阂和排斥,通常被称为势利社区,我认为这是不健康的。这种情况会因进入门槛过高而逐渐减弱,如果规模还不够大,就会枯萎死亡。
## 永不停止学习/要有耐心
任何探戈舞者都会告诉你,无论他们多么有经验或成就,都不会停止学习这种舞蹈。即使在几十年的探戈之旅中,也经常会听到舞者说他们还在练习走步,而这恰好也是你在第一堂课上学到的第一件事。
## 永远不要责怪电脑
在这个著名的需要两个人配合的舞蹈中,很多人很容易在出现问题时责怪自己的舞伴。我认为反其道而行之更有价值,无论你是领舞还是跟舞,在试图指责和纠正舞伴之前,先看看自己的舞蹈有哪些可以改进的地方。
当然,最终可能会有一个突破点,这时你会想提出一些问题,并一起探索解决方案。但是,在你的伴侣还没有机会纠正自己之前,就立即纠正他们,在我看来绝不是一个好方法。
## 不要猜测
我认为在学习舞蹈时很难严格遵守这一条。如果你想在尝试之前就完全确定一个动作,那么你将永远处于瘫痪状态。一开始,我们都必须做一些猜测,相信我们的肌肉会按照舞蹈的正确方式在空间中移动。
然而,我们的这些猜测往往是错误的,会导致不正确的技巧和坏习惯,必须在它们钙化之前加以剔除和纠正。
因此,虽然我认为完全不猜是不可能的,但我认为我们真的不应该低估任何可用来纠正我们所做和积累的错误猜测的手段的价值。这些手段包括我们信任的比我们更有经验的人,或者是由懂行的老师提供的私人课程。
## 保持简单
有趣的是,在探戈课程中也经常听到这样的建议。随着探戈舞的进步和词汇量的增加,现在主要讲的是领舞,很容易就想把所有的词汇都用上,并把你知道的每一个闪亮的新舞步和舞步顺序都扔给被你说服加入你的可怜的跟舞者。
很多人还会紧张,害怕一直不动带来的沉默,在每一个节拍上都保持领舞步法,以避免让人觉得他们没有想法了。
但实际上,放松心情,做好简单的舞步,配合音乐做有品味的停顿,比匆匆忙忙地把自己会的每一个舞步都翻来覆去地跳要好得多。
## 我最后的想法
尽管代码是在电脑上运行的,而舞蹈是由人类表演的,但我认为这个类比非常恰当。仔细想想,舞者不过是一个肉体机器人,在执行他们自己和舞蹈教练写入大脑的模糊指令,或者他们通过观察别人的舞蹈而获得的指令。你可以把这个比喻中的映射总结如下:
我认为这里一个有趣的见解是,学习者和教师都扮演着 “程序员 “的角色。一个完全被动、缺乏自省能力的学习者也许不会学得那么快。因此,文章的观点对这两方都适用。
对于那些自学成才的人来说,最后这部分内容很好地激励了他们进一步思考这篇博文的观点。
除了 “不要责怪电脑 ”之外,其他都是很好的通用建议;-)
我敢打赌,他们中很少有人早早就有了孩子(开玩笑)。
你好,
这篇文章的一个版本已经可以在 archive.org 上找到:
* https://archive.ph/0GcBe
由于 cloudflares:
“Error 1027
This website has been temporarily rate limited
…”
just my 0.02€
1027, so sorry
>您无法访问该网站,因为所有者已达到其计划限制。流量下降后,请稍后再访问。
Rofl?
我还以为会看到一个列表呢
有道理!
可惜作者没有提到瑞典的鼻烟秘诀。这是我所知道的最好的生产力黑客,没有之一。还有人知道吗?