掌握干净代码:开发人员的基本实践

2025-06-07

掌握干净代码:开发人员的基本实践

简洁的代码是每个成功软件项目的基石。作为一名开发者,编写简洁、可维护的代码的能力对于应用程序的效率和寿命至关重要。在本文中,我们将深入探讨 JavaScript 中十个良好和不良编码实践的示例,强调编写简洁代码的重要性,并提供切实可行的建议,帮助您提升开发技能。

示例

  • 描述性变量名称:
// Good:

const totalPrice = calculateTotalPrice(quantity, unitPrice);
Enter fullscreen mode Exit fullscreen mode
// Bad:

const t = calcPrice(q, uP);
Enter fullscreen mode Exit fullscreen mode

好的例子中,变量名具有描述性,能够清晰地表达其用途,从而增强代码的可读性。相反,坏的例子则使用了晦涩难懂的缩写,使其他人难以理解代码的意图。

  • 一致的格式:
// Good:

function greet(name) {
    return `Hello, ${name}!`;
}
Enter fullscreen mode Exit fullscreen mode
// Bad:

function greet(name){
return `Hello, ${name}!`
}
Enter fullscreen mode Exit fullscreen mode

一致的格式可以提高代码的可读性和可维护性。好的例子中,使用了适当的缩进和间距,增强了代码结构。相反,坏的例子缺乏一致性,使代码更难理解。

  • 避免使用神奇数字:
// Good:

const TAX_RATE = 0.1;
const totalPrice = subtotal + (subtotal * TAX_RATE);
Enter fullscreen mode Exit fullscreen mode
// Bad:

const totalPrice = subtotal + (subtotal * 0.1);

Enter fullscreen mode Exit fullscreen mode

魔法数字会掩盖值的含义,使代码更难维护。在一个好的例子中,我们用常量来表示魔法数字,从而提高了代码的清晰度和可维护性。

  • 单一职责原则:
// Good:

function calculateTotalPrice(quantity, unitPrice) {
    return quantity * unitPrice;
}

function formatPrice(price) {
    return `$${price.toFixed(2)}`;
}

Enter fullscreen mode Exit fullscreen mode
// Bad:

function calculateAndFormatTotalPrice(quantity, unitPrice) {
    const totalPrice = quantity * unitPrice;
    return `$${totalPrice.toFixed(2)}`;
}
Enter fullscreen mode Exit fullscreen mode

函数应该具有单一职责,以提升代码的可重用性和可维护性。好的例子中,每个函数执行一项特定的任务,遵循单一职责原则。相反,坏的例子则违反了这一原则,将多个职责合并到一个函数中。

  • 错误处理:
// Good:

function fetchData(url) {
    return fetch(url)
        .then(response => {
            if (!response.ok) {
                throw new Error('Network response was not ok');
            }
            return response.json();
        })
        .catch(error => {
            console.error('Error fetching data:', error);
            throw error;
        });
}
Enter fullscreen mode Exit fullscreen mode
// Bad:

function fetchData(url) {
    return fetch(url)
        .then(response => response.json())
        .catch(error => console.error(error));
}
Enter fullscreen mode Exit fullscreen mode

适当的错误处理可以提高代码的稳健性,并有助于更有效地识别和解决问题。在好的例子中,错误得到了妥善的处理,为开发人员提供了有意义的反馈。相反,糟糕的例子缺乏全面的错误处理,可能会导致静默故障。

  • 评论和文档:
// Good:

// Calculate the total price based on quantity and unit price
function calculateTotalPrice(quantity, unitPrice) {
    return quantity * unitPrice;
}
Enter fullscreen mode Exit fullscreen mode
// Bad:

function calculateTotalPrice(quantity, unitPrice) {
    // calculate total price
    return quantity * unitPrice;
}
Enter fullscreen mode Exit fullscreen mode

注释和文档能够增强代码的可理解性,并促进开发人员之间的协作。好的例子中,清晰的注释能够描述函数的用途,有助于理解代码。相反,坏的例子则提供了含糊不清、毫无价值的注释。

  • 适当的模块化:
// Good:

export function add(a, b) {
    return a + b;
}

export function subtract(a, b) {
    return a - b;
}
Enter fullscreen mode Exit fullscreen mode
// Bad:

function add(a, b) {
    return a + b;
}

function subtract(a, b) {
    return a - b;
}
Enter fullscreen mode Exit fullscreen mode

