میدونم!! خیلی کلیشهای شده. شما هم با این جبهه روی پست کلیک کردید که "همچین چیزی امکانپذیر نیست!!" و بهتون حق میدم. ولی باهام همراه باشید و دلایلم رو بخونید شاید نظرتون عوض شد.
پارادایم شئگرایی از محبوبترین پارادایم های توسعه نرمافزاره و اینجا نیاز به معرفی نداره چون احتمالا همتون باهاش اشنایی دارید. اگه نه، مقاله شئگرایی به زبان ساده رو بخونید. با وجود اینکه شي گرایی از نظر خیلیاتون یک استاندارد طلایی تو دنیای نرمافزاره، ولی باید اینو بدونید که از بزرگترین دلایل به هدر رفتن منابع و زمانها، پارادایم شئ گرايیه. ولی چرا؟
شئ گرایی اشتباه رواج یافته
قبل از هر چیزی میخوام یه نقل قول بزنم. از خالق مفهوم شئ گرايی، آقای Alan Kay
من شيگرایی رو اختراع کردم، ولی اینو بهتون بگم که من سی پلاس پلاس رو در ذهن نداشتم.
الن کی، خالق شيگرایی
و بله درسته. شيگرایی با سیپلاسپلاس پیاده سازی و رواج پیدا کرد. هرچند که سیپلاسپلاس زبانیه با طراحی نه چندان جالب که پیچیدگی بسیار زیادی داخلش وجود داره. دلیل اصلی اون هم اینه که این زبان در سال ۱۹۷۹ ایجاد شد که برنامهنویسی شکل امروزی رو نداشت و بسیاری از مفاهیم در حال توسعه بودند و بلوغ کاملی نداشتند. به همین خاطر طراحانش قصد داشتند که توانایی های ویژه و خارقالعادهای بهش بدن که چون شئگرایی مفهوم جدید و جالبی بود، تصمیم بر این شد که بر پایه اون پیادهسازی بشه.
سیپلاسپلاس امکانات جالبی مثل ارثبری، کپسولهسازی، پیادهسازی ملموس مفهوم انتزاع و ... رو داشت. ولی سیپلاسپلاس کجای کار رو اشتباه رفت؟
یه نقل قول دیگه از الن کی داشته باشیم.
ببخشید که شئگرایی رو مدتها قبل با اسم "شی" ایجاد کردم، چون باعث میشه مردم روی بخش کمتر مهم اون متمرکز بشن. ایده بزرگتر "پیامرسانی" بود.
الن کی، خالق شيگرایی
چیزی که خالق سیپلاسپلاس، اقای Bjarne Stroustrup کاملا جا انداخت همین بود، پیامرسانی. درسته، شئگرایی متد داره که میتونید فراخوانی کنید، ولی متد پیام نیست!
ایده کلی سلولها بودن
الن کی پیشزمینه مطالعات بیولوژیکی داشت و شیگرايی رو هم از همینجا ایده گرفت. سلولهای بیولوژیکی کاملا مستقل از هم هستند و نمیتونند به اطلاعات درونی هم دسترسی داشته باشند. اونا فقط میتونند از طریق پیامرسانی با هم ارتباط برقرار کنند. و الن کی بعدها تونست به درستی مفهومش رو در قالب Smalltalk برسونه. ولی دیگه دیر شده بود، سیپلاسپلاس حکمرانی میکرد.
یه مثال با انتزاع پایین داشته باشیم:
$benz = new Car();
$carParking->park($benz);
ایجا متغیر بنز یه نوع ماشینه که میخوایم داخل پارکینگ ماشین ها پارکش کنیم. که در این سناریو، بنز رو به پارکینگ پاس دادیم. این یعنی اینکه اونا با پیام تعامل نمیکنن و بنز در اختیار پارکینگ قرار گرفته و به اون دسترسی داره. درسته که میتونیم با ترفند هایی مثل access modifier ها این دسترسی رو محدود کنیم، ولی در هر صورت پارکینگ به متدها و ویژگیهای عمومی اون دسترسی داره. که این برخلاف چیزیه که الن کی اختراع کرده.
از اونجایی که اشیاء میتونن اشیاء دیگرو در خودشون ذخیره کنن، اتفاقی که میفته اینه که یک شئ داخل یه شئ دیگه و اون هم داخل یه شئ دیگه قرار میگره. این یعنی یک سلول خیلی بزرگ بهمریخته.
سیستمهای چند هستهای و پردازش موازی
شئگرایی روی یک سیستم تک هسته پیاده شد. لازمه بگیم که شئگرایی همیشه برای طراحان سیستم یک چالش جدی بوده. اینکه اشياء مختلف به هم دادههای قابل تغییری رو به اشتراک میزارن باعث پیچیده شدن برنامه روی چند هسته میشه. راهکارهای زیادی مثل قفل کردن نخها، طردسازی متقابل و موارد دیگه ایجاد شدند ولی هر کدوم از اینها هم مشکل و اثر جانبی خودشون رو دارند مثل deadlock، دیباگکردن کد چند هسته و ... .
مشکل الگوهای طراحی
اگه تجربه برنامهنویسی داشتید، قطعا تا حالا متوجه این شدید که چقدر سخت میتونید توی مفهوم شئگرايی مهارت خوبی پیدا کنید. چرا باید اینطوری باشه؟ چرا باید پیاده سازی یک نرمافزار با اصول شئگرایی با قابلیت نگهداری بالا تا این حد سخت باشه؟ سال ها طول میکشه تا یک متخصص تو شئگرایی بشید. و البته برای اینکه توی شئگرایی بتویند حرفی برای گفتن داشته باشد، باید الگویهای طراحی رو بلد باشد. پس میشه گفت از غولهای این مسیر، الگوهای طراحی هستند.
در ظاهر، الگوهای طراحی شئگرایی خیلی ایده خوبی به نظر میان. چیزی که یک مهندس نرمافزار قابل احترام باید بهشون تسلط داشته باشه. یه راه مناسبه برای سازماندهی سیستمهای نرمافزاری مدرن.
ولی باید به این هم توجه داشته باشد که الگوهای طراحی چرا به وجود اومدن؟ وقتی پیچیدگی نرمافزار هایی که با شئگرایی پیاده سازی میشدن زیاد شد، تیم های توسعه نرمافزار تصمیم گرفتند به جای اینکه شئگرایی رو دور بندازن، راهحلهایی برای کاهش پیچیدگی پیدا کنند. دلیلش هم سرمایهگذاری زیادی بود که روی شئگرایی کرده بودند. نتیجه این شد که این راهحل ها رو با عنوان الگوهای طراحی (Design patterns) مطرح کردند. چرا این اتفاق افتاد؟
اگه شما روی چیزی سرمایهگذاری کنید، در آینده در جهت حفظ اون تلاش خواهیم کرد. حتی اگه شواهد نشون بده که این دیگه بهترین راهحل نیست.
قانون هزینه غرق شده در اقتصاد
این قانون در اینجا هم صدق میکنه. توسعهدهندهها به جای اینکه شئگرایی که منشا پیچیدگی هست رو حذف کنن، برای کاهش پیچیدگی راهحل میدن. راهحل هایی که خودشون پیچیده هستند.
ولی راهحل چیه؟
به جال اینکه برای مشکلمون راهحل پیدا کنیم، مسیری که مهندسی نرمافزار در پیش داره رو یه نگاه بندازیم. ممکنه راهحلمون توی ابرا خودش رو نشون بده.
Serverless Computing
همونطور که میدونید محاسبات ابری در چند سال اخیر جای پای خودشون رو پیدا کردند و در حال پیشرفت هستند. همچنین پشتیبانی بزرگان صنعت نرمافزار مثل آمازون و گوگل و مایکروسافت و ... باعث تغییر مسیر نرمافزارها به این سمت شده. مدل های مختلفی برای پیاده سازی این فضای ابری ارائه و در اختیار توسعه دهنده ها قرار گرفته، مثل IaaS و PasS و ... که باعث میشن توسعه دهنده ها مثل قبل درگیر بخشهایی از توسعه نرمافزار مثل راهاندازی سیستمعامل، اجرای برنامهها، انتقال کانتینر ها و مدیریتاونها با ابزاری مثل کوبرنتیز نشن. این انتزاع باعث به صرفه بودن هزینه نهایی هم برای مصرف کننده و هم برای فراهمکننده فضای ابری شده.
مدلی که چندین سال قبل بوجود اومد، مدل Serverless Computing بود. بر خلاف اسمش این مدل قرار نیست سرور رو حذف کنه بلکه فقط سرور و زیرساخت سیستم رو به طور کامل از دید توسعه دهنده پنهان میکنه. یکی از سرویسهایی که سرورلس در اختیار توسعه دهنده قرار میده، FaaS هستش به معنی Function as a Service . سرویس ارائه شده هم به صورت فراخوانی رویدادهاست. رویدادهایی مثل ورود کاربر به سایت، ثبتنام، گرفتن لیست محصولات و ... . این رویداد ها باعث اجرای توابعی میشن که توسعه دهنده اونها رو پیاده سازی کرده.
لازم به ذکره که توسعه دهنده اینجا فقط کار توسعه توابع رو انجام میده و اجرای اونها، نحوه اجرای اونها، فراهم کردن زیرساخت و شبکه همگی بر عهده سرویس دهنده ابری است. با وجود این که این مدل سرویسدهی به بلوغ کامل نرسیده ولی بازار نرمافزار کشورهای پیشرفته رو به خودش جلب کرده. به صورتی که حتی فریموورکهایی مثل لاراول با فراهم کردن پکیجهایی، مسیر رو برای تغییر جهت به این سمت اماده کردهاند.
Functional programming
سرورلس به این دلیل که توسعه دهنده رو فقط با توابع روبرو میکنه، باعث شده که پارادایم Functional prgramming بیشتر از قبل نمایان باشه. پارادامی که میشه گفت از رقبای اصلی شئ گرایی بوده و هست. ایده اصلی این پارادایم به این صورته که هر عملیاتی، باید در قالب توابعی بدون نگهداری هیچ حالت و دادهای (states) انجام بشن. این توابع میتونن همدیگرو فراخوانی کنند و حتی به همدیگه ارسال بشن.
تمرکز اصلی این پارادایم اینه که "چی رو حل کنیم؟"، به جای اینکه روی "چطوری باید حلش کنیم؟" متمرکز بشه و این چیز خوبیه. نکته دیگه در مورد این پارادایم اینه که اثر جانبی نداره و داده های ارسالی به توابع تغییر پیدا نمیکنن، در حالی که توی شئ گرایی اینطور نیست.
توضیح در همین حد در مورد این پارادایم کفایت میکنه. بردگردیم به نقطه شروعمون!
بازگشت به نقطه شروع
احتمالا تا اینجا ایده کلی رو متوجه شدید. اینکه فضای ابری باعث شده پارادایم برنامهنویسی تابعی بیشتر نمایان بشه. حالا برگردیم سر بحث اصلیمون.
ایا سبک شئگرایی سقوط خواهد کرد؟ ایا واقعا برنامهنویسی تابعی میتونه رقیب واقعی برای سبک محبوب و اشتباه شناختهشده شئگرایی بشه؟ با هم بررسی کنیم:
- برنامهنویسی تابعی اصطلاحا داده و حالت قابل تغییر (mutable state) نداره. به این معنی که دادههایی که بین توابع انتقال داده میشن قابل تغییر نیستند، و باعث حذف اثر جانبی میشه. در حالی که در سبک شئگرایی اینطور نیست و همین مورد باعث پیچیدگیهای سیستمی میشه.
- در برنامهنویسی تابعی الگوهای طراحی وجود ندارند! که این بخشی از پیچیدگی های فهم و پیادهسازی اون رو از بین میبرن.
- برنامهنویسی تابعی بیشتر حول ارسال پیام به توابع عمل میکنه نه بازی با اشیاء. که اگه توضیح الن کی رو اینجا در نظر بگیریم، میتونیم بگیم که برنامهنویسی تابعی، بیشتر از برنامهنویسی شئگرایی شئگرا هست!
- برنامهنویسی تابعی به دلیل کمتر بودن دستورالعملهای پیچیده، کلمات کلیدی و مفاهیم پیشنیاز بسیار ساده تر از شئ گراییست. ایا سادگی بیشتر به معنی نگهداری سادهتر، مقیاسپذیری بالاتر و قابل انعطافتر نیست؟!
- برنامهنویسی تابعی ذاتا برای پردازشهای بزرگ عملکرد بهتری نسبت به شئگرایی داره. پردازشهایی که روز به روز در حال همهگیری بیشتر هستند.
نتیجه گیری
امروزه بیشتر نرمافزارها، زبانهای برنامهنویسی، فریموورکها و از همه مهم تر، نیرو های متخصص بر پایه برنامهنویسی شئگرایی سرمایهگذاری کردهاند و توسعه داده شدهاند. تغییر جهت به سمت برنامهنویسی تابعی ممکنه خیلی دور از چشم باشه، ولی از اونجایی زبانهای برنامهنویسی معروفی مثل PHP ، Javascript ، Python و ... قابلیت پشتیبانی از این پارادایم رو دارند تغییر مسیر به این سمت زیاد هم غیر ممکن نیست. همچنین سرویس ابری serverless توسعه رو بر مبنای توابع رواج میده، میتونه به این تغییر مسیر هم سرعت خوبی ببخشه. تغییر مسیری که شاید یک سال دیگه اتفاق بیفته، یا چند دهه دیگه، ولی بلاخره اتفاق خواهد افتاد. پس از همین الان خودتون رو اماده تغییرات بزرگ توی دنیای توسعه نرمافزار کنید و کمربندهاتون رو ببندید.
با به اشتراک گذاری این پست کمک کنید افراد بیشتری از این تغییر مسیر اگاه بشن.
منابع:
https://suzdalnitski.medium.com/oop-design-patterns-bd2c4fb3014c
https://betterprogramming.pub/modern-languages-suck-ad21cbc8a57c
https://arxiv.org/pdf/1906.02888