编程进阶 | 认知重构与误区规避

注:本文为 "编程进阶" 相关 zhihu 讨论合辑。

图片清晰度受引文原图所限。

略作重排,未整理去重。

如有内容异常,请看原文。


如何成为编程能力出众的人?

笙囧同学

499 人赞同了该回答

一、一个真实案例

研究生一年级刚入学时,实验室有一位博士师兄,其技术能力在整个实验室受到广泛认可。导师遇到难以解决的工程问题会直接联系该同学,其他课题组的研究人员也会寻求其协助进行调试工作。

有一次,遇到一个程序错误(bug),花费两天时间未能解决,于是向其求助。该同学坐下来后,没有立即查看代码,而是先提出三个问题:

"你认为问题可能出现在哪一层?"

"你已经排除了哪些可能性?"

"你是如何排除这些可能性的?"

当时无法清晰回答。因为那两天的"调试"基本上是通过随机修改代码并运行的方式进行的,属于运气导向的尝试。

该同学指出:

"你现在不是在调试程序,你是在进行随机抽样。"

随后,其花费约十分钟时间,在未修改任何代码的情况下,仅通过分析日志和阅读代码逻辑,就精确定位了问题所在。

这一事件带来的关键认知转变是:"你以为自己在编程,但实际上尚未掌握真正的编程方法"

这一认知转变成为后续学习路径调整的起点。本文将基于这一起点,阐述过去两年中对"编程能力出众"这一概念的逐步理解。

以下是个人学习过程中积累的经验与反思。

二编程"很厉害"的本质

大多数人对"编程很厉害"的想象包括:

  • 打字速度快,代码输出效率高
  • 掌握多种编程语言和框架
  • 在 LeetCode 平台上完成大量题目
  • 能够编写复杂的程序

这些属于外部视角,或更准确地说,是"初学者视角下的能力表象"。

真正编程能力出众的人,其共同特征体现在完全不同的维度:

2.1 精确的问题定位能力

如同前述案例所示。面对程序错误,他们不会慌乱,不会进行随机尝试,而是采用系统化的方法缩小排查范围------先确定问题所在的系统层次,再定位具体模块,进而确定相关代码行,最终实现精确定位。整个过程如同外科手术般精准。

这一能力看似基础,但其背后需要建立对整个系统运行机制清晰的认知模型,理解数据流向、处理过程、输出目标以及每一步可能出现的问题。

缺乏这种认知模型的人,面对程序错误只能依赖随机尝试。

2.2 代码的可读性与可维护性

初学者追求"代码能够运行",进阶者追求"代码运行效率高",而真正能力出众的人追求"代码能够被他人(包括三个月后的自己)轻松理解和修改"。

这一追求背后的理念是:代码被编写一次,但会被阅读数十次甚至上百次。 编写代码的时间远小于阅读、修改和调试代码的时间。因此,代码的可读性和可维护性比复杂的技巧更为重要。

阅读过该同学编写的代码,初步印象是"似乎并无特别之处"------没有使用炫技的写法,变量命名清晰明确,逻辑结构一目了然,关键位置配有适度的注释。

后来才理解,能够将代码写得"看起来平常无奇",恰恰是最困难的事情。 这意味着编写者已在大脑中理清了所有复杂性,并用最直接简洁的方式表达出来。

2.3 判断何时不编写代码

这一点最为反直觉。

能力出众的程序员并非编写代码最多的人,很多时候他们反而写得最少。因为他们会预先思考:这个问题是否真的需要通过编写代码来解决?是否存在现有的工具或库可以使用?是否有更简单的方案可以避免编写大量复杂逻辑?

每一行代码都是技术债务------它需要被维护、测试和理解。代码量越少,债务负担越轻。能用十行代码解决的问题绝不多写,能用现有工具解决的问题绝不重复造轮子(除非出于学习目的)。

曾经认为编写大量代码代表高效率和勤奋。后来意识到,这往往是因为思考不充分就开始编码,导致在错误方向上越走越远,最终需要推倒重来。

特别是在 AI 辅助编程普及后,单纯依靠代码量来衡量工作价值的做法已不再适用。

三、常见的学习误区

在理解了"能力出众"的本质特征后,回顾此前的学习路径,发现存在若干普遍性误区:

误区一:追求语言与框架的数量

本科阶段,曾在简历上列出十种编程语言:Python、Java、C++、Go、JavaScript、Rust 等。每种语言仅学习了基础语法,能够编写 Hello World 程序,能够跟随教程制作简单的演示项目。

当时自认为能力较强,掌握如此多样的语言。

后来意识到,这类似于"掌握十种语言的问候语"------表面看起来令人印象深刻,实际上无法用于真正的交流。

编程语言只是工具。熟练使用锤子不代表是优秀的木匠,对木材的理解、结构的直觉、工艺的审美才是决定因素。

真正能力出众的程序员通常只精通一到两种语言,但他们对"编程"本身的理解是深刻的------数据结构、算法思维、系统设计、抽象能力------这些是跨语言的通用能力,一旦掌握便终身受用。

重要认知: 语言和框架属于"会随时间过时"的知识,而编程思维属于"终身受用"的能力。时间应更多地投资于后者。

误区二:仅观看教程而不进行项目实践

这是一个重大且隐蔽的误区。

观看教程时会产生"都已理解"的错觉------视频中教师编写一行代码,跟随编写一行,运行成功,便感觉已掌握。

但当关闭教程,面对空白编辑器,需要从零开始编写程序时,会发现脑海中一片空白。

