برنامه نویسی

تسلط بر کد پاک: تمرین‌های ضروری برای توسعه‌دهندگان

کد پاک سنگ بنای هر پروژه نرم افزاری موفق است. به عنوان یک توسعه دهنده، توانایی شما برای نوشتن کدهای تمیز و قابل نگهداری برای کارایی و طول عمر برنامه های شما بسیار مهم است. در این مقاله، ده نمونه از شیوه‌های کدنویسی خوب و بد در جاوا اسکریپت را بررسی می‌کنیم، که بر اهمیت نوشتن کد پاک و ارائه بینش‌های عملی برای کمک به ارتقای مهارت‌های توسعه خود تأکید می‌کند.

مثال ها

  • نام متغیرهای توصیفی:
// Good:

const totalPrice = calculateTotalPrice(quantity, unitPrice);
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

// Bad:

const t = calcPrice(q, uP);
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

در یک مثال خوب، نام متغیرها توصیفی هستند و هدف خود را به وضوح بیان می کنند و خوانایی کد را افزایش می دهند. برعکس، مثال بد از اختصارات رمزآلود استفاده می کند و درک هدف کد را برای دیگران دشوار می کند.

// Good:

function greet(name) {
    return `Hello, ${name}!`;
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

// Bad:

function greet(name){
return `Hello, ${name}!`
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

قالب بندی مداوم خوانایی و نگهداری کد را بهبود می بخشد. در یک مثال خوب، تورفتگی و فاصله گذاری مناسب استفاده شده است که ساختار کد را بهبود می بخشد. برعکس، مثال بد، سازگاری ندارد و پیروی از کد را سخت‌تر می‌کند.

// Good:

const TAX_RATE = 0.1;
const totalPrice = subtotal + (subtotal * TAX_RATE);
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

// Bad:

const totalPrice = subtotal + (subtotal * 0.1);

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

اعداد جادویی معنای مقادیر را مبهم می کنند و نگهداری کد را سخت تر می کنند. در مثال خوب، ثابت ها برای نمایش اعداد جادویی، بهبود وضوح کد و قابلیت نگهداری استفاده می شوند.

  • اصل مسئولیت واحد:
// Good:

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

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

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

// Bad:

function calculateAndFormatTotalPrice(quantity, unitPrice) {
    const totalPrice = quantity * unitPrice;
    return `$${totalPrice.toFixed(2)}`;
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

توابع باید یک مسئولیت واحد برای ترویج قابلیت استفاده مجدد و نگهداری کد داشته باشند. در مثال خوب، هر تابع وظیفه خاصی را با رعایت اصل مسئولیت واحد انجام می دهد. برعکس، مثال بد این اصل را با ترکیب چندین مسئولیت در یک عملکرد نقض می کند.

// 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;
        });
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

// Bad:

function fetchData(url) {
    return fetch(url)
        .then(response => response.json())
        .catch(error => console.error(error));
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

مدیریت صحیح خطا، استحکام کد را بهبود می بخشد و به شناسایی و حل مشکلات به طور موثرتر کمک می کند. در مثال خوب، خطاها با ظرافت مدیریت می شوند و بازخورد معنی داری را به توسعه دهندگان ارائه می دهند. برعکس، مثال بد فاقد مدیریت جامع خطا است که به طور بالقوه منجر به خرابی های بی صدا می شود.

  • نظرات و مستندات:
// Good:

// Calculate the total price based on quantity and unit price
function calculateTotalPrice(quantity, unitPrice) {
    return quantity * unitPrice;
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

// Bad:

function calculateTotalPrice(quantity, unitPrice) {
    // calculate total price
    return quantity * unitPrice;
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

نظرات و مستندات درک کد را افزایش داده و همکاری بین توسعه دهندگان را تسهیل می کند. در یک مثال خوب، نظرات واضح، هدف تابع را توصیف می‌کنند و به درک کد کمک می‌کنند. برعکس، مثال بد نظرات مبهمی ارائه می دهد که ارزش کمی را اضافه می کند.

// Good:

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

export function subtract(a, b) {
    return a - b;
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

// Bad:

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

function subtract(a, b) {
    return a - b;
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

کد ماژولار قابلیت استفاده مجدد و نگهداری را با سازماندهی عملکرد در واحدهای منسجم ارتقا می دهد. در مثال خوب، توابع به درستی کپسوله شده و صادر می شوند و استفاده مجدد از کد را تسهیل می کنند. برعکس، مثال بد فاقد مدولارسازی است و مدیریت و مقیاس آن را سخت‌تر می‌کند.

  • اصل DRY (خودت را تکرار نکن):
// Good:

const greeting = 'Hello';

function greet(name) {
    return `${greeting}, ${name}!`;
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

// Bad:

function greet(name) {
    const greeting = 'Hello';
    return `${greeting}, ${name}!`;
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

کدهای تکراری خطر خطا را افزایش می دهد و تعمیر و نگهداری را چالش برانگیز می کند. در یک مثال خوب، رشته‌های تکراری به یک ثابت استخراج می‌شوند که به اصل DRY پایبند بوده و قابلیت نگهداری کد را بهبود می‌بخشد. برعکس، مثال بد به طور اضافی احوالپرسی را در تابع تعریف می کند.

  • نام توابع معنی دار:
// Good:

function calculateArea(radius) {
    return Math.PI * radius ** 2;
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

// Bad:

function calc(r) {
    return Math.PI * r ** 2;
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

نام توابع باید دقیقاً هدف آنها را برای افزایش خوانایی کد منعکس کند. در مثال خوب، نام تابع “calculateArea” به وضوح عملکرد آن را نشان می دهد. برعکس، مثال بد از یک مخفف مرموز (“calc”) استفاده می کند که مشخص نیست عملکرد چه کاری انجام می دهد.

// Good:

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

module.exports = sum;
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

// Bad:

function sum(a, b) {
    console.log(a + b);
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

نوشتن کد قابل آزمایش، تست خودکار را تسهیل می‌کند و از قابلیت اطمینان و پایداری کد اطمینان می‌دهد. در مثال خوب، این تابع برای مقاصد آزمایشی صادر می شود و امکان تنظیم و اجرای آسان تست را فراهم می کند. برعکس، مثال بد حاوی عوارض جانبی (console.log) است که آزمایش رفتار عملکرد را به چالش می‌کشد.

  • استفاده صحیح از ساختارهای داده:
// Good:

const studentGrades = [90, 85, 95, 88];
const averageGrade = studentGrades.reduce((total, grade) => total + grade, 0) / studentGrades.length;
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

// Bad:

const grade1 = 90;
const grade2 = 85;
const grade3 = 95;
const grade4 = 88;
const averageGrade = (grade1 + grade2 + grade3 + grade4) / 4;
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

استفاده از ساختارهای داده مناسب خوانایی و نگهداری کد را افزایش می دهد. در مثال خوب، یک آرایه برای ذخیره نمرات دانش آموزان استفاده می شود که امکان دستکاری و محاسبه آسان را فراهم می کند. برعکس، مثال بد به متغیرهای فردی متکی است که منجر به کدهای تکراری و مستعد خطا می شود.

  • مدیریت عملیات ناهمزمان:
// 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;
    }
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

// 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;
        });
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

مدیریت صحیح عملیات ناهمزمان، قابلیت اطمینان و استحکام کد را تضمین می کند. در یک مثال خوب، از syntax async/wait برای ساده کردن کدهای ناهمزمان و رسیدگی به خطاها استفاده می‌شود. برعکس، مثال بد از وعده‌های تودرتو استفاده می‌کند که منجر به جهنم برگشت به تماس و کاهش خوانایی کد می‌شود.

// Good:

import { format } from 'date-fns';
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

// Bad:

const dateFns = require('date-fns');
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

مدیریت وابستگی موثر ماژولار بودن کد و مقیاس پذیری را ارتقا می دهد. در یک مثال خوب، نحو واردات ES6 برای وارد کردن فقط عملکردهای مورد نیاز از کتابخانه ‘date-fns’ استفاده می شود، که واردات غیر ضروری را کاهش می دهد و عملکرد را بهبود می بخشد. برعکس، مثال بد از دستور CommonJS نیازمند استفاده می‌کند، که کل ماژول “date-fns” را وارد می‌کند و به طور بالقوه بسته نرم افزاری را متورم می‌کند.

  • بهینه سازی عملکرد:
// Good:

const sortedNumbers = [5, 2, 8, 1, 9];
sortedNumbers.sort((a, b) => a - b);
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

// Bad:

const unsortedNumbers = [5, 2, 8, 1, 9];
const sortedNumbers = unsortedNumbers.sort();
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

بهینه سازی کد برای عملکرد، اجرای کارآمد را تضمین می کند و تجربه کاربر را افزایش می دهد. در یک مثال خوب، متد sort() با یک تابع مقایسه سفارشی برای مرتب‌سازی اعداد به ترتیب صعودی فراخوانی می‌شود که در نتیجه عملکرد بهتری در مقایسه با الگوریتم مرتب‌سازی پیش‌فرض دارد. برعکس، مثال بد به الگوریتم مرتب‌سازی پیش‌فرض متکی است که ممکن است برای آرایه‌های عددی کارآمدترین نباشد.

  • مدیریت صحیح خطا در API های Node.js:
// 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' });
    }
});
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

// 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);
});
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

مدیریت صحیح خطا در API های Node.js برای اطمینان از استحکام و قابلیت اطمینان بسیار مهم است. در مثال خوب، خطاها شناسایی و ثبت می شوند و کدهای وضعیت HTTP مناسب به مشتری بازگردانده می شوند. برعکس، مثال بد در رسیدگی به خطاها ناکام است، که به طور بالقوه منجر به رد وعده‌های کنترل نشده و پاسخ‌های خطای متناقض می‌شود.

  • عملیات کارآمد سیستم فایل:
// 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);
    }
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

// 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);
    });
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

