构建软件
过早优化是万恶之源。不要低估了这个说法的有效性。
你很少需要自己从头开始去开发一些东西,几乎每一种应用场景都已经有了相应的库和依赖项。所以,不要重复发明轮子。
搞清楚问题域是找到解决方案之前的第一步,但我们却经常会跳过第一步,直接去寻找解决方案。
不要太过于追求完美。首先,让它能够正常运行,然后再去优化。优先级最高的事情应该是先保证交付。
糟糕的程序员操心代码,优秀的程序员操心数据结构以及它们之间的关系。--Linus Torvalds
在代码注释中解释你为什么要写这些代码,而不是解释你在做什么。但不要过度描述,不要把注释当成小说写。
有意义的错误日志可以节省大量的调试时间。在错误日志中提供所有相关信息,而不仅仅是“error occurred in Function X!”另外不要记录任何敏感信息或个人信息。
100% 的代码行或分支覆盖率并不意味着你的代码就没有 bug。测试用例要覆盖所有的功能需求,而不是覆盖代码行或分支。
如果你在修复 bug,请编写相应的测试用例,那么这个 bug 就不会在未来某个时刻出现。bug 的出现通常是因为错误的假设,为所有这些错误的假设编写测试用例将会让应用程序变得更加健壮。
在人们阅读你的代码时,让他们能够在不记住超过 7 样东西的情况下理解你的代码。因为人类大脑的短期记忆无法同时记住 7 样以上的东西。这也是为什么很多代码检查器在遇到包含超过 7 个参数的函数时就会发出警告。
不要因为别人告诉你要怎样去做一件事情,你就照做。你要明白为什么要这么做,如果你不信服,可以挑战一下。
解决问题应该是每个工程师都最擅长的技能。你所在的组织有很多问题需要解决,所以请开始解决问题吧。虽然不是所有问题都能够得到解决,但在尝试解决问题的过程中你会学到很多。
系统设计
最好的系统设计通常是最简单的。Keep it simple, stupid!(KISS 原则)。
设计模式和最佳实践并非银弹。一个好的工程师遵循最佳实践,但一个优秀的工程师知道什么时候打破最佳实践。
理解抽象。代码中引入的不必要的复杂性通常是由于糟糕的抽象导致的。
一个系统的健壮程度取决于它最薄弱的地方。所以,请关注系统的瓶颈部分。
偏离主要源头越远,事情就越糟糕。所以,尽量减少跳跃,这个原则适用于技术和非技术方面。
不存在完美的解决方案,一切都是权衡的结果。列出解决方案的优点和缺点,以及你的真正要求。
你在项目中引入的每一项技术都有相应的风险。衡量风险并制定降低风险的计划,不穿救生衣就不要往海里跳。
避免过早抽象。解决你现在的问题,这样就够了。当你看到类似的问题或者模式出现时,这个时候应该考虑对其进行抽象。
“软件设计有两种方法:一种是保持简单,简单到没有明显的缺陷,另一种是让它变得复杂,复杂到没有明显的缺陷。第一种方法要困难得多,因为要保持简单是很难的”。——Tony Hoare。
不要对编程语言或框架有太多偏见。如果你喜欢某种编程语言,不要过于崇拜它,也不要到处用它。如果你讨厌它,也不要一直抱怨它。每种编程语言或框架都是为特定的场景而设计的。作为工程师,你的工作是为特定场景选择正确的工具。
当你弄清楚代码是怎样运行,却忘记了为什么要这么做,那么代码中就有很多不必要的抽象和复杂性需要清理。
一旦复杂性累积起来,就很难消除。不要认为你当下做出的变更所带来的一点点复杂性没什么大不了的,如果每个开发人员都这么做,复杂性就会成倍地增加。
如果你决定要重写某个组件或服务,请三思而后行。读代码比写代码难,这就是为什么“重写软件”的想法在软件开发中非常常见。
不要犹豫,去挑战高级工程师或架构师提出的设计,有时候你的设计比他们的更好。提出有说服力的观点并进行客观比较,但不要做一个盲目自信的混蛋。
大多数时候,静态类型语言比动态类型语言要好,尽管静态类型系统带来了一些额外的开销。这也是为什么 TypeScript 会是最受欢迎的编程语言之一。
一些其他贴士
优化代码,让它们更容易被读懂。冗长乏味的 20 行代码总比晦涩难懂的 1 行代码要好。
新手容易与自己编写的代码建立情感联系,但在敏捷开发环境中,需求和代码会不断发生变化,所以你要习惯于不断修改和删除旧代码。
对于任何一个问题都要想出不止一种解决方法。试图找到多个解决方案会迫使你以不同的方式思考问题,在有了不同的解决方案之后,你就可以做出权衡。
你负责的模块越多,获得的领域知识就越多。你拥有的领域知识越多,需要参加的会议就越多。你参加的会议越多,写的代码就越少。通过记录和分享领域知识来打破这个链条,这样你就不会成为唯一的瓶颈点。当然,我也知道这说起来容易做起来难。
当你在某个问题上困了很长一段时间而没有任何进展时,重新描述这个问题或向别人解释这个问题,大多数情况下这样做都会有神奇的效果。为什么小黄鸭调试法会如此受欢迎,现在你应该知道答案了。
你不需要在理解了整个代码库之后才开始工作。在了解了系统架构和生命周期之后,就可以开始开发你的模块,不要浪费时间去了解每一类是干什么的。
代码是负债而不是资产。代码越多,需要阅读、理解、测试和维护的代码就越多。最好的代码是没有代码。
学习如何在 StackOverflow 上提问题。你可能很少需要在这类平台上提问题,但是当你使用的库或框架只有很有限的文档或用户时,这就成了一项有用的技能。
如果你发现了其他模块出现了 bug,请通知相应的开发人员,或者在 Scrum 中提及,不要因为这些模块不是你负责的就置之不理。
你编写的函数应该没有副作用,这样易于进行独立的测试。
看在上帝的份上,请不要自己编写日期格式化或日期解析函数。每种编程语言都有很多流行的库,使用它们就可以了,日期和时区问题比你想象的要复杂得多。
关于安全
每个开发人员都应该知道如何编写安全的代码。基于糟糕的设计或抽象写代码是可以的,但有安全漏洞的代码绝对不行。写代码前先了解一下 OWASP 项目(https://owasp.org/www-project-top-ten/)。
当你想要快速格式化或验证 JSON / XML / YAML 数据时,不要使用在线格式化器或验证器,特别是如果你处理的是一些机密的生产数据。这个时候请使用本地编辑器或命令行工具,不要冒着把公司数据泄露出去的风险。(推荐工具 CyberChef,https://gchq.github.io/CyberChef/,请下载离线使用)
永远不要向代码库中推送敏感信息。在提交和推送代码之前,一定要仔细检查代码中是否包含了电子邮件地址、电话号码、密码、认证令牌、私钥等信息。
总是对用户输入进行验证和清理。永远不要假设或期望用户按照指定的格式输入数据。在验证用户输入时,首选白名单而不是黑名单。
关于拉取请求
你可以在拉取请求的评论中加入赞美之词。当我们在代码评审时,总是专注于不好的部分,而一个小小的赞美可以给你的同事带来微笑。下次可以试一试这样做。
每天查看拉取请求,阅读其他开发人员的评论,以获得关于特性和编码标准的不同观点。
代码格式和其他标准应该被自动化。使用代码格式化器和检查器来构建项目开发管道,让整个代码库保持一致和整洁。请停止在评论中进行有关 tab 好还是空格好的争论!
创建小而美的拉取请求。如果你正在处理多个功能,请将它们分成多个拉取请求。给评审人员留有足够的评审时间,不要在部署前 1 小时创建拉取请求。
关于学习
作为一个程序员,你应该喜欢学习和探索。如果你不喜欢这些,需要考虑其他职业选择。
你不需要去学习每一项技术,你只需要紧跟潮流,在需要的时候学习和使用它们。
从一个刚毕业的实习生身上也可以学到很多东西。永远不要把你的学习对象局限于更高职位的人。
阅读你所使用的开源项目的源代码,理解和学习干净的代码实践和代码组织方式。
一种学习技术的方法是自己尝试为某个开源项目构建一个高度简化的版本(https://github.com/danistefanovic/build-your-own-x)。
你可以在几天内学会一门编程语言,但要了解它的生态系统需要几个月甚至几年的时间。
探索不同的编程语言,了解不同的编程范式。了解了不同的编程范式,当你在为不同的应用场景选择正确的编程语言时,就会有所裨益。
学习 git,不仅仅是 git pull 和 git commit,要理解 git 所有的高级概念。不管你使用的是什么技术,都不能没有 git。
大多数开发人员的工作都集中在 Web/网络编程方面,所以了解网络系统的底层协议是很有必要的:HTTP、HTTPS、SSL/TLS、DNS、SMTP、IPv4、IPv6 等。
拥有良好的 CSS 专业知识会让你看起来像一个大神!如果你是一个 Web 全栈开发者,请花几天时间学习 CSS,这将为你避免“不知道自己做什么”的尴尬。
一个有吸引力的 UI 设计比一个健壮的系统架构更容易给人们(显然不是指领域专家)留下深刻的印象。所以,当你在进行概念验证时,拥有良好的设计技能是非常有用的(但不要把所有东西都硬编码成 HTML)。
关于效率
创建细粒度的子任务来跟踪任务进度,尤其是当你在处理一项巨大的任务时。检查某件事是否已经完成,这会给人一种难以言表的愉悦感,这反过来会激励你坚持下去。
不要试图同时做多个任务,专注于一个任务,尽量减少上下文切换,上下文切换的成本比你预想的要高。
改进和定制你的工作流(IDE、调试工具、生产力工具、CI/CD),帮你进行更快的迭代。
迭代得越快,失败得越快。
失败得越快,学习得就越快。
把你的时间花在自动化常规任务上。如果你做某件事超过两次,那就开发一个工具,让它在第三次时可以自动完成。但不要浪费太多时间去自动化一个只需要几分钟时间就可以完成的简单任务。你应该找到一个正确的平衡点!
用文件夹和标签来整理工作邮件(包括私人邮件)。每天稍微整理一下邮件,可以帮助你在需要的时候快速找到重要的文件或聊天记录。
学习基本的 vi 绑定,即使 vi 不是你的默认编辑器。你可以在几乎所有的文本编辑器中使用 vi 绑定,相信我,在这之后你的效率将得到大幅提升。
在这个行业中,文档技能被严重低估了。学习如何撰写设计文档、变更建议等。开始使用笔记工具来组织和记录几乎所有的事情——备忘录、个人目标、职业目标、随机出现的想法、书籍摘要,等等。
在评估任务时,一定要预留一些缓冲时间,你永远不知道在一个未知的洞穴里会遇到什么怪物。
如果你要边听音乐边干活,最好听器乐或低保真节拍或平静的音乐,而不要听带有歌词的音乐。我个人觉得在听演奏器乐时更有效率,这并不奇怪,科学方面已经为此提供了证据支持。
关于自己
马上调整好你的身体姿势!
工作之外最好有其他业余爱好。虽然你是一名开发人员,但也没必要全天候在写代码。
善待每一个人!保持冷静!最重要的是,要谦虚!
记住要经常休息,不要把自己弄得筋疲力尽。
购买一套好的工作站,因为你大部分时间都在办公桌前度过(尤其是在远程工作的日子里),在高质量的产品上多花点钱是值得的。
去了解不同的认知偏见,这样不仅能帮助你做出更好的个人决定,还能帮助你做出更好的技术决策。
在职业生涯早期就开始投资,了解复利的力量,相信我,它很神奇。同时,不要过度储蓄,如果你无法享受当下,就算存了很多钱又有什么意义呢?
关于人际关系
人际交往能力和你的技术能力一样重要。有意识地锻炼指导他人、公共演讲、领导项目等方面的能力。开发者可以打破给人留下的“社交无能”的刻板印象。
并不是每个人都有和你一样的动机。不要因为你对某个话题感兴趣,就指望别人也会感兴趣。不同的人对不同的动机有不同的反应。
不要用你的同事(事实上是任何人)不懂的东西来评判他们。
学习如何推销自己。你可能对很多东西都很熟练,但如果你没有在正确的平台上展示这些技能,没有人会欣赏你。
帮助你周围的人,让他们变得更好。传授或分享你所学到的东西。教授或写一些你学过的东西,这样会让你更好地理解它们。
勇敢地说出“我不知道”。你可能很擅长撒谎,但我们的大脑很善于识别某人是否在撒谎或假装。
你的团队中始终会有一个顶级的开发人员,他几乎可以解决任何问题。不要被他们的技术能力吓倒,看看他们提交的 PR,跟他们聊技术方面的东西,并定期从他们那里获得反馈来提高自己。
你很有可能会在工作中遇到你最好的朋友,不要因此无法向他们敞开心扉(要不要接受这个建议取决于你自己的判断)。
关于沟通
倾听,不疲于倾听!
如果你在会议上没有什么想说的,也没关系,不要东拉西扯,浪费别人的时间。
在给别人发消息时不要只是发“你好”或“早上好”之类的问候,然后等着他们回话。你要告诉他们你找他们有什么事,没有人喜欢你这种毫无意义的问候或祝福。
在向别人介绍你的设计时,尽可能使用图表,一图胜千言。在文档里使用图表也很有意义(推荐工具 draw.io)。
向别人介绍某些设计或概念时,少用行话。不是每个人都很熟悉技术术语,在使用术语时要恰到好处。
不要羞于去问一些你认为琐碎或愚蠢的问题。
如果你想在几分钟内完成工作,那就打电话。如果你想在几个小时内完成工作,那就使用即时通讯工具。如果你不想完成工作,那就发邮件(2021 年人们还在使用邮件吗?)。
当你向别人寻求帮助时,不要只说“嘿,这个有问题,你能帮我吗”,你要说“嘿,我在运行程序 X 时出现了错误 Y,我研究并尝试了解决方案 Z,但它似乎也不行,你能帮我解决这个问题吗”。在向别人寻求帮助之前先自己做一些调查,不要因为代码中小小的拼写错误而浪费别人的时间,说真的!
不要成为自行车棚效应(避重就轻)的牺牲品。在会议或讨论中,重视复杂或关键的事项,而不是琐碎的事项。
关于职业生涯
如果你不喜欢自己做的事情,没关系,但如果你讨厌自己做的事情,那就不能接受了。
当你刚进入职场时,优先考虑的是学习和发展的机会,而不是薪水、福利等。在学习效率高的活动或工作上投入更多的时间。发展综合能力,你必须及早开始。
你工作的动力应该是为团队和项目增加价值,而不是为了给别人留下好印象,进而获得更高的薪水或晋升。如果前者做好了,后者自然会光顾。
花点时间写简历,并让它保持最新。建议为自己做一个可以描述你的项目和经验的作品集网站。
你的职位越高,你要解决的问题就越抽象模糊。所以,你要学会适应不确定性。
每六个月问自己以下这些问题:
我是否在学习新的技能、拓宽自己的专业领域?
我是否对组织产生了影响?
从我的技能和经验来看,我的薪水是否足够高?
如果你的答案都是否定的,那么你必须考虑换公司或团队了。如果你在现在的公司已经工作了 2 至 3 年以上,并且你的答案都是肯定的,那么你应该考虑换公司,或者至少要对换公司持开放态度。
如果你仔细观察,你会发现编程和写作非常相似。编程语言类似于人类语言,程序员类似于作家和诗人。任何人都可以成为作家,但要成为一名优秀的作家需要付出大量时间和努力。
定期与经理进行一对一面谈,并寻求反馈,不要等到年终总结时才发现“惊喜”。
如果你的经理没有为你的失败负责,并责怪你,那么在他们手下工作就是在拿你的个人和职业发展冒险。
经验年限只是一个数字。有时候你会发现初级工程师比高级工程师对某些事情更熟悉。但请不要误解了我的意思,经验教会你的不仅仅是技能。工作经验固然重要,但这并不是评判一个工程师的唯一因素。
额外的建议
记住帕累托法则(80/20 法则),它几乎适用于软件工程的方方面面:
80%的工作是由 20%的工程师完成的;
80%的影响是由 20%的工作所带来的;
80%的错误是由 20%的代码造成的;
80%的慢性能是由 20%的代码造成的。
我可以举出无数个例子。
对于那些在 StackOverflow 出现之前就开始写代码的开发人员,我们是否应该给他们一点掌声?StackOverflow 可以解决你 95%的问题(但千万别在上面问你的个人问题)。
Git 的提交消息应该具备足够好的描述,这样你就可以从成千上万的代码提交中轻松搜索到你想要的。停止使用诸如“修复了一个 bug”、“改进了性能”、“修改了 X 模块”之类的描述。
评论 2 条评论