因为"理解他人代码"与"自己能够编写代码"是完全不同的两种能力。 理解属于识别,编写属于生成。生成的难度远高于识别------能够理解一篇优秀的文章不代表能够写出优秀的文章,同理,能够理解一段优秀的代码不代表能够编写出优秀的代码。

这一误区花了很长时间才克服。转折点是有次强迫自己不看任何教程,仅依靠官方文档和搜索引擎从零开始完成一个小项目。过程非常艰难,以前通过教程两小时能学会的内容,自己摸索花费了两天时间。

但那两天学到的东西比之前观看两周教程还要多。

因为在自主探索过程中,会遇到真实的问题------不是教程中精心设计的、有标准答案的问题,而是杂乱无章的、文档描述不清的、需要在 Stack Overflow 上搜索许久才能找到答案的问题。解决这些问题的过程才是真正的学习。

误区三:追求"最佳实践"而忽视原理理解

学习到中级阶段时,开始热衷收集各种"最佳实践"------设计模式的使用方法、代码架构的搭建方式、不同场景下的技术栈选择。

收集了大量文章和清单:某场景使用策略模式、某场景使用观察者模式、数据量大时使用 Redis、并发高时使用消息队列。

后来发现一个问题:知道"应该用什么",但不知道"为什么要用这个"。

面对具体问题,能够从收藏夹中找到"最佳实践"来套用,但如果问题稍有变化,与收藏夹中的模式不匹配,就会感到困惑。

因为学习的是结论,而非推导过程。

真正理解一个技术方案,意味着掌握:

  • 它解决的关键问题是什么
  • 它的设计思路是什么(为什么选择这种设计而非其他)
  • 它的 trade-off 是什么(获得了什么,牺牲了什么)
  • 它在什么条件下会失效

达到这种理解深度后,就不再需要记忆"最佳实践"------因为可以根据具体场景自行推导出最合适的方案。那些最佳实践不再是死记硬背的教条,而是自然的选择。

四、有效的学习策略

在克服了上述误区后,开始采用不同的学习方法。虽然距离"很厉害"的标准仍有差距,但这些方法确实带来了明显的进步。

策略一:阅读优质代码

这一方法是前述师兄推荐的,也是投入产出比最高的学习方式之一。

不是随意阅读,而是选择公认质量高的开源项目进行研读。

初期阅读过程非常痛苦。大型开源项目包含成千上万行代码,完全不知从何入手。后来总结出一套方法:

  1. 第一步:阅读项目的 README 和文档,理解其功能定位和关键概念。
  2. 第二步:从具体功能入手,追踪其执行流程。例如对于 Web 框架,可以追踪"一个 HTTP 请求从进入到返回响应"经过的代码路径。
  3. 第三步:遇到不理解的设计时,先思考"如果让我来实现我会怎么做",然后对比作者的实现方式,分析差异所在。

这一过程中能够学到大量教程无法传授的内容------代码组织方式、错误处理策略、性能与可读性的权衡、工程实践中的各种技巧。

而且很多时候会发现,顶级项目的代码并非想象中那样"高深莫测"。它们之所以优秀,恰恰是因为用简洁的方式解决了复杂的问题。 阅读后会产生"原来可以这样实现"的领悟,这种领悟积累多了,代码审美和设计直觉便会逐步提升。

策略二:完成"完整"的项目

注意此处强调的关键词是"完整"。

不是跟随教程制作演示项目后就结束,而是从需求定义到最终部署的完整过程全部独立完成。

这两者的差距体现在:

  • 需求不明确时,需要自己定义问题边界
  • 没有指导者告诉你该使用什么技术,需要自己调研和选型
  • 编码过程中发现最初设计存在问题,需要决定是重构还是打补丁
  • 需要处理各种边界情况和异常场景
  • 需要编写测试,考虑部署环境与开发环境的差异
  • 需要在功能、性能、可维护性之间做出权衡
  • 需要处理环境差异导致的问题(如"在我的机器上运行正常")

这些问题的总和构成了真实世界中"编程"的完整图景。仅做演示项目的人永远接触不到这些,因此他们的能力会停滞在某个隐形的天花板上。

项目本身的选择不重要,关键是完整性。一个完整的、即使功能简单的项目,其学习价值也超过十个不完整的演示项目。

策略三:刻意练习"先思考,后编码"

这一习惯是被前述师兄批评后养成的。

以前接到任务后,第一反应是打开编辑器开始编写代码。写到一半发现思路有误,删除重写。再次编写,再次发现问题,再次修改。一个下午过去,代码修改了七八个版本,最终版与第一版可能完全不同。

正确的做法是:接到任务后,先不接触键盘。

先在纸上或大脑中理清几个问题:

  • 该任务的输入和输出分别是什么
  • 关键逻辑分为几个步骤
  • 哪些地方可能出现问题
  • 是否存在不确定的技术点需要先调研

思考清楚后再开始编码。

初期很不适应,因为"打开电脑开始敲代码"会给人"我正在工作"的安全感,而坐在那里对着白纸思考会让人感觉在浪费时间。但逐渐发现,想清楚再写的总耗时反而更短------因为不需要反复推倒重来。

而且代码质量明显提高。因为在思考过程中已经将各种情况预先过了一遍,编写出的代码天然就考虑得更周全。

有一本书中提到:

"Weeks of coding can save you hours of planning."

(数周的编码可以节省数小时的规划------反讽。)

幽默但真实。许多人以为编程的瓶颈在于手速,实际上瓶颈在于思维。

策略四:在正确的层次上"偷懒"

这一表述需要解释。

所谓"在正确的层次上偷懒",是指:将精力集中在真正需要动脑的地方,其他地方能省则省。

