《软件设计的哲学》——16. 修改现有的代码

🎯 开篇故事:房子的改造之路

想象一下,你买了一套老房子。刚开始的时候,你可能会想:"这房子还不错,只要稍微修修补补就能住了。"于是你在这里贴个墙纸,那里换个灯泡,阳台上搭个小棚子...

几年过去了,你突然发现这房子变得越来越奇怪:墙纸层层叠叠,电线拉得到处都是,小棚子挡住了窗户,整个房子像个大杂烩。每次想要做点改动,都得小心翼翼,因为不知道动了哪里会影响到别的地方。

这就是软件开发的真实写照! 🏠

正如第1章所介绍的,软件开发是一个迭代和增量的过程。一个大型软件系统就像这座房子一样,会经历一系列的演化阶段。每个阶段都会添加新功能,修改现有模块。这意味着系统的设计在不断发展变化。

重要认知:你不可能在一开始就为系统构想出完美的设计。一个成熟系统的设计,更多地取决于它在演化过程中的各种改动,而不是最初的设计蓝图。

前面的章节告诉你如何在初始设计时降低复杂性,而本章要讨论的是:如何在系统演化过程中防止复杂性悄悄爬进来


16.1 保持战略性思维 🎯

Stay strategic

还记得第3章中战术编程和战略编程的区别吗?让我们用一个生活例子来回顾一下:

🛠️ 两种修理方式的对比

战术编程(应急修理) 战略编程(用心改造)
水管漏水?用胶带缠一圈! 找出漏水原因,换掉老化的管道
目标:快速解决问题 目标:从根本上解决问题
结果:问题会再次出现 结果:一劳永逸
时间:立即见效 时间:需要投入更多时间

在修改现有代码时,大多数开发者的心态是:"我能做出的最小改动是什么?"

这种想法看起来很合理,特别是当你对要修改的代码不太熟悉时。你可能会想:"改动越小,引入新bug的风险就越小。"

⚠️ 最小改动的陷阱

但是,这种思维方式会导致战术编程!每一个"最小改动"都会引入:

  • 一些特殊情况的处理
  • 新的依赖关系
  • 其他形式的复杂性

结果就是:系统设计会一点点变糟,问题会随着每次修改而累积

🎯 战略性修改的原则

如果你想保持系统的简洁设计,在修改现有代码时必须采取战略性方法

目标:每次修改完成后,系统都应该拥有"如果从一开始就考虑这个改动"而应该有的结构。

具体怎么做呢?

  1. 抵制快速修复的诱惑:先暂停,不要急着动手
  2. 重新审视设计:考虑当前的系统设计是否仍然是最佳的
  3. 必要时重构:如果不是最佳设计,就重构系统
  4. 追求完美结构:让每次修改都改善系统设计
python 复制代码
# 战术编程的做法:
if special_case:
    # 为这个特殊情况添加一个hack
    return handle_special_case()
else:
    return normal_flow()

# 战略编程的做法:
# 重新设计,让新需求自然融入现有架构
strategy = self.get_strategy(context)
return strategy.execute()

💰 投资心态的回报

这也是第15页提到的投资心态的体现:

  • 投入:花费额外时间重构和改进系统设计
  • 收获:获得更干净的系统,加快未来的开发速度
  • 回报:你投入的重构努力会得到回报

黄金法则:每当你修改任何代码时,都要尝试至少让系统设计稍微好一点。如果你没有让设计变得更好,那很可能正在让它变得更糟。

🏢 现实约束的平衡

当然,理想很丰满,现实很骨感。正如第3章讨论的,投资心态有时会与商业软件开发的现实冲突:

  • 时间压力:正确的重构需要3个月,但快速修复只需要2小时
  • 团队影响:重构可能会影响其他团队的工作
  • 截止日期:紧急的发布时间线

🎭 现实中的妥协策略

