مبادئ تصميم البرمجيات كائنية التوجيه OOD

م

السلام عليكم

يوجد عدة مبادئ لتصميم البرمجيات بالطريقة كائنية التوجيه Object Oriented Desing هذه المبادئ تجعل من البرمجيات التي نقوم بكتابتها واضحة اكثر في طريقة عملها وسهلٌ صيانتها وتطويرها بدون إلحاق اي تغيير او ضرر في اساس برامجك.

اول خمس مبادئ مجموعة في كلمة SOLID Principles وقد قام ببدء هذه المبادئ Robert Cecil Martin المعروف باسم Uncle Bob.

كل حرف من كلمة SOLID اختصار لمبدء من المبادئ

   S: Single Responsibility Principle

مبدأ المسؤولية الوحيدة

O: Open-Closed Principle

مبدأ الفتح والاغلاق

L : Liskov Substitution Principle

مبدأ إحلال ليسكوف

I : Interface Segregation Principle

مبدأ فصل الواجهه

D: Dependency Inversion Principle

مبدأ عكس التبعية


– Single Responsibility Principle (SRP)

A class should have only one reason to change.

الـ Class يجب ان يكون له سبب واحد ليتغير.

مانفهمه ان  يكون للبرنامج الخاص بنا Classes للقيام بالوظائف و كل Class جزء من البرنامج له وظيفة معينة متعلقة ببعضها او لها نفس الغرض وقد تكون معتمدة على بعضها  , فاي تعديل في جزء منه قد يؤثر على جزء اخر.

اي يمكننا القول ان لكل Class مسؤولية معينة يقوم بها لا يمكنها ان تتفرع لاجزاء اخرى لا علاقة لها بها.

كمثال بسيط لو ان لدينا class يدعى StudentOperations لابد ان يحتوي على عمليات تتعلق بال Student مثل الاضافة Add  او الحذف Remove والعمليات المتعلقة 

ليس من المنطقي ان اضيف في ال Class دالة تحسب محيط الدائرة او الراتب الاجمالي للموظف , كلها اشياء ليست متعلقة به وتنافي مبدأ SRP

– Open-Closed Principle (OCP)

يعني ان الـclass او الـmethods بداخله يجب ان تكون مغلقة للتعديل مفتوحة للتوسع 

بمعنى اخر يجب ان تكون المحتويات مفتوحة للتوسعة واضافة اجزاء جديدة بشرط عدم المساس بالجزء الاساس , بحيث انه لو استخدمنا هذه الMethods سابقا لن تؤثر على طريقة عملها او على كيفية استخدامنا لها.

سيفيدنا هذه في انه عندما نشرع في كتابة اكواد برمجة نضع في اعتبارنا ان تكون هذه مرنة وقابلة للتوسع مستقبلاً وليست مجرد حالات او اشياء جامدة 

– Liskov Substitution Principle (LSP)

لا تدع الاسم الغريب يزعجك وتظنه انه شئ معقد وصعب  فكرته واضحة جداً  وهي ان الclassesالتي تستخدمها في برامجك يمكن ان تستبدل ب classes اخرى وارثة من نفس الclasses الاساسية او ان تكون هناك Interface معينة ورث منها class الذي تستخدمه وعندها يمكن تبديل ال class باخر ورث من نفس ال Interface

باسلوب الاخر ان تكون الاجزاء التي تستخدمها في برنامجك قابلة للاستبدال باجزاء اخرى بدون التاثير على عمل البرنامج.

– Interface Segregation Principle (ISP)

مبدأ فصل الواجهة

نعني بهذا المبدأ اننا لسنا بحاجة كتابة Methods لسنا بحاجة لاستخدامه , بمعنى اوضح اننا نقوم بعمل Interface للاجزاء التي نريدها منفصلة بعضها عن بعض بدلاً من عمل واحدة كبيرة تشمل كل شئ.

مثال: لو ان لدينا Interface سنقوم باستخدامها في Class , هذه الـ Interface ستحتوي على عدة دوال تقوم باسترجاع المستخدمين والتدوينات من قاعدة البيانات 

اسم الInterface IBlog

وليكن  GetSingleUser(int id) , GetAllUsers() , GetSinglePost(int id) , GetAllPosts()

لو افترضنا اننا في حاجة للتدوينات فقط بدون الحاجة للUser او بيانته في حال قمنا بوراثة هذه الInterface سنكون بحاجة الى عمل Implementation لجميع الMethods بداخلها حتى لو سنتركها فارغة

في حالتنا ستبقى GetSingleUser(int id) , GetAllUsers() بدون اكواد بداخلها لاننا لانريدها ولكن مجبرين لان تكون موجودة لاننا ورثنا من الInterface التي تحتويها , هل هذا منطقي او صحيح !

الصحيح هنا ان نقوم بعمل 2 Interfaces منفصلة واحدة تدعى IUserOperations ونقوم فيها باضافة GetSingleUser(int id) , GetAllUsers()

واخرى تدعى IPostOperations ونقوم فيها باضافة GetSinglePost(int id) , GetAllPosts()

وفي حال احتجنا الى واحدة منهم نقوم بوراثتها منفصلة او نرث كليهما , لانه مدعوم وراثة عدة Interfaces بعكس الوراثة لل Class يكون واحد فقط.

– Dependency Inversion Principle (DIP)

Abstractions should not depend on the details. Details should depend on the abstractions.

Depend on abstractions, not on concretions.

High-level modules should not depend on low-level modules. Both should depend on abstractions

يعني مبدأ عكس التبعية ان نفصل اجزاء البرنامج الخاصة بناء الى وحدات صغيرة تكون عامة ليست معتمدة على بعضها بشكل كامل بحيث انه في حين اردنا استخدامها نجمع هذه الاجزاء سويا ويمكننا استبدال جزء باخر بدون الاعتمادية وحدوث اخطاء في التطبيق.

يمكننا اعتبار الـHigh-level modules هي ال classes في برنامجنا الخاصة بال Application Logic الخاص بنا 

في حين الـ low-level modules الاجزاء التي تقوم بعمل العمليات الخاصة بالبرنامج مثل جلب البيانات من قاعدة البيانات او كتابة بيانات في ملف مثلاً, تاخذ الصيغة عامة ونقوم باستخدامها من الHigh-level modules للقيام بالوظائف الخاصة بنا.

يجب ان لايكونو معتمدين على بعضهما بشكل كلي بل ان يكونو مرنين للتغيير

بحيث لو غيرنا ال High-level module لايؤدي الى تلف اجزاء البرنامج وتوقف وظائفه 

فمثلا لو التطبيق الخاص يعتمد على استرجاع بيانات او ارسالها لقاعدة بيانات من SQL Server 

عند التغيير لـ MySql سيكون التغيير صعب بعض الشئ وستحتاج لتعديل العديد من الاشياء 

لو قمت بعمله من البداية انه SQL(DataBase) والاختلاف يكون في ال Implementation الداخلي 

ستقوم بتغيير الطريقة وكل شئ سيعمل بدون مشاكل


DRY Code

Don’t Repeat Your Self

لاتكرر ماتفعله اكثر من مرة 

اذا وجدت كود لديك تستخدمه اكثر من مرة قم بتضمينه في Method تستدعيها في كل مرة , هذا سيسهل عليك تعديل وتحسين الكود وتوسيعه بعكس تكراره عدة مرات وفي حال اكتشاف خطأ ستحتاج للبحث عن كل الاماكن وتعديله.

أرجو ان اكون قد افدتكم 

ولمزيد من المعلومات فقط قومو بالبحث في جوجل “Google it ” الموضوع رائع وشيق جداً 😀 .

عن الكاتب

أحمد مجدي

Full Stack Software Developer , Geek

أضف تعليقاً

هذا الموقع يستخدم Akismet للحدّ من التعليقات المزعجة والغير مرغوبة. تعرّف على كيفية معالجة بيانات تعليقك.