具体示例:

  • 能用现成的库就不自己编写。时间应花在业务逻辑和关键算法上,而非重复实现 JSON 解析器。
  • 能用工具自动化的就自动化。代码格式化、静态检查、测试、部署------这些重复性工作全部交给工具,脑力留给更有价值的事情。
  • 能用 AI 辅助就使用 AI 辅助。Copilot 等工具对于编写模板代码、查询 API 用法、快速生成初始版本非常有用。但要注意------AI 生成的代码必须能够读懂、评判和修改。 如果只是无脑复制 AI 的输出,那不是编程,而是在充当 AI 的人肉运行器。

见过两种极端。一种人对所有工具和库都抗拒,什么都要自己从头编写,认为这样才"扎实"。另一种人对所有工具和库都过度依赖,离开框架和 AI 什么都写不出来。

两种都有问题。理想的状态是:你有能力从底层开始编写,但你选择不这样做------因为你知道时间更值得花在哪里。

这种"有能力但选择不用"的状态,与"没能力所以只能用工具"的状态,外表看起来相似,但本质完全不同。前者是站在高处做选择,后者是被困在低处无法脱身。

五、待深入思考的问题

前面所述内容属于已经验证的、相对确定的认知。以下提出几个尚未想透彻、但认为重要的问题。

问题一:编程能力的增长模式

个人的体感是阶梯式的。

会有很长一段时间感觉没有进步,每天编程的感受与上个月相似。然后突然有一天,某个概念"通了"------可能是突然理解了某个底层概念,可能是完成某个项目后发现自己看问题的视角发生了变化------然后明显感觉到上了一个台阶。

这种阶梯式特征带来一个问题:在"平台期"很容易失去耐心和动力。 感觉自己在做无用功,想要放弃或转换方向。但实际上平台期可能正是"量变"积累的阶段,只要坚持下去,质变就会发生。

当然这只是个人体验,不一定具有普遍性。但如果读者也有过"明明一直在学习但感觉没有进步"的困惑,或许可以参考这一观点。

问题二:广度与深度的平衡

这一问题至今没有满意的答案。

一方面,编程领域非常广泛------语言、框架、工具、方向------不可能全部学习。不做选择,精力会被稀释。

另一方面,只钻研一个方向,视野会变窄,可能错过其他领域的优秀思路和工具,而且万一该方向过时就会陷入被动。

目前的做法是一个不太优雅但实用的策略:

选择一个主方向深入钻研,同时保持对其他领域的"新闻级别"关注。

"新闻级别"是指大致了解其他领域近期的发展、新趋势、关键概念,但不深入细节。如果某天需要用到该领域的知识,知道该去哪里学习、学习什么。

这种程度的广度不需要太多时间投入------平时浏览技术社区、阅读他人分享的文章、与不同方向的同学交流即可。但它能确保在需要时不会完全陌生。

问题三:AI 时代编程能力的价值

这一问题近期被越来越多地讨论。鉴于作者本身从事 AI 方向研究,对大模型编写代码的能力有较为直观的认识。

判断是:编程能力不但没有变得不重要,反而变得更重要了------只不过"重要的编程能力"的内涵在变化。

以前,编程能力中有相当一部分价值来自于"记忆"------记住语法、记住 API、记住各种写法的细节。这部分价值确实在被 AI 替代。不需要记住 Python 中某个库的某个函数的参数顺序,询问 AI 两秒钟就能得到答案。

但编程能力中的另一部分------设计能力、抽象能力、问题拆解能力、系统性的调试能力、对复杂性的管理能力------这些东西不但没有被替代,反而因为 AI 降低了编码门槛而变得更加稀缺和宝贵。

因为当所有人都能借助 AI 快速写出代码时,瓶颈就不再是"能不能写出来",而是"知不知道该写什么、该怎么设计、出了问题该怎么排查"。

换句话说,AI 提高了编程的下限(不太会写代码的人也能写出可运行的东西),但上限并未降低(真正复杂的系统设计和架构决策,AI 目前无法完成)。

在这种情况下,处于中间层的"能写代码但没有太多思考深度"的程序员会被压缩,而两端------"完全不会写代码但现在可以借助 AI 做一些简单的事情"的人和"真正理解系统设计和底层原理"的人------都会获益。

如果想成为"编程很厉害的人",应该瞄准的是后者。

六、学习路径

最后,如果回到刚开始学习编程的时候,基于现在的认知,应采取以下路径:

第一年:打地基。

不追求学习很多语言和框架,选择一门语言(如 Python 或 C++)扎实学透。同时将数据结构和算法的基础打好------不是为了刷题,而是为了建立"用计算机解决问题"的思维方式。

每周做一些小练习,但更重要的是阅读代码。找几个经典的开源项目,每周花几个小时阅读,不求全部读完,但求读懂的部分真正理解。

第二年:做项目。

开始做完整的项目。从小项目开始,逐渐增加复杂度。每个项目结束后进行复盘:哪些地方设计得不好?如果重做一遍会如何改进?

这个阶段也开始接触操作系统、计算机网络、数据库等基础课程。不需要学得很深,但关键概念要理解------因为你编写的代码最终运行在这些基础之上,不理解它们就无法知道代码在底层到底发生了什么。

第三年及以后:确定方向,深入钻研。

到了这个阶段应该对自己的兴趣和擅长有所认知------是对系统底层感兴趣,还是对应用开发感兴趣,还是对算法和数据感兴趣?选择一个方向深入进去。

同时开始参与开源社区、实习,或在其他真实场景中检验自己的能力。因为到了一定阶段后,闭门造车的学习效率会急剧下降,需要来自真实环境的反馈来了解自己还差在哪里。