即使面临这些约束,你也应该尽可能抵制妥协:

  1. 自我审视:问问自己"在当前约束下,这是我能做的最好的设计吗?"
  2. 寻找替代方案:是否有既相对干净又能快速完成的方案?
  3. 争取未来机会:如果现在不能大规模重构,争取老板分配时间让你稍后回来处理
  4. 组织层面规划:每个开发团队都应该计划将一小部分时间用于清理和重构

长期视角:这种清理和重构的投入,从长远来看会为自己带来回报。


16.2 维护注释:让注释贴近代码 💬

Maintaining comments: keep the comments near the code

📖 注释更新的痛点

你有没有遇到过这样的情况:修改了代码,但忘记更新注释,结果注释和代码说的完全不是一回事?

这种不准确的注释 会让读者感到沮丧。如果这样的注释很多,读者就会开始不信任所有注释

🎯 注释更新的黄金法则

好消息是,只要遵循一些简单的原则,就能轻松保持注释的更新:

核心原则:让注释尽可能贴近它们描述的代码,这样开发者修改代码时就能看到注释。

📍 距离决定更新概率

注释离代码越远,被正确更新的可能性越小

让我们看看不同位置的注释更新难度:

注释位置 更新难度 原因
方法体内部 ⭐ 简单 修改代码时一定会看到
方法声明上方 ⭐⭐ 容易 修改方法时很可能看到
头文件中 ⭐⭐⭐ 中等 需要打开另一个文件
设计文档中 ⭐⭐⭐⭐ 困难 很容易被遗忘

🔍 最佳实践:方法注释的位置

最佳选择:将方法的接口注释放在代码文件中,紧挨着方法体:

java 复制代码
/**
 * 计算用户的信用评分
 * @param userId 用户ID
 * @return 信用评分(0-1000)
 */
public int calculateCreditScore(String userId) {
    // 任何对方法的修改都会经过这里
    // 开发者很容易看到并更新注释
    return scoreCalculator.compute(userId);
}

📂 头文件注释的问题

对于C/C++这样有独立头文件的语言,有些人喜欢把接口注释放在.h文件中:

cpp 复制代码
// 在 user.h 中
/**
 * 计算用户的信用评分
 */
int calculateCreditScore(const std::string& userId);

// 在 user.cpp 中
int calculateCreditScore(const std::string& userId) {
    // 开发者修改这里的代码时,看不到头文件中的注释
    // 很容易忘记更新注释
    return scoreCalculator.compute(userId);
}

问题

  • 距离代码实现太远
  • 开发者修改方法体时看不到注释
  • 需要额外打开另一个文件才能更新注释

🛠️ 现代工具的支持

有人可能会说:"接口注释应该放在头文件中,这样用户学习接口时不用看代码实现。"

但是现代开发工具已经解决了这个问题:

  • 文档生成工具:Doxygen、Javadoc等会自动生成文档
  • IDE集成:现代IDE会自动提取并显示文档
  • 智能提示:输入方法名时自动显示方法文档

结论 :文档应该放在对编写代码的开发者最方便的位置。

📝 实现注释的分布原则

写实现注释时,不要把所有注释都堆在方法顶部。应该分散分布,让每个注释都尽可能靠近它描述的代码:

python 复制代码
def process_user_data(user_id):
    """
    处理用户数据的总体策略:
    阶段1:查找可行的候选项
    阶段2:为每个候选项分配得分  
    阶段3:选择最佳候选项并处理
    """
    
    # 阶段1:查找可行的候选项
    # 这里需要检查用户的基本信息和权限
    candidates = find_feasible_candidates(user_id)
    
    # 阶段2:为每个候选项分配得分
    # 使用机器学习模型进行评分
    for candidate in candidates:
        candidate.score = score_candidate(candidate)
    
    # 阶段3:选择最佳候选项并处理
    # 移除得分最高的候选项,避免重复处理
    best_candidate = max(candidates, key=lambda c: c.score)
    return process_candidate(best_candidate)

🎯 抽象程度的平衡

重要原则:注释离代码越远,应该越抽象。

这样可以减少注释因代码变化而失效的可能性:

  • 方法级注释:描述整体策略和目标
  • 代码块注释:解释具体的实现步骤
  • 行内注释:说明特定的技术细节

16.3 注释属于代码,而不是提交日志 📝

Comments belong in the code, not the commit log

🤔 常见的错误习惯

你是否有过这样的经历:

  • 修复了一个微妙的bug,在Git提交信息中写了长长的解释
  • 实现了一个复杂的功能,详细描述都放在了commit message里
  • 但是代码本身却缺少相应的注释

📚 一个真实的例子

bash 复制代码
# Git提交信息
git commit -m "修复用户登录问题

这个问题是由于在并发情况下,session清理和用户验证之间
存在竞态条件导致的。当用户快速连续点击登录按钮时,
第二次点击可能会在第一次session还未完全建立时就开始
验证,导致验证失败。

解决方案是在session创建时增加一个原子性的锁机制,
确保每次只有一个登录请求被处理。"
java 复制代码
// 但代码中只有这样的注释
public void login(String username, String password) {
    // 处理登录逻辑
    validateUser(username, password);
    createSession(username);
}

⚠️ 为什么这样不好?

  1. 开发者不会想到查看提交日志:当他们遇到问题时,第一反应是看代码和注释
  2. 查找特定信息很困难:即使想到查看日志,也很难找到相关的提交记录
  3. 信息容易丢失:提交日志不是代码的一部分,容易被忽略

🎯 正确的做法

自问:开发者将来是否需要使用提交信息中的这些信息?

如果答案是 ,那么这些信息应该放在代码中

java 复制代码
public void login(String username, String password) {
    // 重要:使用原子性锁防止并发登录的竞态条件
    // 如果用户快速连续点击登录,可能导致session验证失败
    // 参考:GitHub issue #1234
    synchronized (this) {
        validateUser(username, password);
        createSession(username);
    }
}

🔄 防止问题重现

考虑这样一个场景:

  1. 你修复了一个微妙的bug
  2. 几个月后,另一个开发者重构代码时不小心又引入了同样的bug
  3. 如果原因只记录在提交日志中,他们很可能不会发现

解决方案

java 复制代码
public void processData(List<Data> data) {
    // 注意:这里必须先排序再处理,否则会导致数据不一致
    // 曾经因为跳过排序导致严重的数据损坏问题(详见bug报告#5678)
    data.sort(Data::compareTo);
    
    for (Data item : data) {
        process(item);
    }
}

📍 文档放置的黄金原则

核心原则:将文档放在开发者最有可能看到的地方。

提交日志很少是这样的地方,代码才是!

✅ 最佳实践总结

  1. 重要信息放代码中:任何对理解代码至关重要的信息
  2. 提交信息可以重复:在代码中记录了,提交信息里也可以写一份
  3. 但代码是主要的:最重要的是确保信息在代码中
  4. 添加上下文链接:在代码注释中引用相关的issue或文档

16.4 维护注释:避免重复 🔄

Maintaining comments: avoid duplication

📚 重复文档的麻烦

想象一下,你有一个重要的设计决策,需要在5个不同的地方都有相关的说明。如果你在每个地方都写一遍完整的解释,会发生什么?

当这个设计决策发生变化时,你需要:

  1. 记住所有5个地方
  2. 逐一找到这些地方
  3. 确保每个地方都更新正确
  4. 希望不会遗漏任何一处

结果:很可能有些地方会被遗忘,导致文档不一致。

🎯 "一次记录"原则

核心策略:尽量让每个设计决策只记录一次。

🔍 寻找最佳记录位置

当一个设计决策影响多个地方时,你需要找到最明显的单一位置来记录它:

