برنامه نویسی شی گرا در برابر فانکشنال

پرسپولیسی یا استقلالی؟ رئال مادرید یا بارسلونا؟ طرفدار کدام خاندان در game of thrones هستید؟ چپی یا راستی؟ تعداد کمی از افراد این ها را به دو قسمت جداگانه تقسیم میکنند. اما بیشتر مردم به یکی از این جناح های فریبنده می‌پیوندند. به این لیست یک گزینه دیگر هم اضافه میشود: برنامه نویسی شی گرا یا برنامه نویسی فانکشنال.

ممکن است فکر کنید که منظور من از پارادایم های برنامه نویسی چیست؟ بسیار خب. قبل از اینکه این مسئله را بررسی کنیم بیایید ببینیم که شی گرایی و فانکشنال واقعا چه هستند.

برنامه نویسی شی گرا (OOP)

طبق ویکی پدیا، Object Oriented Programming یک پارادایم برنامه نویسی بر اساس مفهوم شی است. هر شیء میتواند داده هایی در خود داشته باشد، که آنها را با عنوان “صفت” میشناسیم. همینطور شامل کدهایی میشود که به عنوان “method” معروف هستند. ویژگی اصلی اشیا، این هست که method ها میتوانند به داده های مرتبط با شی، دسترسی داشته باشند و گاهی آنها را اصلاح کنند. که به تغییر حالت شی معروف است.

علاوه بر این، در بیشتر زبان های OOP اشیا نمونه هایی از کلاس ها هستند که موجودیت های منفردی محسوب میگردند. این موجودیت ها میتوانند با یکدیگر تعامل کنند. استفاده از اشیا نوعی تقلید از جهان واقعی است.

در اینجا مثالی از زبان Ruby را مشاهده میکنید:

class Dog
  attr_accessor :name, :favorite_treat

  def initialize(name, favorite_treat)
    @name = name
    @favorite_treat = favorite_treat
  end

  def change_favorite_treat(treat)
    @favorite_treat = treat
  end
end

charlie = Dog.new("Charlie", "bacon")

ما یک کلاس ایجاد کردیم (یا تقریبا یک قالب). میدانیم که تمامی سگ ها نام و غذای مورد علاقه دارند، بنابرین با پارامترهای مشخصی آنها را مقدار دهی اولیه میکنیم. حال یک نمونه جدید از کلاس Dog ایجاد میکنیم که نام آن charlie است. فرض کنیم چارلی غذای مورد علاقه اش را تغییر میدهد:

charlie.change_favorite_treat('t-bone')

به وسیله متد change_favorite_treat با موفقیت وضعیت چارلی را تغییر دادیم و زمانی که بخواهیم به داده های شی دسترسی داشته باشیم یک مقدار جدید در favorite_treat خواهیم داشت.

برنامه نویسی فانکشنال (FP)

به صورت خیلی ساده، برنامه نویسی فانکشنال بر روی محاسبات در توابع خالص تمرکز دارد. کلمه کلیدی در اینجا pure یا خالص هست. همه چیز بر این اساس است که باید خالص باشند. اما کلمه “خالص” دقیقا به چه معناست:

  • بین داده ها و رفتارهای (methods) برنامه یک جداسازی کامل وجود دارد.
  • تمامی اشیای ساخته شده در برنامه نویسی فانکشنال، تغییر ناپذیر هستند. (نمیتوان آنها را ویرایش کرد)
  • وضعیت شی اشتراک گذاری نمیشود. (اشیا نمیتوانند از محدوده دیگر شی ها اطلاع داشته باشند)
  • تبعیت کردن از توابع خالص. (در پایین توضیح داده شده)

توابع خالص

یک تابع خالص، تابعی است که:

  1. مقدار بازگشت داده شده همیشه بستگی به مقدار ورودی تابع دارد. (به ازای هر ورودی، همیشه مقدار مشخصی بازگشت داده میشود.)
  2. هیچ اثر جانبی وجود ندارد. (برای مثال هیچ شبکه یا دیتابیسی صدا زده نمیشود که روی مقدار بازگشتی اثر گذار باشد.)
  3. این توابع داده هایی که به آنها ارسال شده اند را، تغییر نمیدهند.

نمونه هایی از توابع غیر خالص را در اینجا مشاهده میکنید:

function number(num){
  num * Math.random()
}

function hello(greeting){
  console.log(greeting)
}

var totalPeople = 10
function totalVotes(votes){
 return votes * totalPeople
}