当然这只是理想化的路径。实际情况不会如此整齐,每个人的节奏也不同。但大方向是对的:先打基础,再做项目,然后找方向深入。不要反过来。

七、结语

撰写这篇回答的过程,也是重新梳理这两年学习历程的过程。虽然作者自身也还在学习路上,远未达到"编程很厉害"的标准,但这些体会反而比那些已经到达终点的人的回忆更贴近正在赶路者的真实处境。资深从业者回顾成长路径时,往往会不自觉地简化和美化。而作者现在还记得每次陷入误区时的困境。

最后引用该师兄说过的另一句话作为结尾。有一次问其"你觉得你是什么时候变厉害的",其回答:

"没有哪个特定时刻。只是有一天回头看,发现以前觉得很难的东西现在觉得很自然了。然后你又遇到了新的觉得很难的东西。这个循环好像一直没停过。"

大概编程就是这么一件事------永远觉得自己不够厉害,但确实一直在变厉害。

编辑于 2026-02-26 21:59


草原上唱山歌

389 人赞同了该回答

受 Edward Kmett(函数式编程领域专家)和 John Carmack(3D 游戏引擎开发先驱)的影响,编程水平逐步提升。他们给予的关键启发如下:

编写大量的代码

练习量达到一定程度后,量变自然引起质变,没有其他更好的办法,只有不断进行实践以加深熟悉度。

克隆开源代码

将现有的项目进行复现,作为个人练习,在练习过程中不断深入学习;不能只看,要多动手实践。

在学习编程过程中,应寻找一些简单且简洁的项目,编写自己的版本以理解它们;

当复现他人代码时,应像阅读论文一样,尝试对关键部分进行改造,重新进行设计,这样能够更好地理解作者为何这样设计。记得优先重新改写关键部分,重新进行设计,在改写的过程中搞清楚作者为什么要这样写。

这可能是初学者与专家之间的差距。大多数人学习一项技能时,思维中的关键词都是理解、消化、吸收,甚至采用费曼学习法,然后再将所学知识教给别人。

而专家级别的程序员,是边学习边重构创新,从不走马观花和止步于表面,想尽一切办法搞清楚底层原理,背后的机制是怎样的,是如何产生的,为什么会是这样,与其他知识都有哪些关联等。

多尝试和阅读资料

与学习开源代码类似,将论文的关键部分尝试重新设计。

保持热爱和痴迷

全身心投入,不被其他事物干扰;

纯粹的热爱,沉浸其中;

不为展示、不为盈利、不为成为权威。

发布于 2026-01-05 23:42


耐心等待

237 人赞同了该回答

编程方面可以多向国际优秀开发者学习,例如:

GitHub 上有一个国外开发者的项目,该开发者通过一年自学编程,成功获得 AWS 开发岗位 Offer。他的这套学习清单非常适合学习编程的同学。作者发起这个项目是为了能够进入 Google 工作,放弃了一切,进行脱产式学习,从头开始学习,每天学习时长在 8 到 12 小时左右,强度较高,虽说最终未能获得 Google 的 Offer,但成功进入亚马逊的 AWS 部门。

对编程有兴趣的人,可以尝试挑战一下。

还有一个国外作者,撰写了《超速学习》书籍,用一年时间挑战自学 MIT CS 四年的全部课程,且最终通过所有考试。

还有像专家 John Carmack(最早的 3D 游戏引擎开发者)和 Edward Kmett(函数式编程专家),学习他们的方法,能够提高编程能力。

Edward Kmett 的方法是:克隆一个编程项目,将项目的关键部分重新进行设计,并进行改变,通过编写自己的版本进行理解,在这个过程中尽量明白作者为什么要这样写。

John Carmack 的方法是:复现现有项目进行练习、大量的编写代码、不断深入学习、多阅读和保持痴迷。

大致总结两位专家的方法:

  1. 编写大量的代码

    和高中题海战术是一个道理,唯有熟能生巧,方能量变引起质变;

  2. 深入学习开源项目

两位专家的关键要点:

(1)不能只是看不做练习;

(2)尽可能编写自己的版本,并加强理解;

(3)改变关键部分,重新进行设计;

(4)要进行深入学习,不能止步于表面和走马观花,尽可能搞懂每个方法背后的原理。

  1. 边实践边阅读

    和学习开源代码相同,重新尝试设计论文的关键部分;

  2. 对编程保持痴迷

发布于 2026-01-14 23:07


南山烟雨珠江潮

267 人赞同了该回答

向优秀开发者学习即可。《Effective C++》的作者 Scott Meyers 就是值得普通人学习的专家,他是靠学习、总结、分享 的路线获得认可的,而不是靠发明创造的天赋,这样的路线对普通人来说是可以复制的。

《Effective C++》在当时的影响力非常大,但是这本书没有发明任何东西,它的副标题"改善程序与设计的 55 个具体做法"直接揭示了它的目的:它就是工程实践的总结归纳。

现在可以看到很多名字叫《Effective XXX》的书,其实都是在模仿它,可见其影响力之大。

Scott Meyers 很早的时候说过这样一句话,"我写书,是为了解决我自己遇到的问题。"年轻时,误以为这格局不够。后来才明白,这才是所有有效分享的起点------最强大的内驱力,就源于切身的困惑与求索。不从"装点门面"出发,而从"解决问题"出发,这条路径最务实,也最可持续。

《Effective C++》的开篇金句:"条款 1:视 C++ 为一个语言联邦。",这句话现在看起来很平常,但是在当时反响确实非常巨大,因为 C++ 社区以分裂而闻名,不同的风格和流派水火不容。但是正是这句话,让各种争论的声音小了很多。他的书也是从这句话迅速传播开来的。这句话体现了他化繁为简的洞察力和归纳能力。