java 复制代码
public class UserAccount {
    // 重要:这个状态值的变化会影响整个系统的行为
    // 状态转换规则:
    // PENDING -> ACTIVE: 用户完成邮箱验证
    // ACTIVE -> SUSPENDED: 检测到可疑活动
    // SUSPENDED -> ACTIVE: 管理员手动恢复
    // ACTIVE -> INACTIVE: 用户主动停用账户
    private AccountStatus status;
    
    // ... 其他代码
}

在其他使用这个状态的地方,只需要简单引用

java 复制代码
public void processLogin(String userId) {
    UserAccount account = getAccount(userId);
    
    // 账户状态检查逻辑参见 UserAccount.status 字段的注释
    if (account.getStatus() == AccountStatus.SUSPENDED) {
        throw new AccountSuspendedException();
    }
    
    // ... 登录逻辑
}

📂 创建设计文档文件

如果找不到"明显的"位置来放置某个文档,你可以:

  1. 创建designNotes文件(如第13.7节所述)
  2. 选择最佳可用位置,并在其他地方添加引用
java 复制代码
// 在 designNotes.md 中
## 用户权限系统设计

### 权限继承规则
- 子角色自动继承父角色的所有权限
- 权限撤销会级联影响所有子角色
- 权限检查采用深度优先搜索算法

// 在代码中
public boolean hasPermission(String userId, String permission) {
    // 权限检查逻辑的详细说明参见 designNotes.md 中的"用户权限系统设计"
    return permissionChecker.checkWithInheritance(userId, permission);
}

🔗 引用的自我验证特性

使用引用的好处是自我验证

java 复制代码
// 错误的引用会暴露问题
// 参见 UserService.calculateScore 方法中的注释
public void updateUserScore(String userId) {
    // 如果 UserService.calculateScore 方法被删除或移动了,
    // 开发者在查找时会发现找不到,从而知道引用过时了
}

相比之下,如果是重复的文档,当部分副本没有更新时,开发者不会意识到他们使用的是过时信息。

📄 外部文档的引用

如果信息已经在程序外部有文档记录,不要在程序内部重复:

java 复制代码
/**
 * 实现HTTP/1.1协议的客户端
 * 
 * 协议详细说明参见:https://tools.ietf.org/html/rfc7230
 * 
 * 注意:本实现不支持HTTP/2,如需HTTP/2支持请使用HttpClient2
 */
public class HttpClient {
    // ... 实现代码
}

🎮 用户手册的引用

如果你的程序实现了用户手册中描述的命令,不需要重复这些信息:

java 复制代码
/**
 * 实现用户手册中的 "export" 命令
 * 详细参数说明参见用户手册第4.2节
 */
public void exportCommand(String[] args) {
    // 实现逻辑
}

⚡ 避免不必要的重复

不要做的事情

java 复制代码
// 错误:重复解释被调用方法的功能
public void processOrder(Order order) {
    // validateOrder方法会检查订单的有效性,包括价格、数量等
    // 如果验证失败,会抛出ValidationException
    validateOrder(order);
    
    // saveOrder方法会将订单保存到数据库中
    // 使用事务确保数据一致性
    saveOrder(order);
}

正确的做法

java 复制代码
public void processOrder(Order order) {
    // 让方法的接口注释自己说话
    validateOrder(order);
    saveOrder(order);
}

🛠️ 工具的自动支持

现代开发工具会自动显示方法的文档:

  • IDE提示:鼠标悬停在方法名上会显示其文档
  • 代码导航:可以快速跳转到方法定义查看详细注释
  • 自动完成:输入时显示方法的签名和说明

📋 最佳实践总结

  1. 一次记录原则:每个设计决策只在一个地方详细记录
  2. 选择最佳位置:放在开发者最容易找到的地方
  3. 使用引用:其他地方通过引用指向主要文档
  4. 避免重复:不要重复已有的外部文档
  5. 依赖工具:让开发工具帮助展示文档信息

16.5 维护注释:检查差异 🔍

