روی خط زندگی

گشت و گذار من در هنر نرم افزار

روی خط زندگی

گشت و گذار من در هنر نرم افزار

مفاهیم برنامه نویسی شی گرا یا (Object Oriented Programming (OOP بر محور چهار ایده اصلی بنا شده است. این چهار ایده و مفهوم زیربنایی عبارتند از:

  • انتزاع یا تجرید (Abstraction)
  • چند ریختی (Polymorphism)
  • وراثت (Inheritance)
  • کپسوله سازی (Encapsulation)

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


۰ نظر موافقین ۱ مخالفین ۰ ۰۲ بهمن ۹۳ ، ۲۰:۲۱
حسین گویا

GRASP مخفف General Responsibility Assignment Software Pattern است که همان طور که از نامش پیداست، به مبحث تعیین و توزیع مسئولیت ها بین موجودیت ها می پردازد. مانند اینکه چه کسی وظیفه تولید این اطلاعات را دارد، یا چه کسی مسئولیت نگه داری از اطلاعات را دارد، یا چه کسی باید پیام های ارسالی سیستم را مدیریت کند و مانند آن.


GRASP از نه عدد الگو تشکیل شده است. این نه الگو به ما کمک می کنند تا مسئولیت هر موجودیت در سیستم را تعیین کنیم:

1) Creator

چه کسی مسئول ایجاد یک شی است؟ برای یافتن فردی که این مسئولیت را به وی بدهیم سوالات زیر را می پرسیم:

  • آیا موجودیت این شی، موجودیت شی یا اشیای دیگری را هم ایجاب می کند؟ (همان رابطه Composition در نمودار کلاس ها)
  • آیا کلاسی هست که اطلاعات لازم برای تولید این شی را داشته باشد؟

2) Controller

هیچگاه مستقیما یک عنصر مرتبط با رابط کاربری (UI) را مستقیما به Business Class متصل نکنید (این امر یکی از دلایل افزایش Coupling می باشد). بهتر است یک کلاس Controller در بین آنها قرار دهیم که این دو با واسطه کلاس Controller به هم متصل شوند. الگوی MVC یکی از بهترین نمونه ها برای این مطلب است.


3) Pure Fabrication

اگر دیدید که یک مسئولیت قواره تن هیچ یک از کلاس های موجود نیست، بهتر آن است که یک کلاس جدید بسازیم و مسئولیت را به آن کلاس دهیم، چرا که در صورتی که مسئولیت مورد نظر را به یکی از کلاس های موجود بدهیم، در واقع Cohesion را کاهش داده ایم.


4) Information Expert

مسئولیت را به کسی (کلاسی) بدهیم که اطلاعات لازم برای انجام آن کار را در اختیار دارد.


5) High Cohesion

شاید اگر برای این یکی مثال عکس بزنم راحت تر بتوان توضیح داد، فرض کنید که یک کلاس داریم با تعداد بالایی از Property  ها و Method ها، که این Property ها و Method ها هیچ کاری با هم ندارند و هر کدام برای خودشان کار خود را انجام می دهند. این یعنی Low Cohesion که ناقض اصول طراحی شی گرا، مانند اصل تک مسئولیت ای (Single Responsibility) و God Object Code Smell است.


6) Indirection

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


7) Low Coupling

یعنی ارتباطات بین موجودیت ها را به نحوی کاهش دهیم که کمترین وابستگی را به یکدیگر داشته باشند. این بدان معنی نیست که موجودیت ها نباید هیچ وابستگی به هم داشته باشند، بلکه باید این وابستگی ها را تا حد ممکن کاهش داد.


8) Polymorphism

هر موجودیت، رفتار خودش را با توجه به نوع خود ، به صورت خودکار تعیین و اصلاح کند!


9) Protected Variation

ذات سیستم ها تغییر است. مهم نیست حجم تغییرات چه میزان ست، بلکه مهم آن است که سیستم را در برابر تغییرات ایمن سازی کنیم. اگر اصولی مانند وراثت، یا Open Close Principle (OCP) را رعایت کنیم، می توانیم تغییرات را در سیستم مدیریت کنیم.


۰ نظر موافقین ۱ مخالفین ۰ ۲۸ دی ۹۳ ، ۲۰:۴۳
حسین گویا

Code Smell ها علائم سطحی ای هستند که حاکی از وجود مشکلات عمیق در سیستم می باشند. (مارتین فولر)