《Effective C++》通篇都在处理'细节':如何管理内存、如何设计接口、如何避免隐晦的错误......这让当时许多追逐"宏大架构"的人不以为然。但恰恰是这些可被标准化、可被学习、可被执行的细节,构筑了软件可靠性的基石。他的成功揭示了一个朴素真理:对于绝大多数人,卓越并非源于对宏大叙事的空想,而是来自对无数关键细节的掌控。把自己遇到的"问题"尽可能地解决,就是最扎实的晋升之路

最后说说"学习、总结、分享"方法中的第三个步骤:分享。

现在深切认同,分享是最高阶的学习。正如"费曼学习法"所揭示的:教会别人,是巩固自身理解的最佳途径。当开始尝试向他人解释一个技术点时,才会发现自己逻辑的断层和知识的模糊。如果能更早地实践'以教促学',技术肯定比现在要高很多。

而且分享也需要一种长期主义,对自己的执行力也是一种考验和锻炼。三分钟热度的人处处可见,这种性格对程序员的技术精进来说,是一种阻碍。

所以,如果问如何成为编程很厉害的人,答案不再是泛泛而谈的"多写代码",而是:

  1. 下次遇到一个编译错误或设计难题时,别急着跳过。 把它当作一个 Scott Meyers 式的"条款"去深入研究,直到能清晰地总结出问题的原因和解决方案。
  2. 尝试将你的解决方案分享出去。 写一篇博客,或在团队内做一次简短的分享。这个过程会极大地深化你的理解。

这条路看似笨拙,却是最务实、最可持续的路径。它不挑天赋,只考验耐心和执行力。掌控细节,从有效解决一个具体问题开始,就是走向"厉害"最务实的起点。

编辑于 2026-02-21 11:50


前线 SRE 康某

198 人赞同了该回答

编程说到底就是这几件事:

第一是抽象。绝大多数人脑的存储空间是有限的,能记忆的上下文也是有限的。这就要求在需要的时候,把一部分程序当成黑盒子,只关注给它输入他会给出什么输出。

比如一个常见的场景:对每个用户找到他所有的关注者。那么常见的抽象方法是建一个 FollowerDao 或者 FollowerRepository 的类或者服务,定义一下接口,比如 getAllFollowers(user_id),或者支持分页:getAllFollowers(user_id, page, page_size)

开发这个类的时候,你得调用数据库的 client,日志库,语言标准库等。这些库在此阶段就是黑盒子。然后在开发过程中大概分两步,首先用 user_id 去 query 数据库,然后把数据库返回的结果转成内部 data class 或者 json 或者其他格式。这就需要实现两个辅助函数:user_id 到 query 的 mapping,数据库返回的裸结果转换成这个类定义的返回结果的 mapping,以及程序本体。

在辅助函数写完之后,这两个辅助函数又成了黑盒子,供程序本体调用,程序本体调用辅助函数 1,搭起来 query,然后 query 数据库,然后调用辅助函数 2 把结果转换,然后返回。

在这个模块开发完了之后,它也成为了黑盒子,供其他模块调用。比如前端有个页面显示每个用户的关注者,前端只需要调用 getAllFollowers(user_id, page, page_size)。再大的程序就是这么一点一点搭起来的。

实现抽象又有三个学派:面向过程,面向对象,面向函数。优秀的程序员不是狂信徒,而应该吸收使用任何有益的思想。实战中又分自顶向下和自底向上。比如我刚才讲的故事是自顶向下的分解这个场景。但实战中你会发现代码有重复的部分,程序结构逻辑有一些类似的部分,他们自然产生了。这就可以自底向上的产生抽象的函数,模块。

落地要解决的问题还有抽象程度。二极管的一头是复制粘贴一把梭,另一头是过度设计。以刚才的场景为例,getAllFollowers 肯定不是这个服务唯一的接口,分页也一定是个重复需要的请求,build query,execute,map result 这个 pattern 也肯定存在。那么什么该被抽象成可复用的代码,什么可以一把梭?这样的决策贯穿开发的始终,优秀的程序员应该会做出一个平衡的决策。

第二 是反过来,姑且叫调试,就是把这些黑盒子打开的过程。如果一个程序写挂了或者好端端挂了,得知道怎么办。以上面的例子,如果这个网站或者 app 显示关注者显示不出来了或者对不上号,那么怎么办呢?系统有若干阶段:App/web 到后台,后台到数据库。那么按 F12,或者使用 curl 等工具先看 app 到后台的 query 返回对不对。如果对了,问题在前端,如果错了,问题在后端。然后再分别往下一层一层的拆开黑盒子,前端就定位到显示那个列表的控件,后端就继续测试 query 数据库返回的对不对,如果返回错了就接着查数据库等。这个流程除了调 bug 也适用于学习现成的项目代码或者刚到新组熟悉环境。

第三是纪律性 。绝大多数人都不是圣人。那么保证程序能跑不能靠自己手底下有准,而是要靠流程和纪律性。就像面对 gank,你不能总想着一打二而是要依赖眼和小地图,假设性原则。比如应当永远怀疑程序的输入,采取防御式编程。以上面为例,常见的坑是 page_size 可以是任意值,然后调用者直接写了个正无穷,然后谜之 OOM,卡顿什么的就发生了。然后要写各种测试,要人肉测试,要正确处理,log 异常等。

至于各种具体的技术,工具都是实现层面的问题。良好的 IDE,AI 补全可以减少记忆负担;有时候一些技术和工具已经解决了手头的问题,但调包和可定制又是不能兼得的。优秀的程序员应当保持学习,了解最新的信息,动手获取实际经验。这些信息和经验又是做出决策的依据。

编辑于 2025-09-17 06:34


全小鱼

162 人赞同了该回答

真正编程厉害的人,从不体现在代码里,而在代码之外。

眼中编程厉害的人,是这样的:

1、能在需求模糊、时间紧迫、接口混乱的情况下,按时交付一个能稳定运行,不崩溃的系统。

2、能保证自己三个月前写的代码,今天还能被新人轻松阅读、安全修改,哪里不清楚,还能讲得明白。

3、能在凌晨三点接到告警,十分钟内定位问题、回滚修复,天亮后还能正常开站会,没有丝毫抱怨。

如果不是,也没关系,因为这条路,不是靠天赋,这是一套编程思维的架构体系,需要靠日复一日的积累。

以下用 20 年一线实战的经验,说明普通人怎么一步步向"编程厉害的人"靠近。

一、编程厉害的人,到底"厉害"在哪儿?

职场 20 多年,发现编程真正厉害的程序员,往往在这三个维度上的能力都很强。

1、技术深度

不是那种炫技,而是"稳、快、可维护"

技术深度不是算法的难度,过去不是,AI 时代更不是,借助 AI 再复杂的算法也能快速帮你理清思路。

真正的技术深度,是能快速理清复杂的业务,并能划分出合理的功能模块,分给新人后他们不抱怨,知道什么时候用缓存、什么时候加锁、什么时候该妥协。

有个同事,用了不到 200 行的 C# 代码,优化了一个每天卡死 3 次的订单对账服务,到现在已经稳定运行了 5 年。

他没用什么"高大上"框架,只是把状态机理清楚了,并覆盖了异常路径。

2、解决问题的能力

能将不确定的需求,通过代码实现

这是 90% 的程序员欠缺的能力。

当产品经理说:"用户上传文件后,要能'马上看到结果'。"

新手会直接在用户上传文件后,直接返回页面;

而老手会在文件上传后开启异步处理,前端展示状态,出错了有提示还能重试。

这就是差距,编程厉害的人,都是需求翻译器,能把模糊不确定的需求,转化成可执行、可测试的代码。

3、代码之外的能力

代码之外的能力,是最容易被忽视,也是最能拉开彼此差距的能力。

软件开发从不是单打独斗,而是靠团队合作的力量。

能写出清晰的提交信息,能用日志、监控、告警提前发现问题,愿意写文档、做分享,这些看似和代码无关,实则很重要。

一个人再厉害,也架不住团队拖后腿,真正厉害的程序员,懂得如何让整个团队变得更强。

二、编程思维,是可以培养的

理解能力强的人,在编程上确实很有天赋,但这不是唯一。编程思维是可以培养的,只要肯下功夫,也能成为编程厉害的人。

可以从以下 3 个方面锻炼自己的编程思维

1、从"怎么做"转向"为什么做"

新手程序员最多的问题是:这个功能怎么实现?

而厉害点的人会考虑:这个功能解决了用户的什么问题?有没有更简单的解法?

带新人时,第一件事不是讲开发要求,而是让他们学会画流程图,把复杂的问题,转变成可执行的逻辑。

用户点击按钮 → 系统做了什么 → 数据怎么流转 → 异常怎么处理?

把模糊的需求转变成确定的业务逻辑,思维就清晰了。

2、学会"拆解"需求

面对复杂问题,没有好的方法会让你陷入焦虑的漩涡,要学会把复杂的问题拆解成一个个可实现的小步骤。

每一步只做一件事,每一步都可测试就可以了,一步一步的去完成,复杂的问题就解决了。

用户登录这个需求,可以这么拆解:

  • 验证邮箱格式(输入校验)
  • 查询数据库(数据访问)
  • 比对密码(安全逻辑)
  • 生成 Token(状态管理)
  • 记录日志(可观测性)

拆得越细,思路越清晰,越不容易出错。

3、拥抱"失败"

失败是成功之母,这事不仅是说来听听的,还要正确的去面对。

写过最烂的代码,上线三天,崩溃了三次,经理气的敲着电脑屏幕,帮我分析问题的原因。

于是详细记录了每次崩溃的现象、复盘的业务逻辑,并添加可用的监控。

后来那个系统成了公司最稳定的模块,已经稳稳的运行了多年。

编程不是"一次写对",而是"快速试错 + 快速修复"。

三、厉害的人,每天都在"坚持"这三件事

天赋决定起点,习惯决定终点。

1、每天写一点实用的代码

刷题是有用的,但是到一定程度,你就会发现没啥意思了。

但你可以去尝试着用代码解决一些日常中的小问题,比如:做个自动化日志分析工具,为家人做个记账小程序等。

关键是要做到**闭环,**从需求、编码、运行、优化,走完整个流程。

这种训练,比刷几道算法题更能锻炼你的实战经验。

2、多读一些优秀的代码

先读团队内,你认为厉害的程序员写的代码,这样可以熟悉团队内的习惯,遇到问题还有人请教。

然后去读一些其他优秀的代码,比如:框架的源码,或者去 GitHub 上寻找一些优秀的项目。

读的时候多问问自己几个为什么,比如,这里为什么用接口不用类,异常是怎么处理的,配置和逻辑是怎么分离的。

读好代码,会在潜移默化中,提升自己代码的品质。

3、写"可读"的代码

代码是写给别人看的,顺便让机器能执行。

见过很多炫技的程序员,写出的代码很高深,没人能看懂,甚至过几天他自己也看不懂了。