模块化代码通过将功能组织成内聚单元来提升可重用性和可维护性。好的模块化代码,其函数被合理封装和导出,从而促进代码重用。相反,坏的模块化代码缺乏模块化,使其更难管理和扩展。

  • DRY 原则(不要重复自己):
// Good:

const greeting = 'Hello';

function greet(name) {
    return `${greeting}, ${name}!`;
}
Enter fullscreen mode Exit fullscreen mode
// Bad:

function greet(name) {
    const greeting = 'Hello';
    return `${greeting}, ${name}!`;
}
Enter fullscreen mode Exit fullscreen mode

重复的代码会增加出错的风险,并使维护变得困难。一个好的例子是,将重复的字符串提取为常量,这样既符合 DRY 原则,又能提高代码的可维护性。相反,一个坏的例子则是在函数内部重复定义了问候语。

  • 有意义的函数名称:
// Good:

function calculateArea(radius) {
    return Math.PI * radius ** 2;
}
Enter fullscreen mode Exit fullscreen mode
// Bad:

function calc(r) {
    return Math.PI * r ** 2;
}
Enter fullscreen mode Exit fullscreen mode

函数名应准确反映其用途,以增强代码的可读性。在好的例子中,函数名“calculateArea”清楚地表明了其功能。相反,坏的例子使用了含糊不清的缩写“calc”,导致函数功能不明。

  • 可测试性:
// Good:

function sum(a, b) {
    return a + b;
}

module.exports = sum;
Enter fullscreen mode Exit fullscreen mode
// Bad:

function sum(a, b) {
    console.log(a + b);
}
Enter fullscreen mode Exit fullscreen mode

编写可测试的代码有助于自动化测试,确保代码的可靠性和稳定性。在好的示例中,函数被导出用于测试,从而可以轻松设置和执行测试。相反,坏的示例包含副作用(console.log),这使得测试函数的行为变得具有挑战性。

  • 数据结构的正确使用:
// Good:

const studentGrades = [90, 85, 95, 88];
const averageGrade = studentGrades.reduce((total, grade) => total + grade, 0) / studentGrades.length;
Enter fullscreen mode Exit fullscreen mode
// Bad:

const grade1 = 90;
const grade2 = 85;
const grade3 = 95;
const grade4 = 88;
const averageGrade = (grade1 + grade2 + grade3 + grade4) / 4;
Enter fullscreen mode Exit fullscreen mode

使用合适的数据结构可以增强代码的可读性和可维护性。好的例子中,使用数组存储学生成绩,方便操作和计算。相反,坏的例子依赖于单个变量,导致代码重复且容易出错。

  • 处理异步操作:
// Good:

async function fetchData(url) {
    try {
        const response = await fetch(url);
        if (!response.ok) {
            throw new Error('Network response was not ok');
        }
        return await response.json();
    } catch (error) {
        console.error('Error fetching data:', error);
        throw error;
    }
}
Enter fullscreen mode Exit fullscreen mode
// Bad:

function fetchData(url) {
    return fetch(url)
        .then(response => {
            if (!response.ok) {
                throw new Error('Network response was not ok');
            }
            return response.json();
        })
        .catch(error => {
            console.error('Error fetching data:', error);
            throw error;
        });
}
Enter fullscreen mode Exit fullscreen mode

正确处理异步操作可确保代码的可靠性和健壮性。好的例子中,使用 async/await 语法来简化异步代码并优雅地处理错误。相反,坏的例子使用了嵌套的 Promise,这会导致回调地狱并降低代码的可读性。

  • 依赖管理:
// Good:

import { format } from 'date-fns';
Enter fullscreen mode Exit fullscreen mode
// Bad:

const dateFns = require('date-fns');
Enter fullscreen mode Exit fullscreen mode

有效的依赖管理能够提升代码的模块化和可扩展性。一个好的例子是,使用 ES6 的 import 语法从“date-fns”库中导入所需的功能,从而减少不必要的导入并提升性能。相反,一个不好的例子是使用 CommonJS 的 require 语法,它会导入整个“date-fns”模块,这可能会使应用程序包变得臃肿。

  • 性能优化:
// Good:

const sortedNumbers = [5, 2, 8, 1, 9];
sortedNumbers.sort((a, b) => a - b);
Enter fullscreen mode Exit fullscreen mode
// Bad:

const unsortedNumbers = [5, 2, 8, 1, 9];
const sortedNumbers = unsortedNumbers.sort();
Enter fullscreen mode Exit fullscreen mode

