十年很短,编程很难

前天冲浪看到的一篇文章,深有感触,翻译给大家一起看看吧

许多年前,当我仍是一名主修计算机科学的高年级学生时,我整天浏览各种在线招聘信息,希望能找到适合程序员的实习职位

除了实习职位,我偶尔也会点击一些“高级工程师”的招聘信息。回顾那些帖子,除了令人眼花缭乱的技术术语外,对我印象最深的是第一行注明的工作经验要求:“此职位要求至少5年工作经验。”

作为一个从未工作过的新手,这些经验要求看起来极为夸张。然而,在感到不知所措并赞叹不已的同时,有时我会在心里偷偷幻想:“有五年工作经验的程序员一定很厉害吧!对他们来说,编程像吃饭一样简单吗?

时光飞逝,一转眼已过去十多年。现在回首,我也已成为一名拥有10年工作经验的光荣从业者。在自大学高年级以来在软件开发行业中挣扎并获得实际经验的过程中,我发现很多事情与当初的想象大不相同。例如:

  • 随着经验的增长,编程并没有变得更简单。“像吃饭一样简单”只存在于梦中
  • 为许多“大项目”编写代码不仅令人乏味,而且很危险。解决LeetCode上的算法问题更有趣
  • 仅从技术角度思考问题不能使人成为一个好的程序员。有些事情比技术更重要

进一步思考,关于编程仍有许多想法。我整理了其中的八个,并写下了这篇文章。如果这些建议中有任何一点与你产生共鸣,我会感到非常高兴

1. 编写代码简单,但编写优质代码却相当困难

编程曾经是一项极具挑战性的专业技能。在过去,普通人学习编程的最常见方式是通过教科书和书籍。然而,大多数编程教科书非常晦涩难懂,对初学者不友好。因此,许多人在体验到编程的乐趣之前就半途而废了

但如今,学习编程变得越来越容易。学习不再局限于仅仅研读书籍;现在有许多新的学习方式。观看教学视频,参与Codecademy的互动课程,甚至通过在CodeCombat上玩游戏直接学习编程 — 每个人都可以找到适合自己的学习方法

在这里插入图片描述

此外,编程语言变得越来越用户友好。经典语言如C和Java不再是大多数初学者的首选。许多更简单、易学的动态类型语言变得流行起来,相关工具如集成开发环境(IDE)也变得日益复杂。这些因素进一步降低了编程的学习门槛

总的来说,编程早已摆脱了神秘的面纱。它已经从只有少数人能掌握的技能转变为任何人都可以学会的普通技艺

然而,学习门槛降低和友好的编程语言并不意味着每个人都能写出良好的代码。如果你已经工作并参与了一些项目,我想问你一个问题:“你每天遇到的这些项目的代码质量如何?好的代码多还是糟糕的代码多?”

我不知道你会如何回答这个问题,但让我先分享一下我的回答

好的代码仍然很少

2013年,我转职到了一家大型互联网公司

在加入这家公司之前,我只在大约十个人的小公司工作过。因此,在各个方面我对新公司都寄予了很高的期望,尤其是对软件质量的期望。当时,我的想法可能是这样的:“这是一个支持拥有数百万用户的产品的‘大’项目。代码质量肯定比以前好了许多!”

直到在新公司工作了一周后,我才意识到我是多么错误。所谓的“大”项目的代码质量远远不符合我的期望。打开IDE,到处都是数百行的函数和神秘的数字常量;开发一个小需求感觉就像攀登珠穆朗玛峰一样艰难

后来,在更多公司工作并接触到更多软件项目后,我总结了这样的经验:无论公司或项目有多么大或令人印象深刻,实际工作中遇到好的代码仍然是不太可能的事情

什么是好代码的要素?

说到这里,什么样的代码被认为是好代码呢?在这方面,Martin Fowler的一句话经常被大家引用:

“任何傻瓜都能写出计算机能理解的代码。优秀的程序员编写人类能理解的代码。”

我认为这可以作为评价好代码的起点:好的代码必须是可读的,易读的,容易理解的。写好代码的第一原则是优先考虑人类读者