این تعریف جناب فولر، بیان عمیق و درستی از مفهوم Code Smell ها ارائه می دهد. وقتی در یک سیستم نشانه هایی از Code Smell ها مشاهده می کنیم می توانیم حدس بزنیم که این سیستم احتمالا در جایی به مشکل خواهد خورد و یا توسعه و پشتیبانی آن دچار اشکال خواهد بود. Code Smell ها نشانه هایی از زلزله ای قریب الوقوع در سیستم می باشند. به برخی از مهمترین Code Smell ها به اختصار اشاره می کنیم:


  • Duplicated code: کد های تکراری در برنامه که ناقض اصل DRY هستند.
  • Long Method: وجود متد های طولانی در سیستم علاوه بر نقض اصول OOP بخصوص اصل تک مسئولیتی (Single Responsibility) ، پیگیری خطاها را مشکل خواهد کرد.
  • Large Class یا God Object: اصل تک مسئولیتی را نقض می کنند و به مانند متد های طولانی رهگیری خطاها را دشوار می سازند. همچنین عموما این کلاس ها سبب ایجاد درهم تنیدگی (Coupling) در سیستم می شوند.

  • Feature envy: استفاده بیش از حد یک کلاس از کلاس دیگر. این مورد شاید توضیح بیشتری لازم داشته باشد. فرض کنید یک کلاس برای مدیریت نمرات دانش آموزان داریم. حال می خواهیم معدل دانش آموزان را حساب کنیم. برای این کار می توانیم تک تک نمرات دانش آموز را از کلاس بگیریم و معدل وی را در خارج از کلاس دانش آموز محاسبه کنیم، اما این یک مشکل بزرگ ایجاد می کند. ما (به عنوان یک کلاس دیگر) بیش از حد به کلاس دانش آموز وابسته شده ایم و با هر تغییری در لیست نمرات کد های کلاس ما نیز دچار مشکل می شود. بهتر آن است که این وظیفه را به خود کلاس دانش آموز بدهیم و در واقع کلاس دانش آموز یک تابع ارائه نماید که معدل دانش آموزان را حاسبه کرده و نتیجه را در اختیار ما قرار می دهد. به بیان دیگر، یک کلاس باید در ارائه خصوصیات به دنیای بیرون خساست به خرج دهد و فقط چیز هایی را به بیرون ارائه دهد که لازم است.

۰ نظر موافقین ۱ مخالفین ۰ ۱۸ دی ۹۳ ، ۲۲:۲۹
حسین گویا

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


S: Single Responsibility Principle 

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

Single Responsibility Principle

O: Open / Close Principle

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

یکی از بهترین مثال ها برای این اصل، وراثت است. فرض کنید یک کلاس رفتاری را ارائه می دهد و چند کلاس دیگر از آن به ارث رفته اند، حال می خواهیم کلاس جدیدی به سیستم اضافه کنیم که آن رفتار را تغییر دهد، این امر به سادگی با ارث بری از کلاس پدر و بازنویسی (Overriding) آن رفتار در کلاس فرزند جدید، محقق می شود، بدون آنکه سایر کلاس ها دچار تغییر شوند.

بهترین قاعده ای که در پیاده سازی این اصل به کار می آید، قاعده چند ریختی پویا یا Dynamic Polymorphism می باشد.یک مثال خوب در این مورد را می توانید در این آدرس ببینید.

Open Closed Principle

 

L: Liskov Substitution Principle

اصل جایگزینی لیسکوف، می گوید یک کلاس که از کلاس دیگری به ارث رفته است، باید بتواند، جایگزین کلاس والد شود. یک مثال کاربردی در این باب به شفاف تر شدن مطلب کمک می کند:

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

 Liskov Subtitution Principle

I: Interface Segregation Principle

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

 Interface Segregation Principle

D: Dependency Inversion Principle

رعایت این اصل بخصوص از در هم تنیدگی (Coupling) سیستم جلوگیری می کند. اصل وابستگی معکوس، بر این مهم تاکید دارد که ماژول های سطح بالا نباید به ماژول های سطح پایین وابستگی داشته باشند، بلکه هر دو این ها باید به یک مفهوم مجازی مانند یک interface وابسته باشند. با بزرگ تر شدن سیستم ها، این اصل امروزه آنچنان مهم شده است که ابزار های زیادی مانند Ninject برای جلوگیری از وابستگی ها و مدیریت و تزریق وابستگی های ضروری از بیرون کلاس ها، ایجاد شده اند

 Dependency Inversion Principle


۰ نظر موافقین ۱ مخالفین ۰ ۲۰ آذر ۹۳ ، ۱۹:۱۹
حسین گویا