不要浪费时间写完美的代码

本文探讨了代码的生命周期及其重要性变化,强调不应追求完美的代码,而是关注代码的实际效果和可维护性。介绍了务实编码和重构的方法,帮助开发者提高工作效率。
系统可以持续运行 5 年、10 年甚至 20 年或者更多年。但是,特定的代码行的生命,即使是经过设计,通常要短得多:当你通过各种方式来迭代寻求解决方案时,它会有几个月、几天甚至几分钟的生命。-- Jim Bird


本文导航◈ 一些代码比其他代码重要 03%◈ 我们应该尝试编写完美的代码么? 11%◈ 务实编码和重构 46%◈ (不只是)代码无关 68% 编译自 | https://dzone.com/articles/dont-waste-time-writing 
 作者 | Jim Bird
 译者 | geekpi

系统可以持续运行 5 年、10 年甚至 20 年或者更多年。但是,特定的代码行的生命,即使是经过设计,通常要短得多:当你通过各种方式来迭代寻求解决方案时,它会有几个月、几天甚至几分钟的生命。

一些代码比其他代码重要

通过研究代码如何随时间变化[1],Michael Feathers 确定了一个代码库的冥曲线[2]。每个系统都有代码,通常有很多是一次性写成,永远都不会改变。但是有少量的代码,包括最重要和最有用的代码,会一次又一次地改变、会有几次重构或者从头重写。

当你在一个系统、或者问题领域、体系结构方法中有更多经验时,会更容易了解并预测什么代码将一直改变,哪些代码将永远不会改变:什么代码重要,什么代码不重要。

我们应该尝试编写完美的代码么?

我们知道我们应该写干净的代码[3],代码应该一致、清晰也要尽可能简单。

有些人把这变成了极端,他们迫使自己写出美丽[4]、优雅、接近完美[5]的代码,痴迷于重构[6]并且纠结每个细节。

但是,如果代码只写一次而从不改变,或者如果在另一个极端下,它一直在改变的话,就如同尝试去写完美的需求和尝试做完美的前期设计那样,写完美的代码难道不是既浪费又没有必要(也不可能实现)的么?

“你不能写出完美的软件。是不是收到了伤害?并不。把它作为生活的公理接受它、拥抱它、庆祝它。因为完美的软件不存在。在计算机的短暂历史中从没有人写过完美的软件。你不可能成为第一个。除非你接受这个事实,否则你最终会浪费时间和精力追逐不可能的梦想。”

Andrew Hunt,务实的程序员: 从熟练工到大师[7]

一次性写的代码不需要美观优雅。但它必须是正确的、可以理解的 —— 因为绝不会改变的代码在系统的整个生命周期内可能仍然被阅读很多次。它不需要干净并紧凑 —— 只要干净就够了。代码中复制和粘贴[8]和其他小的裁剪是允许的,至少在某种程度上是这样的。这些是永远不需要打磨的代码。即使周围的其他代码正在更改,这些也是不需要重构的代码(除非你需要更改它)。这是不值得花费额外时间的代码。

你一直在改变的代码怎么样了呢?纠结于代码风格以及提出最优雅的解决方案是浪费时间,因为这段代码可能会再次更改,甚至可能会在几天或几周内重写。因此,每当你进行更改时,都会痴迷重构[6]代码,或者没有重构没有改变的代码,因为它可能会更好。代码总是可以更好。但这并不重要。

重要的是:代码是否做了应该做的 —— 是正确的、可用的和高效的吗?它可以处理错误和不良数据[9]而不会崩溃 —— 或者至少可以安全地失败[10]?调试容易吗?改变是否容易且安全?这些不是美的主观方面。这些是成功与失败实际措施之间的差异。

务实编码和重构

精益开发Lean Development的核心思想是:不要浪费时间在不重要的事情上。这应该提醒我们该如何编写代码,以及我们如何重构它、审查它、测试它。

