مقدمة: لماذا Rust صارم جدًا، وكيف تساعد مراجعة الكود في الحفاظ على الصحة العقلية
\nلقد كتبت كودًا بلغة Rust. تم تجميعه - مرحى! ولكن المشكلة: المطور الكبير، عند فتح طلب السحب الخاص بك، يتنهد ويبدأ في كتابة التعليقات. هل هذا مألوف؟ Rust هي لغة ذات فلسفة فريدة: إنها تثق بك، ولكنها تتحقق من كل شيء. ومع ذلك، فإن المترجم لا يرى ما تراه العين الخبيرة. لن يقول: "مرحبًا، يمكن فعل هذا بشكل أكثر أناقة" أو "الكود الخاص بك يتسرب - ليس بالذاكرة، بل بالأداء".
\nفي هذه المقالة، سنجري مراجعة كود Rust ونحلل الملاحظات النموذجية للمطورين الكبار. ستتعلم كيفية تحويل "الكود الذي يعمل فقط" إلى كود اصطلاحي وموثوق. هيا بنا!
\n\n1. تجاهل نظام الأنواع: "دعني أضع كل شيء في String"
\nالخطأ الأكثر شيوعًا للمبتدئين هو استخدام String أو الأنواع العامة حيث تكون الأنواع المحددة مطلوبة. سيقول المطور الكبير: "يجب أن يعكس نوعك منطق الأعمال، وليس مجرد أن يكون سلسلة نصية".
المشكلة: فقدان الدلالة
\nتخيل أنك تكتب دالة للعمل مع عناوين البريد الإلكتروني:
\nfn send_email(to: String, subject: String, body: String) {\n // ...\n}\nما الخطأ هنا؟ يمكنك الخلط بين to و subject - لن يلاحظ المترجم. سيقترح المطور الكبير استخدام نمط newtype:
struct Email(String);\nstruct Subject(String);\nstruct Body(String);\n\nfn send_email(to: Email, subject: Subject, body: Body) {\n // ...\n}\nهل يبدو هذا زائدًا عن الحاجة؟ في مراجعة كود Rust، هذا النهج هو المعيار الذهبي. إنه يجعل الكود موثقًا ذاتيًا ويستبعد فئة كاملة من الأخطاء.
\n\n2. الإفراط في استخدام clone(): النسخ لا يعني الملكية
\nغالبًا ما يستخدم المطورون المبتدئون .clone() في كل مكان حيث يشتكي المترجم من الاقتراض. سيقول المطور الكبير: "أنت تستسلم ببساطة أمام مدقق الاقتراض. فكر بطريقة مختلفة".
مثال: clone غير ضروري
\nfn process(data: Vec<i32>) {\n let first = data[0].clone();\n let second = data[1].clone();\n // ...\n}\ni32 ينفذ trait Copy - clone() هنا غير ضروري تمامًا. لكن المشكلة أعمق: إذا كنت تستنسخ هياكل كبيرة (مثل Vec أو String)، فستحصل على ضربة في الأداء.
النهج الصحيح هو العمل مع المراجع:
\nfn process(data: &[i32]) {\n let first = &data[0];\n let second = &data[1];\n // ...\n}\nفي مراجعة كود Rust، يجب عليك شرح سبب استنساخك. إذا كانت الإجابة "حتى لا يشتكي المترجم" - فاستعد لتعليق مدمر.
\n\n3. معالجة الأخطاء السيئة: .unwrap() ليس حلاً نهائيًا
\nيكره المطورون الكبار unwrap() و expect() في كود الإنتاج. لماذا؟ لأنهما يحولان الخطأ القابل للاسترداد إلى حالة ذعر. والذعر في Rust يعني إنهاء الطوارئ.
ما الخطأ في هذا الكود؟
\nlet file_content = std::fs::read_to_string("config.txt").unwrap();\nإذا لم يكن الملف موجودًا - سينهار البرنامج. سيقترح المطور الكبير:
\nlet file_content = std::fs::read_to_string("config.txt")\n .map_err(|e| format!("Failed to read config: {}", e))?;\nاستخدم عامل ? وأنواع الأخطاء الخاصة بك. هذا هو أساس Rust الاصطلاحي. في مراجعة كود Rust، هذه واحدة من أولى الملاحظات.
4. الأداء المنسي: التخصيصات والمكررات
\nRust هي لغة نظام. سينظر المطور الكبير ليس فقط إلى الأمان، ولكن أيضًا إلى السرعة. إحدى المشكلات النموذجية هي إنشاء مجموعات غير ضرورية.
\nمثال: التجميع بدون حاجة
\nlet numbers: Vec<i32> = (0..100).collect();\nlet doubled: Vec<i32> = numbers.iter().map(|x| x * 2).collect();