优化代码性能可确保高效执行并提升用户体验。在一个好的例子中,sort() 方法使用自定义比较函数进行升序排序,与默认排序算法相比,其性能更佳。相反,坏的例子依赖于默认排序算法,而该算法对于数值数组而言可能并非最高效。

  • Node.js API 中的正确错误处理:
// Good:

app.get('/user/:id', async (req, res) => {
    try {
        const user = await getUserById(req.params.id);
        if (!user) {
            return res.status(404).json({ error: 'User not found' });
        }
        res.json(user);
    } catch (error) {
        console.error('Error fetching user:', error);
        res.status(500).json({ error: 'Internal server error' });
    }
});
Enter fullscreen mode Exit fullscreen mode
// Bad:

app.get('/user/:id', async (req, res) => {
    const user = await getUserById(req.params.id);
    if (!user) {
        res.status(404).json({ error: 'User not found' });
    }
    res.json(user);
});
Enter fullscreen mode Exit fullscreen mode

在 Node.js API 中,正确的错误处理对于确保健壮性和可靠性至关重要。在好的示例中,错误会被捕获并记录下来,并将相应的 HTTP 状态代码返回给客户端。相反,坏的示例未能处理错误,可能会导致未处理的 Promise 拒绝和不一致的错误响应。

  • 高效的文件系统操作:
// Good:

const fs = require('fs').promises;

async function readFile(filePath) {
    try {
        const data = await fs.readFile(filePath, 'utf-8');
        console.log(data);
    } catch (error) {
        console.error('Error reading file:', error);
    }
}
Enter fullscreen mode Exit fullscreen mode
// Bad:

const fs = require('fs');

function readFile(filePath) {
    fs.readFile(filePath, 'utf-8', (error, data) => {
        if (error) {
            console.error('Error reading file:', error);
            return;
        }
        console.log(data);
    });
}
Enter fullscreen mode Exit fullscreen mode

在文件系统操作中使用 Promise 可以增强代码的可读性并简化错误处理。一个好的例子是使用 fs.promises.readFile() 异步读取文件,并使用 try-catch 处理错误。相反,一个不好的例子使用了基于回调的方法,这可能会导致回调地狱,降低代码的可读性。

  • 高效的内存管理:
// Good:

const stream = fs.createReadStream('bigfile.txt');
stream.pipe(response);
Enter fullscreen mode Exit fullscreen mode

// 坏的:

fs.readFile('bigfile.txt', (error, data) => {
    if (error) {
        console.error('Error reading file:', error);
        return;
    }
    response.write(data);
});
Enter fullscreen mode Exit fullscreen mode

在 Node.js 中使用流处理大型文件可以节省内存并提高性能。一个好的例子是,使用 fs.createReadStream() 和 stream.pipe() 高效地将数据从文件流式传输到 HTTP 响应。相反,一个不好的例子是,在将整个文件写入响应之前,先将其读入内存,这可能会导致大型文件的内存问题。

  • 正确的模块导出和导入:
// Good:

module.exports = {
    add: (a, b) => a + b,
    subtract: (a, b) => a - b
};

Enter fullscreen mode Exit fullscreen mode
// Bad:

exports.add = (a, b) => a + b;
exports.subtract = (a, b) => a - b;

Enter fullscreen mode Exit fullscreen mode

一致的模块导出和导入实践可以提高代码的可读性和可维护性。在好的例子中,使用 module.exports 导出包含函数的对象;而在坏的例子中,则直接使用 exports。虽然两种方法都有效,但坚持一种约定可以增强代码的一致性。

  • 异步控制流:
// Good:

async function processItems(items) {
    for (const item of items) {
        await processItem(item);
    }
}
Enter fullscreen mode Exit fullscreen mode
// Bad:

function processItems(items) {
    items.forEach(item => {
        processItem(item);
    });
}
Enter fullscreen mode Exit fullscreen mode

正确的异步控制流可确保操作根据需要顺序或并发执行。一个好的例子中,异步函数与 for...of 循环一起使用,顺序处理项目,并等待每个操作。相反,一个不好的例子是使用 forEach,它不能很好地处理异步操作,可能会导致意外行为。

文章来源:https://dev.to/mahabubr/mastering-clean-code-essential-practices-for-developers-1287
PREV
使用 Go 和 Redis 构建快速 URL 缩短器
NEXT
如何编写技术设计文档