كود نظيف في Rust: كتابة أنيقة وفعالة

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

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

ابدأ الدورة

لماذا الكود النظيف في Rust ليس رفاهية بل ضرورة

\n\n

Rust هي لغة تتطلب الانضباط من المطور. المترجم هنا صارم ولكنه عادل: لا يتسامح مع الإهمال في الذاكرة، لكنه يعطي في المقابل سرعة وأمانًا لا يصدقان. ومع ذلك، لتحقيق الإمكانات الحقيقية لـ Rust، لا يكفي مجرد جعل الكود يترجم. بل يجب كتابة كود نظيف — مفهوم، قابل للصيانة، وأنيق.

\n\n

في هذه المقالة، سنشرح كيفية كتابة كود نظيف في Rust بحيث لا يتحول مشروعك إلى متاهة من كتل unsafe والأنواع العامة المعقدة. ستتعرف على مبادئ التسمية، والتعابير الاصطلاحية للتعامل مع الملكية، ومعالجة الأخطاء، وهيكلة الكود. هيا بنا!

\n\n

1. التسمية: تحدث بلغة Rust

\n\n

التسمية الصحيحة هي نصف النجاح. في Rust، هناك اتفاقيات صارمة، وانتهاكها يُعتبر بمثابة إشارة خطر (خاصة في مراجعة الكود).

\n\n

القواعد الأساسية

\n
    \n
  • snake_case للمتغيرات، الدوال، الدوال الأعضاء، والوحدات النمطية.
  • \n
  • PascalCase للأنواع (struct, enum, trait).
  • \n
  • SCREAMING_SNAKE_CASE للثوابت والمتغيرات الثابتة.
  • \n
\n\n

مثال:

\n\n
// سيء\nlet UserName = "Alice";\nfn GetUserData() {}\nconst MAX_SIZE: u32 = 100;\n\n// جيد\nlet user_name = "Alice";\nfn get_user_data() {}\nconst MAX_SIZE: u32 = 100;
\n\n

تجنب الاختصارات (إذا لم تكن واضحة)

\n

بدلاً من calc_avg()، من الأفضل كتابة calculate_average(). بدلاً من tmp، استخدم temp_buffer. Rust تشجع على الوضوح، وليس الإيجاز.

\n\n

نصيحة: إذا كنت تكتب دالة تقبل إغلاقًا (closure)، استخدم الأسماء f أو g أو closure — فهذه ممارسة شائعة.

\n\n

2. الملكية والاقتراض: كن صديقًا للمترجم

\n\n

نظام الملكية هو قلب Rust. الكود النظيف يحترم قواعد ownership و borrowing، دون محاولة تجاوزها عبر clone() أو Rc بدون داعٍ.

\n\n

القاعدة: فضّل الاقتراض على الملكية

\n

إذا كانت الدالة لا تحتاج إلى أخذ الملكية، استقبل مرجعًا &T أو مرجعًا قابلًا للتغيير &mut T.

\n\n
// سيء: clone غير ضروري\nfn process(data: Vec<i32>) {\n    let mut sum = 0;\n    for &val in &data {\n        sum += val;\n    }\n    println!("المجموع: {}", sum);\n}\n\n// جيد: الاقتراض\nfn process(data: &[i32]) {\n    let mut sum = 0;\n    for &val in data {\n        sum += val;\n    }\n    println!("المجموع: {}", sum);\n}
\n\n

تجنب الاستنساخ المفرط

\n

إذا كنت بحاجة إلى تمرير البيانات إلى عدة أماكن، استخدم Rc (للسيناريوهات أحادية الخيط) أو Arc (للسيناريوهات متعددة الخيوط). لكن لا تفرط في استخدامها: في الحالات البسيطة، تكفي المراجع.

\n\n

3. معالجة الأخطاء: تخلّ عن الذعر (panic)

\n\n

في Rust، هناك طريقتان رئيسيتان لمعالجة الأخطاء: panic! (خطأ غير قابل للاسترداد) و Result<T, E> (خطأ قابل للاسترداد). الكود النظيف يستخدم Result أينما أمكن. الذعر هو الملاذ الأخير للحالات الاستثنائية حقًا (مثل القسمة على صفر).

\n\n

استخدم العامل ?

\n

هذه طريقة موجزة لتمرير الخطأ إلى الأعلى. بدلاً من match الطويلة، اكتب:

\n\n
use std::fs::File;\nuse std::io::Read;\n\nfn read_file(path: &str) -> Result<String, std::io::Error> {\n    let mut file = File::open(path)?;\n    let mut contents = String::new();\n    file.read_to_string(&mut contents)?;\n    Ok(contents)\n}
\n\n

أنشئ أنواع أخطاء خاصة بك

\n

بدلاً من استخدام String كخطأ، عرّف تعدادًا (enum):

\n\n
#[derive(Debug)]\nenum MyError {\n    Io(std::io::Error),\n    Parse(std::num::ParseIntError),\n}\n\nimpl From<std::io::Error> for My                

المدونات

توصيات الكتب