Clean Code与代码重构

什么是 Clean Code

Clean Code 是指简洁、清晰、易读、易维护的代码。核心原则包括:

  • 可读性:代码应该像书写好的文章,易于理解。
  • 可维护性:代码应该便于修改和扩展。
  • 无重复:避免重复代码,提升复用性。
  • 高内聚、低耦合:模块之间依赖最小,每个模块职责单一。

在项目一开始就要做好Clean code,避免屎山代码越写越多

可读性

良好的命名、注释和代码结构是实现可读性的关键。

javascript 复制代码
// 不清晰的代码 神秘命名(Mysterious Name)
const d = new Date();
const n = d.getFullYear();

// 更清晰的代码
const currentYear = new Date().getFullYear();
js 复制代码
// 差的命名和结构
function calc(a, b) {
    return a + b;
}

// 良好的命名和结构
function calculateSum(number1, number2) {
    // 将两个数字相加并返回结果
    return number1 + number2;
}

无重复

重复代码(Duplicated Code)

javascript 复制代码
//问题代码:
function getUserFullName(user) {
    return user.firstName + ' ' + user.lastName;
}

function getAuthorFullName(author) {
    return author.firstName + ' ' + author.lastName;
}

//改进代码(抽取公共方法):
function getFullName(person) {
    return person.firstName + ' ' + person.lastName;
}

可维护性

代码应该便于修改和扩展。模块化设计和单一职责原则有助于提高代码的可维护性。

js 复制代码
// 不易维护的代码
function processData(data) {
    // 验证数据
    if (!data) {
        throw new Error("数据不能为空");
    }
    // 处理数据
    const result = data.map(item => item * 2);
    // 保存结果
    console.log("结果已保存");
    return result;
}

// 易维护的代码
function validateData(data) {
    if (!data) {
        throw new Error("数据不能为空");
    }
}

function transformData(data) {
    return data.map(item => item * 2);
}

function saveResult(result) {
    console.log("结果已保存");
}

function processData(data) {
    validateData(data);
    const result = transformData(data);
    saveResult(result);
    return result;
}

高内聚、低耦合

模块之间依赖最小(低耦合),每个模块的职责单一(高内聚)。

js 复制代码
// 高耦合、低内聚的例子
class UserManager {
    constructor() {
        this.users = [];
    }

    addUser(user) {
        this.users.push(user);
        // 直接操作数据库
        database.save(user);
    }

    getUser(id) {
        // 直接从数据库获取
        return database.find(id);
    }
}

// 高内聚、低耦合的例子
class UserRepository {
    constructor(database) {
        this.database = database;
    }

    save(user) {
        this.database.save(user);
    }

    find(id) {
        return this.database.find(id);
    }
}

class UserManager {
    constructor(userRepository) {
        this.userRepository = userRepository;
        this.users = [];
    }

    addUser(user) {
        this.users.push(user);
        this.userRepository.save(user);
    }

    getUser(id) {
        return this.userRepository.find(id);
    }
}

代码重构方法

重构工作是怎么执行的?

  • 局部:代码片段的重构,识别坏味道 (小步迭代,日常开发)
  • 广泛:架构级的重构 (专家投入,统一规划)

何时重构?

重构本应该是个渐进式的过程,不是只有伤筋动骨的改造才叫重构

不是所有软件开发过程都一定要重构,较能凸显重构价值的场景是:代码规模较大、生命周期还较长、承担了较多责任、有一个较大团队在其上工作的单一代码库。

识别坏味道

  • 命名混乱?➡ 重命名变量和函数
  • 代码重复?➡ 提取函数
  • 逻辑复杂?➡ 拆分成小函数
  • 过长参数列表?➡ 使用对象封装参数

(命名混乱)重命名变量和函数

javascript 复制代码
// 问题代码:
function calc(a, b) {
    let c = a * b / 100;
    return c;
}

//改进代码:
function calculateDiscount(price, discountRate) {
    let discountAmount = price * discountRate / 100;
    return discountAmount;
}

改进点

  • 使用明确的函数名 calculateDiscount 代替 calc
  • 使用 pricediscountRate 代替 ab
  • 让代码可读性更高,减少理解成本

(代码重复)提取方法

javascript 复制代码
// 重复代码
function calculateTotal(items) {
    let total = 0;
    for (let i = 0; i < items.length; i++) {
        total += items[i].price * items[i].quantity;
    }
    return total;
}

