مبادئ SOLID في Rust: النظرية والتطبيق للمطورين

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

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

ابدأ الدورة

مقدمة: مبادئ SOLID في Rust — لماذا نحتاج إليها؟

SOLID — هي خمسة مبادئ أساسية في البرمجة كائنية التوجه تساعد في إنشاء كود مرن وقابل للصيانة والتوسع. على الرغم من أن Rust ليست لغة OOP كلاسيكية (لا تحتوي على وراثة الفئات بالشكل المألوف)، إلا أن نظام الملكية (ownership) والـ traits والـ generics الخاص بها يسمح بتطبيق جميع مبادئ SOLID بشكل رائع. فهم هذه المبادئ في سياق Rust يساعد في كتابة كود يسهل اختباره وإعادة هيكلته وتوسيعه.

في هذه المقالة، سنشرح كل مبدأ من مبادئ SOLID الخمسة بأمثلة عملية في Rust. سترى كيف يستبدل trait الواجهات (interfaces)، وكيف يساعد Box<dyn Trait> في عكس التبعيات (dependency inversion)، وكيف تتجنب الأخطاء الشائعة.



1. مبدأ المسؤولية الواحدة (SRP) في Rust

Single Responsibility Principle (SRP): يجب أن يكون لكل وحدة (module) أو هيكل (struct) أو دالة سبب واحد فقط للتغيير. في Rust، هذا يعني أن الهيكل يجب أن يكون مسؤولاً عن كيان واحد، وألا يخلط بين منطق الأعمال ومعالجة البيانات والإخراج.



مثال على انتهاك SRP

struct User {    name: String,    email: String,}

impl User { // خلط منطق الأعمال مع الحفظ fn save_to_db(&self) { println!("حفظ {} في قاعدة البيانات", self.name); } fn send_email(&self, message: &str) { println!("إرسال بريد إلكتروني إلى {}: {}", self.email, message); }}

هنا، الهيكل User مسؤول عن بيانات المستخدم وعن الحفظ وعن إرسال الرسائل الإلكترونية. هذا انتهاك لمبدأ SRP.



التنفيذ الصحيح لمبدأ SRP

struct User {    name: String,    email: String,}

struct UserRepository;impl UserRepository { fn save(&self, user: &User) { println!("حفظ {} في قاعدة البيانات", user.name); }}

struct EmailService;impl EmailService { fn send(&self, user: &User, message: &str) { println!("إرسال بريد إلكتروني إلى {}: {}", user.email, message); }}

الآن كل هيكل لديه مسؤولية واحدة: User — البيانات، UserRepository — التخزين، EmailService — الإرسال. أصبح الكود أكثر نمطية (modular) وقابلية للاختبار.



2. مبدأ الانفتاح/الانغلاق (OCP) من خلال الـ traits

Open/Closed Principle (OCP): يجب أن تكون الكيانات البرمجية مفتوحة للتمديد (extension) ولكن مغلقة للتعديل (modification). في Rust، يتم تحقيق ذلك بشكل مثالي باستخدام trait والإرسال الديناميكي (dynamic dispatch).



مثال بدون OCP

fn calculate_area(shape: &str, params: &[f64]) -> f64 {    match shape {        "circle" => std::f64::consts::PI * params[0] * params[0],        "rectangle" => params[0] * params[1],        _ => panic!("شكل غير معروف"),    }}

عند إضافة شكل جديد (مثل المثلث)، سيتعين تعديل الدالة.



النهج الصحيح مع OCP

trait Shape {    fn area(&self) -> f64;}

struct Circle { radius: f64 }impl Shape for Circle { fn area(&self) -> f64 { std::f64::consts::PI * self.radius * self.radius }}

struct Rectangle { width: f64, height: f64 }impl Shape for Rectangle { fn area(&self) -> f64 { self.width * self.height }}

// الدالة مغلقة للتعديل ولكن مفتوحة للتمديدfn print_area(shape: &dyn Shape) { println!("المساحة: {}", shape.area());}

الآن، لإضافة مثلث، يكفي إنشاء هيكل جديد وتنفيذ trait Shape. الدالة print_area لا تحتاج إلى تغيير.



3. مبدأ استبدال ليسكوف (LSP) والوراثة عبر الـ traits

Liskov Substitution Principle (LSP): يجب أن تكون الكائنات في البرنامج قابلة للاستبدال بنسخ من الأنواع الفرعية (subtypes) دون التأثير على صحة البرنامج. في Rust، يتحقق ذلك من خلال الـ traits والأنواع العامة (generics).



مثال على انتهاك LSP

trait Bird {    fn fly(&self);}

struct Sparrow;impl Bird for Sparrow { fn fly(&self) { println!("العصفور يطير"); }}

struct Penguin;impl Bird for Penguin { fn fly(&self) { panic!("البطريق لا يستطيع الطيران!"); }}

هنا، Penguin ينتهك مبدأ LSP لأنه لا يمكن استبداله بـ Bird دون التسبب في خطأ.



الحل الصحيح

trait Bird {    fn move_around(&self);}

struct Sparrow;impl Bird for Sparrow { fn move_around(&self) { println!("العصفور يطير"); }}

struct Penguin;impl Bird for Penguin { fn move_around(&self) { println!("البطريق يسبح"); }}

fn make_bird_move(bird: &dyn Bird) { bird.move_around();}

الآن، كل الأنواع تتبع العقد (contract) المحدد بواسطة trait Bird ويمكن استبدالها بأمان.

المدونات

توصيات الكتب