استفاده از وعده ها در عملیات سیستم فایل خوانایی کد را افزایش می دهد و مدیریت خطا را ساده می کند. در یک مثال خوب، fs.promises.readFile() برای خواندن یک فایل به صورت ناهمزمان استفاده می شود و خطاها با استفاده از try-catch کنترل می شوند. برعکس، مثال بد از رویکرد مبتنی بر تماس استفاده می‌کند، که می‌تواند منجر به جهنم برگشت به تماس و کد کمتر قابل خواندن شود.

  • مدیریت کارآمد حافظه:
// Good:

const stream = fs.createReadStream('bigfile.txt');
stream.pipe(response);
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

// بد:

fs.readFile('bigfile.txt', (error, data) => {
    if (error) {
        console.error('Error reading file:', error);
        return;
    }
    response.write(data);
});
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

استفاده از استریم ها برای پردازش فایل های بزرگ در Node.js باعث حفظ حافظه و بهبود عملکرد می شود. در یک مثال خوب، fs.createReadStream() و stream.pipe() برای انتقال موثر داده ها از یک فایل به یک پاسخ HTTP استفاده می شوند. برعکس، مثال بد، قبل از نوشتن آن در پاسخ، کل فایل را در حافظه می خواند، که می تواند منجر به مشکلات حافظه برای فایل های بزرگ شود.

  • صادرات و واردات صحیح ماژول:
// Good:

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

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

// Bad:

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

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

شیوه‌های صادرات و وارد کردن ماژول‌ها خوانایی و نگهداری کد را بهبود می‌بخشد. در مثال خوب، module.exports برای صادرات یک شی حاوی توابع استفاده می شود، در حالی که در مثال بد، صادرات مستقیما استفاده می شود. اگرچه هر دو روش کار می کنند، اما پایبندی به یک قرارداد قوام کد را افزایش می دهد.

  • جریان کنترل ناهمزمان:
// Good:

async function processItems(items) {
    for (const item of items) {
        await processItem(item);
    }
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

// Bad:

function processItems(items) {
    items.forEach(item => {
        processItem(item);
    });
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

جریان کنترل ناهمزمان مناسب تضمین می کند که عملیات به صورت متوالی یا همزمان در صورت نیاز اجرا می شوند. در یک مثال خوب، یک تابع async با یک حلقه for… برای پردازش موارد به صورت متوالی، در انتظار هر عملیات استفاده می شود. برعکس، مثال بد از forEach استفاده می کند، که عملیات ناهمزمان را به خوبی مدیریت نمی کند و ممکن است منجر به رفتار غیرمنتظره شود.

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا