English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

إدارة Rust

كل لغة برمجة لا يمكنها تنظيم الكود تكون صعبة للغاية للدخول فيها، لا يوجد تقريبًا أي منتج برمجي يتم تجميعه من ملف مصدر واحد.

كل البرامج حتى الآن في هذا الدليل مكتوبة في ملف واحد، وهو لتحسين سهولة تعلم بنية اللغة Rust والمفاهيم.

للمشروع، التنظيم البرمجي مهم جدًا.

هناك ثلاثة مفاهيم تنظيمية مهمة في Rust: crates، الحزم، والمودولات.

crates

"crates" هي ملفات البرامج الثنائية أو المكتبات، وتوجد داخل "الحزمة".

"crates" هي بنية شجرة، ويكون الجذر هو البرنامج الذي يتم تجميعه عند بدء تشغيل المُعالج.

ملاحظة: "ملف البرنامج الثنائي" لا يكون بالضرورة "ملف يمكن تنفيذه ثنائيًا"، يمكن فقط التأكد من أنه يحتوي على لغة الآلة الخاصة بالماكينة المستهدفة، ويمكن أن يختلف تنسيق الملف بناءً على بيئة التجميع المختلفة.

الحزمة (Package)

عندما نستخدم Cargo لتنفيذ الأمر new لإنشاء مشروع Rust، سيتم إنشاء ملف Cargo.toml في مجلد المشروع. الجوهر للمشروع هو حزمة، ويجب أن تُدار الحزمة باستخدام ملف Cargo.toml، والذي يصف معلومات الحزمة الأساسية وكذلك الاعتمادات.

يمكن للحزمة أن تحتوي على مكتبة واحدة "crates"، ولكن يمكن أن تحتوي على أي عدد من الثنائيات "crates"، ولكن يجب أن تحتوي على على الأقل "crates" واحدة (سواء كانت مكتبة أو ثنائية "crates")

بعد إنشاء الحزمة باستخدام الأمر cargo new، سيتم إنشاء ملف المصدر main.rs في مجلد src، ويقوم Cargo بتعيين هذا الملف كجذر الحزمة الثنائية، وسيكون الثنائي المُنتج بعد التجميع متطابقًا مع اسم الحزمة.

مodule

للعملية في الهندسة البرمجية، نحن ننظم عادة وفقًا للمعايير التنظيمية لللغة البرمجية المستخدمة، والهيكل الرئيسي للمodule غالبًا هو شجرة. وحدة التنظيم الرئيسية في Java هي الفئة، بينما الطريقة الرئيسية لتنظيم module في JavaScript هي function.

يمكن لكل وحدة التنظيم المتقدمة أن تحتوي على وحدات أخرى، مثل بنية دليل نظام الملفات. وحدة التنظيم في Rust هي المodule.

mod nation {
    mod government {
        fn govern() {}
    }
    mod congress {
        fn legislate() {}
    }
    mod court {
        fn judicial() {}
    }
}

هذا هو وصف عملية دولة القانون: تشمل الدولة (nation) الحكومة (government) والمجلس التشريعي (congress) والقضاء (court)، وكل منها له وظائف إدارية، تشريعية، وعدلية. يمكن تحويلها إلى بنية شجرة:

nation
 ├── government
 │ └── govern
 ├── congress
 │ └── legislate
 └── court
   └── judical

في نظام الملفات، بنية الدليل غالبًا تعبر عن موقع الكائن في سلسلة المسار باستخدام الرمز المائل، وseparator في Rust هو ::.

يتم تقسيم المسار إلى مسار مطلق ومسار مطلق. المسار المطلق يبدأ من كلمة المفتاح crate. المسار المطلق يبدأ من كلمة المفتاح self أو super أو وسم معين. على سبيل المثال:

crate::nation::government::govern();

هو مسار الوصول إلى وظيفة govern بشكل مطلق، المسار الخاص يمكن تمثيله كالتالي:

nation::government::govern();

الآن يمكنك محاولة تعريف هيكل module مشابه في برنامج المصدر واستخدام المسار في الدالة الرئيسية.

إذا قمت بذلك، ستجد بالتأكيد أن هناك أخطاء: module government ووظائفه الخاصة هي سرية، لا يمكنك الوصول إليها.

صلاحيات الوصول

هناك نوعان بسيطان من صلاحيات الوصول في Rust: العامة (public) والخاصة (private).

بالتقديم، إذا لم يتم تزويدهم بمزيج، فإن صلاحيات أعضاء المodule ستكون سرية.

إذا كنت ترغب في استخدام الصلاحيات العامة، يجب استخدام كلمة المفتاح pub.

للمodule الخاصة، يمكن الوصول إليها فقط من موقعها أو موقع أقل من مستواها، ولا يمكن الوصول إليها من الخارج.

mod nation {
    pub mod government {
        pub fn govern() {}
    }
    mod congress {
        pub fn legislate() {}
    }
    
    mod court {
        fn judicial() {
            super::congress::legislate();
        }
    }
}
fn main() {
    nation::government::govern();
}

هذا البرنامج قابلة للترميز. يرجى ملاحظة طريقة الوصول إلى super في module court.

إذا كان هناك تعريف للهيكل في المodule، فإن الحقول الخاصة به هي افتراضياً سرية. لذا، إذا كنت ترغب في استخدام الهيكل والحقول في المodule، يجب استخدام pub:

mod back_of_house {
    pub struct Breakfast {
        pub toast: String,
        seasonal_fruit: String,
    }
    impl Breakfast {
        pub fn summer(toast: &str) -> Breakfast {
            Breakfast {
                toast: String::from(toast),
                seasonal_fruit: String::from("peaches"),
            }
        }
    }
}
pub fn eat_at_restaurant() {
    let mut meal = back_of_house::Breakfast::summer("Rye");
    meal.toast = String::from("Wheat");
    println!("I'd like {} toast please", meal.toast);
}
fn main() {
    eat_at_restaurant()
}

نتيجة التنفيذ:

I'd like Wheat toast please

يمكن لفروع المجموعات أن تحتوي على حقول، لكنها لا تملك نفس الخصائص:

mod SomeModule {
    pub enum Person {
        King {
            name: String
        },
        Quene
    }
}
fn main() {
    let person = SomeModule::Person::King {
        name: String::from("Blue")
    };
    match person {
        SomeModule::Person::King {name} => {
            println!("{}", name);
        }
        _ => {}
    }
}

نتيجة التنفيذ:

Blue

الوحدة غير المرئية

المطورون الذين استخدموا Java غالباً ما يكونون مستائين من كتلة class الخارجية الأكثر - الاسم الخاص بها هو نفس اسم الملف، لأنه يمثل حاوية الملف، على الرغم من أن ذلك يمكن أن يكون معقداً لكن لا بد أن نكتبه لنؤكد "هذه الكلاس هي الكلاس الموجودة في الملف".

لكن هناك بعض الفوائد: على الأقل يجعل المطورون مدركين وجود كلاسس التغليف، ويمكنهم وصف علاقات النسب بين الكلاسات بوضوح.

في Rust، الوحدة تشبه كلاسس Java لكن يمكنك كتابة دالة رئيسية في بداية الملف، كيف يمكن تفسير ذلك؟

محتويات كل ملف Rust هي وحدة 'غير مرئية'.

لنستخدم اثنين من الملفات لشرح هذا الأمر:

ملف main.rs

// main.rs
mod second_module;
fn main() {
    println!("هذا هو الوحدة الرئيسية.");
    println!("{}", second_module::message());
}

ملف second_module.rs

// second_module.rs
pub fn message() -> String {
    String::from("هذا هو الوحدة الثانية.")
}

نتيجة التنفيذ:

هذا هو الوحدة الرئيسية.
هذا هو الوحدة الثانية.

كلمة المفتاح 'use'

استخدام كلمة المفتاح 'use' يمكن أن يدخل معرف وحدة إلى نطاق العمل الحالي:

mod nation {
    pub mod government {
        pub fn govern() {}
    }
}
use crate::nation::government::govern;
fn main() {
    govern();
}

يمكن ترميز هذا البرنامج.

بسبب أن كلمة المفتاح use قامت باستيراد معرف govern إلى هذا المodule، يمكن استخدامه مباشرة.

بهذا يمكننا حل مشكلة الطريق الطويل للمكتبات المحلية.

بالطبع، هناك بعض الحالات التي تتضمن نفس الاسمين، ويجب استيرادهما، يمكننا استخدام كلمة المفتاح as لإضافة اسم بديل للمعرف:

mod nation {
    pub mod government {
        pub fn govern() {}
    }
    pub fn govern() {}
}
    
use crate::nation::government::govern;
use crate::nation::govern as nation_govern;
fn main() {
    nation_govern();
    govern();
}

هناك اثنان من وظائف govern، واحدة هي تحت nation، والأخرى تحت government، نستخدم as لتغيير اسم nation تحت nation_govern. يمكن استخدام الاسمين في نفس الوقت.

يمكن استخدام كلمة المفتاح use مع كلمة المفتاح pub:

mod nation {
    pub mod government {
        pub fn govern() {}
    }
    pub use government::govern;
}
fn main() {
    nation::govern();
}

الإشارة إلى المكتبة القياسية

مفردات مكتبة Rust الرسمية:https://doc.rust-lang.org/stable/std/all.html

بعد دراسة مفاهيم هذا الفصل، يمكننا بسهولة استيراد مكتبات النظام لتطوير البرامج بشكل مريح:

use std::f64::consts::PI;
fn main() {
    println!("{}", (PI / 2.0).sin());
}

نتيجة التنفيذ:

1

جميع مكتبات النظام هي مدمجة بشكل افتراضي، لذا يمكنك استخدام كلمة المفتاح use لتقريب المسار واستخدامها بسهولة.