编程中的重复:何时允许 | AI生成和翻译
问题:在编程中是否不可能完全避免重复?我们应该在什么时候有意允许重复,又在什么时候应该消除它们?例如,在像“abc”这样的字符串中,移除像“a”这样的重复字母会使其更难阅读或构造某些单词。
答案:
在编程中,实际上不可能完全避免所有形式的重复,而且这也不总是可取的。重复是代码和数据的自然且通常必要的组成部分。关键在于区分有益的重复(它提高了清晰度、性能或表达性)和有害的重复(它导致维护问题、错误或效率低下)。
我们应该有意允许或引入重复的情况:
- 为了可读性和表达性
重复值或模式使意图更清晰。- 示例:字符串
"Mississippi"自然包含重复字母(’s’、’i’、’p’)。将重复项删除得到"Misp"会破坏其含义和可读性。 - 在代码中:在数组初始化
[0, 0, 0, 0]中重复常量0多次比不必要地进行抽象更清晰。
- 示例:字符串
-
数据本身包含重复
真实世界的数据通常有重复:日志、用户输入、测量、文本等。过早地删除它们可能会丢失重要信息(例如,文本分析中的词频)。 -
出于性能原因
数据库中的非规范化有意引入重复,以避免昂贵的连接并提高查询速度。 -
简单的算法或早期原型
当逻辑不稳定或重复程度极小时,少量复制的代码是可以接受的。过早的抽象可能会使代码更难理解。 - 当抽象增加复杂性时
试图消除每个重复的字符或值可能会导致代码过于复杂。例如,在英语中,在不重复任何字母的情况下生成"hello"是不可能且无意义的。
我们应该消除重复的情况:
-
配置和魔术值
重复的硬编码值(例如,散布在代码中的42)应该被提取到命名常量中。 - 重复逻辑(DRY原则)
最常见的有害重复:多个地方存在相同或相似的代码块。修改其中一个需要修改所有→导致错误。- 重构为函数、类、模块或模板。
- 唯一性很重要的数据处理
- 当顺序无关紧要且需要唯一性时(例如,唯一的用户名ID),将列表转换为集合以删除重复项。
- 数据库或数据集中记录的去重。
-
大规模维护
当相同的模式出现在许多地方且很可能发生变化时,抽象(函数、循环、高阶函数、宏)可以减少未来的工作量。 - 内存或存储效率
在资源受限的环境中,删除不必要的重复可以节省空间(例如,字符串驻留、享元模式)。
总结指南:
- 允许重复当它们具有意义、提高清晰度或删除它们会增加不必要的复杂性时。
- 消除重复当它们是偶然的、在多个地方代表相同的概念或导致维护/可伸缩性问题时。
你的"abc"示例很完美:如果字符串代表一个单词或消息,重复的字母不仅被允许,而且是正确含义所必需的。只有当问题明确要求唯一性时(例如,“查找不同的字符”或“唯一用户名检查”),才删除重复项。
简而言之:重复本身不是坏事。深思熟虑的重复通常会使代码和数据更人性化。盲目地应用“绝不重复”会导致复杂、难以阅读的解决方案。应审慎而非教条式地应用DRY原则。