در مصاحبه های شغلی، جواب "آیا با مفاهیم شی گرا آشنایی دارید؟" را چگونه بدهیم؟

در مصاحبه های شغلی، جواب "آیا با مفاهیم شی گرا آشنایی دارید؟" را چگونه بدهیم؟

در بسیاری از مصاحبه هایی که برای موقعیت شغلی توسعه دهنده ی نرم افزار انجام می شود، یکی از اولین سوال هایی که از مصاحبه شونده پرسیده می شود این سوال است که "آیا با مفاهیم شی گرا آشنایی دارید؟!". در این مقاله قصد دارم به این موضوع بپردازم که اگر در چنین موقعیتی قرار گرفتید چه جوابی به مصاحبه کننده بدهید. 

دنیای قبل از برنامه نویسی شی گرا 

پیش از آن که بررسی کنیم که در دنیای برنامه نویسی شی گرا چه اتفاق هایی می افتد، بیایید با هم ببینیم که قبل از برنامه نویسی شی گرا، دنیا چه شکلی بوده است و با آمدن مفهومی به نام برنامه نویسی شی گرا، چه چیز یا چیز هایی تغییر کرده است.

قبل از برنامه نویسی شی گرا، سبک رایج برنامه نویسی، برنامه نویسی رویه ای یا Procedural Programming بود. در این سبک برنامه نویسی، برنامه به مجموعه ای از کارکرد ها یا توابع یا function ها تقسیم بندی می شد و داده های برنامه هم در متغییر ها ذخیره می شد که توابع با این متغیر ها کار می کردند. مثلا شکل زیر را در نظر بگیرید که برنامه به دو بخش توابع (Func1 , Func2) و متغییر ها (X1 , X2) تقسیم بندی شده است:

Program {
        X1 , X2
        Func1 () , Func2 ()
}

این روش برنامه نویسی بسیار ساده می باشد و این همان چیزی است که بسیاری از ما در شروع کار برنامه نویسی مان از آن استفاده کرده ایم. 

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

برنامه نویسی شی گرا به چه معناست؟ 

برنامه نویسی شی گرا یا به اختصار OOP (Object Oriented Programming)، یک شیوه یا سبک برنامه نویسی می باشد که در آن به جای این که به توابع یا کارکرد ها فکر کنیم، باید به شی ها فکر کنیم. تفاوت دیگر این نوع تفکر آن است که در برنامه نویسی شی گرا به جای این که همه ی توابع و داده ها را در یک جا و کنار هم قرار دهیم، گروهی از توابع و متغیر هایی که از نظر مفهومی به هم مربوط می شوند را در یک گروه قرار می دهیم. به این گروه، دسته یا Class گفته می شود. در دنیای برنامه نویسی شی گرا به متغیر ها،‌ خصوصیت یا property و به توابع، متد یا method گفته می شود. پس از تعریف کلاس، باید از آن ها نمونه هایی بسازیم و در برنامه با این نمونه ها کار خواهیم کرد. به نمونه های ساخته شده از یک کلاس شی یا Object گفته می شود. 

برای این که این موضوع برایتان روشن شود دو مفهوم انسان و شخصی به نام احمد را در نظر بگیرید. تمام خصوصیت ها و رفتار هایی که یک انسان می تواند داشته باشد را در کلاسی به نام انسان جمع آوری می کنیم. پس از ساختن کلاس باید از آن نمونه هایی ساخته شود. از کلاس انسان شخص احمد را می سازیم که شی ای از کلاس انسان می باشد و یه این ترتیب همه ی خصوصیات و رفتارهایی که در کلاس انسان تعریف شده است، در شخص احمد هم موجود می باشند. 

به عنوان یک مثال عملی اگر برنامه ای که در بخش قبل دیدید را به روش برنامه نویسی شی گرا باز نویسی کنیم، به شکل زیر در خواهد آمد. همان طور که می بینید، خصوصیت X1 و متد Func1 در یک کلاس و خصوصیت X2 و متد Func2 در یک کلاس دیگر گروه بندی شده اند. سپس از روی دو کلاس Class1 و Class2 دو شی Object1 و Object2 ساخته شده اند.

Program {
                Class1 {
                                X1 ,  // Property
                                Func1 () // Method
                }
                Class2 {
                                X2 ,  // Property
                                Func2 () // Method
                }
} 
Object1 = new Class1
Object2 = new Class2

بیایید موضوع را با یک مثال واقعی روشن تر کنیم. 

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

این شیوه ی برنامه نویسی از اوایل دهه ی 70 میلادی شروع به کار کرد. این سبک از برنامه نویسی با وجود این که سال ها از آن می گذرد، اما کماکان دارای کاربرد های فراوانی می باشد و به صورت گسترده از آن استفاده می شود، چون برنامه نویسی شی گرا یک زبان برنامه نویسی خاص یا یک ابزار خاص نیست که در طول زمان کاربرد خود را از دست بدهد، برنامه نویسی شی گرا یک سبک برنامه نویسی است که در زبان های مختلف قابل استفاده می باشد. 

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

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

اصول برنامه نویسی شی گرا

