السلام عليكم
يوجد عدة مبادئ لتصميم البرمجيات بالطريقة كائنية التوجيه 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 ” الموضوع رائع وشيق جداً 😀 .