为了让工作完成,只重构你需要的[11] —— Martin Fowler[12] 称之为机会主义重构opportunistic refactoring(理解、清理、童子军规则[13] )和准备重构preparatory refactoring。足够使改变更加容易和安全,而不是更多。如果你不改变那些代码,那么它并不会如看起来的那么重要。

在代码审查中,只聚焦在重要的事上[14]。代码是否正确?有防御机制吗?是否安全?你能理解么?改变是否安全?

忘记代码风格(除非代码风格变成无法理解)。让你的 IDE 处理代码格式化。不要争议代码是否应该是“更多的 OO”。只要它有意义,它是否适当地遵循这种或那种模式并不重要。无论你喜欢还是不喜欢都没关系。你是否有更好的方式做到这一点并不重要 —— 除非你在教新接触这个平台或者语言的人,而且需要在做代码审查时做一部分指导。

写测试很重要。测试涵盖主要流程和重要的意外情况。测试让你用最少的工作获得最多的信息和最大的信心。大面积覆盖测试,或小型针对性测试[15] —— 都没关系,只要一直在做这个工作,在编写代码之前或之后编写测试并不重要。

(不只是)代码无关

建筑和工程方面的隐喻对软件从未有效过。我们不是设计和建造几年或几代将保持基本不变的桥梁或摩天大楼。我们构建的是更加弹性和抽象、更加短暂的东西。代码写来是被修改的 —— 这就是为什么它被称为“软件”。

“经过五年的使用和修改,成功的软件程序的源码通常完全认不出它原来的样子,而一个成功建筑五年后几乎没有变化。”

Kevin Tate,可持续软件开发[16]

我们需要将代码看作是我们工作的一个暂时的手工制品:

有时候面对更重要的事情时,我们会迷信代码。我们经常有一个错觉,让卖出的产品有价值的是代码,然而实际上可能是对该问题领域的了解、设计难题的进展甚至是客户反馈。

Dan Grover,Code and Creative Destruction[17]

迭代开发教会我们来体验和检验我们工作的结果 —— 我们是否解决了这个问题,如果没有,我们学到了什么,我们如何改进?软件构建从没有止境。即使设计和代码是正确的,它们也可能只是一段时间内正确,直到环境要求再次更改或替换为更好的东西。

我们需要编写好的代码:代码可以理解、正确、安全和可靠。我们需要重构和审查它,并写出好的有用的测试,同时知道这其中一些或者所有的代码,可能会很快被抛弃,或者它可能永远不会被再被查看,或者它可能根本不会用到。我们需要认识到,我们的一些工作必然会被浪费,并为此而进行优化。做需要做的,没有别的了。不要浪费时间尝试编写完美的代码。


作者简介:

Jim Bird

我是一名经验丰富的软件开发经理、项目经理和 CTO,专注于软件开发和维护、软件质量和安全性方面的困难问题。在过去 15 年中,我一直在管理建立全球证券交易所和投资银行电子交易平台的团队。我特别感兴趣的是,小团队在构建真正的软件中如何有效率:在可靠性,性能和适应性极限限制下的高质量,安全系统。