خروجی تابع number هیچکاری با ورودی num انجام نمیدهد و عدد را با یک مقدار random ضرب میکند. (خالص نیست!) در توابع خالص ما فقط به مقدار بازگشت داده شده اهمیت میدهیم، بنابرین تابع hello خالص نیست به این خاطر که یک اثر جانبی ایجاد میکند (log کردن در console). تابع totalVotes به یک مقدار خارج از محدوده خود وابسته است. (که به این معنی است: اصلا به هیچ وجه!)

حالا مثالی از یک تابع pure را ببینید:

function plusTwo(num){
  return num + 2
}

خروجی pulsTwo فقط و فقط به ورودی num وابسته است.

برنامه نویسی OOP در مقابل FP

برای نشان دادن چگونگی تفاوت عملکرد در OOP و FP از مثال زیر استفاده میکنم:

شما یک شرکت را اداره میکنید و قصد دارید حقوق هر کارمند را 1 میلیون تومان افزایش دهید. از دیدگاه برنامه نویسی، چطور با این مسئله برخورد میکنید؟

در OOP

  1. یک کلاس برای کارمند ایجاد میکنیم که شامل نام و حقوق میشود. و همچنین تابعی برای اصلاح حقوق دارد.
  2. نمونه های کارمندان را از کلاس ایجاد میکنیم.
  3. به وسیله تابع each یکی یکی حقوق هر کارمند را افزایش میدهیم.

در FP

  1. آرایه کارمندان را ایجاد میکنیم که از آرایه هایی با نام و حقوق هر کارمند تشکیل شده است.
  2. یک تابع با نام change_salary ایجاد میکنیم که کپی شده یک کارمند را با تغییر دادن حقوق باز میگرداند.
  3. تابع change_salaries را ایجاد میکنیم که با پیمایش آرایه کارمندان، هر کارمند را به change_salary ارسال میکند.
  4. از این دو تابع برای ایجاد یک مجموعه داده جدید استفاده میکنیم و نام آن را “کارمندان خوشحالتر” میگذاریم.

میتوانیم ببینیم که FP از توابع خالص استفاده میکند و به تغییر ندادن متغیرها پایبند است. با OOP ما نمیتوانیم به سادگی تشخیص دهیم که یک تابع در شی صدا زده شده است مگر اینکه از ابتدا شروع کنیم. در حالی که در FP خود شی اکنون یک شی با نام جدید است، که فهمیدن اینکه چه چیزی تغییر کرده را به طور قابل توجهی ساده میکند.

این مثال و توضیحاتش از این لینک گرفته شده:

https://www.codenewbie.org/blogs/object-oriented-programming-vs-functional-programming

بنابرین بحث در مورد چیست؟

به طور واضح، آنهایی که در تیم های OOP فعالیت دارند، میگویند که رویکرد بهتری برای ایجاد برنامه هاست، در حالی که افراد در تیم های FP میگویند که FP بهتر است. خب؟  تیم OOP بحث میکند که مفاهیم وراثت و کپسوله کردن مدیریت و دستکاری داده ها را راحت تر میکند. و تیم FP میگوید که جداسازی داده ها از method ها، سبب میشود که بالا بودن سطح انتزاعات، خطاهای کمتری ایجاد کند.

به نظر میرسد توافق عمومی اینست که بهتر بودن OOP و FP بستگی به شرایط دارد، بنابرین ما قرار نیست مطلبی راجع به پایان این بحث بشنویم.

*لطفا در نظر بگیرید که این مطلب خلاصه ای از این بحث بود و ممکن است برخی جزئیات در آن نیامده باشد. بنابرین برای داشتن دید عمیق تر، stack overflow و دیگر وبسایت های کدنویسی را مشاهده کنید.

منابع:
https://www.innoq.com/en/blog/fp-vs-oo/

https://www.codenewbie.org/blogs/object-oriented-programming-vs-functional-programming

http://www.eecs.ucf.edu/~leavens/ComS541Fall97/hw-pages/paradigms/major.html

https://medium.com/javascript-scene/master-the-javascript-interview-what-is-a-pure-function-d1c076bec976

منبع ترجمه:
https://medium.com/@sho.miyata.1/the-object-oriented-programming-vs-functional-programming-debate-in-a-beginner-friendly-nutshell-24fb6f8625cc

2 دیدگاه

  1. narges گفت:

    عالی بود. ممنون

  2. سینا گفت:

    خیلی عالی بود در منابع انگلیسی هم با چنین جزییاتی پیدا نکردم ممنون از شما

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *