كود نظيف في Rust: المبادئ والأمثلة للمبتدئين
\nRust هي لغة برمجة نظامية قوية، تشتهر بأدائها وأمان الذاكرة. ومع ذلك، كما هو الحال في أي لغة أخرى، فإن كتابة كود نظيف (Clean Code) هي مهارة بالغة الأهمية. الكود النظيف أسهل في القراءة والصيانة والتوسيع. بالنسبة للمطورين المبتدئين في Rust، فإن إتقان مبادئ الكود النظيف منذ البداية سيساعد في تجنب الأخطاء النموذجية وجعل كودك أنيقاً وموثوقاً. في هذه المقالة، سنستعرض المبادئ الأساسية للكود النظيف في Rust مع أمثلة محددة.
\n\n1. تسمية المتغيرات والدوال
\nيجب أن يشرح الاسم الجيد نية المبرمج. في Rust، من المعتاد استخدام snake_case للمتغيرات والدوال والوحدات النمطية، و CamelCase للأنواع والـ traits.
\n\nمثال سيء:
\nfn c(a: i32, b: i32) -> i32 {\n let x = a + b;\n x\n}\n\nمثال جيد:
\nfn calculate_sum(first_number: i32, second_number: i32) -> i32 {\n let result = first_number + second_number;\n result\n}\nاستخدم أسماء ذات معنى: user_name بدلاً من un، process_data بدلاً من pd. تجنب الاختصارات ما لم تكن شائعة (مثل idx للفهرس).
2. دوال صغيرة ومسؤولية واحدة
\nينص مبدأ المسؤولية الواحدة (Single Responsibility Principle) على أن كل دالة يجب أن تفعل شيئاً واحداً فقط. إذا كانت الدالة تؤدي عدة إجراءات، يصبح من الصعب اختبارها وتعديلها.
\n\nمثال سيء (الدالة تفعل الكثير):
\nfn process_user(user_id: u32) {\n // الحصول على المستخدم من قاعدة البيانات\n // التحقق من صحة البيانات\n // إرسال البريد الإلكتروني\n // تسجيل السجلات\n println!("Processing user {}", user_id);\n}\n\nمثال جيد (تقسيم إلى دوال صغيرة):
\nfn get_user(user_id: u32) -> User {\n // منطق الحصول على المستخدم\n User { id: user_id }\n}\n\nfn validate_user(user: &User) -> bool {\n // منطق التحقق من الصحة\n user.id > 0\n}\n\nfn send_email(user: &User) {\n // منطق إرسال البريد الإلكتروني\n println!("Email sent to user {}", user.id);\n}\n\nfn process_user(user_id: u32) {\n let user = get_user(user_id);\n if validate_user(&user) {\n send_email(&user);\n }\n}\nحاول أن تكون الدالة في حدود 10-20 سطراً. إذا كانت أطول، فقم بتقسيمها.
\n\n3. التعامل مع الأخطاء: استخدم Result و Option
\nيشجع Rust على معالجة الأخطاء بشكل صريح من خلال أنواع Result<T, E> و Option<T>. تجنب استخدام .unwrap() أو .expect() في كود الإنتاج - فهذا يؤدي إلى تعطل البرنامج عند حدوث خطأ.
مثال سيء (استخراج خطير):
\nfn read_file(path: &str) -> String {\n let content = std::fs::read_to_string(path).unwrap(); // قد يتعطل!\n content\n}\n\nمثال جيد (معالجة الخطأ):
\nuse std::fs;\n\nfn read_file(path: &str) -> Result<String, std::io::Error> {\n let content = fs::read_to_string(path)?; // عامل ? لتمرير الخطأ\n Ok(content)\n}\n\nfn main() {\n match read_file("data.txt") {\n Ok(data) => println!("File content: {}", data),\n Err(e) => eprintln!("Error reading file: {}", e),\n }\n}\nاستخدم عامل ? للاختصار، ولكن تعامل دائماً مع الأخطاء على المستوى الأعلى. للأخطاء الخاصة بك، قم بإنشاء تعدادات مع trait std::error::Error.
4. التعليقات والتوثيق
\nيجب أن يكون الكود النظيف موثقاً ذاتياً. التعليقات تشرح لماذا، وليس ماذا. لتوثيق الـ APIs العامة، استخدم /// (تعليقات التوثيق).
مثال سيء (تعليق عديم الفائدة):
\n// زيادة العداد بمقدار 1\ncounter += 1;