مدوّنة L-One Systems
كيفية تصميم البرامج، التي يسهل التحكم بها
مبادئ SOLID لتصميمٍ جيدٍ للبرمجيات
تخضع الحلول الرقمية للعديد من التغييرات خلال دورة حياتها. لتسهيل هذه التغييرات، يجب على المطورين اتباع المبادئ الخمسة SOLID لتصميمٍ جيدٍ للبرمجيات.
بقلم رنا الحنيس وحمزة رباح، مطورين في L-One
يتطور المنتج البرمجي الناجح باستمرار. يتم تحسينه وإضافة وظائف جديدة وواجهات إضافية، وأكثر من ذلك. ومع ذلك، إذا لم يتم إعداد البرمجيات بحرص منذ البداية، فإن تنفيذ هذه التغييرات يصبح أكثر صعوبة مع مرور الوقت.
لتجنب هذه المشكلة، ينبغي اتباع المبادئ الخمسة SOLID لتصميمٍ جيدٍ للبرمجيات، التي قدمها المطور الأمريكي، المستشار في تقنيات المعلومات، والكاتب روبرت سي. مارتن في عام 2000.
استناداً إلى هذه المبادئ، يتم إنشاء برمجيات توفر المزايا التالية:
- سهولة الصيانة والاختبار
- سهولة التوسع وإعادة الاستخدام
- سهولة الفهم
القائمة المرجعية
أهمية مبادئ SOLID
"تُعتبر أنظمة البرمجيات جيدة عندما تبدأ بالشفرة الرقمية الواضحة. لأنه من جهة، إذا لم تكن الطوب مصنوعة بإتقان، فإن هيكل المبنى لن يكون ذي قيمة كبيرة.
من جهة أخرى، يمكنك أن تخلق فوضى كبيرة حتى مع الطوب المصنوع بإتقان. وهنا يأتي دور مبادئ SOLID."
روبرت سي. مارتن
الاختصار SOLID يمثل:
- S - مبدأ المسؤولية الفردية (Single Responsibility Principle)
- O - مبدأ الفتح-الإغلاق (Open-Closed Principle)
- L - مبدأ استبدال ليسكوف (Liskov Substitution Principle)
- I - مبدأ فصل الواجهات (Interface Segregation Principle)
- D - مبدأ عكس الاعتمادية (Dependency Inversion Principle)
سنقدم كل مبدأ على حدا لإظهار كيف يمكن لمبادئ SOLID أن تساعد في تطوير برمجيات أفضل ذات توسّع أسهل.
فهرس
› وظائف: هي وحدات مستقلة من الشفرة الرقمية تهدف إلى أداء مهمة محددة. عادةً، تتضمن هذه المهمة استقبال ومعالجة البيانات وإرجاع النتيجة.
› بنية البيانات: هي صيغ لاسترجاع وتنظيم ومعالجة وتخزين البيانات. تنظم المعلومات لغرض معين وتتيح للمستخدمين الوصول إلى المعلومات والتعامل معها بسهولة.
مبادئ SOLID تحدد كيفية تنظيم الوظائف وهياكل البيانات ضمن فئات وكيفية ربط هذه الفئات. استخدام كلمة "فئة" لا يعني أن هذه المبادئ تُطبق فقط في البرمجة الشيئية (Object-Oriented Programming). في هذه الحالة، تصف كلمة "فئة" مجموعة معينة أو مجموعة من الوظائف والبيانات. يجب تطبيق المبادئ الخمسة على هذه المجموعات.
"SOLI" مبادئ
1. مبدأ المسؤولية الفردية (SRP)
يعرّف روبرت سي. مارتن المبدأ الأول كما يلي:
"لا ينبغي أن يكون هناك أكثر من سبب لتعديل الفئة."
ومع ذلك، عادةً ما يُوصَف هذا المبدأ بطرق متعددة. تشمل الصيغ الأخرى:
"يجب أن يكون للوحدة مسؤولية واحدة فقط، ولا شيء سوى ذلك."
"اجمع الأشياء التي تتغير لأسباب متشابهة. وفرّق بين الأشياء التي تتغير لأسباب مختلفة."
يعمل مطوروا أنظمة L-One باستمرار على تحسين مهاراتهم في تصميم البرمجيات، مثل تطبيق مبادئ SOLID. يخصصون 10% من وقت عملهم للتعليم المستمر.
يشرح روبرت سي. مارتن قائلاً: "من بين جميع مبادئ SOLID، يُعتبر مبدأ المسؤولية الفردية (SRP) ربما الأقل فهماً. ربما يكون ذلك لأن التسمية SRP غير مناسبة على الخصوص. يحدث عادةً أن يسمع المطورون الاسم ثم يفترضون أنه يعني أن كل فئة يجب أن تقوم بشيء واحد فقط."
للأسف، هذه فكرة خاطئة. ومع ذلك، هذا صحيح بالنسبة للوظائف: حيث يجب أن تقوم الوظيفة بشيء واحد، وشيء واحد فقط لا غير.
خدمات
«المسؤوليات» هي المحور الأساسي للتغيير
يعرّف مارتن «المسؤولية» على أنها سبب للتغيير ويخلص إلى أنه يجب أن يكون لدى الفئة/الوحدة سبب واحد فقط للتغيير. إذا كان من الممكن العثور على أكثر من سبب لتغيير الفئة، فلا بد أن هذه الفئة لديها أكثر من مسؤولية. يصعب رؤية هذا أحياناً لأننا معتادون على التفكير في المسؤوليات في مجموعات.
ما هي المشكلة إذا كان للفئة/الوحدة أكثر من مسؤولية واحدة ؟ لماذا من المهم تقسيم هذه المسؤوليات إلى فئات/وحدات متعددة ؟
والسبب هو أن كل مسؤولية تعمل كمحور أساسي للتغيير. لذلك عندما تتغير متطلبات البرامج (وستتغير)، تنعكس هذه التغييرات في المسؤوليات. إذا كانت هذه المسؤوليات تنطبق على فئات/وحدات متعددة، فإن الأخيرة لديها أكثر من سبب للتغيير.
نتيجة لذلك، سيتطلب تنفيذ التغييرات الكثير من الجهد.
مثال
من أين تأتي أهمية مبدأ المسؤولية الفردية ؟
وتوضّح الحالة التالية المشاكل التي تحدث عندما لا يتبع المطورون مبدأ المسؤولية الواحدة.
تخيل أن لدينا فئة «شخص» منظمة كما هو موضح في الشكل أدناه:
ينتهك هذا التصميم أول مبادئ SOLID، مبدأ المسؤولية الفردية (SRP)
ويبين الشكل أن فئة الأشخاص لها مسؤوليتان. الأول هو إبلاغ الموارد البشرية بساعات، والثاني يوفر وظائف كشوف المرتبات للمحاسبة. تستخدم كلتا الوظيفتين طريقة الساعات العادية، والتي تعيد ساعات العمل العادية للموظفين، بما في ذلك أوقات الاستراحة.
من خلال دمج الشفرة الرقمية المصدرية لهاتين المسؤوليتين في فئة «شخص» واحدة، قام المطورون بربط الفاعلين، الموارد البشرية والمحاسبة.
كيف يمكن أن يؤثر ذلك سلباً ؟
تخيل أن يطلب قسم الموارد البشرية من المطور تغيير الساعات العادية حتى لا تتضمن وقت الاستراحة. ثم يقوم المطور بتغيير طريقة الساعات العادية لاستبعاد وقت الاستراحة.
غير أن ذلك سيؤثر على وظيفة نظام كشف المرتبات. هذا لأن المحاسبة لا تزال تفترض أن طريقة الساعات العادية تعيد الوقت بما في ذلك وقت الاستراحة. تستند حسابات القسم إلى هذا الافتراض.
إذا نسي المطور التحقق من الطرق الأخرى التي تستخدم طريقة الساعات العادية، فسيؤدي ذلك إلى بيانات محاسبية غير صحيحة دون أن يلاحظ أحد.
يمنع الاقتران إعادة استخدام الوظائف داخل فئة الشخص.
أيضاً، يمكن أن يتسبب في تأثير تصرفات الموارد البشرية على شيء تعتمد عليه المحاسبة والعكس صحيح. بعبارة أخرى، هناك أكثر من سبب لتغيير الشخص.
اجعل الحلول الرقمية قابلة للتطوير بسهولة.
ويعد مبدأ المسؤولية الواحدة هو أحد أبسط المبادئ، ولكنه أيضاً من أصعب المبادئ في التنفيذ. غالباً ما نربط المسؤوليات تلقائياً. حيث أن العثور على هذه المسؤوليات وفصلها، هو جزء أساسي من تصميم البرامج.
إذا كان لدى دالة أو وحدة أو فئة سبب واحد فقط للتغيير، فهذا يعني أنها تتوافق مع مبدأ المسؤولية الفردية. هذا يجعل من السهل تنفيذ التغييرات ومقاييس الحل الرقمي بسهولة.
تداعيات
2. مبدأ الفتح-الإغلاق (OCP)
يعرّف روبرت سي. مارتن المبدأ الثاني على النحو التالي:
«يجب أن تكون كيانات البرمجيات (الفئات والوحدات والوظائف وما إلى ذلك) مفتوحة للتوسيع ولكنها مغلقة أمام التغيير».
روبرت سي مارتن
إذا أدى تغيير واحد في تطبيق ما إلى سلسلة من التغييرات في الوحدات المعتمدة - بعبارة أخرى، فرض تغييرات هائلة على البرنامج - فإن التصميم ليس مثالياً.
عندما يتم تطبيق مبدأ الفتح-الإغلاق بدقّة، يتم تحقيق التغييرات عن طريق إضافة رمز جديد، وليس عن طريق تغيير الشفرة الرقمية القديمة التي تعمل بالفعل.
زيادة المرونة وإمكانية إعادة الاستخدام والصيانة
والهدف من مبدأ الفتح-الإغلاق هو جعل النظام قابلاً للتوسع دون إجراء تغييرات جذرية.
يؤدي تطبيق هذا المبدأ إلى أكبر المزايا المنسوبة إلى التقنية الموجهة نحو الشيء: المرونة وإمكانية إعادة الاستخدام والصيانة.
تتميز الفئات/الوحدات التي تتوافق مع مبدأ الفتح-الإغلاق بخاصتين أساسيتين:
1) مفتوحة للتوسيع:
يمكن توسيع سلوك الوحدة. أي أنه مع تغير المتطلبات، يمكن توسيع الوحدة لتشمل سلوكيات جديدة لتلبية تلك التغييرات. أي أن المطورين قادرون على تغيير سلوك الوحدة.
2) مغلقة للتغيير:
إن إضافة أو توسيع سلوك هذه الوحدات لا يغير شفرتها الرقمية الأساسية، أي أن الشكل القابل للتنفيذ للوحدات لم يتغير.
استخدم التجريد، ولكن بشكل صحيح
من الواضح أن هاتين السمتين تتعارضان مع بعضهما البعض، لأن الطريقة العادية لتوسيع سلوك الوحدة هي تعديل شفرتها الرقمية الأساسية.
إذاً، السؤال هو: كيف يمكننا تغيير سلوك الوحدة دون تعديل شفرتها الرقمية الأساسية؟
الجواب هو: باستخدام التجريد. من خلال عملية التجريد، يخفي المبرمج جميع البيانات غير ذات الصلة لشيء ما لتقليل التعقيد وزيادة الكفاءة.
هناك بعض أنماط التصميم التي يمكن استخدامها لتطبيق مبدأ الفتح-الإغلاق بطريقة أفضل، على سبيل المثال ما يلي:
ومع ذلك، فإن المطورين مسؤولون عن تطبيق التجريد فقط على أجزاء الحل التي تتغير بتكرار. لا تقل مقاومة التجريد المبكر أهمية عن التجريد نفسه.
تجريد
free consultation
تعلم المزيد