این پست ترجمه بخشی از مقاله "Object-Oriented Programming — The Trillion Dollar Disaster" از Medium است. مقاله اصلی خیلی طولانی بود . به همین خاطر مجبور شدم ان را به چند بخش تقسیم کنم.
قسمت دوم- OOP به جای چیزهای درست به کار میرود
شاید بهتر باشد قبل از شروع این بخش اطلاعاتی مختصری در مورد state و functional programmingو programming paradigm داشته باشید. منابع زیر میتواند مفید باشد و لازمه که بگم اصلا از اسم بزرگ مباحث نترسید . موضوع ساده تر از این حرف هاست.
-برنامه نویسی شی گرا - Master the JavaScript Interview: What is Functional Programming? -- با اینکه این مقاله در مورد جاوا اسکریپته ولی خوندنش به شدت توصیه میشه.
-الگو برنامه نویسی - What exactly is a programming paradigm?
- وضعیت-State (computer science) - ویکی پدیا -- مخصوصا بخش program state
*** مطمعن باشید وقت گذاشتن روی مقاله ارزشش را دارد.اگر با دقت و حوصله خوانده شود در های جدیدی به رویمان باز میشود.حداقل برای من اینطور بود.
من متاسفم که اصطلاح "اشیا" را مدت ها پیش ایجاد کردم چون باعث میشود مردم روی ایده کوچکتر تمرکز کنند. ایده بزرگ پیامرسان است. -- الن کی Alan Kay مخترع OOP
معمولا ارلانگ-Erlang به عنوان یک زبان شی گرا شناخته نمیشود. اما احتمالا Erlang تنها زبان شی گرا واقعی موجود است. بله, البته, Smalltalk نیز به عنوان یک زبان شی گرا شناخته میشود -- با این حال کاربرد گسترده ای ندارد. هم Smalltalk و هم Erlang از OOP ای که توسط مخترع آن، آلن کی در نظر گرفته شدهبود، استفاده میکنند.
الن کی اصطلاح "برنامه نویسی شی گرا" را در سال 1960 ابداع کرد. او پیش زمینه ای در زیست شناسی داشت و تلاش میکرد برنامه های کامپیوتری را همان طور که سلول های زنده با هم ارتباط برقرار میکنند , شکل دهد.
ایده بزرگ الن کی این بود که برنامه های کامپیوتری مستقل (سلول ها), با ارسال پیام به یکدیگر با هم ارتباط برقرار کنند. وضعیت برنامه های مستقل هرگز نباید به جهان بیرون منتشر شود(محصور سازی - encapsulation)
همینه . OOP هیچوقت قصد نداشت چیز هایی مثل وراثت, چند ریختی, کلمه "new" و بی شمار الگو طراحی داشته باشد.
ارلانگ OOP در خالص ترین شکل است.بر خلاف بیشتر زبان های اصلی, روی ایده اصلی OOP تمرکز میکند -- پیام رسانی. در Erlang اشیا با فرستادن پیام های تغییر ناپذیر با هم ارتباط برقرار میکنند.
آیا اثباتی وجود دارد که پیام های تغییر ناپذیر بهتر از ارتباط متد هاست ؟
بله, Erlang شاید مورد اعتماد ترین زبان در جهان باشد. ارلانگ به بیشتر زیرساخت های ارتباطی جهان(از جمله اینترنت) نیرو میبخشد. بعضی از سیستم های نوشته شده با ارلانگ اطمینان پذیری 99.9999999% داردند (درست میخوانید -- ۹۹ درصد).
با زبان های برنامه نویسی تاثیر گرفته از OOP , نرم افزار های کامپیوتری طولانی تر, ناخواناتر, غیر تشریحی تر و سخت تر برای نگهداری و تغییر میشوند --- Richard Mansfield
مهمترین جنبه توسعه نرم افزار, پایین نگه داشتن پیچیدگی کد است. هیچ کدام از قابلیت های فانتزی مهم نیست اگر کد غیرقابل نگهداری نباشد. حتی پاس کردن ۱۰۰٪ تست ها هم ارزشی ندارد اگر کد پیچیده و غیر قابل نگهداری باشد.
چه چیزی کد را پیچیده میکند؟ موارد زیادی را باید در نظر گرفت اما به نظر من عوامل اصلی این ها هستند:اشتراک وضعیت تغییرپذیر, انزوا نادرست و نسبت سیگنال به نویز کم (با کمی جست و جو در مورد اینها میتوانید اطلاعات بدست اورید که موضوع بحث ما نیست). همه اینها در OOP رواج دارد.
وضعیت(یا حالت یا state) چیست؟ به بیان ساده, وضعیت هرگونه اطلاعات موقت ذخیره شده در حافظه است. مثل متغیر ها یا فیلد/properties در OOP. برنامه نویسی مطلق (از جمله OOP), محاسبات را از طریق وضعیت برنامه و تغییرات وضعیت توضیح میدهد. برنامه نویسی اعلانی(functional) به جای ان نتایج مورد نظر را توصیف میکند و تغییرات وضعیت را صراحتا مشخص نمیکند
من فکر میکنم برنامه های شی گرا با ساختن نمودار های بزرگ اشیا تغییر پذیر برای کاهش پیچیدگی تقلا میکنند. میدانید, سعی در درک و یادآوری در ذهن خود دارید که هنگام فراخوانی یک متد چه اتفاقی رخ میدهد و عوارض جانبی ان چیست. --Rich Hickey خالق زبان Clojure
وضعیت به خودی خود کاملا بی ضرر است. با این حال وضعیت تغییر پذیر یک مشکل بزرگ است. مخصوصا اگر انتشار یافته باشد. وضعیت تغییر پذیر دقیقا چیست؟ هر وضعیتی که قابلیت تغییر داشته باشد. مثل متغیر ها و فیلد ها در OOP.
یک مثال واقعی, خواهش میکنم!
شما یک کاغذ سفید دارید, یادداشتی روی ان مینویسید و در نهایت همان تکه کاغذ اما با وضعیت (یادداشت) متفاوت را دارید. شما به طور موثری وضعیت کاغذ را تغییر داده اید. این امر در دنیای واقعی کاملاً خوب است زیرا احتمالاً هیچ کس دیگری به آن کاغذ اهمیت نمی دهد. مگر اینکه این تکه کاغذ نقاشی اصلی مونا لیزا باشد.
وضعیت تغییر پذیر چنین مشکل بزرگی است؟ مغز انسان قدرتمندترین ماشین در جهان شناخته شده است.با این حال ، مغز ما در کار با وضعیت واقعاً بد است زیرا ما فقط می توانیم حدود 5 مورد را در یک زمان در حافظه خود نگه داریم. بسیار راحت تر است که اگر در مورد کاری که یک قطعه کد انجام میدهد فکرکنید , نه اینکه چه متغیر هایی را در کد تغییر میدهد.
برنامه نویسی به وضعیت تغییر پذیر یک عمل دستکاری ذهن است.
متاسفانه این دستکاری ذهنی وضعیت تغییر پذیر در همه جای OOP وجود دارد. تنها دلیل برای وجود متد هایی برای یک شی ,تغییر دادن همان شی است.
برنامه نویسی شی گرا مشکل سازماندهی کد را با پراکندگی وضعیت حتی بدتر میکند. سپس وضعیت پراکنده به طور آشکارانه بین اشیاء مختلف به اشتراک گذاشته می شود.
یک مثال واقعی , خواهش میکنم!
بیایید برای چند ثانیه فراموش کنیم بزرگ شده ایم, و تلاش کنیم یک کامیون لگو با حال درست کنیم.
با این حال ، یک مشکل وجود دارد - تمام قطعات کامیون شما به طور تصادفی با قطعات سایر اسباب بازی های لگو مخلوط می شوند.و آنها را در 50 جعبه مختلف ، دوباره به طور تصادفی قرار داده اند. و شما اجازه ندارید قطعات کامیون را در کنار هم جمع کنید. باید قسمت های مختلف کامیون را در قسمت ذهن خود نگه دارید و فقط می توانید آنها را یکی به یکی بیرون بیاورید.
بله ، در نهایت آن کامیون را مونتاژ خواهید کرد ، اما چقدر طول خواهد کشید؟
ارتباط این با برنامه نویسی چیست؟
در برنامه نویسی functional معمولا وضعیت ایزوله است. همیشه میدانید یک وضعیت از کجا می آید. وضعیت هرگز بین تابع های شما پراکنده نمیشود. در OOP هر شی وضعیت خود را دارد, هنگام ساخت برنامه , باید وضعیت همه اشیا ای که با انها کار میکنید را بدانید.
برای اسانتر کردن زندگی بهتر است کد ,معاملات خیلی کمی با وضعیت داشته باشد. بگذارید قسمتهای اصلی برنامه شما خالص باشد.
وضعیت منتشر شده اشکارا
وضعیت قابل تغییر در دنیای واقعی تقریباً هرگز مشکلی به وجود نمی اورد ، زیرا همه چیز خصوصی نگه داشته می شود و هرگز مشترک نیست.این یعنی "انزوا مناسب" . نقاشی را تصور کنید که در حال کشیدن نقاشی بعدی مونا لیزا است. او به تنهایی روی نقاشی کار می کند ، به پایان میرساند و سپس شاهکار خود را به میلیون ها نفر میفروشد.
حالا ، او با این همه پول حوصله اش سر میرود و تصمیم می گیرد کار متفاوتی انجام دهد. او فکر می کند برگزاری مهمانی نقاشی ایده خوبی خواهد بود. او دوستانش ، جن ، تقی ، پلیس و زامبی را دعوت می کند تا به او کمک کنند. کار گروهی! همه آنها همزمان شروع به کشیدن نقاشی روی یک بوم میکنند. البته هیچ چیز خوبی از آن بیرون نمی آید - نقاشی یک فاجعه کامل است!
انتشار وضعیت تغییر ناپذیر در جهان واقعی مفهومی ندارد. این دقیقاً اتفاقی است که در برنامه های OOP رخ می دهد - وضعیت آشکارا بین اشیاء مختلف به اشتراک گذاشته می شود ، و آنها به هر شکلی که مناسب می بینند ، آن را ارتقا و تغییر می دهند. این به نوبه خود ، به دلیل رشد کد استدلال در مورد برنامه را سخت تر و سخت تر می کند.
مساعل مربوط به همزمانی
با وجود انتشار وضعیت بی قاعده در OOP , موازی کردن ان کد غیر ممکن میشود. مکانیسم های پیچیده ای برای رفع این مشکل اختراع شده است. Thread locking, mutex و مکانیسم های دیگری اختراع شده است. البته ، چنین رویکردهای پیچیده اشکالات خاص خود را دارد - deadlock ها ، عدم سازگاری ، دیباگ کردن کد های چند نخی بسیار سخت و زمانگیر است. من حتی در مورد افزایش پیچیدگی ناشی از استفاده از مکانیزم های همزمانی صحبت نمی کنم.
همه وضعیت ها شر نیستند
همه وضعیت ها شر هستند؟ نه وضعیت الن کی احتمالا بد نیست. تغییر وضعیت ها اگر به طور صحیح ایزوله شده باشد احتمالا خوب است.
داشتن اشیاء تغییر ناپذیر برای انتقال داده خیلی هم خوب است. نکته اینجا"تغییر ناپذیر" است. از چنین اشیا ای برای انتقال داده ها بین توابع استفاده می شود.
با این حال , چنین اشیایی ممکن است متد ها و ویژگی ها (properties) در OOP را کاملا زائد کند. وقتی متد ها و ویژگی های یک شی نمیتواند تغییر کند پس کاربرد انها چیست؟
بعضی ها ممکن است استدلال کنند که تغییر وضعیت در OOP یک انتخاب است نه یک اجبار. این استدلال مشکلاتی دارد. این یک انتخاب در طراحی نیست, تقریبا تنها گزینه است. بله میتوان در جاوا و C#اشیا تغییر ناپذیر را به متد ها منتقل کرد.اما این به ندرت انجام می شود زیرا بسیاری از برنامه نویسان به صورت پیش فرض در حال تغییر داده ها هستند. حتی اگر توسعه دهندگان بخواهند از تغییر ناپذیری در برنامه شی گرا شان درست استفاده کنند, زبان ها مکانیسم داخلی ای برای تغییر ناپذیری و استفاده موثر از تغییر ناپذیری فراهم نکرده اند.
بله ، ما می توانیم اطمینان حاصل کنیم که اشیاء فقط با ارسال پیام های غیرقابل تغییر ارتباط برقرار می کنند و هرگز هیچ مرجعی (references)را منتقل نمی کنند (که بندرت انجام می شود). چنین برنامه هایی قابل اعتماد تر از OOP اصلی هستند. با این حال ، پس از دریافت پیام ، اشیاء هنوز هم باید حالت خود را تغییر دهند. پیام یک اثر جانبی دارد و تنها هدف آن ایجاد تغییرات است.پیام ها اگر نتوانند وضعیت اشیاء دیگر را تغییر دهند ،بی فایده هستند.
این غیر ممکن است که از OOP استفاده کنیم و وضعیت تغییر نکند.
این داستان ادامه دارد...