برنامهنویسی تابعی یا FP یک فریمورک یا کتابخانه نیست؛ سبک فکر کردن به مسئله است. در این سبک، برنامه را مجموعهای از تبدیلهای کوچک روی داده میبینیم، نه دنبالهای از دستورها که وضعیت را مدام عوض میکند. خروجیاش کدهای پیشبینیپذیرتر، تستپذیرتر و کمحاشیهتر است و بسیاری از ابزارهایی که امروز استفاده میکنید — از React تا Redux — بر همین تفکر سوارند. بیایید اصولش را یکبهیک بفهمیم.
تابع خالص چیست؟
ستون فقرات FP تابع خالص است؛ تابعی که فقط به ورودیاش نگاه میکند و خروجیاش همیشه برای همان ورودی یکسان است. لمس کردن متغیر بیرونی، خواندن ساعت سیستم یا چاپ در کنسول آن را «ناخالص» میکند چون به دنیای بیرون وابستهاش میسازد:
// خالص: هر بار با همان ورودی، همان خروجی
function calculateTax(price, rate) {
return price * rate;
}
// ناخالص: به متغیر بیرونی وابسته است
let taxRate = 0.09;
function calculateTaxImpure(price) {
return price * taxRate;
}
تغییرناپذیری داده
اصل دوم این است که داده را دستکاری نکنیم؛ بهجای تغییر، نسخه جدید بسازیم. این عادت ردیابی تغییرات را آسان، اشکالزدایی را سریع و بازگشت به حالت قبل را ممکن میکند:
const cart = ["کتاب", "قلم"];
// بهجای push که اصل را تغییر میدهد
const newCart = [...cart, "دفتر"];
console.log(cart); // ["کتاب", "قلم"] بدون تغییر
console.log(newCart); // سه قلم کالا
اجتناب از جهشهای پنهان
اثر جانبی یعنی تابع علاوه بر جواب، کاری دیگر هم بکند؛ مثل ویرایش آرایهای که گرفته یا تغییر DOM. در FP اثر جانبی را به لبههای برنامه میبریم — همانجایی که واقعاً باید اتفاق بیفتد — و قلب منطق را خالص نگه میداریم:
// خالص: فقط محاسبه و بدون چاپ
function applyDiscount(price, discount) {
return price - (price * discount / 100);
}
// اثر جانبی کنترلشده در لبه برنامه
const finalPrice = applyDiscount(1000000, 15);
console.log(`قیمت نهایی: ${finalPrice} تومان`);
محصول اورجینال INZIP
دانلود پوسته وردپرس باریستا؛ قالب کافیشاپ، رُستری قهوه و فروشگاه قهوه دوزبانه با منوی رومیزی، رزرو آنلاین میز با کد پیامکی و ووکامرس. طراحی اختصاصی inzip.ir
تحویل آنی
آپدیت رایگان
بدون قفل لایسنس
پشتیبانی واقعی
٪۲۶
تخفیف ویژه
۱,۰۳۰,۰۰۰ تومان
کامپوز کردن به جای ردیف کردن
بهجای این که چند دستور پشت سر هم بنویسیم و متغیر میانی را مدام عوض کنیم، خروجی هر تابع را مستقیم به تابع بعدی میدهیم؛ مثل ایستگاههای یک خط تولید که هر کدام فقط یک کار تخصصی انجام میدهد:
const numbers = [1, 2, 3, 4, 5, 6, 7, 8];
// خط تولید: فیلتر زوج، دوبرابر و بعد جمع
const result = numbers
.filter(n => n % 2 === 0)
.map(n => n * 2)
.reduce((sum, n) => sum + n, 0);
console.log(result); // 40
Currying؛ تفکیک ورودیها
کاریکردن یعنی تابعی که چند ورودی میگرفت را به زنجیرهای از توابع تکورودی تبدیل کنیم؛ این کار باعث میشود نسخههای پیشتنظیمشده از یک منطق بسازیم و از آنها دوباره استفاده کنیم:
// بهجای: add(3, 4)
const add = a => b => a + b;
const add5 = add(5);
console.log(add5(10)); // 15
console.log(add(2)(3)); // 5
FP در کنار سبکهای دیگر
هیچ قانونی نمیگوید باید صددرصد تابعی کد بزنید؛ در عمل، یک توسعهدهنده خوب منطق محاسباتی را خالص نگه میدارد و اثرات جانبی را در لبهها کنترل میکند. همین تعادل کافی است تا تست واحد برای توابع محاسباتی شما بدون راهاندازی DOM یا شبکه، فقط با ورودی و خروجی انجام شود و بخش بزرگی از پروژه از پایداری لازم برخوردار بماند. آنهایی که با React کار میکنند این را در رندر کامپوننتها میبینند که باید خالص باشد تا هر بار با همان prop خروجی یکسان بدهد.
جمعبندی
برنامهنویسی تابعی سه فرمان دارد: توابع را خالص نگه دارید، داده را تغییرناپذیر کنید و بهجای ردیف دستورها، توابع را کامپوز کنید. نیازی نیست عاشق ریاضیات باشید؛ فقط کافی است از امروز به هر تابعی که مینویسید دو سؤال بپرسید: «آیا فقط به ورودیام نگاه میکند؟» و «آیا چیزی بیرون از خودش را لمس میکند؟» همین دو سؤال، کیفیت کدتان را متحول میکند.