<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های حسین عابدی</title>
        <link>https://virgool.io/feed/@hsa</link>
        <description>سلام من حسین عابدی هستم یه علاقه مند به فعالیت در حوزه وب و برنامه نویسی. مدتیه تصمیم گرفتم تجربیات و دل نوشته های خودم رو با شما به اشتراک بذارم. امیدوارم  مطالبی که میذارم براتون مفید باشه :)</description>
        <language>fa</language>
        <pubDate>2026-04-15 02:51:03</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/1457555/avatar/Ul6IPq.jpg?height=120&amp;width=120</url>
            <title>حسین عابدی</title>
            <link>https://virgool.io/@hsa</link>
        </image>

                    <item>
                <title>معماری Clean Code؛ هنر ساخت کدی که نفس می‌کشد!</title>
                <link>https://virgool.io/@hsa/%D9%85%D8%B9%D9%85%D8%A7%D8%B1%DB%8C-clean-code-%D9%87%D9%86%D8%B1-%D8%B3%D8%A7%D8%AE%D8%AA-%DA%A9%D8%AF%DB%8C-%DA%A9%D9%87-%D9%86%D9%81%D8%B3-%D9%85%DB%8C-%DA%A9%D8%B4%D8%AF-er7yi1qal6ud</link>
                <description>Clean Code Architectureدر دنیای توسعه نرم‌افزار، بزرگ‌ترین کابوس یک برنامه‌نویس کدهای شلخته و سخت‌فهم است؛ همان کدهایی که بعد از چند ماه حتی نویسنده‌اش هم متوجه منطقشان نمی‌شود!اینجاست که Clean Code (کد تمیز) وارد می‌شود. Clean Code فقط یک اصطلاح نیست، بلکه سبکی از تفکر و معماری نرم‌افزار است که باعث می‌شود برنامه‌ها:خوانا باشند،قابل تغییر و توسعه باشند،و تست‌پذیری بالا داشته باشند.حالا بیاییم ۵ اصل کلیدی این معماری را با مثال‌های ملموس بررسی کنیم:1️⃣ خوانایی (Readability)؛ کدی برای انسان‌ها، نه کامپیوترکدی که فقط برای اجرای کامپیوتر نوشته شود، مثل نامه‌ای است که با رمز نوشته شده؛ خواندنش برای بقیه سخت است.در Clean Code، نام‌ها، ساختارها و توضیحات باید خودتوضیح باشند.🔹 مثال بد:function c(n, m) {
  return n * 60 + m;
}🔹 مثال خوب:function convertHoursToMinutes(hours, minutes) {
  return hours * 60 + minutes;
}وقتی کسی مثال دوم را می‌بیند، بدون هیچ کامنتی متوجه می‌شود تابع چه کاری انجام می‌دهد.2️⃣ توابع کوچک و هدفمند (Small &amp; Purposeful Functions)تابع‌های بزرگ مثل یک آشپزخانه شلوغ هستند؛ همه چیز در یکجا قاطی شده. اما در Clean Code، هر تابع باید یک وظیفه مشخص داشته باشد.🔹 مثال بد:def process_user(data):
    # ثبت کاربر
    # ارسال ایمیل خوشامد
    # ثبت گزارش در لاگ🔹 مثال خوب:def register_user(data):
    ...

def send_welcome_email(user):
    ...

def log_registration(user):
    ...این ساختار هم تست کردن را ساده‌تر می‌کند، هم خواندن را 😊3️⃣ کاهش وابستگی‌ها و افزایش انسجام (Low Coupling &amp; High Cohesion)یک برنامه خوب مثل یک شهر منظم است؛ هر بخش کار خودش را می‌کند و اگر یک خیابان خراب شود، کل شهر فلج نمی‌شود.در Clean Code، هر کلاس یا ماژول باید یک مسئولیت مشخص داشته باشد و تا حد امکان کمترین وابستگی را به بخش‌های دیگر داشته باشد.🔹 مثال ملموس:اگر یک کلاس هم وظیفه ثبت کاربر را داشته باشد، هم ارسال ایمیل را، هم تولید فاکتور را، این یعنی وابستگی زیاد.اگر هرکدام این وظایف در یک ماژول جدا باشد، تغییر ایمیل یا فاکتور هیچ اثری روی ثبت کاربر ندارد.4️⃣ تست‌پذیری (Testability)؛ پیشگیری بهتر از درمانکدی که تمیز نوشته شود، به راحتی می‌توان برایش تست خودکار نوشت. کد شلخته مثل یک دستگاه پیچیده بدون نقشه است؛ هر تغییری ممکن است چیزی را خراب کند.🔹 مثال:تابعی که ۴ تا وظیفه انجام می‌دهد را نمی‌توان راحت تست کرد. اما اگر همان وظایف در ۴ تابع کوچک باشد، هر کدام را جدا می‌شود Unit Test کرد. این یعنی پیدا کردن سریع‌تر باگ‌ها و تغییر راحت‌تر بدون ترس از خراب شدن بخش‌های دیگر.5️⃣ اصل پرهیز از تکرار (DRY Principle)؛ دشمن نامرئی زمان شماتکرار کد مثل تکرار یک اشتباه است؛ هر بار که منطق یکسان را در چند جا کپی کنید، برای هر تغییر باید چند جا را اصلاح کنید.🔹 مثال بد:$totalPrice = $price + $price * 0.09; // محاسبه مالیات