除了可读性,还有许多其他方面可以评估代码的质量:

  • 合适的编程语言:当前编程语言的推荐写作风格是否被采用?语言特性和语法糖是否得当使用?
  • 易于修改:代码设计是否考虑了未来的需求变化?发生更改时,代码是否容易相应修改?
  • 合理的API设计:API设计是否合理且易于使用?一个好的API在简单场景中使用方便,在高级场景中根据需要可以扩展
  • 避免过度设计:代码是否受到过度设计和过早优化的问题?
  • ……

简而言之,好的代码不是程序员在任何水平上都能轻松获得的东西。写好代码需要在许多方面进行反复权衡和慎重设计,最终进行不断的打磨

那么,如果你想迅速掌握编码的技艺,有没有什么捷径呢?

提升编码技能的捷径

在许多层面上,我认为编程和写作非常相似。两者都使用文字和符号来表达思想,只是表达的方式略有不同

说到写作,我想问一个关于作家的问题:“你曾听说过一个作家不读书吗?你曾听说过一个作家说他从不读别人的作品,只读自己的吗?”我猜答案应该是否定的

如果你查找相关信息,你会发现许多专业作家的日常生活都围绕着阅读和写作。在开始写作之前,他们每天花费大量时间阅读各种文本

同样作为“文字工作者”,程序员往往忽略了阅读。然而,如果我们想迅速提高我们的编程技能,阅读是不可或缺的一部分。除了我们在日常工作中遇到的项目之外,我们还应该多读一些经典的软件项目,并从中学习API设计、模块架构和代码编写技巧

不仅是代码和技术文档,定期阅读一些与计算机相关的专业书籍也是推荐的,以保持阅读书籍的习惯。在这方面,我认为Jeff Atwood在15年前写的一篇名为“程Programmers Don’t Read Books – But You Should”的文章今天仍然具有相关性

提高编程技能的捷径在于“阅读 <-> 编码”之间的无尽循环

2. 编程的本质是“创造”

在程序员的日常工作中,许多事情都能带来成就感,甚至使人惊叹“编程是多么美妙”。例如,修复一个难以定位的错误,通过使用新算法提高代码性能等。但在所有这些事情中,没有哪一样能比“用自己的双手创造出某物”的感觉更棒

在编程时,创造新事物的机会随处可见。这不仅仅涉及发布新软件。编写可重用的实用函数或设计清晰的数据模型也可以被视为“创造”

作为程序员,保持对“创造”的热情至关重要,因为它可以帮助我们:

  • 更高效地学习:学习新技术的最有效方式是使用它开发一个真实的项目,在创造过程中学习会取得最好的结果
  • 偶然遇到一些不同寻常的事情:许多改变世界的开源软件项目最初都是作者纯粹出于兴趣创建的,比如Linus Torvalds和Linux,Guido van Rossum和Python。

尽管“创造”有很多好处,程序员有充足的机会去创造,但很多人常常缺乏“创造者”的意识。就像一个广为流传的故事说的那样:一位哲学家问一个正在砌砖的泥瓦匠,有些人知道他们正在建造一座大教堂,而其他人认为他们只是在铺砖。许多程序员“只看到砖块,而没有看到大教堂”

一旦将自己定位为创造者,对事物的看法将发生翻天覆地的变化。例如,在为API添加错误提示文本时,创造者可以摆脱“只是快速满足需求”的思维陷阱,向前迈出一步,提出更重要的问题:“我想为用户创造什么样的产品体验?什么样的错误消息会帮助我实现那个目标?”

就像任何有用的编程模式一样,“创造者思维”也可以成为你职业生涯中的巨大推动力。因此,现在试着问问自己一个问题 — “我的下一个创作会是什么呢?”

3. 为高效的试错创造环境至关重要

我曾参与开发一个设计精美、功能丰富,每天有大量用户使用的互联网产品

然而,尽管从市场的角度来看,这是一个成功的产品,但其工程质量非常糟糕。如果你打开它的后端项目并把所有目录颠倒过来,你根本找不到任何单元测试代码,更别说其他自动化测试流程了。而且,业务逻辑非常复杂。最终,项目代码之间存在着意想不到的耦合,就像牛背上无数的毛发一样。开发一个新功能很容易破坏旧的功能

在这里插入图片描述