《代码大全》里有一句话说的好

你写的代码,被阅读的次数远远多于被编写的次数。

所以,在敲代码的时候,要知道优秀的代码要具有可读性,函数别超过 50 行,要有注释,注释要写清楚"为什么"这么做。

四、真正的"厉害"在技术之外

程序员不仅要能写出可运行、可维护的代码,还要注重技术之外的能力培养。

五、别追求厉害,追求实用

20 年前,入行时也焦虑,每天幻想自己能成为技术牛人。

现在想想,那些真正厉害的时刻,并不是因为写出了多么厉害的代码,而是帮助客户挽回一笔大额订单,让团队少加几天班,让新人一天能快速进入工作状态。

编程的魅力,不是征服机器,而是为人民服务。

已经在这条路上走了 20 多年,依然觉得,每日编程、每天写一行好代码是值得的。

以上。

发布于 2025-10-26 09:47


程墨 Morgan

274 人赞同了该回答

什么样的人不适合学编程?

盲人,真的干不了这活。

没有逻辑思维能力的人,是、非、与、或、充分条件、必要条件......这些是基本功。

书面表达能力不佳的人,写代码其实就和写文章,是一种书面表达。

纠结『哪一种编程语言最有前途』的人,这种投机心理,是无法适应编程的要求的。

自学能力不强的人,这行很多知识都要靠自学。

没有耐心坐下来写代码的人,编程要的不是几分钟内的当机决断,而是要持续地耕耘。

不能理解他人需要的人,编程,作为爱好可以只满足自己的需要,但作为职业就是满足其他人的需要。

以上,就写 7 条吧。

发布于 2021-05-20 12:32


古法 + AI 编程

一、认知转变

高水平开发者面对问题时,会通过系统分析定位异常,而非随机试错。调试效率与对系统运行机制的理解直接相关,缺乏整体认知会导致开发行为缺乏逻辑性。

二、高水平编程

  1. 问题定位
    按层级逐步缩小排查范围,依托系统认知实现精准异常定位,调试过程具备清晰流程与依据。
  2. 代码质量
    优先保障可读性与可维护性,采用规范命名与清晰结构,以简洁形式呈现复杂逻辑,降低后续维护成本。
  3. 工程取舍
    合理控制代码规模,优先复用现有工具与库,减少非必要自研实现,降低代码带来的维护与迭代负担。

三、常见学习误区

  1. 片面追求语言与框架数量,忽视跨语言的通用编程思维。
  2. 依赖教程模仿,缺少独立项目实践,无法形成自主开发能力。
  3. 机械记忆工程方案,不理解设计原理与适用场景,难以应对需求变化。

四、能力提升路径

  1. 阅读优质开源代码
    遵循文档阅读、流程追踪、思路对比的步骤,吸收工程化代码组织与异常处理方式。
  2. 完成全流程项目
    覆盖需求、设计、开发、部署全环节,应对真实场景中的各类边界与异常问题。
  3. 先规划后编码
    明确输入输出、逻辑步骤与风险点,减少反复重构,提升开发效率与代码完整性。
  4. 合理复用资源
    依托库与工具简化重复工作,借助AI辅助基础编码,同时保持对代码的理解与把控能力。

五、关键问题思考

  1. 编程能力呈阶梯式提升,平台期为量变积累阶段,持续实践可实现阶段性突破。
  2. 以核心方向深耕为主,同步了解其他领域动态,平衡知识深度与视野广度。
  3. AI 替代基础编码工作,设计、抽象、调试与复杂度管理能力成为更具价值的竞争力。

六、学习路径规划

  1. 夯实基础语言、数据结构与算法基础,建立计算思维。
  2. 开展完整项目实践,配合计算机底层知识学习,理解程序运行环境。
  3. 选定方向深入研究,通过真实场景反馈持续优化能力结构。

七、总结

编程能力提升为长期渐进过程,复杂问题的处理水平随实践逐步提高,持续积累是能力稳步提升的关键。

补充观点

  1. 大量编码、复刻开源项目、重构关键设计、保持专注,是高效提升编程能力的方式。
  2. 高强度系统性自学可快速构建知识体系,行业优秀从业者均强调实践与原理探究。
  3. 以解决实际问题为出发点,通过总结与分享深化理解,是可复制的能力成长路径。
  4. 编程能力体现在抽象封装、逐层调试与开发规范三个方面,需平衡复用性与实现合理性。
  5. 高水平编程能力聚焦稳定交付、可维护性与问题响应,思维训练与长期习惯决定最终水平。
  6. 逻辑能力、书面表达、自学能力、耐心与需求理解能力,是从事编程工作的基础条件。

软件工程领域的奠基性著作、认知科学实证研究与工程实践指南

一、认知重构:编程思维与专家表现

1. The Psychology of Computer Programming (《程序开发心理学》)

Gerald M. Weinberg, 1971/1998

认知重构、专家vs新手差异

软件工程心理学的奠基之作。Weinberg 通过实证研究揭示了专家程序员与新手在问题表征(Problem Representation)上的本质差异:专家依赖语义记忆与心理模型进行推理,而非语法细节记忆。书中对"调试认知过程"的分析直接对应"精确问题定位"的方法论基础。

2. The Cambridge Handbook of Expertise and Expert Performance

K. Anders Ericsson et al. (Eds.), 2006/2018

能力进阶的阶梯性、刻意练习

关于专家表现科学的权威综述。其中第 16-18 章专门讨论软件工程领域的专家技能习得机制,证实了提到的"阶梯式增长"(Stepwise Growth)与"平台期"(Plateau)现象的认知神经科学基础。

3. Conceptual Blockbusting: A Guide to Better Ideas

James L. Adams, 1974/2019

认知障碍突破、思维模式转换

斯坦福大学设计思维课程核心教材。系统分析了工程师在问题求解中常见的"概念障碍"(Conceptual Blocks),如知觉障碍、文化障碍、情感障碍,提供对应"从怎么做转向为什么做"的认知重构技术。

二、误区规避:反模式与工程陷阱

4. The Mythical Man-Month (《人月神话》)

Frederick P. Brooks Jr., 1975/1995

系统化误区、复杂性管理

软件工程史上最具警示性的著作。Brooks 提出的"本质复杂度 vs 偶然复杂度"(Essential vs Accidental Complexity)区分,正是"每一行代码都是负债"的理论源头。书中对"Second-System Effect"(第二系统效应)的分析,对应"过度设计"误区。

5. Facts and Fallacies of Software Engineering

Robert L. Glass, 2002

误区诊断、证据式软件工程

以 55 条"事实"与 10 条"谬误"的形式,系统纠正常见认知偏差(如"增加人手能加速延期项目"谬误)。Glass 强调基于经验数据(Empirical Data)而非直觉的决策,对应"从最佳实践转向原理理解"的诉求。

6. The Leprechauns of Software Engineering

Laurent Bossavit, 2015

批判性思维、方法论祛魅

对软件工程领域广为流传但缺乏实证支撑的"常识"(如"10x 程序员"概念、需求变更成本曲线)进行系统性质疑与溯源,培养的"探究底层原理"的学术态度。

三、系统化实践:工程方法与代码质量

7. Code Complete (《代码大全》)

Steve McConnell, 1993/2004

系统化编码实践、可读性工程

软件构建(Construction)领域的百科全书。

第 7-11 章关于"隐喻"(Metaphors)与"设计构建块"的论述,直接支撑"建立心理模型"的观点;第 32 章"自说明代码"(Self-Documenting Code)是"代码是写给人读的"的技术实现指南。

8. A Philosophy of Software Design

John Ousterhout, 2018

复杂度控制、抽象层次管理

Stanford CS 190 课程教材。提出"深度模块 vs 浅层模块"(Deep vs Shallow Modules)理论,系统阐述"在正确的层次上偷懒"的抽象哲学,以及"类与函数设计"中的信息隐藏原则。

9. The Pragmatic Programmer (《程序员修炼之道》)

Andrew Hunt & David Thomas, 1999/2019

系统化学习路径、工程纪律性

强调"ETC 原则"(Easier to Change)与"正交性"(Orthogonality),对应"可维护性优先于炫技"的工程伦理。第 2 章"务实的方法"(A Pragmatic Approach)提供的知识投资组合(Knowledge Portfolio)策略,是"广度与深度平衡"的操作框架。

10. Structure and Interpretation of Computer Programs (SICP)

Harold Abelson & Gerald Jay Sussman, 1985/1996

计算思维本质、抽象层次

MIT 6.001 经典教材。通过 Lisp/Scheme 教授"控制复杂度"的本质方法(过程抽象、数据抽象、元语言抽象),是理解"编程思维是跨语言"的理论基石。

四、能力进阶:刻意练习与专家路径

11. Peak: Secrets from the New Science of Expertise (《刻意练习》)

Anders Ericsson & Robert Pool, 2016

能力进阶机制、阶梯式增长

"刻意练习"(Deliberate Practice)理论的原始出处。澄清了"一万小时定律"的误读,强调有目的练习(Purposeful Practice)需要包含明确目标、即时反馈与舒适区外的挑战,完美解释"平台期"与"质变"的科学机制。

12. Apprenticeship Patterns: Guidance for the Aspiring Software Craftsman

Dave Hoover & Adewale Oshineye, 2009

导师制学习、代码阅读策略

针对软件学徒制(Apprenticeship)的模式语言。第 4 章"阅读代码"(Read Code)与第 6 章"实践,实践,再实践"(Practice, Practice, Practice)提供"克隆开源项目"与"阅读优质代码"的具体实施框架。

13. Exercises in Programming Style

Cristina Videira Lopes, 2014

多范式思维、语言联邦概念

通过同一算法(Term Frequency)的 33 种不同编程风格实现(从原始过程式到约束编程),训练强调的"语言只是工具,思维才是核心"的认知灵活性。

14. 《编程珠玑》(Programming Pearls)

Jon Bentley 著,黄倩等译

算法思维、问题拆解

通过"位图排序"等经典案例,演示"将复杂问题拆解为可实现小步骤"的工程思维。

15. 《软件工程:实践者的研究方法》(Software Engineering: A Practitioner's Approach)

Roger S. Pressman 著,郑人杰等译

系统化工程实践、软件生命周期

软件工程领域的标准教材,提供从需求分析到维护的完整工程框架,纠偏"只写代码"的狭隘认知。

阅读路径

阶段一(认知奠基): Weinberg → Brooks → SICP
阶段二(误区识别): Glass → Bossavit → The Mythical Man-Month
阶段三(工程实践): McConnell → Ousterhout → The Pragmatic Programmer
阶段四(能力精进): Ericsson (Peak ) → Hoover (Apprenticeship Patterns) → 源码阅读实践

共同构建了一个从认知科学基础工程实践落地的完整知识体系,支撑提出的"先打基础,再做项目,然后找方向深入"的进阶路径。


Reference

相关推荐
EXtreme354 个月前
链表进化论:C语言实现带哨兵位的双向循环链表,解锁O(1)删除的奥秘
c语言·数据结构·性能优化·双向链表·编程进阶·链表教程