// 改进代码
function calculateItemTotal(item) {
    return item.price * item.quantity;
}

function calculateTotal(items) {
    return items.reduce((sum, item) => sum + calculateItemTotal(item), 0);
}

改进点

  • 提取 calculateItemTotal 函数,使 calculateTotal 逻辑更清晰
  • 避免重复代码,提高可读性和复用性

(逻辑复杂)拆分成小函数

将复杂的逻辑拆分成多个小函数,每个函数负责单一任务。

js 复制代码
// 逻辑复杂的代码
function processOrder(order) {
    if (order.status === "pending") {
        if (inventory.checkStock(order.items)) {
            const total = order.items.reduce((sum, item) => sum + item.price, 0);
            if (order.discountCode) {
                total *= 0.9; // 10% 折扣
            }
            order.status = "processed";
            database.save(order);
        } else {
            order.status = "out_of_stock";
        }
    }
}

// 拆分成小函数后的代码
function checkStock(items) {
    return inventory.checkStock(items);
}

function calculateTotal(items, discountCode) {
    let total = items.reduce((sum, item) => sum + item.price, 0);
    if (discountCode) {
        total *= 0.9; // 10% 折扣
    }
    return total;
}

function updateOrderStatus(order, status) {
    order.status = status;
}

function saveOrder(order) {
    database.save(order);
}

function processOrder(order) {
    if (order.status === "pending") {
        if (checkStock(order.items)) {
            const total = calculateTotal(order.items, order.discountCode);
            updateOrderStatus(order, "processed");
            saveOrder(order);
        } else {
            updateOrderStatus(order, "out_of_stock");
        }
    }
}
  • 原函数包含库存检查、总价计算、状态更新和订单保存等复杂逻辑。
  • 重构后,每个任务被拆分到独立的小函数(如 checkStock、calculateTotal 等),使 processOrder 更简洁,逻辑更清晰。

(过长参数列表)对象封装参数

javascript 复制代码
//问题代码:
function createUser(name, age, email, address, phone, gender) {
    return { name, age, email, address, phone, gender };
}

// 改进代码(引入参数对象):
function createUser(userInfo) {
    return { ...userInfo };
}

const user = createUser({
    name: 'Alice',
    age: 25,
    email: '[email protected]',
    address: '123 Street',
    phone: '123456789',
    gender: 'Female'
});

改进点

  • 使用对象作为参数,避免参数过多
  • 提高函数的可扩展性和可维护性

重构工具

检测工具

  • sonar 生成质量报告

IDE

vscode

实测vscode 只支持简单的 Rename symbol重命名

refactor 也只有简单的剪切方法

使用vscode重构代码不太理想

webstorm

实测非常强大,跟另外一个IDEA一样强大, 支持各个重命名,方法提取,类提取

单元与集成测试

结语

Clean Code 和代码重构是提升代码质量的重要手段。实践过程中,可以遵循以下原则:

  • 保持代码清晰易懂
  • 减少重复代码,提取可复用逻辑
  • 合理设计参数,避免过长参数列表
  • 持续优化代码,提高可维护性

推荐书籍:

  • 《重构:改善既有代码的设计》
  • 《代码整洁之道》
相关推荐
小杨40427 分钟前
springboot框架项目实践应用八(validation自定义校验)
spring boot·后端·架构
GISer_Jing29 分钟前
设计模式分类解析与JavaScript实现
开发语言·javascript·设计模式
一块plus2 小时前
弹性扩展何以助力 Polkadot 2.0 触达无缝互操作的理想愿景?
设计模式·架构·github
全栈若城3 小时前
84.HarmonyOS NEXT 路由导航与页面管理:构建清晰的应用架构
华为·架构·harmonyos·harmonyos next
小小工匠3 小时前
架构思维:软件建模与架构设计的关键要点
架构·架构设计·软件建模
trsoliu4 小时前
关于产品研发测试运维对软件项目版本号规范
代码规范
小天努力学java4 小时前
【软考-架构】11.3、设计模式-新
设计模式·架构
皇家小黄5 小时前
设计模式,持续更新
java·设计模式
JustHappy6 小时前
「工具链🛠️」package-lock.json? yarn.lock? pnpm-lock.yaml?这些文件存在的意义是什么?
前端·javascript·代码规范