Maintaining comments: check the diffs

🚀 提交前的5分钟检查

你有没有这样的经历:

  • 修改了代码,兴奋地提交了
  • 几天后发现注释和代码说的不是一回事
  • 或者不小心留下了调试代码
  • 甚至忘记处理TODO标记

💡 简单而有效的习惯

在提交代码到版本控制系统之前,花几分钟扫描一遍所有的更改

这个简单的习惯可以帮你:

  1. ✅ 确保每个代码变更都在文档中得到正确反映
  2. ✅ 发现意外留下的调试代码
  3. ✅ 检查是否有未处理的TODO项
  4. ✅ 确认所有变更都是有意的

🔍 提交前检查清单

让我们看看一个典型的检查过程:

bash 复制代码
# 查看即将提交的所有更改
git diff --staged

# 或者使用图形化工具
git difftool --staged

检查要点

检查项目 查找内容 常见问题
🔄 注释更新 注释是否匹配代码变更 修改了方法但没更新注释
🐛 调试代码 console.log, print, 临时变量 忘记删除调试输出
📝 TODO项 新增或修改的TODO 承诺修复但没完成
🔒 敏感信息 密码、密钥、内部URL 意外提交了敏感数据
🧹 代码清理 无用的导入、空行、格式 代码格式不一致

📝 实际检查示例

diff 复制代码
public class UserService {
-    // 获取用户信息
+    // 获取用户信息并验证权限
    public User getUserInfo(String userId) {
-        return userRepository.findById(userId);
+        User user = userRepository.findById(userId);
+        if (!permissionChecker.canRead(user)) {
+            throw new PermissionDeniedException();
+        }
+        return user;
    }
}

检查思路

  • ✅ 注释已更新,反映了新增的权限验证
  • ✅ 代码逻辑清晰,没有调试代码
  • ✅ 没有TODO项需要处理

🛠️ 工具辅助检查

Git工具

bash 复制代码
# 查看详细的变更统计
git diff --stat

# 只查看文件名
git diff --name-only

# 查看特定文件的变更
git diff path/to/file.java

IDE集成

  • Visual Studio Code:源代码控制面板
  • IntelliJ IDEA:VCS -> Local Changes
  • Eclipse:Team -> Synchronize Workspace

🔍 常见问题和解决方案

问题1:调试代码遗留

java 复制代码
// 发现这样的代码
public void processData(List<Data> data) {
    System.out.println("Processing " + data.size() + " items"); // 调试代码!
    
    for (Data item : data) {
        process(item);
    }
}

解决方案:使用合适的日志级别

java 复制代码
public void processData(List<Data> data) {
    logger.debug("Processing {} items", data.size());
    
    for (Data item : data) {
        process(item);
    }
}

问题2:TODO项未处理

java 复制代码
// 发现这样的TODO
public void calculateScore(User user) {
    // TODO: 需要考虑用户的历史记录
    return user.getBaseScore();
}

解决方案:要么完成,要么创建issue跟踪

java 复制代码
public void calculateScore(User user) {
    // 当前只使用基础分数,历史记录集成见 issue #1234
    return user.getBaseScore();
}

📊 检查效果的数据

根据经验,这个5分钟的检查可以:

  • 减少90%的注释不一致问题
  • 避免100%的调试代码泄露
  • 发现80%的TODO遗漏
  • 提高代码质量和团队效率

🎯 养成习惯的建议

  1. 设置Git hooks:在提交时自动运行检查
  2. 使用IDE插件:提交前自动显示差异
  3. 团队规范:将此作为代码审查的标准流程
  4. 定期提醒:在团队会议中强调这个习惯
bash 复制代码
# 设置Git提交前钩子
#!/bin/sh
echo "正在检查即将提交的更改..."
git diff --cached --name-only | while read file; do
    if [[ $file =~ \.(java|js|py)$ ]]; then
        echo "检查文件: $file"
        # 检查是否有调试代码
        if git diff --cached "$file" | grep -q "console.log\|print\|TODO"; then
            echo "⚠️  发现调试代码或TODO项,请检查: $file"
        fi
    fi
done

📋 检查清单模板

你可以创建一个个人检查清单:

复制代码
□ 注释是否与代码变更匹配?
□ 是否有遗留的调试代码?
□ TODO项是否已处理或记录?
□ 是否有敏感信息泄露?
□ 代码格式是否一致?
□ 是否有不必要的文件被包含?
□ 提交信息是否清晰描述了变更?

16.6 高级注释更易维护 🏔️

Higher-level comments are easier to maintain

🎯 最后的智慧:抽象的力量

在讨论维护文档的最后,我想分享一个重要的观点:越高级、越抽象的注释,越容易维护

🔍 注释的抽象层次

让我们通过一个例子来理解这个概念:

java 复制代码
// 低级注释(容易过时)
public void processUser(String userId) {
    // 从数据库查询用户表的id字段
    // 使用SELECT语句,连接users表
    // 检查返回的ResultSet是否为空
    User user = userRepository.findById(userId);
    
    // 调用validate方法传入user对象
    // 该方法会检查user.email是否为null
    // 如果为null则抛出IllegalArgumentException
    validateUser(user);
    
    // 将user对象传递给processUserData方法
    // 该方法会更新user的lastProcessed字段
    processUserData(user);
}
java 复制代码
// 高级注释(稳定持久)
public void processUser(String userId) {
    // 用户处理的标准流程:获取、验证、处理
    // 任何验证失败都会终止处理并抛出异常
    
    User user = userRepository.findById(userId);
    validateUser(user);
    processUserData(user);
}

📊 不同层次注释的维护成本

注释类型 维护频率 原因 示例
实现细节 🔴 经常变化 代码重构时需要更新 "使用HashMap存储"
算法步骤 🟡 偶尔变化 算法优化时需要修改 "首先排序,然后二分查找"
业务逻辑 🟢 很少变化 业务需求稳定 "验证用户权限"
设计意图 🟢 极少变化 核心设计理念稳定 "确保数据一致性"

🎨 编写高级注释的技巧

1. 描述"为什么"而不是"怎么做"

java 复制代码
// 低级:描述具体实现
// 遍历数组,比较每个元素,找到最大值
int max = findMaxValue(numbers);

// 高级:描述目的
// 需要找到最大值来确定缓存容量的上限
int max = findMaxValue(numbers);

2. 关注业务意图而不是技术细节

java 复制代码
// 低级:技术实现细节
// 使用Redis缓存,TTL设置为3600秒
// 如果缓存未命中,从MySQL数据库查询
String userData = cacheManager.get(userId);

// 高级:业务目的
// 优化频繁访问的用户数据读取性能
String userData = cacheManager.get(userId);

3. 解释设计决策而不是代码行为