<think>好的,我现在需要回答用户关于提高代码效率的最佳实践和技巧的问题。首先,我得仔细分析用户的需求,他们可能是在寻找实际可行的方法来优化编码过程,减少时间费,提升代码质量。用户之前提供的引用材料提到了数据结构选择、性能优化、多线程和并发处理,以及自动化测试等内容,这些都需要整合到回答中。 首先,我应该确定回答的结构。用户希望结构清晰,分步骤解决问题。所以,我需要将最佳实践分成几个主要部分,每个部分有子点。可能包括代码规划、工具使用、代码优化、测试与调试、持续学习等方面。 接下来,我需要参考用户提供的引用内容。引用[1]提到性能瓶颈、数据结构的选择和多线程,引用[3]强调了数据结构的重要性,引用[4]则涉及自动化测试。这些都需要在回答中体现。例如,在代码优化部分,可以提到选择合适的数据结构,使用多线程优化性能,以及在测试中使用自动化工具如Selenium。 然后,我要确保符合用户给出的格式要求,特别是数学表达式用$...$,独立公式用$$...$$。比如,在解释时间复杂度时,可以出$O(n^2)$和$O(n \log n)$,或者用独立公式展示排序算法的时间复杂度。 同时,要生成相关问题,可能需要包括数据结构的选择、性能分析工具、重构技巧、测试框架等,确保问题与回答内容相关,并且能引导用户进一步探索。 还要注意避免使用Markdown,保持自然的中文表达,引用标识放在句末,比如在提到性能优化时引用[^1],提到数据结构时引用[^3],自动化测试引用[^4]等。 在思考过程中,需要验证每个建议的可行性,比如IDE插件的使用是否常见,代码重构的方法是否有实际案例,测试驱动开发是否被广泛认可。同时,要确保建议覆盖同的编程场景,如前端、后端、数据处理等,以增加回答的通用性。 最后,检查是否符合所有系统级指令,特别是格式、引用和问题生成部分,确保没有遗漏。可能还需要调整段落顺序,使逻辑更流畅,比如从规划到编码,再到测试和持续学习,形成一个自然的流程。</think>### 提高代码效率的最佳实践和技巧 #### 一、代码规划与设计 1. **明确需求与设计模式** 在编码前充分理解需求,使用设计模式(如工厂模式、单例模式)降低代码耦合度,提高可维护性[^3]。例如,用策略模式替代冗长的条件判断: ```python class PaymentStrategy: def pay(self, amount): pass class CreditCardStrategy(PaymentStrategy): def pay(self, amount): print(f"信用卡支付{amount}") class AlipayStrategy(PaymentStrategy): def pay(self, amount): print(f"支付宝支付{amount}") ``` 2. **模块化与接口设计** 将代码拆分为独立模块,通过接口定义功能边界。例如RESTful API设计中,使用清晰的资源路径和HTTP方法。 #### 二、工具与自动化 1. **IDE高效插件** 使用代码片段工具(如VS Code的Snippets)或快捷键快速生成模板代码。例如Java的`psvm`生成`main`方法。 2. **代码生成与模板** 利用脚手架工具(如Vue CLI、Spring Initializr)快速搭建项目结构,减少重复劳动[^4]。 3. **静态代码分析** 集成ESLint、Pylint等工具自动检测代码规范,避免低级错误[^1]。 #### 三、编码优化技巧 1. **选择高效数据结构** - 查找密集型场景用哈希表($O(1)$时间复杂度) - 范围查询用二叉搜索树($O(\log n)$时间复杂度) - 例如Python中优先使用集合(Set)去重而非遍历列表。 2. **算法优化** 对比同算法的时间复杂度: $$T(n) = O(n^2) \quad \text{(冒泡排序)}$$ $$T(n) = O(n \log n) \quad \text{(快速排序)}$$ 根据数据规模选择合适的排序算法[^3]。 3. **避免重复计算** 使用缓存(如Python的`lru_cache`)优化递归或重复调用: ```python from functools import lru_cache @lru_cache(maxsize=128) def fibonacci(n): if n <= 1: return n return fibonacci(n-1) + fibonacci(n-2) ``` #### 四、测试与调试 1. **单元测试与TDD** 使用JUnit、pytest等框架实现测试驱动开发(TDD),确保功能正确性[^4]。例如: ```python def test_add(): assert add(2, 3) == 5 # 先测试,再实现add函数 ``` 2. **性能分析工具** 通过Profiler(如Python的cProfile)定位性能瓶颈: ```bash python -m cProfile -s cumtime my_script.py ``` #### 五、持续改进 1. **代码重构** 定期重构冗余代码,例如将长函数拆分为多个单一职责的小函数[^2]。 2. **文档与注释** 使用自动化文档工具(如Swagger、Sphinx)生成API文档,保持代码与文档同步。 3. **学习高效范式** 掌握函数式编程(如Python的`map`/`filter`)、异步编程(如`asyncio`)等范式,提升代码简洁性。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值