因此,每次项目发布时,开发团队和产品团队都必须保持高度警惕,创造一种非常紧张的氛围。整个发布过程也非常惊心动魄,紧急回滚时有发生。在这样的环境中工作,不仅促进了技术的成长,而且无疑地考验了一个人的心理韧性

编程原本是一份有趣的工作,但是为这样的项目编程却消除了任何愉悦感。究竟是什么夺走了编程的乐趣呢?

理想的编程体验 ≈ “刷题”

LeetCode是一个著名的编程学习网站,提供许多涵盖各种难度的编程问题,其中大多数与算法有关。用户可以选择他们感兴趣的问题,直接编写代码(支持几十种编程语言),并在浏览器中执行。如果所有测试用例都通过,就被认为是一个成功的解决方案。

在这里插入图片描述
在 LeetCode 上解决问题就像玩游戏一样,充满挑战和乐趣。整个解决问题的过程完美地展示了理想的编程体验:

  • 关注点分离:每个问题都是一个独立的实体,让开发人员能够一次完全沉浸在一个问题中
  • 快速准确的反馈:开发人员可以通过自动测试快速获得代码调整反馈
  • 零成本试错:编写有语法错误或逻辑问题的代码不会产生任何不良后果,从而减轻了心理负担

不过,你可能会认为我在屏幕前胡说八道

"还有什么?解决算法问题、编写小脚本,不都是一样的体验吗?"你可能会继续补充:“你知道我们公司的项目有多复杂吗?它们规模庞大,模块众多。我们每天为数百万人提供服务。我们有多套数据库和三种类型的消息队列。当然,开发工作会很麻烦!”

的确,世界各地的软件开发工作千差万别,不可能所有项目都像在 LeetCode 上解决问题那样轻松愉快。但是,这并不意味着我们不应该努力改善我们的编程环境,哪怕只是一点点

可用于改善编程体验的概念和工具包括

  • 模块化思维:正确设计项目中的每个模块,降低耦合度,增强正交性
  • 设计原则:在微观层面,应用经典的设计原则和模式,如 "SOLID "原则
  • 动化测试:编写标准化的单元测试,必要时使用 Mock 技术,并通过自动化测试覆盖关键业务路径
  • 缩短反馈回路:改用更快的编译工具,优化单元测试性能,尽一切可能缩短从 "修改代码 "到 "获得反馈 "的等待时间
  • 微服务架构:必要时,将单体系统拆分成多个具有不同职责的微服务,以分散复杂性

关注编程环境,刻意营造 “代码天堂”,允许高效试错,让工作像解决问题一样轻松愉快。这是经验丰富的程序员能为团队做出的最佳贡献之一

4. 避免陷入代码完美主义的陷阱

对代码质量精益求精是好事,但也要注意不要陷入完美主义的陷阱。因为编程不是艺术创作,它不鼓励人们无限追求完美。作家可以花数年时间打磨一部杰作,但程序员如果过于专注于代码,就会出现问题

世界上没有完美的代码。大多数时候,只要你的代码能满足当前的要求,并为将来的扩展留有余地,就足够了。有几次,我看到应聘者在简历上给自己贴上了 "代码强迫症 "的标签。隔着屏幕,我能感受到他们对代码质量的重视,但在我内心深处,我希望他们把完美主义的陷阱远远抛在脑后

5. 技术固然重要,但 "人 "可能更重要

在软件开发领域,“单一责任原则”(Single Responsibility Principle,简称 SRP)是一个非常著名的设计原则。它的定义很简单,可以用一句话概括:“每个软件模块应该只有一个改变的理由”

在这里插入图片描述
要掌握 SRP 原则,关键是要了解 "修改的原因 "是什么。程序没有生命,无法主动改变自己。修改程序的任何原因都来自与程序相关的人,而人是修改程序的罪魁祸首

举个简单的例子。以下两类程序中,哪一类违反了 SRP 原则?

  • 字典数据类,支持两种类型的操作:存储数据和检索数据;
  • 一个雇员档案类,支持两类操作:更新个人信息和渲染用户档案卡图像。

在大多数人看来,第一个例子没有问题,但第二个例子却违反了 SRP 原则。要得出这个结论,似乎不需要严格的分析或证明,只需运用一点直觉即可。然而,如果我们认真分析一下,就不难发现修改第二个例子有两个不同的可疑理由:

  • 经理认为数据中的 "个人电话号码 "字段不应包含非法数字,因此需要添加简单的验证逻辑
  • 员工认为个人名片图片上的 "姓名 "部分太小,希望增加字体大小

“要求更改的是人。你不想把许多不同的人出于不同的原因而关心的代码混在一起,从而使这些人或你自己感到困惑”。- 单一责任原则

理解 SRP 原则的关键在于首先了解人以及他们在软件开发中扮演的角色

这里还有一个例子。微服务架构是近年来的热门话题。然而,很多人在讨论时往往只关注技术本身,却忽略了微服务架构与人之间的关系

区分微服务架构风格的关键在于,将单体系统拆分成独立的微服务后,不同模块之间的界限会变得更加清晰。与数百人的团队维护单体系统相比,许多维护独立微服务的小型组织具有更高的运营效率

如果缺乏特定的组织规模(即 “人”)作为前提,谈论微服务的各种技术优势和那些花哨的技术就会完全错位

技术当然重要。作为专业技术人员,那些华丽的架构图和巧妙的代码细节自然会吸引我们的注意力。但是,请不要忽视软件开发中的另一个重要因素–“人”。必要时,改变一下视角(从 "技术 "到 “人”),这将使你受益匪浅

6. 渴求知识是好事,但也要注意方法

现在大家都在讲 “终身学习”,而程序员是一个特别需要终身学习的职业。因为计算机技术的迭代和更新是非常快的,三年前流行的框架或编程语言,很可能一个月前就已经过时了

在这里插入图片描述
要想在工作中表现出色,程序员需要学习的东西很多,涉及方方面面。以我比较熟悉的后端领域为例,一名合格的后端工程师至少需要掌握以下内容:

一种或多种后端编程语言/关系数据库(如 MySQL)/常用存储组件(如 Redis)/设计模式/用户体验/软件工程/编译器原理/操作系统/网络基础知识/分布式系统/…

虽然要学的东西很多,但据我观察,大多数程序员都喜欢学习(或至少不排斥学习),因此心态不是问题。不过,有时仅有 "求知若渴 "的心态是不够的。学习时尤其要注意 “性价比”

注重学习的成本效益

下图展示了学习效果与投入之间的关系

在这里插入图片描述
从图中可以看出,在学习的早期阶段,当输入量较少时,学习效率会迅速提高。然而,一旦学习效率超过某个临界值,进一步提高学习效率所需的学习输入量就会呈指数增长

正因为如此,我建议大家在学习新知识时,首先要在头脑中想清楚:"我应该在图形的哪个位置停下来?"而不是盲目地学习

知识的海洋浩瀚无边,有些东西需要几个月甚至几年的持续学习和不断提高,也有一些事情,掌握肤浅的知识就足够了。准确评估和分配自己有限的学习精力,比努力学习更重要。

选择合适的学习材料

确定了学习目标,下一步就是寻找合适的学习材料。在这方面,我想与大家分享一个失败的亲身经历

有一段时间,我突然对产品交互设计产生了浓厚的兴趣,认为自己应该在这方面有所提高。于是,我精心挑选了一本该领域非常经典的专业书籍:《About Face 4: The Essentials of Interaction Design》,并满怀信心地把它带回了家,相信自己的交互设计能力一定能很快得到提高

然而,事与愿违。当我捧起那本经典著作时,却发现自己连第一章都无法顺利读完–正所谓 “转行如过山车”

从这次失败中,我总结了一些经验。那就是在学习新知识时,我们最好选择那些更容易阅读、更适合初学者的教材,而不是一味地追求最经典、最权威的教材,不考虑自己的水平

回顾以往的经验,我认为以下几本书非常适合初学者学习,而且物美价廉:

  • 《The Non-Designer’s Design Book》:设计相关
  • 《Don’t Make Me Think》:网络用户体验相关

也许每个人的内心都渴望成为一个知识渊博、无所不知的人。然而,可供分配的时间和精力总是有限的,我们无法也没有必要成为所有领域的专家

7. 越早开始编写单元测试越好

我喜欢单元测试。我相信,编写单元测试对我的编程生涯产生了巨大的影响。夸张一点说,如果以 "开始编写单元测试 "为分界线,我职业生涯的后半段要比前半段精彩得多

编写单元测试有很多好处,比如可以推动代码设计的改进,还可以作为代码的一种文档形式等等。此外,全面的单元测试对于创造一个可以高效犯错的环境也至关重要

我曾写过几篇关于单元测试的文章,如《关于单元测试的 5 条建议》和《《Celeste》游戏教会了我编程原理》。我只想说:如果你还没有尝试过编写单元测试,或者到目前为止对测试还不太重视,我建议你从明天开始做起

在这里插入图片描述

8. 程序员最大的敌人是什么?

在大多数程序员笑话中,产品经理往往以对立的角色出现。他们口中的项目需求总是不断变化,每天都有新的想法冒出来,这让程序员们非常沮丧

在这里插入图片描述
在这些笑话的背景下,不断修改需求的产品经理似乎成了程序员最大的敌人。似乎只要产品不修改需求,大家的工作环境就会立刻变成乌托邦

虽然偶尔拿产品经理开开玩笑很有意思,但我还是想严肃地说一句:产品经理不是敌人

因为从某种角度看,软件生来就是用来修改的(否则,你猜它为什么叫 "软件 “?)从这个意义上说,开发软件与建造房屋完全不同。因为没有人会在完成一栋建筑后说"我们把它拆了重建吧!同样的建筑,但钢筋水泥要少 30%!”

因此,产品经理和不稳定的需求并不是程序员的敌人。此外,能否写出易于修改和适应变化的代码,也是区分普通程序员和优秀程序员的重要标准之一

那么,程序员最大的敌人是什么呢?

复杂性是最大的敌人

正如《代码大全 2》中所说:软件开发的核心问题是管理复杂性,不受控制的复杂性是程序员最大的敌人

让我们来看看导致项目复杂性持续增长的因素:

  • 增加新功能的数量:更多的功能意味着更多的代码,而更多的代码通常意味着更高的复杂性
  • 高可用性要求:为了实现高可用性,需要引入额外的技术组件和代码,如消息队列
  • 高性能要求:为提高性能,需要引入缓存和相关模块代码。一些模块被拆分并用高性能语言重写
  • 反复推迟重构:由于项目时间紧迫,紧急重构任务被一再推迟,导致技术债务不断积累
  • 忽视自动化测试:没有人编写单元测试,也没有人关心测试

有一天,当项目的复杂性达到一定程度时,空气中就会响起一声巨响。"咚!"一个人人都不愿也不敢改变的 "大坑 "突然出现在每个人的集成开发环境中

猜猜这个坑是谁挖的?

在这里插入图片描述

减缓日益复杂的过程

虽然复杂性总是不可避免地继续增长,但许多做法可以减缓这一进程。如果每个人都能做到以下几点,就有可能把复杂性长期控制在一个合理的范围内

  • 精通当前的编程语言和工具,编写简洁的代码
  • 使用适当的设计模式和编程范例
  • 对重复代码、抽象库和框架零容忍
  • 适当应用简洁的架构和领域驱动设计原则
  • 编写详细的文档和注释
  • 根据规范编写结构合理的单元测试
  • 将可变类型与不可变类型分开

这些要求看似繁多,但概括起来,核心只有一句话:写出更好的代码

写在最后

2021 年,我给团队做了一次演讲。当时 PPT 的标题是《编程八年后的八点思考》。把材料分享到公司内网后,一位同事看到了,说光看 PPT 还不够,希望我能把它扩展成一篇文章。我回复说没问题。如今,三年过去了,我终于实现了自己的诺言

当年准备演讲时,我完成了整个 PPT,却不知道最后一页该写什么。于是,我灵机一动,在纯白的背景上,中间加了一行粗黑的文字:“十年很短,编程很难”。现在,在第二个十年即将过半之际,这句话的后半部分似乎仍然适用于我–进展甚微,但仍在继续努力

https://medium.com/gitconnected/i-have-been-in-this-industry-for-10-years-and-i-still-find-programming-difficult-15a5be97e82f

  • 27
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

啥都生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值