Quick Overview of SOLID Principles

في هندسة البرمجيات، تعد الـSOLID واحدة من أكثر مجموعات مبادئ التصميم شيوعًا في تطوير برامج الـObject-Oriented Programming، قام بتقديم Robert C. Martin مبادئ SOLID في ورقته البحثية عام 2000 بعنوان  “Design Principles and Design Patterns.
Quick Overview of SOLID Principles
Quick Overview of SOLID Principles

في هذه الصفحة

ما هى الـSOLID وكيف تساعدنا في كتابه كود أفضل؟، هذا ما سنتعرف عليه سويًا في هذا المقال.. 

في هندسة البرمجيات، تعد الـSOLID واحدة من أكثر مجموعات مبادئ التصميم شيوعًا في تطوير برامج الـObject-Oriented Programming، قام بتقديم Robert C. Martin مبادئ SOLID في ورقته البحثية عام 2000 بعنوان  “Design Principles and Design Patterns.”، وتم بناء هذه المفاهيم لاحقًا بواسطة Michael Feathers، الذي قدّمنا ​​إلى اختصار SOLID.

وفي آخر 21 عامًا، أحدثت هذه المبادئ الخمسة ثورة في عالم الـObject-Oriented Programming، غيرت الطريقة التي نكتب بها البرامج، وتؤسس هذه المبادئ الممارسات التي تعمل على تطوير البرامج مع مراعاة اعتبارات Maintaining و Adopting و Extending عندما يكبر المشروع ويمكن أن تساهم هذه الممارسات أيضًا في تجنب الـCode Smell والـRefactoring. في هذا المقال، ستتعرف على كل مبدأ على حدة؛ لفهم كيف يمكن أن يساعدك SOLID في جعلك مبرمج أفضل.

Single Responsibility

مبدأ الـ Single-Responsibility

ينص مبدأ المسؤولية الفردية (SRP) على ما يلي:

يجب أن يكون للـclass سبب واحد فقط للتغيير، مما يعني أن الـclass يجب أن يكون له وظيفة واحدة فقط، وإذا كان الـclass له مسؤوليات عديدة، فإنه يزيد من احتمالية وجود أخطاء لأن إجراء تغييرات على إحدى مسؤولياته، قد يؤثر على المسؤوليات الأخرى دون علمك.

دعونا نرى بعضًا من فوائده:

  1.  Testing: الـclass الذى له مسؤولية واحدة سيكون  له test cases أقل. 
  2. Lower coupling: وظيفة واحدة لكل class هتقلل الاعتمادية -dependencies- عليه. 
  3. Organization: كود أقل؛ لذلك هيكون منظم وسهل التعلم والوصول إلى أجزائه المختلفة. 

الهدف

يهدف هذا المبدأ إلى فصل الـbehaviors بحيث إذا ظهرت أخطاء نتيجة للتغيير الذي أجريته، فلن تؤثر على الـbehaviors الأخرى التي ليس لها صلة أو علاقة به.

Open-Closed Principles

مبدأ الـ Open-Closed

ينص مبدأ Open-Closed (OCP) على ما يلي:

يجب أن تكون الـObjects أو الـEntities مفتوحة للإضافة ولكن مغلقة للتعديل.

هذا يعني أنه يجب أن يكون الـclass قابل للإضافة دون تعديله نفسه أو التغيير فيه، والذي سيؤثر تغيير الـbehavior الحالي على جميع الـsystems التي تستخدم هذه الـclass. فإذا ما كنت تريد أن يقوم class بأداء المزيد من الوظائف، فإن الأسلوب المثالي هو الإضافة إلى الوظائف الموجودة بالفعل وليس تغييرها.

الهدف

يهدف هذا المبدأ إلى توسيع الـClass behavior دون تغيير behavior الحالي لتلك الـclass؛ لتجنب التسبب في حدوث أخطاء أينما يتم استخدام الـClass.

Liskov Substitution

مبدأ الـ Liskov Substitution

ينص مبدأ استبدال Liskov على ما يلي:

إذا كان S نوعًا فرعيًا من T، فيمكن استبدال objects من النوع T في برنامج OOP من النوع S دون تغيير أي من الخصائص المرغوبة لهذا البرنامج.

هذا يعني أن كل subclass or derived class يجب أن تكون قابلة للاستبدال من base or parent class. فعندما يتعذر على child class أداء نفس الإجراءات التي تقوم بها parent class، قد يتسبب ذلك في حدوث أخطاء.