java 复制代码
// 低级:代码行为描述
// 检查status字段是否等于"ACTIVE"
if (user.getStatus() == UserStatus.ACTIVE) {

// 高级:设计决策说明
// 只有激活用户才能执行敏感操作
if (user.getStatus() == UserStatus.ACTIVE) {

🔄 抽象注释的变化阻力

为什么高级注释更稳定?

  1. 实现可以变化,意图不变

    java 复制代码
    // 这个注释不会因为存储方式改变而失效
    // 持久化用户偏好设置
    saveUserPreferences(user, preferences);
  2. 算法可以优化,目标不变

    java 复制代码
    // 这个注释不会因为算法改进而过时
    // 确保响应时间在可接受范围内
    optimizeQuery(query);
  3. 技术可以升级,需求不变

    java 复制代码
    // 这个注释不会因为技术栈变化而失效
    // 防止用户数据泄露
    encryptSensitiveData(userData);

🎯 实践建议

在不同层次使用不同抽象级别的注释

java 复制代码
/**
 * 用户服务核心类
 * 
 * 设计理念:确保所有用户操作都经过适当的权限验证和审计
 * 这是整个系统安全策略的基础
 */
public class UserService {
    
    /**
     * 更新用户资料
     * 
     * 业务规则:只有用户本人或管理员可以修改用户信息
     * 所有修改都会记录审计日志
     */
    public void updateUserProfile(String userId, UserProfile profile) {
        // 权限验证:确保当前用户有修改此资料的权限
        validateUpdatePermission(userId);
        
        // 数据验证:确保新资料符合业务规则
        validateProfileData(profile);
        
        // 执行更新:使用事务确保数据一致性
        userRepository.updateProfile(userId, profile);
        
        // 记录审计:用于安全追踪和合规要求
        auditLogger.logProfileUpdate(userId, profile);
    }
}

📈 维护成本的投资回报

投资高级注释的收益

  1. 减少维护工作量:注释更新频率降低80%
  2. 提高代码理解速度:新人理解代码时间减少50%
  3. 降低bug引入风险:设计意图清晰,修改更谨慎
  4. 改善团队协作:共同理解业务目标和设计理念

🎪 平衡详细性和抽象性

当然,正如第13章讨论的,某些注释确实需要详细和精确。关键是要找到平衡:

  • 接口注释:侧重于抽象的契约和意图
  • 实现注释:在需要时提供具体细节
  • 设计注释:专注于高级的架构决策

📋 最佳实践总结

  1. 优先写高级注释:描述意图和目标,而不是实现细节
  2. 分层次注释:不同抽象级别的注释服务不同目的
  3. 关注稳定性:越抽象的注释越不容易过时
  4. 投资回报思维:高级注释的维护成本更低,价值更高

🎯 本章核心要点总结

通过这一章的学习,你应该掌握了在代码演化过程中保持简洁设计的核心技能:

🧠 战略思维

  • 投资心态:每次修改都要改善系统设计
  • 抵制快速修复:寻找既优雅又实用的解决方案
  • 长期视角:清理和重构的投入会带来长期回报

📝 注释维护

  • 贴近原则:注释越靠近代码,越容易保持同步
  • 避免重复:每个设计决策只记录一次
  • 提交检查:养成提交前检查的习惯
  • 抽象优先:高级注释比低级注释更容易维护

🎨 实践技巧

  • 差异审查:每次提交前扫描所有变更
  • 引用而非重复:用引用连接相关文档
  • 工具辅助:利用现代IDE的文档展示能力

记住:如果你没有让设计变得更好,那很可能正在让它变得更糟。每一次代码修改都是一次改善系统的机会!


"优秀的软件设计不是一蹴而就的,而是在无数次精心的修改中逐步完善的。" 🌟

相关推荐
徐小夕4 小时前
失业半年,写了一款多维表格编辑器pxcharts
前端·react.js·架构
绝无仅有4 小时前
OSS文件上传解析失败,错误:文件下载失败的排查与解决
后端·面试·架构
brzhang6 小时前
OpenAI 7周发布Codex,我们的数据库迁移为何要花一年?
前端·后端·架构
boyedu7 小时前
Hyperledger Fabric深入解读:企业级区块链的架构、应用与未来
架构·区块链·fabric·企业级区块链
泉城老铁8 小时前
Gitee上开源主流的springboot框架一探究竟
spring boot·后端·架构
枯萎穿心攻击9 小时前
响应式编程入门教程第三节:ReactiveCommand 与 UI 交互
开发语言·ui·unity·架构·c#·游戏引擎·交互
一切顺势而行11 小时前
flink 和 spark 架构的对比
架构·flink·spark
Codebee11 小时前
OneCode AI体系设计深度剖析:从架构哲学到技术实现
人工智能·低代码·架构
前端付豪11 小时前
21、前端权限体系设计:动态路由、按钮级权限与灰度控制
前端·javascript·架构