...
$finalPrice = $price + $price * 0.09; // محاسبه مالیات دوباره🔹 مثال خوب:function addTax($price) {
  return $price + $price * 0.09;
}

$totalPrice = addTax($price);
$finalPrice = addTax($price);حالا اگر نرخ مالیات تغییر کرد، فقط یکجا باید تغییرش دهید.🔎 نتیجه‌گیریClean Code یعنی احترام به زمان آینده خودت و تیم توسعه‌دهنده.وقتی اصول خوانایی، توابع کوچک، کاهش وابستگی‌ها، تست‌پذیری و پرهیز از تکرار را رعایت کنید، درواقع دارید برای قابلیت نگهداری و توسعه پروژه در آینده سرمایه‌گذاری می‌کنید.کد تمیز مثل یک کتابخانه منظم است؛ هر چیزی سر جای خودش است و پیدا کردنش آسان. نتیجه:توسعه سریع‌ترباگ کمتررضایت بیشتر تیم و مشتریدر نهایت همیشه به یاد داشته باش:کد تمیز یعنی نرم‌افزاری که امروز کار می‌کند و فردا هم رشد می‌کند.</description>
                <category>حسین عابدی</category>
                <author>حسین عابدی</author>
                <pubDate>Mon, 15 Sep 2025 11:27:12 +0330</pubDate>
            </item>
                    <item>
                <title>درک مفاهیم سالید (SOLID) در جاوا اسکریپت و نود جی اس (NodeJS)</title>
                <link>https://virgool.io/@hsa/%D8%AF%D8%B1%DA%A9-%D9%85%D9%81%D8%A7%D9%87%DB%8C%D9%85-%D8%B3%D8%A7%D9%84%DB%8C%D8%AF-solid-%D8%AF%D8%B1-%D8%AC%D8%A7%D9%88%D8%A7-%D8%A7%D8%B3%DA%A9%D8%B1%DB%8C%D9%BE%D8%AA-%D9%88-%D9%86%D9%88%D8%AF-%D8%AC%DB%8C-%D8%A7%D8%B3-nodejs-eg0v1eaemoxk</link>
                <description>درک مفاهیم سالید (SOLID) در جاوا اسکریپت و نود جی اس (NodeJS)خوب در ابتدا بذارید یه بررسی داشته باشیم ببینیم SOLID چی هست و چه فایده ای میتونه برامون داشته باشه؟سالید (SOLID) چیست؟به زبون ساده بخوایم بگیم SOLID یه مجموعه از قوانین برنامه نویسی در زبان های شی گراست که به ما کمک میکنه بتونیم قاعده مندتر و بهتر کلاس ها و توابع داخلشون رو تعریف کنیم تا هم کدمون خواناتر بشه و هم توسعه پروژه در آینده بهتر و کم چالش تر باشه برامون.حالا شاید بگید مگه بدون این اصول نمیشه کد زد برنامه نویسی کرد؟ در پاسخ باید بگم چرا میشه اما ببینید برنامه نویسی یه کار مهندسی هست، یعنی مثل سایر رشته های مهندسی، اگه یه سری اصول و قوانین رو بدونی و تو کارت پیاده سازی کنی، کیفیت و ارزش کارت رو بالاتر میبره. اینجا هم همینطوره!پس توصیه میکنم اگه قصد داری برنامه های تجاری تولید کنی که آینده روشنی براشون در نظر بگیریم، حتما به این نکات یه نیم نگاهی داشته باش و سعی کن خوب یادشون بگیری. پشیمون نمیشی :)قوانین SOLID:خوب کلا SOLID از ۵ اصل ساخته شده که حروف اون هر کدوم اشاره به یه اصل دارن. پس ابتدا از حرف S شروع میکنیم ببینیم منظورش چیه؟۱. Single Responsibility Principle (SRP)تو این قانون میگه هر کلاس باید تنها یه وظیفه مشخص داشته باشه و پیش ببره. به عبارت دیگه همه کارها رو قرار نیست رو دوش یه کلاس بذاریم که برامون انجام بده :) نمونه کد زیر و ببینید خودتون متوجه میشید:// Without SRP
class User {
    constructor(name) {
        this.name = name;
    }
    sendSMS() {
        // Send welcome sms to the user
    }
    sendEmail() {
        // Send welcome email to the user
    }
}خوب همونطوری که میبینید اینجا SMS و Email رو لزومی نداره کلاس User انجام بده، پس بهتره این کار رو بسپاریم به دست کلاس های مختص به خودش:// With SRP
class User {
    constructor(name) {
        this.name = name;
    }
}

class SMSService {
    sendSMS(user) {
        // Send welcome sms to the user
    }
}
class EmailService {
    sendWelcomeEmail(user) {
        // Send welcome email to the user
    }
}حالا هر کلاس وظیفه خودش و به درستی انجام میده و کاری به بقیه نداره. چقدر کدمون مرتب تر شد! :)۲. Open/Closed Principle (OCP)این اصل میگه موجودیت های نرم افزاری مون مثل کلاس ها، باید برای توسعه باز باشن و برای اصلاح بسته! یعنی اگه کلاسی نوشتیم که به خوبی تعریف شده بود، نباید به خاطر توسعه های آتی سیستم، دائم کلاس رو اصلاح کنیم و تغییرش بدیم. اجازه بدید بریم روی مثال زیر تا واضح تر این مسئله دیده بشه:// Without OCP
class Square {
    constructor(side) {
        this.side = side;
    }
}
class AreaCalculator {
    calculateSquareArea(square) {
        return square.side * square.side;
    }
}خوب الان اینجا ما یه کلاس Square ایجاد کردیم، واسه محاسبه مساحت باید یه نمونه ازش بسازیم و به عنوان پارامتر به تابع کلاس AreaCalculator پاس بدیم. خوب به نظر بد نیست اما مشکل از اینجا شروع میشه که اگه شکل های دیگه مثل دایره، مستطیل و ... داشتیم، برای هر شکل که جدید به مجموعه اضافه بشه، باید این کلاس رو اصلاح کنیم و یه متد جدید براش بنویسیم! راه حل این مشکل رو در ادامه آوردم:// With OCP
class Shape {
    calculateArea() { }
}

class Square extends Shape {
    constructor(side) {
        super();
        this.side = side;
    }
    calculateArea() {
        return this.side * this.side;
    }
}

class Circle extends Shape {
    constructor(radius) {
        super();
        this.radius = radius;
    }
    calculateArea() {
        return Math.PI * this.radius * this.radius;
    }
}حالا Shape یه Abstraction کلاس شد و با ارث بری تونستیم این مشکل رو حل کنیم! حالا هر چی شکل دیگه اضافه بشه، ما اونو از کلاس Shape ارث بری میکنیم و بعد متد calculateArea رو داخلش پیاده سازی می کنیم. پس با این کار دیگه کلاس هامون با توسعه پروژه دائم نمیخواد اصلاح و بروز رسانی بشن که شد همون اصل دوم که دنبالش بودیم :)۳. Liskov Substitution Principle (LSP)این اصل میگه متدها و آبجکت هایی که در سوپر کلاس استفاده میکنیم، نباید با زیر کلاس هایی که اون رو ارث بری میکنن مغایرت داشته باشه. به عبارت دیگه هر متدی که در کلاس Parent میاد، نباید یا عملکرد کلاس های child در تضاد باشه. به مثال زیر توجه کنید تا موضوع روشن تر بشه برامون:// Without LSP
class Bird {
    fly() {
        // Fly logic
    }
}

class Penguin extends Bird {
    // Penguins can&#039;t fly
    fly() {
        throw new Error(&#039;Penguins can\&#039;t fly&#039;);
    }
}خوب تو این مثال ببینید تابع fly توی کلاس والدمون (Parent) که Bird هست اومده. خوب مشکلی که داره درست میکنه اینه که اگه پنگوئن ها رو بخوایم از این کلاس ارث بری کنیم، دیگه متد fly موجود در کلاس bird نمیتونه جوابگو باشه! پس در واقع اون متد غلط شد که نباید اینجا باشه! پس حالا بریم ببینیم راه حلش چیه// With LSP
class Bird {
    move() { }
}

class FlyingBird extends Bird {
    fly() {
        // Fly logic
    }
}

class Penguin extends Bird {
    // Penguins can&#039;t fly
    move() { }
}همونطور که دیدید فقط کافی بود با دقت بیشتری به مسئله نگاه میکردیم و به جای تعریف متد fly در سوپر کلاس، متد دیگه ای تحت عنوان move در نظر میگرفتیم و تعریف متد fly رو به کلاس دیگه ای که مختص پرندگان پروازی بود اختصاص می دادیم.۴. Interface Segregation Principle (ISP)این اصل هم میگه که یه کلاس نباید اینترفیس هایی (Interface) رو پیاده سازی کنه که خودش بهشون نیازی نداره! به عبارت دیگه همون طور که قبلا هم گفتم هر کلاس باید کار مختص به خودش رو انجام بده. نمونه کد زیر و یه نگاه بندازیم تا موضوع شفاف تر بشه:// Without ISP
class Worker {
    work() {
        // Work logic
    }
    eat() {
        // Eat logic
    }
}خوب همونطوری که در بالا میبینیم به طور نمونه دو تا کار متفاوت به کلاس ورکر داده شده در صورتی که میشه اون رو به شکل زیر نوشت تا خوانایی کدمون بالاتر بره:// With ISP
class Workable {
    work() { }
}

class Eatable {
    eat() { }
}

class Worker implements Workable, Eatable {
    work() {
        // Work logic
    }
    eat() {
        // Eat logic
    }
}که در بالا اومدیم دو تا کلاس تعریف کردیم و هر کدوم تسک مربوط به خودش رو داره انجام میده. در نهایت در کلاس Worker کافیه دو کلاس Workable و Eatable رو implement کنیم و به راحتی ازشون استفاده کنیم. فقط نکته ای که باید توجه کنیم اینه که با توجه به این که این قوانین که داریم میگیم مربوط به زبان های شی گرا هستن، از همین جهت تو جاوا اسکریپت عملا دستور implements کار نمیکنه و این نحوه پیاده سازی توی Typescript که بر مبنای شی گرایی کار میکنه معتبر هست.۵. Dependency Inversion Principle (DIP)و اما قانون آخرمون که خیلی هم مهم هست اینه که وابستگی مستقیم کلاس های سطح بالا رو به کلاس های سطح پایین منع میکنه. دلیل این کارم اینه که اگه کلاس های سطح بالا مستقیما به سطح پایین متصل بشن، بعد بابت هر تغییری که روی کلاس های سطح پایین صورت بگیره، باید کلاس های سطح بالامون رو هم اصلاح کنیم که خوب نیست!حالا مثال زیر و بررسی کنیم با هم تا عملا توی کد ببینیم منظور از این قانون چی هست و داره بهمون چی میگه؟// Without DIP
class LightBulb {
    turnOn() {
        // Turn on logic
    }
    turnOff() {
        // Turn off logic
    }
}

class Switch {
    constructor(bulb) {
        this.bulb = bulb;
    }
    operate() {
        // Operate the bulb
        if (/* some condition */) {
            this.bulb.turnOn();
        } else {
            this.bulb.turnOff();
        }
    }
}خوب در مثال بالا کلاس LightBulb، کلاس سطح بالاست و Switch کلاس سطح پایین محسوب میشه. همونطوری که میبینیم، اینجا دو کلاس مستقیما به هم وصل شدن و در نتیجه در آینده هر تغییری که در Switch اعمال شه باید مستقیما روی کلاس LightBulb هم ایجاد بشه اما بریم ببینیم چطوری میشه این مشکل رو حل کرد؟!// With DIP
class Switchable {
  turnOn() {}
  turnOff() {}
}

class LightBulb implements Switchable {
  turnOn() {
    // Turn on logic
  }
  turnOff() {
    // Turn off logic
  }
}

class Switch {
  constructor(device) {
    this.device = device;
  }
  operate() {
    // Operate the device
    if (/* some condition */) {
      this.device.turnOn();
    } else {
      this.device.turnOff();
    }
  }
}همون طور که میبینیم اینجا یه کلاس Switchable ایجاد کردیم که به واسطه اون بتونیم وابستگی کلاس سطح بالامون رو از کلاس سطح پایین جدا کنیم که اونم از طریق همین کلاس Switchable انجام شد.خوب اینم از بحث اصول SOLID در جاوا اسکریپت، قطعا برای تسلط بر این موضوعات، نیاز به تمرین و تکرار بیشتری خواهید داشت که شاید اول کمی اذیت شید اما ارزشش رو داره و کمک میکنه سطح برنامه نویسی تون چند لول بالاتر بیاد.</description>
                <category>حسین عابدی</category>
                <author>حسین عابدی</author>
                <pubDate>Tue, 14 May 2024 08:45:39 +0330</pubDate>
            </item>
            </channel>
</rss>