مبادئ SOLID في Kotlin: النظرية والتطبيق من الألف إلى الياء

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

مقدمة: لماذا تعتبر مبادئ SOLID مهمة في Kotlin؟



SOLID هو اختصار لخمسة مبادئ أساسية في البرمجة كائنية التوجه، صاغها روبرت مارتن (العم بوب). في بيئة Kotlin، التي تجمع بين أفضل ميزات البرمجة كائنية التوجه والبرمجة الوظيفية، يساعد الالتزام بمبادئ SOLID في إنشاء كود مرن وقابل للاختبار والصيانة. هذه المبادئ ذات أهمية خاصة لتطوير تطبيقات Android، وتطبيقات الخادم باستخدام Ktor، والأنظمة متعددة الخيوط باستخدام coroutines.



في هذه المقالة، سنشرح كل مبدأ من مبادئ SOLID الخمسة مع أمثلة مكيفة مع تعابير Kotlin. ستتعلم كيفية تجنب الأخطاء الشائعة وجعل الكود ليس فقط عملياً، بل عالي الجودة حقاً.



1. مبدأ المسؤولية الواحدة (Single Responsibility Principle - SRP)



جوهر المبدأ

يجب أن يكون للفصل سبب واحد فقط للتغيير. بمعنى آخر، كل فصل مسؤول عن وظيفة واحدة فقط.



مثال سيء (انتهاك SRP)

class UserManager {    fun createUser(name: String, email: String) { /* ... */ }    fun deleteUser(id: Int) { /* ... */ }    fun sendEmail(to: String, subject: String) { /* ... */ }    fun generateReport(userId: Int): String { /* ... */ }}

هنا، UserManager مسؤول عن إدارة المستخدمين، وإرسال البريد الإلكتروني، وإنشاء التقارير. تغيير منطق البريد الإلكتروني سيؤدي إلى تغيير هذا الفصل، على الرغم من أنه لا ينبغي أن يتعلق بالبريد.



مثال جيد (الالتزام بـ SRP)

class UserRepository {    fun createUser(name: String, email: String) { /* ... */ }    fun deleteUser(id: Int) { /* ... */ }}

class EmailService { fun sendEmail(to: String, subject: String) { /* ... */ }}

class ReportGenerator { fun generateReport(userId: Int): String { /* ... */ }}

الآن كل فصل لديه سبب واحد للتغيير. هذا يبسط اختبار الكود وصيانته.



2. مبدأ الفتح/الإغلاق (Open-Closed Principle - OCP)



جوهر المبدأ

يجب أن تكون الكيانات البرمجية (الفصول، الوحدات، الدوال) مفتوحة للتمديد ولكن مغلقة للتعديل. هذا يعني أن السلوك الجديد يُضاف من خلال الوراثة أو التركيب، وليس من خلال تغيير الكود الموجود.



مثال سيء (انتهاك OCP)

class PaymentProcessor {    fun process(paymentType: String) {        when (paymentType) {            "credit_card" -> // معالجة بطاقة الائتمان            "paypal" -> // معالجة PayPal            else -> throw IllegalArgumentException()        }    }}

عند إضافة طريقة دفع جديدة (مثل Apple Pay)، سيتعين تعديل PaymentProcessor، مما ينتهك OCP.



مثال جيد (الالتزام بـ OCP)

interface PaymentMethod {    fun process(amount: Double)}

class CreditCardPayment : PaymentMethod { override fun process(amount: Double) { /* ... */ }}

class PayPalPayment : PaymentMethod { override fun process(amount: Double) { /* ... */ }}

class PaymentProcessor(private val method: PaymentMethod) { fun processPayment(amount: Double) { method.process(amount) }}

الآن لإضافة طريقة دفع جديدة، يكفي إنشاء فصل يقوم بتطبيق PaymentMethod، دون لمس الكود الموجود.



3. مبدأ استبدال ليسكوف (Liskov Substitution Principle - LSP)



جوهر المبدأ

يجب أن تكون الكائنات في البرنامج قابلة للاستبدال بنماذج من أنواعها الفرعية دون التأثير على صحة البرنامج. ببساطة، إذا كان لديك فصل Bird وفصل فرعي Penguin، فإن الكود الذي يعمل مع Bird يجب ألا يتعطل عند استبداله بـ Penguin.



مثال سيء (انتهاك LSP)

open class Rectangle {    open var width: Int = 0                

المدونات

توصيات الكتب