- Published on
مقدمهای بر برنامهنویسی واکنشی و تفاوت آن با مدلهای سنتی
- نویسندگان
- نام
- هومن امینی
- توییتر
- @HoomanAmini
مقدمه:
برنامهنویسی واکنشی (Reactive Programming) یک الگوی برنامهنویسی است که به توسعهدهندگان امکان میدهد برنامههایی بسازند که به صورت غیرهمزمان (asynchronous)، بدون مسدودسازی (non-blocking) و مقیاسپذیر (scalable) عمل کنند. این نوع برنامهنویسی برای مدیریت حجم بالای درخواستها و پاسخها در سیستمهایی که نیاز به پردازش همزمان دادهها دارند، بهینه است.
برنامهنویسی واکنشی چیست؟
برنامهنویسی واکنشی به ما اجازه میدهد به جای انتظار برای کامل شدن عملیات، از منابع سیستم به صورت بهینه استفاده کنیم و از مفهوم جریان دادهها (stream) برای پردازش همزمان استفاده کنیم. بهجای مدلهای سنتی که در آنها هر درخواست باید تا پایان پردازش منتظر بماند، برنامهنویسی واکنشی امکان پردازش غیرمسدودکننده را فراهم میکند.
تفاوت بین برنامهنویسی مسدودکننده و غیرمسدودکننده
- مدل مسدودکننده: در این مدل، هر درخواست باید منتظر بماند تا پردازش کامل شود. برای مثال، در برنامههای سنتی وب، هر کاربر تا پایان درخواست خود، منتظر میماند و دیگر کاربران نیز باید صبر کنند. این روش باعث اتلاف زمان و منابع میشود.
- مدل غیرمسدودکننده: در این مدل، پس از ارسال درخواست، برنامه میتواند به فعالیتهای دیگر بپردازد و منتظر پاسخ نماند. این ویژگی باعث افزایش کارایی و استفاده بهینه از منابع میشود.

سبکهای دستوری و واکنشی
دو سبک کدنویسی مطرح میشود:
- سبک دستوری (Imperative): در این روش، دستورات به صورت ترتیبی اجرا میشوند. اگر یکی از دستورات سنگین باشد، اجرای برنامه ممکن است مسدود شود.
- سبک واکنشی (Reactive): در این روش، وظایف میتوانند به صورت همزمان و موازی اجرا شوند و از منابع سیستم به طور بهینه استفاده شود.
ویژگی | سبک دستوری (Imperative) | سبک واکنشی (Reactive) |
---|---|---|
پردازش | ترتیبی و مسدودکننده | غیرترتیبی و غیرمسدودکننده |
پیچیدگی مدیریت همزمانی | بالا | پایین |
منابع سیستم | استفاده ناکارآمد | استفاده بهینه |
کاربرد | مناسب برای وظایف ساده | مناسب برای پردازشهای پیچیده و همزمان |
چالشها و محدودیتهای برنامهنویسی واکنشی
هرچند برنامهنویسی واکنشی ابزار بسیار قدرتمندی است، اما نباید آن را به عنوان یک راهحل جادویی (silver bullet) در نظر گرفت. در واقع، در بسیاری از سناریوها ممکن است برنامهنویسی دستوری سادهتر و قابل درکتر باشد. استفاده از برنامهنویسی واکنشی باید با دقت و با توجه به نیازهای خاص پروژه انجام شود.
برخی ممکن است تصور کنند که برنامهنویسی دستوری بد است و برنامهنویسی واکنشی نجاتبخش همه مشکلات است، اما این دیدگاه کاملاً صحیح نیست. در واقع، هر دو سبک مزایا و معایب خاص خود را دارند و انتخاب بین آنها باید بر اساس نوع و نیاز پروژه صورت گیرد.
کد دستوری: خوب است ... تا وقتی که مشکل ایجاد نشود
در برنامهنویسی دستوری، زمانی که یک وظیفه در حال اجرا است—به ویژه اگر این وظیفه یک عملیات I/O باشد، مانند نوشتن دادهها در پایگاه داده یا دریافت داده از یک سرور راه دور—رشتهای (thread) که آن وظیفه را فراخوانی کرده است مسدود میشود و تا پایان وظیفه قادر به انجام هیچ کار دیگری نیست.
راهحل دستوری: بیشتر زبانهای برنامهنویسی، از جمله جاوا، از برنامهنویسی همزمان (concurrent programming) پشتیبانی میکنند. برای حل این مشکل، میتوان رشتههای دیگری را ایجاد کرد. با این حال، هرچه تعداد رشتهها بیشتر شود، پیچیدگی مدیریت آنها نیز افزایش مییابد.
راهحل واکنشی: در برنامهنویسی واکنشی به جای ایجاد رشتههای متعدد برای مدیریت همزمانی، از جریان دادهها (streams) و مدلهای غیرمسدودکننده استفاده میشود. به این صورت که به محض دریافت دادهها یا نتیجه یک عملیات، یک callback یا متد دیگر فراخوانی میشود تا عملیات پردازش ادامه یابد، بدون اینکه نیاز به مسدود کردن رشتهها یا مدیریت پیچیده همزمانی باشد. این رویکرد باعث کاهش پیچیدگی و افزایش کارایی میشود.
مدل ترد به ازای هر درخواست در REST API سنتی
در تصویر اول، مدل "ترد به ازای هر درخواست" نمایش داده شده است. در این مدل، هر درخواست از سمت کاربر یک رشته (Thread) در سرور ایجاد میکند. این رشته مسئول پردازش درخواست و انتظار برای پاسخ از پایگاه داده خارجی است. در این روش، هر رشته در زمان انتظار برای پاسخ از پایگاه داده مسدود میشود و قادر به انجام هیچ کار دیگری نیست. این موضوع باعث میشود تا استفاده از منابع سیستم ناکارآمد باشد، به ویژه در زمانی که تعداد درخواستها زیاد شود.

در تصویر دوم، مدل رویدادمحور با استفاده از حلقه رویداد (Event Loop) نمایش داده شده است. در این مدل، تمام درخواستها توسط یک رشته پردازش میشوند و به جای مسدود کردن رشته، هر زمان که یک عملیات I/O نیاز به زمان داشت (مانند دسترسی به پایگاه داده یا شبکه)، آن عملیات ثبت میشود و ادامه پردازش به حلقه رویداد سپرده میشود. با تکمیل عملیات، یک رویداد جدید ایجاد میشود که باعث ادامه پردازش میشود. این مدل باعث میشود که تعداد زیادی درخواست به صورت همزمان و بدون نیاز به ایجاد تعداد زیادی رشته پردازش شوند، که این امر کارایی و مقیاسپذیری را بهبود میبخشد.

برنامهنویسی واکنشی (Reactive Programming) برنامههای واکنشی در بسیاری از موارد کاربرد دارند که شامل موارد زیر میشود:
- بازیابی داده از پایگاه داده و انجام عملیات (فیلتر) بر اساس تنظیمات کاربر.
- رندر کردن رابط کاربری با استفاده از چندین منبع داده.
- ایجاد مدل بلادرنگ برای قیمتهای سهام.
- نمایش نتایج جستجوی خودکار به کاربران.
- ثبت دادههای مربوط به دما و باد.
- اینترنت اشیا (IoT).
- برنامههای اندروید و وب.
نتیجهگیری:
برنامهنویسی واکنشی، مدلی است که به برنامهها امکان میدهد مقیاسپذیرتر، سریعتر و مؤثرتر باشند. با درک تفاوتهای بین برنامهنویسی سنتی و واکنشی، توسعهدهندگان میتوانند از مزایای این سبک بهرهمند شوند، اما باید به این نکته توجه داشت که برنامهنویسی واکنشی همه مشکلات را حل نمیکند و انتخاب سبک برنامهنویسی مناسب نیازمند بررسی دقیق پروژه است.