سوال اصلی در مورد برنامه نویسی شی گرا این است که "آیا با اصول برنامه نویسی شی گرا آشنایی دارید؟".

برنامه نویسی شی گرا از 4 اصل تشکیل شده است: 

1 – Encapsulation یا محصور سازی

2 – Abstraction یا تجرید

3 - Inheritance یا ارث بری

4 – Polymorphism یا چند ریختی

بیایید هر یک از این اصول را با هم بررسی کنیم.

1. Encapsulation یا محصور سازی

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

let baseSalary = 50000 ;
let overTime = 5 ;
let rate = 10 ;
function getWage ( baseSalary , overtime , rate ) {
    return baseSalary + ( overTime * rate ) ;
}

در این جا سه متغیر baseSalary و overtime و rate را داریم و در کنار آن ها تابع getWage را داریم که کار محاسبه دستمزد کارمندان را انجام می دهد. در این سبک برنامه نویسی، متغییر ها در یک طرف تعریف می شوند و توابع در طرفی دیگر و این دو بخش کاملا جدا هستند. این قطعه کد را با استفاده از روش برنامه نویسی شی گرا باز نویسی می کنیم. پس خواهیم داشت : 

let employee = {
    baseSalary : 50000 ,
    overtime : 5 ,
    rate : 10 ,
    getWage : function() {
        return this.baseSalary + ( this.overTime + this.rate ) ;
    }
}

employee.getWage () ;

همان طور که می بینید، یک شی به نام employee داریم که ۳ تا خصوصیت baseSalary و overtime و rate و متد getWage را درون خودش دارد. در این روش برنامه نویسی، خصوصیات و متد ها، در داخل یک شی کپسوله شده و همه داخل یک شی قرار می گیرند چون از نظر مفهومی مرتبط به هم هستند. در روش برنامه نویسی شی گرا، چون خصوصیات و متد ها درون یک شی قرار گرفته اند و با هم در ارتباط هستند، متد getWage هیچ گونه پارامتری نمی گیرد پس استفاده از آن هم آسان تر شده است ولی در روش برنامه نویسی رویه ای چون توابع و متغییر ها از هم جدا شده اند، متد getWage دارای ۳ پارامتر می باشد. از نظر طراحی شی گرا، هر چه تعداد پارامتر های متد ها کمتر باشد، آن متد خوانا تر خواهد بود و نحوه ی استفاده از آن آسان تر می شود. 

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

2. Abstraction یا تجرید

این اصل را با یک مثال دیگر بررسی می کنیم. تلویزیون منزل تان را به عنوان یک شی در نظر بگیرید. درون جعبه تلویزیون که ما آن را نمی بینیم، یک مدار پیچیده وجود دارد که ما کاری با آن نداریم و درگیر این نخواهیم شد که آن چگونه کار می کند. در بیرون از تلویزیون یکسری دکمه تعبیه شده است که ما با آن دکمه ها کار می کنیم و نقطه ی تعامل ما با تلویزیون این دکمه ها هستند. مثلا دکمه تعویض کانال را می زنیم و انتظار داریم کانال تلویزیون عوض شود و نگران آن نیستیم که درون آن مدار پیچیده چه می گذرد و آن چگونه این تعویض کانال را مدیریت می کند. در واقع پیچیدگی درون جعبه تلویزیون و پیچیدگی چگونگی کارکرد تلویزیون از دید شما پنهان شده است. اصل Abstraction یا تجرید به این مورد اشاره دارد یعنی پنهان سازی پیچیدگی از دید استفاده کننده. 

در برنامه نویسی شی گرا می خواهیم این اصل را در طراحی شی ها رعایت کنیم. به این صورت که تا جایی که می توانیم خصوصیات و متد های اضافی را از دید استفاده کننده پنهان کرده تا این خصوصیات و متد ها از بیرون دیده نشوند، چون آن ها جزئیات پیاده سازی (implementation details) شی ها بوده و استفاده کننده نباید آن ها را ببیند. این طراحی دو مزیت اصلی با خود دارد.

1 – به این دلیل که با خصوصیت و متد های کمتری مواجه هستیم، استفاده کردن و فهم این گونه اشیاء بسیار آسان تر از اشیایی است که خصوصیت و متد های بیشتر و پیچیده تری دارند و در نتیجه، رابط کاربری یا interface اشیاء ساده تر خواهد شد و پیچیدگی های استفاده کمتر خواهد شد.

2 – مزیت دیگرش این است که تغییر در درون یک شی، به بیرون از شی درز پیدا نمی کند. اگر در آینده خصوصیت و متد های داخلی شی، که از دید استفاده کننده پنهان شده است را تغییر دادیم، هیچ کدام یک از این تغییرات، تاثیری روی اشیاء بیرون نخواهد داشت، به این دلیل که هیچ یک از اشیاء بیرون این خصوصیت و متد های داخلی را نمی بینند تا بخواهند از آن ها استفاده کند و در صورت تغییر کردن خصوصیت و متد های داخلی، این اشیاء مجبور باشند خودشان را با تغییرات وفق دهند. پس با خیال راحت می توانید بعضی از خصوصیت و متد ها را حذف کنید یا پارامتر های آن ها را تغییر بدهید، بدون این که تاثیر بدی روی دیگر اشیاء داشته باشند. 

در یک جمله اگر بخواهیم این اصل تعریف کنیم باید بگوییم که اصل Abstraction یا تجرید، اصل پنهان سازی جزییات و پیچیدگی ها و نمایان کردن ملزومات است. 

3. Inheritance یا ارث بری

Inheritance یا ارث بری، به عنوان سومین اصل در برنامه نویسی شی گرا، این کمک را به ما می کند تا بتوانیم کد های تکراری را از برنامه حذف کنیم و تا جایی که ممکن است از آن ها فاکتور گرفته شود و از آن ها در جا های مختلف استفاده مجدد یا reuse کنیم. بیایید این اصل را با یک مثال پیش ببریم. در برنامه نویسی رابط کاربری یا UI، با عناصری مانند TextBox، Button، CheckBox و... رو به رو هستیم. همه ی این عناصر دارای خصوصیاتی مانند Enable و Visible هستند و هم چنین متد هایی مانند Click و Focus دارند. مانند شبه کد زیر:

TextBox {
                Visible ,
                Enable ,
                Click () ,
                Focus () ,
}
Button {
                Visible ,
                Enable ,
                Click () ,
                Focus () ,
}
...

طراحی خوب این است که به جای تعریف خصوصیات و متد ها در همه ی عناصر، آن ها را یک بار در یک عنصر عمومی تری مانند Control تعریف کنیم و سایر عناصر این خصوصیات و متد ها را از عنصر Control به ارث ببرند. مانند شبه کد زیر. 

Control {
                Visible ,
                Enable ,
                Click () ,
                Focus () ,
}
TextBox  inherit from Control {
}
Button inherit from Control {
}
... 

با این روش، از تکرار کد های اضافی جلوگیری کرده و قطعه کد های تکراری را در یک جا قرار می دهیم و از آن ها استفاده مجدد (reuse) خواهد شد دقیقا مانند کاری که با Control انجام دادیم.

4. Polymorphism یا چند ریختی

کلمه Polymorphism از دو بخش تشکیل شده است. poly به معنای چند تایی و morphism به معنای شکل. پس polymorphism یعنی چند شکلی. در برنامه نویسی شی گرا، به کمک این اصل می توانیم if... else های طولانی یا switch... case های طولانی را از کد حذف کنیم. اجازه دهید این تکنیک را با مثالی که در بخش قبل بیان کردیم، بررسی کنیم. هر یک از عناصر یک برنامه ی رابط کاربری، باید این توانایی را داشته باشند که روی صفحه رسم شوند. هر یک از این عناصر به گونه ای متفاوت بر روی صفحه رسم می شوند. اگر بخواهیم کدی بنویسیم تا عناصر مختلف را بر روی صفحه رسم کند، تقریبا کدی مشابه زیر را خواهیم داشت. 

Switch (... ) {
                Case ‘ textbox ‘ : renderTextBox () ;
                Case ‘ button ‘ : renderButton () ;
                Case ‘ checkbox ‘ : renderCheckBox () ;
                Case... 
                Case...
                Case...
}

همان طور که می بینید، با چندین شکل و نحوه‌ی رسم شدن عناصری مواجه هستیم که بین آن ها رابطه ای وجود دارد و این رابطه این است که همگی آن ها یک عنصر رابط کاربری یا UI هستند. مشکل switch... case های طولانی را می توان با اصل Polymorphism یا چند ریختی حل کرد به این صورت که اگر متدی مانند render را در Control قرار دهیم و همه ی عناصر از آن ارث بری کنند، پس این متد در همه ی این عناصر وجود خواهد داشت. سپس هر یک از عناصر، متد render را به شیوه ی خاص خودش پیاده سازی خواهد کرد. مثلا TextBox به شیوه ی خودش و Button به شیوه ی خودش. پس می توانیم switch... case های طولانی را با خط کد زیر جایگزین کنیم.

Control.render () ;

در این خط هر بار Control به یکی از عناصر صفحه اشاره می کند و در نتیجه متد render آن عنصر فراخوانی و اجرا می شود و آن عنصر روی صفحه رسم می شود و نیازی نیست نوع هر عنصر را بررسی کنیم و متد render آن عنصر را فراخوانی کنیم. 

اصولی که بیان شد در همه ی زبان های شی گرا مانند سی شارپ و جاوا قابل پیاده سازی هستند. در این جا سعی کردیم وارد نحوه پیاده سازی این اصول توسط یک زبان خاص نشویم. اما اگر علاقمندان به زبان برنامه‌نویسی پی‌اچ‌پی (PHP) با اصول Object Oriented Programming هستید، می توانید به دوره آموزشی OOP در PHP در سکان آکادمی مراجعه کنید.

 امیدوارم با یاد گیری اصول برنامه نویسی شی گرا و جواب صحیح تان به سوال "آیا با مفاهیم شی گرا آشنایی دارید؟!" شانس تان را برای استخدام بالا ببرید.

از بهترین نوشته‌های کاربران سکان آکادمی در سکان پلاس


online-support-icon