إذا كان لديك class وأنشأت class آخر منه، فإنه يصبح parent ويصبح class الجديد child. يجب أن يكون child class قادرًا على القيام بكل ما يمكن parent class القيام به. هذه العملية تسمى الوراثة -Inheritance-، كذلك يجب أن تكون قادرة على معالجة نفس الطلبات وتقديم نفس النتيجة مثل parent class. 

فعلى سبيل مثال لو الـparent class مكينة قهوة (يمكن أن يكوّن أي نوع من القهوة). من المقبول أن يقوم الـchild class بتوصيل الكابتشينو؛ لأنه نوع معين من القهوة، ولكن ليس من المعقول أن يقوم بتوصيل الماء.

إذا كان الـchild class لا يفي بهذه المتطلبات، فهذا يعني أنه تم تغيير الـchild class تمامًا وأنه لا يطابق المبدأ: لأنه إذا كانت class A نوعًا فرعيًا من class B، فيجب أن نكون قادرين على استبدال B بـ A دون الإخلال بسلوك برنامجنا.

الهدف

يهدف هذا المبدأ إلى فرض الـConsistency بحيث يمكن استخدام الـparent class أو الـchild class بنفس الطريقة دون أي أخطاء.

Interface Segregation

مبدأ الـ Interface Segregation

تم تحديد مبدأ فصل الواجهة من قبل Robert C. Martin أثناء استشارته لشركة Xerox لمساعدتهم في بناء البرنامج لأنظمة الطابعة الجديدة الخاصة بهم، حيث قام بتعريفها على أنها: لا ينبغي أبدًا إجبار العميل على تنفيذ interface لا يستخدمها، أو لا يجب إجبار العملاء على الاعتماد على methods لا يستخدمونها.

فعندما يُطلب من class تنفيذ actions غير مفيدة، فإن ذلك يعد إهدارًا وقد ينتج عنه أخطاء غير متوقعة إذا لم يكن لدى الـclass القدرة على تنفيذ تلك الـactions، لذلك يجب أن يؤدي الـclass فقط الـactions اللازمة لأداء دوره وأى action آخر يجب إزالته تمامًا أو نقله إلى مكان آخر إذا كان من الممكن استخدامه بواسطة class أخرى في المستقبل.

الهدف

يهدف هذا المبدأ إلى تقسيم مجموعة من الـactions إلى مجموعات أصغر بحيث ينفذ الـclass فقط مجموعة الـactions المطلوبة منه ولا يحتوي على أي زيادات.

Dependency Inversion

مبدأ الـ Dependency Inversion

ينص مبدأ انعكاس التبعية على ما يلي:

تنص على أن الـHigh-level module يجب ألا تعتمد على الـLow-level module بشكل مباشر، ولكن يجب أن يعتمدوا على Abstractions. ويجب ألا تحتوى الـabstractions على details، بل يجب أن تعتمد الـdetails على الـabstractions.

يسمح هذا المبدأ بالفصل (decoupling) 

High-level Module or Class: هى class تقوم بتنفيذ action معين باستخدام أداة.

Low-level Module or Class: الأداة المطلوبة لتنفيذ action. 

Abstraction: عبارة عن interface تربط بين النوعين من الـclass.

Details: وهي كيف تعمل الأداة. 

ينص هذا المبدأ على أنه لا ينبغي للـclass استخدام الأداة التي يستخدمها لتنفيذ action ما بشكل مباشر،  

بدلاً من ذلك، يجب استخدام interface والتي تسمح للـclass استخدام تلك الأداة من خلالها. تنص أيضًا على أن كلا من الـClass interface يجب ألا يعرفوا كيفية عمل الأداة، ومع ذلك يجب أن تفي الأداة بمواصفات الـinterface. بتطبيق ذلك المبدأ تغيير الأداة لا يؤثر على الـclass لأنه يعتمد على الـinterface وليس الأداة.

الهدف

يهدف هذا المبدأ إلى تقليل تبعية الـHigh-level Module على الـLow-level Module  من خلال إستخدام Interface.

اشترك الآن بنشرة اقرأ-تِك الأسبوعية

لا تدع أي شيء يفوتك. واحصل على أحدث المقالات المميزة مباشرة إلى بريدك الإلكتروني وبشكل مجاني!