有人说,编码很简单,就像骑自行车一样。但编程其实就是一辆摩托车,一辆非常强大和快速的摩托车。编码就像骑车一样,你需要负责任和有意识地坐在马鞍上,并加倍努力才能成为赢家。事实上,骑手和程序员都犯了同样的新手错误:新手往往倾向于关注快速、强大的工具和创新的技巧,认为只有这样才能成为真正的大师。这种心态部分是由于“邓宁-克鲁格效应”,新手无法理解他们职业的复杂性和重要性。幸运的是,凭借经验,即使是最狂热的初学者也会意识到编程的艺术不仅仅涉及选择最佳算法。在本文中,我想分享我对程序员真正重要的事情以及新手和经验丰富的开发人员在创建软件和编写代码时应该记住的事情的看法。
典型的新手摩托车手从哪里开始?数字和小工具。功率、扭矩、性能部件,在四分之一英里的比赛中以理论上的毫秒数完成……就像他们即将进入 MotoGP 起跑线一样。同时,他们的主要任务只是学习如何安全骑行。同样,初学者开发人员经常会专注于不必要的代码性能。争论 Python 中 `dict()` 或 `{}` 哪个更高效的文章,或者使用框架的利弊(尽管它们可能会降低性能)的文章,助长了这种痴迷。虽然了解编程语言的复杂性是有益的,有时是至关重要的——例如在飞机软件、股票交易机器人或医疗设备中——但对于我们每天创建的大多数程序来说,这并不总是至关重要的。即使你正在开发性能至关重要的软件,也必须知道代码的哪些部分需要高性能,哪些不需要。
然而,代码的可读性始终是最重要的。许多研究和调查证实,开发人员花在阅读和理解代码上的时间比编写代码的时间要多。例如,研究
在大多数情况下,我们的目标是创建一款可维护的产品,不需要复杂的支持,并在竞争环境中蓬勃发展。这并不意味着我们可以完全忽略性能;我们必须找到可维护性和性能共存的平衡点。如果需要高性能代码,我们可以在项目启动后优化速度较慢的部分。
还要记住,编译器和解释器会不断发展,但您的代码保持不变。为一个编译器版本编写的超级优化的神奇代码片段可能会成为另一个编译器版本中无关紧要的失败之作。此外,未来的开发人员(甚至您)都需要使用该代码。那么,我们什么时候应该牺牲可读性来换取性能呢?
确定何时优先考虑性能而不是可读性涉及查明应用程序中的瓶颈:
对应用程序进行分析:如果分析表明特定的关键代码段对性能有显著影响,则优化这些片段可能会导致可读性降低。
负载测试:模拟高负载可以帮助在性能瓶颈成为实际问题之前识别它们。
用户反馈分析:收集用户反馈可以突出显示性能不佳的领域。
日志记录和监控:分析执行日志和指标可以识别应用程序实际运行过程中的问题区域。此阶段可能会发现意外问题,例如 API 使用不当导致性能问题。
静态代码分析工具:某些工具可以在代码审查期间提出性能改进建议。在任务审查期间自动运行这些工具是一种很好的做法。
这些技巧可以帮助您识别应用程序的弱点,让您专注于必要的优化。根据我的个人经验,这些优化不太可能涉及奇特的语言构造,而更有可能涉及优化数据库交互或外部 API 的使用。
在路上行驶时,一项至关重要的安全技能是可预测性,同样,要读懂别人的意图。编码就像骑行一样,你无法直接读懂别人的想法。骑两轮车时,你必须注意细微的动作,并预测别人下一秒会做什么。程序员拥有(但并不总是使用)一个强大的工具来代替心灵感应:文书工作。大多数开发人员都同意文档对于项目至关重要,调查结果如下:
文档可以采用多种形式,从 Confluence 等系统中的详细项目描述到代码注释以及自动或半自动生成的项目描述网站。它甚至可以像项目根目录中的 README 文件一样简单。无论格式如何,创建文档的过程远远超出了仅仅传达有关产品如何工作的信息。这个过程让我们重新思考我们所做的事情,这通常可以导致 API 和整体架构的改进。在记录我创建的功能时,我经常意识到它可能很难使用,并且我已经找到了解决这个问题的方法。
需要记住的是,维护文档始终需要付出巨大努力,尤其是在项目处于频繁更改的阶段时。在这种情况下,您应该权衡所有风险,并仔细考虑要记录哪些逻辑。如果您的项目已经达到成熟状态,那么良好的文档将带来的好处多于挑战:新开发人员可以更快地加入并获得动力,而老员工可以快速弄清楚某些功能的工作原理。此外,在拥有许多团队的大型项目中,具有良好搜索功能的文档可以防止功能重复。
使用转向灯是成为可预测骑手的最基本方式。同样,代码注释可能是告诉别人你在做什么的最简单、最直接的方式。而且,就像使用转向灯一样,它不会让你变得不那么酷。我知道,人们普遍认为注释是不必要的,因为代码应该是不言自明的。但是,不,我不完全同意这一点。高质量的代码通常可以通过良好的变量和函数命名、清晰的结构和遵守干净的代码原则来直观地理解。然而,即使在这种情况下,经过深思熟虑的注释也可以提供宝贵的信息。
对于需要额外背景信息才能理解的复杂算法或解决方案,注释起着至关重要的作用。它们可以解释方法背后的“原因” ,而代码本身并不总是能说明问题。当代码针对性能进行了优化,但其意图和逻辑并不一目了然时,注释就显得尤为重要。注释还可以帮助重新考虑所选算法是否朝着正确的方向发展。
在复杂的业务逻辑或项目特定需求中,注释可以起到救星的作用,而对于新团队成员或长期项目支持来说,这些需求可能并不明显。它们有助于在团队中保留知识,并使开发人员之间的项目转移变得更加容易。
当然,必须避免过多的注释,因为注释会陈述显而易见的内容,或者变得过时和具有误导性。注释的目的是确保代码清晰并支持对代码的理解,而不是用不必要的信息来扰乱代码。
好的,现在想象一下我们终于学会了如何骑车,现在我们想在真正的赛道上试试运气。好吧,我们很快就会发现,真正的比赛不仅仅是能够“踩下油门”。它涉及训练和测试,以及微调你的机器以适应你的习惯和比赛条件。这同样适用于代码:在真正启动之前,应该彻底尝试、测试和纠正它。因此,以最大的责任感进行代码测试至关重要。测试通常被视为一种查找错误的工具,但它们的作用更为广泛:
有效的测试对于生成高质量、可靠且易于理解的代码至关重要。但是,就像文档一样,测试可能耗费大量资源,尤其是在项目的早期阶段。在测试的必要性与时间和资源限制之间取得平衡至关重要。
显然,复杂代码的绝对测试覆盖率根本无法实现。因此,开发人员必须优先测试关键功能和关键代码部分,并知道何时停止,以避免无休止的测试循环。
最后,没有适当的维护,摩托车就无法可靠运行。有不少人忽视了骑车的这个方面,但他们编造的故事(从有趣到可怕再到悲伤)都是我们绝对不想参与其中的。在编程世界中,就像在摩托车世界中一样,代码维护不仅仅是一种建议,而是一种必需,尤其是对于长期项目而言。缺乏维护和更新会导致产品过时和安全漏洞。
如果代码未更新以兼容最新的编译器和解释器,更新代码可能会(实际上也会)变得越来越困难。如果您正在开发桌面或移动应用程序,您的产品可能无法在新操作系统版本上运行。对于网站,它可能会由于工具和技术过时而停止运行。最简单的问题可能是安全证书过期或续订软件过时。
定期更新和重构对于保持代码的可读性也至关重要。这可以使项目易于管理,并简化未来的更改和功能添加。
简而言之,热爱你的代码并投入时间——但不要过度,否则你最终会像“零定理”的主角一样。祝你好运!